一、OS的初始化与启动
- 1.OS初始化,初始化各种内核对象和全局变量
函数原型:void OSInit (OS_ERR *p_err) 参数:p_err,用于返回错误码 返回值:无
它是第一个执行的函数。
- 2.启动OS,创建任务后调用
函数原型:void OSStart (OS_ERR *p_err) 参数:p_err,用于返回错误码 返回值:无
二、任务的管理
- 1.创建任务
void OSTaskCreate (OS_TCB *p_tcb,//类似于线程id,控制任务 CPU_CHAR *p_name,//任务的名字,可以自定义 OS_TASK_PTR p_task,//任务函数,类似线程函数 void *p_arg,//任务传递参数,类似于给线程函数传递参数 OS_PRIO prio,//任务的优先级 CPU_STK *p_stk_base,//任务栈基址,提供一个数组基址(任务栈数组基地址) CPU_STK_SIZE stk_limit,//空出10%的栈空间给到堆栈检测函数使用,反过来说,当前任务只能使用90%栈空间 CPU_STK_SIZE stk_size,//任务栈的大小,以字(32位)为单位 OS_MSG_QTY q_size,//任务内消息队列的大小,若不使用,写0 OS_TICK time_quanta,//时间片轮转调度算法,若不使用,写0(这是时间片的长度) void *p_ext,//提供额外存储空间用于存储浮点运算单元寄存器,若不提供,写NULL OS_OPT opt,//在创建任务的时候,提供额外操作,如果不使用,写OS_OPT_TASK_NONE OS_ERR *p_err)//返回错误码,没有错误的就返回OS_ERR_NONE
例如,创建任务1
//task control block,任务1控制块 OS_TCB Task1_TCB; //任务1函数,类似线程函数 void task1(void *parg); //任务1的任务堆栈,大小为128字,即512字节 CPU_STK task1_stk[128]; //创建任务1 OSTaskCreate( (OS_TCB *)&Task1_TCB,//任务控制块,等同于线程id (CPU_CHAR *)"Task1",//任务的名字,可以自定义 (OS_TASK_PTR)task1,//任务函数,等同于线程函数 (void *)0,//给任务函数传递参数 (OS_PRIO)5,//任务优先级,数值越小,优先级越高 (CPU_STK *)task1_stk,//任务堆栈基地址 (CPU_STK_SIZE)128/10,//任务堆栈深度限位,用到这个位置,任务不能再继续使用 (CPU_STK_SIZE)128,//任务堆栈大小 (OS_MSG_QTY)0,//任务内消息队列的大小,不使用,写0 (OS_TICK)0,//时间片轮转调度算法,若不使用,写0(默认时间片长度) (void *)0,//提供额外存储空间用于存储浮点运算单元寄存器,若不提供,写NULL (OS_OPT)OS_OPT_TASK_NONE,//在创建任务的时候,提供额外操作,如果不使用,写OS_OPT_TASK_NONE &err//返回错误码,没有错误的就返回OS_ERR_NONE );
注意:
创建任务特别检查传递的数组的大小是否空间充足,因为它是作为任务的栈空间使用,若空间不足,会导致程序不能执行,直接跑到HardFault_Handler这个函数。
原因如下:
1)任务里申请大空间的局部变量,例如数组、结构体......,将会占用大量的栈空间
2)任务里包含很多复杂的函数,将会占用大量的栈空间
3)若任务需要用到浮点数运算,要特别注意,出现HardFault_Handler可以尝试分配大一点任务栈,或则提供额外存储空间用于存储浮点运算单元寄存器
- 2.任务挂起
暂停任务的执行
void OSTaskSuspend (OS_TCB *p_tcb, OS_ERR *p_err) 参数: p_tcb,类似于线程id,控制任务 p_err,返回错误码,没有错误的就返回OS_ERR_NONE 返回值:无 用途:1)如果当前任务不是经常要执行的,可以挂起 2)保护共享资源,可以挂起
- 3.任务恢复执行
void OSTaskResume (OS_TCB *p_tcb, OS_ERR *p_err) 参数:p_tcb,类似于线程id,控制任务 p_err,返回错误码,没有错误的就返回OS_ERR_NONE 返回值:无
4.任务的删除
void OSTaskDel (OS_TCB *p_tcb, OS_ERR *p_err) 参数:p_tcb,类似于线程id,控制任务 p_err,返回错误码,没有错误的就返回OS_ERR_NONE 返回值:无 用途:专门用于初始化硬件,一般来说,硬件只做一次初始化,完毕后可将该任务删除。
三、中断代码编写
void USART1_IRQHandler(void) { uint8_t d=0; //进入中断,告诉UCOS,要停止任务调度,因为中断处理是一个原子过程,不可拆分 bug kernel:interrupt atom //中断里面不能再有任务调度 OSIntEnter(); //添加中断处理代码 ..... //退出中断,告诉UCOS,准备可以进行任务调度 OSIntExit(); }
四、互斥锁
互斥锁常用于任务之间的共享资源(任务之间访问到相同的函数、相同的全局变量)访问,当某个任务得到互斥锁后,就可以访问共享资源,其他任务等待该任务释放互斥锁才能进行访问。
void task(void *parg) { while(1) { 加锁 访问共享资源 解锁(立即) ..... 加锁 访问共享资源 解锁(立即) .... } }
- 1.创建互斥锁
void OSMutexCreate (OS_MUTEX *p_mutex, CPU_CHAR *p_name, OS_ERR *p_err) 参数:p_mutex,互斥锁对象 p_name,互斥锁名字 p_err,返回错误码,没有错误的就返回OS_ERR_NONE 返回值:无
- 2.等待互斥锁,若等待成功,则锁定共享资源
void OSMutexPend (OS_MUTEX *p_mutex, OS_TICK timeout, OS_OPT opt, CPU_TS *p_ts, OS_ERR *p_err) 参数:p_mutex,互斥锁对象 timeout,超时时间,默认写0,一直等待 opt,设置当前等待互斥锁的阻塞方式,默认写OS_OPT_PEND_BLOCKING,阻塞等待 p_ts,用于记录等待互斥锁花了多长时间,默认写NULL,不记录。 p_err,返回错误码,没有错误的就返回OS_ERR_NONE
- 3.释放互斥锁,解锁
void OSMutexPost (OS_MUTEX *p_mutex, OS_OPT opt, OS_ERR *p_err) 参数:p_mutex,互斥锁对象 opt,释放互斥锁后希望其他等待锁的任务(最高优先级及就绪)得到立即执行,可以填写这个参数OS_OPT_POST_NONE。 若使用了OS_OPT_POST_NO_SCHED这个参数,得到互斥锁的任务不会立即执行,会等到当前任务让出cpu才会执行。 p_err,返回错误码,没有错误的就返回OS_ERR_NONE