上海专业做网站电话,杭工e家app是哪个网站做的,软件定制开发公司官网,采集网站seoWhat is uC/OS-III?
C/OS-III 的发音为“Micro C O S Three”#xff0c;这意味着 C/OS-III 是基于 C 语言编写的第三代 小型操作系统#xff0c;当然这里所说的第三代是相对于 C/OS 的前两个版本 C/OS 和 C/OS-II 而言 的#xff0c;后面也会介绍这三个版本的差别。C/OS/…What is uC/OS-III?
µC/OS-III 的发音为“Micro C O S Three”这意味着 µC/OS-III 是基于 C 语言编写的第三代 小型操作系统当然这里所说的第三代是相对于 µC/OS 的前两个版本 µC/OS 和 µC/OS-II 而言 的后面也会介绍这三个版本的差别。µC/OS/III 是一个操作系统准确地说应该是一个实时操 作系统也就是 RTOSReal Time Operating System与之类似的 RTOS 还有 FreeRTOS、RTX、 RT-Thread 等. 官方手册呀跟github一个鸟样随缘访问除非。。。。。。
uC/OS-III 的特点
抢占式多任务管理
uC/OS-III 是一个支持多任务抢占的内核因此总是优先执行任务优先级高的任务。
时间片调度
uC/OS-III 允许系统中有多个相同任务优先级的任务如果系统中处于就绪状态的任务中优先级最高的任务有多个那么 µC/OS-III 将以时间片的方式调度任务即根据用户指定的时间时间片轮流调度这些任务。
极短的中断禁用时间
uC/OS-III 通过锁定任务调度器代替禁用中断来保护一些关键区域临界区这确保了 uC/OS-III 能够快速地响应中断。
任务数量不限
µC/OS-III 理论上支持不受限制的任务数量但实际上系统中任务的最大数量受处理器内存空间的限制。
任务优先级数量不限
uC/OS-III 支持的任务优先级数量不受限制但对于大多数应用场景而言使用 32~256 个任务优先级就绰绰有余了。
内核对象数量不限
uC/OS-III 提供了多种内核对象如任务、信号量、事件标志、消息队列、软件定时器和内存区等并且在不考虑处理器内存限制的情况下用户可以无限制的创建这些内核对象。
时间戳
uC/OS-III 提供了时间戳功能用户可以非常方便地测量系统在运行过程中处理器处理某些事件所消耗的时间以方便用户对系统进行针对性的优化。自定义钩子函数µC/OS-III 提供了一些在内核执行操作之前、之后或过程中的钩子函数这样可以方便用户扩展 µC/OS-III 的功能。
防死锁uC/OS-III 允许任务在等待某些内核对象前设置一个等待的最大超时时间这样
可以有效地防止死锁的发生。
软件定时器
在 uC/OS-III 中用户可以创建任意数量的“单次”和“周期”软件定时器并且每个软件定时器都可以有独立的超时回调函数。
任务内嵌信号量
uC/OS-III 提供了任务的内嵌信号量功能这使得任务可以直接获取来自其他任务或中断的信号而不需要任何的中间内核对象大大地提高了系统的运行效率。
任务内嵌消息队列
uC/OS-III 提供了任务的内嵌消息队列这使得任务可以直接接收来自其他任务或中断的消息而不需要任何的中间内核对象大大地提高了系统的运行效率。
临界区
uC/Os-Ill defines one macro for entering a critical section and two macros for leavingucos定义了一个进入临界区的函数两个退出临界区的函数。
os_CRITICAL_ENTER(); //进入临界区
os_CRITICAL_EXIT(); //退出临界区
os_CRITICALEXIT_NO_SCHED(); //退出街区任务
任务调度
任务优先级
任务优先级是决定任务调度器如何分配 CPU 使用权的因素之一。每一个任务都被分配一个0~(OS_CFG_PRIO_MAX-1)的任务优先级并且 uC/OS-III 支持多了任务具有相同的任务优先级宏 OS_CFG_PRIO_MAX 是在 uC/OS-III 的配置文 os_cfg.h 中定义配置的。在 cpu_cfg.h文件中有宏CPU_CFG_LEAD_ZEROS_ASM_PRESENT该宏用于配置 µC/OS-III 使用硬件指令的方法或是软件算法的方法计算前导零数量uC/OS-III 使用位图的方式记录当前系统中存在的所有任务优先级在 uC/OS-III 系统中存在的最高任务优先级时就会使用到前导零计数。对于 STM32 而言STM32 是具有硬件计算前导零的指令的并且最大支持 32比特位的数因此宏 OS_CFG_PRIO_MAX 的最大值就是 32。当然配置系统支持的任务优先级数量越多系统消耗的资源也就越多因此读者的实际的工程开发中应当合理地根据实际需求配置宏 OS_CFG_PRIO_MAX。µC/OS-III 的任务优先级高低与其对应的任务优先级数值是成反比的也就是说任务优先级数值为 0 的任务是最高优先级的任务任务优先级数值为(OS_CFG_PRIO_MAX-1)的任务是优先级最低的任务。如下图
任务调度
任务调度是 uC/OS-III 的一部分负责确定接下来应该运行哪一个任务。uC/OS-III 是一个 基于任务优先级的抢占式内核抢占式调度是 uC/OS-III 的主要任务调度方式并且 uC/OS-III 在抢占式调度的基础上还支持时间片调度接下来分别介绍这两种任务调度方式。
抢占式
在 uC/OS-III 中每一个任务都会根据其重要性被分配一个任务优先级重要性高的任务分配到的任务优先级高任务优先级高的任务就能够抢占任务优先级低的任务从而获得 CPU的使用权。在抢占式调度中如果一个具有高任务优先级的任务因等待某一事件而被挂起后CPU 的使用权会交给任务优先级低的任务此时只要任务优先级高的任务等待的事件发生那么uC/OS-III 会立即挂起正在运行的低任务优先级的任务而去处理任务优先级高的任务这一过程就是抢占的过程。 同样的如果被挂起的高优先级的任务所等待的事件在中断中发生那么中断服务函数退出后不会返回任务优先级低的任务运行而是会直接返回任务优先级高的任务去运行。抢占式调度主要是针对任务优先级不同的任务每一个任务都有一个任务优先级任务优先级高的任务可以抢占任务优先级低的任务运行只有当任务优先级高的任务被挂起低任务优先级的任务才能够运行。
时间片轮转
时间片调度是针对任务优先级相同的任务而言的当多个具有相同任务优先级的任务就绪时任务调度器会根据用户设置的任务时间片轮流地运行这些任务当然这些任务的运行依然会被任务优先级更高的任务抢占。时间片是以一次系统时钟节拍为单位的例如uC/OS-III 默认设置的任务时间片为 100则 uC/OS-III 会在当前任务运行 100 次系统时钟节拍的时间后切换到另一个相同任务优先级的任务中运行。
任务状态 任务挂起
************************************************************************************************************************
* SUSPEND A TASK
*
* Description: This function is called to suspend a task. The task can be the calling task if p_tcb is a NULL pointer
* or the pointer to the TCB of the calling task.
*
* Arguments : p_tcb is a pointer to the TCB to suspend.
* If p_tcb is a NULL pointer then, suspend the current task.
*
* p_err is a pointer to a variable that will receive an error code from this function.
*
* OS_ERR_NONE if the requested task is suspended
* OS_ERR_SCHED_LOCKED you cant suspend the current task is the scheduler is
* locked
* OS_ERR_TASK_SUSPEND_ISR if you called this function from an ISR
* OS_ERR_TASK_SUSPEND_IDLE if you attempted to suspend the idle task which is not
* allowed.
* OS_ERR_TASK_SUSPEND_INT_HANDLER if you attempted to suspend the idle task which is not
* allowed.
*
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it.
*
* 2) You should use this function with great care. If you suspend a task that is waiting for an event
* (i.e. a message, a semaphore, a queue ...) you will prevent this task from running when the event
* arrives.
************************************************************************************************************************任务挂起函数
void OS_TaskSuspend (OS_TCB *p_tcb, //任务TCBOS_ERR *p_err); //错误返回值任务恢复
/*$PAGE*/
/*
************************************************************************************************************************
* RESUME A SUSPENDED TASK
*
* Description: This function is called to resume a previously suspended task. This is the only call that will remove an
* explicit task suspension.
*
* Arguments : p_tcb Is a pointer to the tasks OS_TCB to resume
*
* p_err Is a pointer to a variable that will contain an error code returned by this function
*
* OS_ERR_NONE if the requested task is resumed
* OS_ERR_STATE_INVALID if the task is in an invalid state
* OS_ERR_TASK_RESUME_ISR if you called this function from an ISR
* OS_ERR_TASK_RESUME_SELF You cannot resume self
* OS_ERR_TASK_NOT_SUSPENDED if the task to resume has not been suspended
*
* Returns : none
*
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
************************************************************************************************************************
*/任务恢复函数
void OS_TaskResume (OS_TCB *p_tcb,OS_ERR *p_err);任务删除
/*$PAGE*/
/*
************************************************************************************************************************
* DELETE A TASK
*
* Description: This function allows you to delete a task. The calling task can delete itself by specifying a NULL
* pointer for p_tcb. The deleted task is returned to the dormant state and can be re-activated by
* creating the deleted task again.
*
* Arguments : p_tcb is the TCB of the tack to delete
*
* p_err is a pointer to an error code returned by this function:
*
* OS_ERR_NONE if the call is successful
* OS_ERR_STATE_INVALID if the state of the task is invalid
* OS_ERR_TASK_DEL_IDLE if you attempted to delete uC/OS-IIIs idle task
* OS_ERR_TASK_DEL_INVALID if you attempted to delete uC/OS-IIIs ISR handler task
* OS_ERR_TASK_DEL_ISR if you tried to delete a task from an ISR
*
* Note(s) : 1) p_err gets set to OS_ERR_NONE before OSSched() to allow the returned error code to be monitored even
* for a task that is deleting itself. In this case, p_err MUST point to a global variable that can be
* accessed by another task.
************************************************************************************************************************
*/任务删除函数
void OSTaskDel (OS_TCB *p_tcb,OS_ERR *p_err);任务控制块
这个系统的TCB是真牛逼管那么多。
struct os_tcb { CPU_STK *StkPtr; /* 指向任务栈栈顶的指针 */void *ExtPtr; /* 指向用户自定义数据的指针 */CPU_STK *StkLimitPtr; /* 指向任务栈“水位”限制的指针 */#if (OS_CFG_DBG_EN 0u)CPU_CHAR *NamePtr; /* 指向任务名的指针 */
#endifOS_TCB *NextPtr; /* 指向任务链表中下一个任务控制块的指针 */OS_TCB *PrevPtr; /* 指向任务链表中上一个任务控制块的指针 */
#if (OS_CFG_TICK_EN 0u)OS_TCB *TickNextPtr; /* 指向 Tick 任务链表中下一个任务控制块的指针 */OS_TCB *TickPrevPtr; /* 指向 Tick 任务链表中上一个任务控制块的指针 */
#endif
#if ( (OS_CFG_DBG_EN 0u) || \(OS_CFG_STAT_TASK_STK_CHK_EN 0u) || \(OS_CFG_TASK_STK_REDZONE_EN 0u))CPU_STK *StkBasePtr; /* 指向任务栈起始地址的指针 */
#endif
#if defined(OS_CFG_TLS_TBL_SIZE) (OS_CFG_TLS_TBL_SIZE 0u)OS_TLS TLS_Tbl[OS_CFG_TLS_TBL_SIZE]; /* 任务本地存储数组 */
#endif#if (OS_CFG_DBG_EN 0u)OS_TASK_PTR TaskEntryAddr; /* 指向任务函数的指针 */void *TaskEntryArg; /* 指向任务函数参数的指针 */
#endifOS_TCB *PendNextPtr; /* 指向挂起态任务链表中下一个任务控制块的指针 */OS_TCB *PendPrevPtr; /* 指向挂起态任务链表中上一个任务控制块的指针 */OS_PEND_OBJ *PendObjPtr; /* 指向所等待内核对象的指针 */OS_STATE PendOn;/* 任务挂起等待内核对象的类型 */OS_STATUS PendStatus; /* 任务挂起的结果 */OS_STATE TaskState; /* 任务当前的状态 */OS_PRIO Prio; /* 任务优先级 */
#if (OS_CFG_MUTEX_EN 0u)OS_PRIO BasePrio; /* 任务原始优先级 */OS_MUTEX *MutexGrpHeadPtr; /* 指向任务拥有的互斥信号量链表的指针 */
#endif
#if ( (OS_CFG_DBG_EN 0u) || \(OS_CFG_STAT_TASK_STK_CHK_EN 0u) || \(OS_CFG_TASK_STK_REDZONE_EN 0u))CPU_STK_SIZE StkSize; /* 任务栈大小 */
#endifOS_OPT Opt; /* 任务操作选项 */
#if (OS_CFG_TS_EN 0u)CPU_TS TS; /* 任务时间戳 */
#endif
#if (defined(OS_CFG_TRACE_EN) (OS_CFG_TRACE_EN 0u))CPU_INT16U SemID; /* 用于第三方调试工具 */
#endifOS_SEM_CTR SemCtr; /* 用于任务接收信号的计数型信号量 */
#if (OS_CFG_TICK_EN 0u)OS_TICK TickRemain; /* 任务延时的剩余时钟节拍数 */OS_TICK TickCtrPrev; /* 用于任务周期延时 */
#endif
#if (OS_CFG_SCHED_ROUND_ROBIN_EN 0u)OS_TICK TimeQuanta; /* 任务时间片 */OS_TICK TimeQuantaCtr; /* 任务剩余时间片 */
#endif
#if (OS_MSG_EN 0u)void *MsgPtr;/* 指向任务接收到的消息的指针 */OS_MSG_SIZE MsgSize; /* 任务接收到的消息的大小 */
#endif
#if (OS_CFG_TASK_Q_EN 0u)OS_MSG_Q MsgQ; /* 任务内嵌消息队列 */
#if (OS_CFG_TASK_PROFILE_EN 0u)CPU_TS MsgQPendTime; /* 消息从发送到接收花费的时间 */CPU_TS MsgQPendTimeMax; /* 消息从发送到接收花费的最长时间 */
#endif
#endif
#if (OS_CFG_TASK_REG_TBL_SIZE 0u)OS_REG RegTbl[OS_CFG_TASK_REG_TBL_SIZE]; /* 特定于任务的寄存器表 */
#endif
#if (OS_CFG_FLAG_EN 0u)OS_FLAGS FlagsPend; /* 任务挂起等待的事件标志 */OS_FLAGS FlagsRdy; /* 任务挂起等待但已发生的事件标志 */OS_OPT FlagsOpt; /* 任务挂起等待事件标志的类型 */
#endif
#if (OS_CFG_TASK_SUSPEND_EN 0u)OS_NESTING_CTR SuspendCtr; /* 记录任务被挂起的嵌套次数 */
#endif
#if (OS_CFG_TASK_PROFILE_EN 0u)OS_CPU_USAGE CPUUsage; /* 任务的 CPU 使用率 */OS_CPU_USAGE CPUUsageMax; /* 任务最大的 CPU 使用率 */OS_CTX_SW_CTR CtxSwCtr; /* 任务执行次数 */CPU_TS CyclesDelta;/* 任务在任务切换前的运行时间 */CPU_TS CyclesStart; /* 任务启动时的时间戳 */OS_CYCLES CyclesTotal; /* 任务的总运行时间 */OS_CYCLES CyclesTotalPrev; /* 任务上次的总运行时间 */CPU_TS SemPendTime; /* 信号量发出信号所用时间 */CPU_TS SemPendTimeMax; /* 信号量发出信号所用的最大时间 */
#endif
#if (OS_CFG_STAT_TASK_STK_CHK_EN 0u)CPU_STK_SIZE StkUsed; /* 任务栈已使用量 */CPU_STK_SIZE StkFree; /* 任务栈剩余量 */
#endif#ifdef CPU_CFG_INT_DIS_MEAS_ENCPU_TS IntDisTimeMax; /* 任务关闭中断的最长时间 */
#endif
#if (OS_CFG_SCHED_LOCK_TIME_MEAS_EN 0u)CPU_TS SchedLockTimeMax; /* 任务锁定任务调度器的最长时间 */
#endif
#if (OS_CFG_DBG_EN 0u)OS_TCB *DbgPrevPtr; /* 指向用于代码调式的任务链表中上一个任务控制块的指针 */OS_TCB *DbgNextPtr; /* 指向用于代码调试的任务链表中下一个任务控制块的指针 */CPU_CHAR *DbgNamePtr; /* 指向用于代码调试的任务名的指针 */
#endif
#if (defined(OS_CFG_TRACE_EN) (OS_CFG_TRACE_EN 0u))CPU_INT16U TaskID; /* 用于第三方调试工具 */
#endif
};任务栈
对于 uC/OS-III在创建一个任务前需要为任务准备好一块内存空间这一内存空间将作为任务的栈空间进行使用。 用CPU_STK 数据类型来定义任务堆栈CPU_STK在 cpu.h中有定义其实CPU_STK就是CPU_INT32U可以看出一个CPU_STK变量为4字节因此任务的实际堆栈大小应该为我们定义的4倍。下面代码就是我们定义了一个任务堆栈TASK_STK堆栈大小为64*4256字节。 任务的栈占用的是MCU 内部的 RAM当任务越多的时候需要使用的栈空间就越大即需要使用的 RAM空间就越多。一个 MCU 能够支持多少任务就得看你的 RAM 空间有多少。
创建任务
参数说明
/*$PAGE*/
/*
************************************************************************************************************************
* CREATE A TASK
*
* Description: This function is used to have uC/OS-III manage the execution of a task. Tasks can either be created
* prior to the start of multitasking or by a running task. A task cannot be created by an ISR.
*
* Arguments : p_tcb is a pointer to the tasks TCB任务控制块
*
* p_name is a pointer to an ASCII string to provide a name to the task.任务名字
*
* p_task is a pointer to the tasks code 任务函数
*
* p_arg is a pointer to an optional data area which can be used to pass parameters to
* the task when the task first executes. Where the task is concerned it thinks
* it was invoked and passed the argument p_arg as follows:任务函数参数
*
* void Task (void *p_arg)
* {
* for (;;) {
* Task code;
* }
* }
*
* prio is the tasks priority. A unique priority MUST be assigned to each task and the
* lower the number, the higher the priority.任务优先级
*
* p_stk_base is a pointer to the base address of the stack (i.e. low address).堆栈基地址
*
* stk_limit is the number of stack elements to set as watermark limit for the stack. This value
* represents the number of CPU_STK entries left before the stack is full. For example,
* specifying 10% of the stk_size value indicates that the stack limit will be reached
* when the stack reaches 90% full.任务堆栈预警值
*
* stk_size is the size of the stack in number of elements. If CPU_STK is set to CPU_INT08U,
* stk_size corresponds to the number of bytes available. If CPU_STK is set to
* CPU_INT16U, stk_size contains the number of 16-bit entries available. Finally, if
* CPU_STK is set to CPU_INT32U, stk_size contains the number of 32-bit entries
* available on the stack.以元素个数表示的堆栈大小。
*
* q_size is the maximum number of messages that can be sent to the task消息数量
*
* time_quanta amount of time (in ticks) for time slice when round-robin between tasks. Specify 0 to use
* the default.时间片调度时所占时间
*
* p_ext is a pointer to a user supplied memory location which is used as a TCB extension.
* For example, this user memory can hold the contents of floating-point registers
* during a context switch, the time each task takes to execute, the number of times
* the task has been switched-in, etc.
*
* opt contains additional information (or options) about the behavior of the task.
* See OS_OPT_TASK_xxx in OS.H. Current choices are:任务选项
*
* OS_OPT_TASK_NONE No option selected 没有
* OS_OPT_TASK_STK_CHK Stack checking to be allowed for the task堆栈检查
* OS_OPT_TASK_STK_CLR Clear the stack when the task is created创建任务时先打扫卫生
* OS_OPT_TASK_SAVE_FP If the CPU has floating-point registers, save them
* during a context switch.
* OS_OPT_TASK_NO_TLS If the caller doesnt want or need TLS (Thread Local
* Storage) support for the task. If you do not include this
* option, TLS will be supported by default.
*
* p_err is a pointer to an error code that will be set during this call. The value pointer
* to by p_err can be:
*
* OS_ERR_NONE if the function was successful.
* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the task after you called
* OSSafetyCriticalStart().
* OS_ERR_NAME if p_name is a NULL pointer
* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum
* allowed (i.e. OS_CFG_PRIO_MAX-1) or,
* if OS_CFG_ISR_POST_DEFERRED_EN is set to 1 and you tried
* to use priority 0 which is reserved.
* OS_ERR_STK_INVALID if you specified a NULL pointer for p_stk_base
* OS_ERR_STK_SIZE_INVALID if you specified zero for the stk_size
* OS_ERR_STK_LIMIT_INVALID if you specified a stk_limit greater than or equal
* to stk_size
* OS_ERR_TASK_CREATE_ISR if you tried to create a task from an ISR.
* OS_ERR_TASK_INVALID if you specified a NULL pointer for p_task
* OS_ERR_TCB_INVALID if you specified a NULL pointer for p_tcb
*
* Returns : A pointer to the TCB of the task created. This pointer must be used as an ID (i.e handle) to the task.
************************************************************************************************************************
*/任务创建函数
void OSTaskCreate (OS_TCB *p_tcb, //任务控制块由用户自己定义。CPU_CHAR *p_name, //任务名字字符串形式这里任务名字最好要与任务函数入口名字一致方便进行调试。OS_TASK_PTR p_task,//任务入口函数即任务函数的名称需要我们自己定义并且实现。void *p_arg,//任务入口函数形参不用的时候配置为 0 或者 NULL 即可p_arg是指向可选数据区域的指针用于将参数传递给任务因为任务一旦执行那必须是在一个死循环中所以传参只在首次执行时有效。OS_PRIO prio,//任务的优先级由用户自己定义。CPU_STK *p_stk_base,//指向堆栈基址的指针即堆栈的起始地址。CPU_STK_SIZE stk_limit,//设置堆栈深度的限制位置。这个值表示任务的堆栈满溢之前剩余的堆栈容量。例如指定 stk_size 值的 10表示将达到堆栈限制当堆栈达到 90满就表示任务的堆栈已满。CPU_STK_SIZE stk_size,//任务堆栈大小单位由用户决定如果 CPU_STK 被设置为CPU_INT08U则单位为字节而如果 CPU_STK 被设置为 CPU_INT16U则单位为半字同理如果 CPU_STK 被设置为 CPU_INT32U单位为字。在 32 位的处理器下STM32一个字等于 4 个字节那么任务大小就为 APP_TASK_START_STK_SIZE * 4 字节。OS_MSG_QTY q_size,//设置可以发送到任务的最大消息数按需设置即可。OS_TICK time_quanta,//在任务之间循环时的时间片的时间量以滴答为单位。指定 0则使用默认值void *p_ext,//是指向用户提供的内存位置的指针用作 TCB 扩展。例如该用户存储器可以保存浮点寄存器的内容在上下文切换期间每个任务执行的时间次数、任务已经切换等。OS_OPT opt,//用户可选的任务特定选项OS_ERR *p_err);//用于保存返回的错误代码。启动任务和删除任务
删除任务函数
void OSTaskDel (OS_TCB *p_tcb,OS_ERR *p_err);启动任务函数
void OSStart (OS_ERR *p_err);系统内部任务
1、空闲任务
void OS_IdleTask (void *p_arg)2、时钟节拍任务
void OS_TickTask (void *p_arg);3、统计任务
void OSStatTaskCPUUsageInit (OS_ERR *p_err)4、定时任务
void OS_TmrInit (OS_ERR *p_err);5、中断服务任务
void OS_IntQTask(void *p_arg);6、钩子函数
void OSIdleTaskHook(void);消息队列
后面再写。