Chinaunix首页 | 论坛 | 博客
  • 博客访问: 58342
  • 博文数量: 11
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 70
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-28 18:12
文章分类

全部博文(11)

文章存档

2015年(3)

2014年(8)

我的朋友

分类: 嵌入式

2014-12-14 12:24:41

STM32学习记录14 ucosii中的串口中断 - zmurder - 起点的博客

(下图中横坐标为时间)

里面写到:μ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)的大量数据,而这种机制没有应用到中断处理被切换出去的情景。

阅读(5156) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~