@richey
2020-09-29T15:07:31.000000Z
字数 6306
阅读 1364
嵌入式软件 实时操作系统





//ucos-II代码void vButtonTask(void){while(TRUE) {//阻塞直至有键按下}}void vLevelTask(void){while(TRUE){//读油箱液位,完成 读油箱液位,完成各种计算}}void void main(void main(void){OSInit OSInit();OSTaskCreateExt( OSTaskCreateExt(vButtonTask vButtonTask);OSTaskCreateExt( OSTaskCreateExt(vLevelTask vLevelTask); );OSStart OSStart();}

任务上下文切换
任务优先级调度



再谈函数的可重入性
多任务程序使用下面的重入机制
由信号量保护的全局或静态变量
struct {long lTankLevel;long lTimeUpdated;} tankdata[MAX_TANKS];void vButtonTask(void){int inti;while(TRUE){//阻塞直至有键按下i = //获取键值TakeSemphore();//输出i号油箱液位及其更新时间ReleaseSemphore();}}void vCaculateTankLevel(){int inti = 0;while(TRUE){TakeSemphore();//修改 tankdata[i].lTimeUpdated及tankdata[i].TankLevelReleaseSemphore ReleaseSemphore();}}

void main(void){OSInit(); /* 初始化uC/OS-II *///通过调用OSTaskCreate()或//OSTaskCreateExt()创建至少一个任务;OSStart(); /* 开始多任务调度!OSStart()永远不会返回*/}
static OS_STK AppTaskKbdStk[APP_TASK_KBD_STK_SIZE];static void AppTaskKbd(void*p_arg);OSTaskCreate(AppTaskKbd,(void *)0,(OS_STK *)&AppTaskKbdStk[APP_TASK_KBD_STK_SIZE-1],APP_TASK_KBD_PRIO)
任务管理
中断
用户ISR框架
(1)保存全部CPU寄存器的值;
(2)调用OSIntEnter(),或直接把全局变量OSIntNesting(中断嵌套层次)加1;
(3)执行用户代码做中断服务;
(4)调用OSIntExit();
(5)恢复所有CPU寄存器;
(6)执行中断返回指令
void USART1_IRQHandler(void){ //STM32中断示例INT8U err, c ;OS_CPU_SR cpu_sr cpu_sr; // ; // OSIntExit用到改变量OS_ENTER_CRITICAL();OS_ENTER_CRITICAL();OSIntNesting++;OS_EXIT_CRITICAL();OS_EXIT_CRITICAL();if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){c = USART_ReceiveData(USART1);UartPutRxChar(c,COM1 );USART_ClearITPendingBit(USART1, USART_IT_RXNE);}if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) {c = UartGetTxChar UartGetTxChar( &err,COM1);if( err == UART_OK )USART_SendData(USART1, c);USART_SendData(USART1, c);USART_ClearITPendingBit(USART1, USART_IT_TXE);}OSIntExit OSIntExit(); (); }}
// 时钟节拍ISRvoid OSTickISR(void) {(1)保存处理器寄存器的值;(2)调OSIntEnter()或将OSIntNesting加1;(3)调用OSTimeTick(); /*检查每个任务的时间延时*/(4)调用OSIntExit();(5)恢复处理器寄存器的值;(6)执行中断返回指令; ;}void SysTickHandler(void){OS_CPU_SR cpu_sr;OS_ENTER_CRITICAL();OSIntNesting++;OS_EXIT_CRITICAL();OSTimeTick();OSIntExit();}
与时间管理相关的系统服务

系统时间:
信号量在多任务系统中的功能
uC/OS中信号量由两部分组成:
信号量的计数值(16位无符号整数)和等待该信号量的任务所组成的等待任务表;
信号量系统服务
OSSemCreate()
OSSemPend(), OSSemPost()
OSSemAccept(), OSSemQuery()

创建信号量:OSSemCreate()
创建一个信号量,并对信号量的初始计数值赋值,该初始值为 0到65,535之间的一个数;
OS_EVENT *OSSemCreate(INT16U cnt); cnt:信号量的初始值。
等待一个信号量
OSSemPend() 等待一个信号量,将信号量的值减1;
OSSemPend (OS_EVENT *pevent,INT16U timeout, INT8U *err);
执行步骤
• 如果信号量的计数值大于0,将它减1并返回;
• 如果信号量的值等于0,则调用本函数的任务将被阻塞起 来,等待另一个任务把它唤醒;
• 调用OSSched()函数,调度下一个最高优先级的任务运行
发送一个信号量:OSSemPost()
发送一个信号量,将信号量的值加1;
OSSemPost (OS_EVENT *pevent); 执行步骤
• 检查是否有任务在等待该信号量,如果没有,将信号量的计 数值加1并返回;
• 如果有,将优先级最高的任务从等待任务列表中删除,并使 它进入就绪状态;
• 调用OSSched(),判断是否需要进行任务切换。

OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err);
OSMboxPost():发送一个消息到邮箱中如果有任务在等待 该消息,将其中的最高优先级任务从等待列表中删除,变为就 绪状态;

//技巧void * 强制类型转换INT8U CommRxBuf[100];void CommTaskRx(void *pdata){for (;;){...err = OSMboxPost(CommMbox, (void*)&CommRxbuf[0]);...}}







