STM32 uC/OS-III

news2024/11/26 17:38:05

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);

消息队列

后面再写。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试 - 最大社交距离(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷C卷)》。 刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试…

this.$route.back()时的组件缓存

1.this.$route.back()回到上一个路径会重新加载 跳转时,前一个路由的内容会被销毁,当回来时,重新创建树,组件内有保存了距离,没有一开始是0. 2.keep-alive写在router-view上面,这个地方所代表的路由会被保存,因此可以写在上面,保存,当返回时,如果是这个路由,里面的内容是一样…

深入理解数据结构(1):复杂度详解

文章主题:复杂度详解🌱所属专栏:深入理解数据结构📘作者简介:更新有关深入理解数据结构知识的博主一枚,记录分享自己对数据结构的深入解读。😄个人主页:[₽]的个人主页🔥…

[C++]使用OpenCV去除面积较小的连通域

这是后期补充的部分&#xff0c;和前期的代码不太一样 效果图 源代码 //测试 void CCutImageVS2013Dlg::OnBnClickedTestButton1() {vector<vector<Point> > contours; //轮廓数组vector<Point2d> centers; //轮廓质心坐标 vector<vector<Point&…

概率、似然、极大似然估计

概率、似然、极大似然估计 概率&#xff1a;特定情况下某事件发生的可能性&#xff08;参数已知&#xff0c;事件发生的可能性&#xff09;似然&#xff1a;根据已经确定的结果推测产生这个结果的可能的环境&#xff08;事件发生的可能性已知&#xff0c;参数未知&#xff0c;推…

C++心决之内联函数+auto关键字+指针空值

目录 7.内联函数 7.1 概念 7.2 特性 8. auto关键字(C11) 8.1 类型别名思考 8.2 auto简介 8.3 auto的使用细则 8.4 auto不能推导的场景 9. 基于范围的for循环(C11) 9.1 范围for的语法 9.2 范围for的使用条件 10. 指针空值nullptr(C11) 10.1 C98中的指针空值 7.内联…

计算机专业学生有必要参加软考吗?

有&#xff0c;因为后面真的用得上。 一、行业背景&#xff1a; 你考虑过毕业以后从事什么工作吗&#xff1f;大概率会是去做IT吧&#xff0c;随着这几年总体就业形势不太好&#xff0c;给各位计算机专业毕业生跨行择业的机会也越来越少&#xff0c;再加之外有强敌虎视眈眈&am…

c#仿ppt案例

画曲线 namespace ppt2024 {public partial class Form1 : Form{public Form1(){InitializeComponent();}//存放所有点的位置信息List<Point> lstPosition new List<Point>();//控制开始画的时机bool isDrawing false;//鼠标点击开始画private void Form1_MouseD…

蓝牙耳机推荐哪个品牌好?2024火爆机型推荐,拒绝云测

​音乐和有声读物是许多人放松身心、缓解等待无聊时刻的好伴侣。尽管市面上蓝牙耳机琳琅满目&#xff0c;挑选合适的款式却颇具挑战。作为一个经验丰富的耳机用户&#xff0c;我深知哪些蓝牙耳机值得你的信赖。接下来&#xff0c;我将分享几款我个人认为很不错的蓝牙耳机来给大…

hcia datacom课程学习(5):MAC地址与arp协议

1.MAC地址 1.1 含义与作用 &#xff08;1&#xff09;含义&#xff1a; mac地址也称物理地址&#xff0c;是网卡设备在数据链路层的地址&#xff0c;全世界每一块网卡的mac地址都是唯一的&#xff0c;出厂时烧录在网卡上不可更改 &#xff08;2&#xff09;作用&#xff1a…

Git 如何合并多个连续的提交

我平常的编程喜欢是写一段代码就提交一次&#xff0c;本地一般不攒代码&#xff0c;生怕本地有什么闪失导致白干。但这样就又导致一个问题&#xff1a;查看历史日志时十分不方便&#xff0c;随便找一段提交可以看到&#xff1a; > git log --oneline 8f06be5 add 12/qemu-h…

突破数据障碍—如何使用IP代理服务获取量子科学研究领域最新数据

写在前面 在这个数字化的时代&#xff0c;人们越来越关注隐私保护和网络访问自由。我最近也深入研究了一下IP代理服务&#xff0c;在规避地理限制、绕过封锁以及保护个人隐私方面&#xff0c;它确实发挥了关键作用。 一、基础介绍 起因是有个项目需要对量子领域进行深入的研究之…

Android Studio学习5——布局layout与视图view

wrap_content&#xff0c;内容有多大&#xff0c;就有多宽&#xff08;包裹&#xff09; 布局 padding 边框与它自身的内容 margin 控件与控件之间

漫谈测试策略

作者&#xff1a;小瑕 一、测试策略是什么&#xff1f; 策略&#xff1a; 基本含义&#xff1a;指为达到某种目的而制定的行动方案或计划。 详细解释&#xff1a;策略是指在特定情况下为达到某种目的而采取的有系统性的行动方案或计划。它通常包括分析、决策和执行三个阶段。策…

gitlab代码迁移,包含历史提交记录、标签、分支

1、克隆现有的GitLab仓库&#xff08;http://localhost:8888/aa/bb/cc.git&#xff09;到本地&#xff0c;包括所有分支和标签 git clone --bare http://localhost:8888/aa/bb/cc.git 2、在gitlab上创建一个空的仓库&#xff08;http://localhost:7777/aa/bb/cc.git&#xff…

浅谈通信校验码及 CRC 校验

一、信息论中的 CRC 我上大学的时候,有一门课程叫做信息论,我就是从这个课程中学到的 CRC 校验这个词的,没错,当时学完整个课程后,CRC 对我来说依然只是一个单薄的缩写词语,全称我都不知道是啥。 CRC 全称是循环冗余校验(Cyclic Redundancy Check)。 说到信息论中的…

vue3+ts 调用接口,数据显示

数据展示 &#xff08;例&#xff1a;展示医院等级数据&#xff0c;展示医院区域数据同理。&#xff09; 接口文档中&#xff0c;输入参数 测试一下接口&#xff0c;发请求 看是否能够拿到信息 获取接口&#xff0c;api/index.ts 中 /home/index.ts // 统一管理首页模块接口 i…

SPI通信----Flash存储器W25Q64

SPI怎么配置&#xff1a; 控制器配置&#xff08;更稳定效率高&#xff09; IO模拟的方式&#xff08;更灵活移植性高&#xff09; 首先我会选择用IO模拟的方式配置&#xff0c;SPI根据时钟极性以及时钟相位的不同对应不同等的时序&#xff0c;我选择用时钟极性和时钟相位都…

The Google File System [SOSP‘03] 论文阅读笔记

原论文&#xff1a;The Google File System 1. Introduction 组件故障是常态而非例外 因此&#xff0c;我们需要持续监控、错误检测、容错和自动恢复&#xff01; 按照传统标准&#xff0c;文件数量巨大大多数文件都是通过添加新数据而不是覆盖现有数据来改变的&#xff0c;因…

基于springboot实现教师人事档案管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现在线商城系统演示 摘要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本ONLY在线商城系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理…