@richey
2020-09-29T15:07:31.000000Z
字数 6306
阅读 1202
嵌入式软件
实时操作系统
//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].TankLevel
ReleaseSemphore 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(); (); }
}
// 时钟节拍ISR
void 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]);
...
}
}