STM32 uC/OS-III

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 是一个操作系统,准确地说应该是一个实时操
作系统,也就是 RTOS(Real 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 leaving(ucos定义了一个进入临界区的函数,两个退出临界区的函数)。

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 can't 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,  //任务TCB
                       OS_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 task's 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-III's idle task
*                             OS_ERR_TASK_DEL_INVALID      if you attempted to delete uC/OS-III's 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; /* 指向任务名的指针 */
#endif
	 OS_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;  /* 指向任务函数参数的指针 */
#endif
 	OS_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; /* 任务栈大小 */
#endif
 	OS_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; /* 用于第三方调试工具 */
#endif
	 OS_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_EN
	 CPU_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*4=256字节。
任务的栈占用的是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 task's TCB(任务控制块)
*
*              p_name         is a pointer to an ASCII string to provide a name to the task.(任务名字)
*
*              p_task         is a pointer to the task's 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 task's 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 doesn't 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);

消息队列

后面再写。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/506463.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue前端项目打包

4.1编译打包 npm run build 4.2 前端项目 nginx的配置文件default.conf 和 dockerfile default.conf upstream wms-app { server 192.168.14.3:3666 ; server 192.168.14.3:3777 ; } server { listen 80; listen [::]:80; server_name localhost; access_log /var/log/nginx…

毛利率低从哪些维度分析?零售服装行业如何提升毛利率?

在零售服装行业中,毛利率是评估公司盈利能力的关键指标之一。然而,某服装公司在一段时间内销售总额达到5878.28万,但其总毛利额仅为591.26万,平均毛利率仅为10.06%。这一数字明显低于了服装行业通常的毛利率范围(一般在…

语义分割——Dark Zurich数据集

一、重要性及意义 首先,Dark Zurich为语义分割提供了大量真实且多样化的图像数据。该数据集包含了在夜间、黄昏和白天拍摄的大量图像,涵盖了不同光照条件和场景下的图像变化。这些图像数据不仅丰富了语义分割任务的数据集,也为模型提供了更全…

政安晨:【Keras机器学习实践要点】(七)—— 使用TensorFlow自定义fit()

目录 前言 导入 来一个简单例子 下沉到更低的级别 支持样本权重和类别权重 提供您自己的评估步骤 总结:一个端到端的GAN示例 政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的…

【Linux】TCP网络套接字编程+守护进程

文章目录 日志类(完成TCP/UDP套接字常见连接过程中的日志打印)单进程版本的服务器客户端通信多进程版本和多线程版本守护进程化的多线程服务器 日志类(完成TCP/UDP套接字常见连接过程中的日志打印) 为了让我们的代码更规范化&…

3万字80道Java基础经典面试题总结(2024修订版)

大家好,我是哪吒。 本系列是《10万字208道Java经典面试题总结(附答案)》的2024修订版。 目录 1、说说跨平台性2、Java是如何实现跨平台性的?3、JDK 和 JRE 有什么区别?4、为何要配置Java环境变量?5、Java都有哪些特性&#xff1f…

(八)Gateway服务网关

Gateway服务网关 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。…

Linux/Headless

Headless Enumeration nmap 用 nmap 扫描了常见的端口,发现对外开放了 22 和 5000,而且 nmap 显示 5000 端口的服务是 upnp? ┌──(kali㉿kali)-[~/vegetable/HTB/headless] └─$ nmap 10.10.11.8 Starting Nmap 7.93 ( https://nmap.or…

打造安全医疗网络:三网整体规划与云数据中心构建策略

医院网络安全问题涉及到医院日常管理多个方面,一旦医院信息管理系统在正常运行过程中受到外部恶意攻击,或者出现意外中断等情况,都会造成海量医疗数据信息的丢失。由于医院信息管理系统中存储了大量患者个人信息和治疗方案信息等,…

神奇的css radial-gradient

使用css radial-gradient属性,创造一个中间凹陷进去的形状。如下图 background: radial-gradient(circle at 50% -0.06rem, transparent 0.1rem, white 0) top left 100% no-repeat;

vue系列——v-on

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>v-on指令</title> </head> <body>…

docker部署DOS游戏

下载镜像 docker pull registry.cn-beijing.aliyuncs.com/wuxingge123/dosgame-web-docker:latestdocker-compose部署 vim docker-compose.yml version: 3 services:dosgame:container_name: dosgameimage: registry.cn-beijing.aliyuncs.com/wuxingge123/dosgame-web-docke…

贪吃蛇:从零开始搭建一个完整的小游戏

目录 导语&#xff1a; 一、游戏框架 二、蛇的实现 三、绘制游戏界面 四、食物 五、移动蛇 六.得分系统&#xff0c;是否吃到食物 七、检查碰撞 八、处理按键事件 九、得分系统 十、游戏状态管理 导语&#xff1a; 贪吃蛇这个经典的小游戏&#xff0c;我上学的时候就…

设计模式-概述篇

1. 掌握设计模式的层次 第1层&#xff1a;刚开始学编程不久&#xff0c;听说过什么是设计模式第2层&#xff1a;有很长时间的编程经验&#xff0c;自己写了很多代码&#xff0c;其中用到了设计模式&#xff0c;但是自己却不知道第3层&#xff1a;学习过了设计模式&#xff0c;…

【机器学习】无监督学习与聚类技术:解锁数据的隐藏结构

无监督学习介绍 无监督学习&#xff0c;作为机器学习的一大分支&#xff0c;专注于探索未经标记的数据集中的潜在结构。不同于有监督学习&#xff0c;无监督学习不依赖于外部提供的标签或输出结果&#xff0c;而是通过数据本身的特征来寻找模式、聚类或降维。这种学习方法在多…

03-MySQl数据库的-用户管理

一、创建新用户 mysql> create user xjzw10.0.0.% identified by 1; Query OK, 0 rows affected (0.01 sec) 二、查看当前数据库正在登录的用户 mysql> select user(); ---------------- | user() | ---------------- | rootlocalhost | ---------------- 1 row …

PI案例分享--2000A核心电源网络的设计、仿真与验证

目录 摘要 0 引言 1 为什么需要 2000A 的数字电子产品? 2 2000A 的供电电源设计 2.1 "MPM3698 2*MPM3699"的 MPS扩展电源架构 2.2 使用恒定导通时间(COT)模式输出核心电压的原因 2.3 模块化 VRM 的优势 2.4 用步进负载验证2000A的设计难点 2.4.1 电源网络 …

初始Java篇(JavaSE基础语法)(5)(类和对象(上))

个人主页&#xff08;找往期文章包括但不限于本期文章中不懂的知识点&#xff09;&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 目录 面向对象的初步认知 面向对象与面向过程的区别 类的定义和使用 类的定义格式 类的实例化 this引用 什么是this引用&#xff1f; this引用…

Python爬虫-懂车帝城市销量榜单

前言 本文是该专栏的第23篇,后面会持续分享python爬虫干货知识,记得关注。 最近粉丝留言咨询某汽车平台的汽车销量榜单数据,本文笔者以懂车帝平台为例,采集对应的城市汽车销量榜单数据。 具体的详细思路以及代码实现逻辑,跟着笔者直接往下看正文详细内容。(附带完整代码…

Gradle 使用详解

目录 一. 前言 二. 下载与安装 2.1. 下载 2.2. 配置环境变量 2.3. 配置镜像 2.3.1. 全局设置 2.3.2. 项目级设置 三. Gradle 配置文件 3.1. build.gradle 3.2. settings.gradle 3.3. gradle.properties 3.4. init.d 目录 3.5. buildSrc 目录 四. Java Library 插…