里面写到:μC/OS中,中断服务子程序要用汇编语言来写。
再看《M3权威指南》2.11.2节与9.11节中讲到Cortex-M3在进入异常时自动压栈, 返回时自动出栈,使用stm32的时候再也不需要汇编语言编写了。也就是说我们可以使用C语言来编写中断服务程序。并且省去了上面程序清单的(1)(5)(6).
其实ucos中的终端和裸奔的中断写法基本一致,只是加了几条语句,如下为串口中断的写法:
void USART1_IRQHandler(void)
{
uint8_t RxData;
OS_CPU_SR cpu_sr;
OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */
OSIntNesting++; //中断嵌套数加一
OS_EXIT_CRITICAL();
if(USART_GetITStatus(USART1, USART_IT_RXNE )==SET)//接收中断
{
USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清楚接收中断标志位
RxData = USART_ReceiveData(USART1); //接收数据
if(RxData!=0)//字符串接收完毕
{
Usart1RXArray[Usart1RXLen++]=RxData;
}
}
OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR */
}
红色为ucosii中与裸奔相比添加的代码。
为更好的理解上面的模式, 可以参考os_cpu_c.c中的一段代码
/*
*********************************************************************************************************
* OS_CPU_SysTickHandler()
*
* Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-II tick
* interrupt.
*
* Arguments : none.
*
* Note(s) : 1) This function MUST be placed on entry 15 of the Cortex-M3 vector table.
*********************************************************************************************************
*/
#if ........ //条件编译0,表示我们将其注释掉
void OS_CPU_SysTickHandler (void)
{
OS_CPU_SR cpu_sr; //定义一个数据
OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */
OSIntNesting++;
OS_EXIT_CRITICAL();
OSTimeTick(); /* Call uC/OS-II's OSTimeTick() */
OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR */
}
#endif
下面再看看论坛大神的讨论, 或许对你很有帮助
ucosii操作系统下,中断函数都是要求
开始处运行 OSIntEnter();
在结束处运行OSIntExit();
这样做会避免在中断中进行任务切换,请问为什么不允许在中断中进行任务切换??
|
这是为了中断嵌套准备的,每嵌套一次中断计数加1,直到最后一个中断处理完成才允许任务调度。
中断中不能进行任务调度的理由很多啊,想到一条是,你要是调度了的话,此时如果你已经清了中断标志,那么剩下的中断将无法再调度回来,得不到执行,因为中断不是任务,切换出去了如果没有特殊复杂的手段就回不来。如果你此时没有清中断,那就更乱了,再回中断的话整个处理什么的都要再执行一遍,都是错的。
另外中断的执行是要有时间要求,在操作系统的设计理念中中断的优先级就是高于所有任务的,中断切到任务的话,如果任务是个长时间执行的任务,那么万一再有相同中断进来,那么必然有一次中断就被淹没了。
中断事件一般来说对实时性要求比较高,所以在中断期间不允许任务切换比较合理。有的处理器在硬件上还具有这种保护措施,如果在一个中断还未退出的时候就试图切入线程模式(任务模式),会导致硬件fault。
再问:上面说“要是调度了的话,此时如果你已经清了中断标志,那么剩下的中断将无法再调度回来......”
但是我认为中断也是函数(虽然执行中断不是函数调用),中断中做任务切换时,也会保存当前寄存器值到任务堆栈中,等这个任务再次就绪时,就会找到这个入口处继续执行。所以不存在“剩下的中断将无法再调度回来”. 不知道说的对不对!
回不来,因为你说的是调度,而不是调用,中断不是你起的一个task,不在任务列表里面,中断的生命周期只有从激起cpu响应到处理结束,而task的生命周期是从你主动建立到你主动销毁,这段时间内不管你喜欢它还是讨厌它,它始终会存在于系统中。
如果中断被调度程序打断切换出去,那么打断它的任务在几种情况下交出cpu,一是高优先级抢占,二是自己主动释放cpu(这种情况下cpu交给低优先级任务或者idle task),三是被中断打断,任何一种情况都回不到你以前的中断处理中去,四是自己的时间片到期交给同优先级的下一个就绪任务(这个叫做round robin调度,这种情况ucos不用考虑,因为ucos不支持多任务同优先级)。另外你从这段描述中会发现一个问题,如果你没有清中断标志位,那么即使调度出去了,那个task也要马上交还cpu,因为有中断在。
中断里面的pc指针入栈之类的操作是isr自己完成的而不是操作系统完成的。操作系统在进行任务调度的时候会记录tcb(task control block)的大量数据,而这种机制没有应用到中断处理被切换出去的情景。
|