博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UCOS 中的中断处理
阅读量:5086 次
发布时间:2019-06-13

本文共 5979 字,大约阅读时间需要 19 分钟。

最近遇到一个问题,当我在UCOS里调用系统延时"OSTimeDlyHMSM(0, 0, 0, 10)",程序进入硬件错误中断“HardFault_Handler”中。

我开始以为是主堆栈空间嵌套过多导致溢出,于是设置增大了主堆栈,但依然没有解决问题,和一个朋友联系后得知,他写代码很少在ISR中调用系统延时,我开始有了想法,如果说ISR里不允许,那为什么操作系统端没做限制呢?查看相关资料得知,是我对操作系统的不了解。

uCOS为了防止主堆栈的用空导致程序跑飞,定义了“OSIntNesting”全局变量。

而通过这个全局变量,操作系统能很容易的监控中断的嵌套层次。

而想要利用这个样的机制,你得在你的中断服务程序中配合使用:

OSIntEnter()//告知操作系统你已经进入中断 OSIntNesting++

OSIntExit()//告知操作系统你已经进入中断 OSIntNesting--

 

正对此次问题的摘要:

摘要1:

1 //文章来源:http://gliethttp.cublog.cn[转载请声明出处]  2   3 //----------------------------------------------------------------------  4 //1.OSTimeDly()函数  5 void OSTimeDly (INT16U ticks)  6 {  7     INT8U y;  8 #if OS_CRITICAL_METHOD == 3  9     OS_CPU_SR cpu_sr = 0; 10 #endif 11     if (OSIntNesting > 0) { 12         return;//在中断处理函数中调用了OSTimeDly(),那么直接退出 13     } 14     if (ticks > 0) { 15         OS_ENTER_CRITICAL(); 16 //调用OSTimeDly()的进程自己把自己从就绪控制矩阵中拿下来, 17 //即:去掉调度器(x,y)矩形阵列(OSRdyTbl,OSRdyGrp)中该task对应的bit位,使得调度器不考虑 18 //该task的调度 19         y = OSTCBCur->OSTCBY; 20         OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX; 21         if (OSRdyTbl[y] == 0) { 22             OSRdyGrp &= ~OSTCBCur->OSTCBBitY; 23         } 24 //延时ticks值,放入OSTCBDly单元,在os时钟滴答处理函数OSTimeTick()中,会处理该单元[gliethttp] 25         OSTCBCur->OSTCBDly = ticks; 26         OS_EXIT_CRITICAL(); 27 //因为本task正在运行,所以本task现在的优先级最高,现在本task已经将自己从就绪控制矩阵中--调度器(x,y)矩形阵列 28 //把自己摘掉,所以调度函数OS_Sched()一定会切换到另一个task中执行新task的代码[gliethttp] 29         OS_Sched();//具体参见《浅析μC/OS-II v2.85内核调度函数》 30     }//ticks==0,那么什么也不做 31 } 32 //---------------------------------------------------------------------- 33 //2.OSTimeTick()--在定时中断里引用的系统滴答函数 34 void OSTimeTick (void) 35 { 36     OS_TCB *ptcb; 37 #if OS_TICK_STEP_EN > 0 38     BOOLEAN step; 39 #endif 40 #if OS_CRITICAL_METHOD == 3 41     OS_CPU_SR cpu_sr = 0;//该3方式将使中断状态寄存器放入堆栈中 42  43 #endif 44  45 #if OS_TIME_TICK_HOOK_EN > 0 46     OSTimeTickHook(); 47 #endif 48 #if OS_TIME_GET_SET_EN > 0 49     OS_ENTER_CRITICAL(); 50     OSTime++; 51     OS_EXIT_CRITICAL(); 52 #endif 53     if (OSRunning == OS_TRUE) { 54 #if OS_TICK_STEP_EN > 0 55 //控制内核的tick 56         switch (OSTickStepState) { 57             case OS_TICK_STEP_DIS: 58                  step = OS_TRUE; 59                  break; 60             case OS_TICK_STEP_WAIT: 61                  step = OS_FALSE; 62                  break; 63             case OS_TICK_STEP_ONCE: 64 //本次tick将将影响到task的OSTCBDly域 65 //但以后的tick将一直被屏蔽,不会影响到OSTCBDly域 66 //直到外部将OSTickStepState改变为止[gliethttp] 67                  step = OS_TRUE; 68                  OSTickStepState = OS_TICK_STEP_WAIT; 69                  break; 70             default: 71                  step = OS_TRUE;//本次tick将影响到task的OSTCBDly域 72                  OSTickStepState = OS_TICK_STEP_DIS; 73                  break; 74         } 75         if (step == OS_FALSE) { 76             return; 77         } 78 #endif 79         ptcb = OSTCBList; 80 //2007-09-08 gliethttp 81 //OSTCBList是一个按进程创建的先后顺序链接成的task单向链表,最后创建的task在最前面,最先创建的 82 //task在单向链表的尾端, 83 //所以OS_TaskIdle空闲进程在链表的最后,因为它最先创建 84         while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) { 85             OS_ENTER_CRITICAL(); 86             if (ptcb->OSTCBDly != 0) { 87                 if (--ptcb->OSTCBDly == 0) { 88 //该task的延时时间已到,解析此次延时是OSTimeDly()引起的,还是OSQPend()之类超时引起的[gliethttp] 89                     if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) { 90                         //2007-09-08 gliethttp 91                         //如:由OSSemPend (pevent,timeout,perr);定义的timeout已经到了,对应task需要运行了 92                         //超时时间到,所以不论当前进程是在做什么,只要时间一到 93                         //该task就可以运行了,所以清除所有事件标志,之后状态标示为OS_STAT_PEND_TO(超时) 94                         ptcb->OSTCBStat &= ~(INT8U)OS_STAT_PEND_ANY; 95                         ptcb->OSTCBStatPend = OS_STAT_PEND_TO;//超时异常 96                     } else { 97                         //2007-09-08 gliethttp 98                         //说明该task调用的是OSTimeDly() 99                         ptcb->OSTCBStatPend = OS_STAT_PEND_OK;//正常结束100                     }101                     if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {102                         //2007-09-08 gliethttp103                         //如果该task没有suspend,那么把当前就绪的task加入到运行调度器的就绪控制矩阵中104                         //等待被调度105                         OSRdyGrp |= ptcb->OSTCBBitY;106                         OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;107                     }108                 }109             }110             ptcb = ptcb->OSTCBNext;//继续运算下一个task的OSTCBDly时间域111             OS_EXIT_CRITICAL();112         }113     }114 }

摘要2:

前些天参照FL2440的bootloader的程序,写了关于裸机USB设备驱动的测试程序。然后就想把USB的驱动程序移植到uCos系统中运行。

    对于USB设备驱动的工作原理,我这里不多说,网上有很多这方面的资料。这里只说明在UCOS系统中移植USB设备驱动所需要注意的细节。
    第一步:在uCos系统启动以后,首先对USB设备进行初始化。 这里的初始化包含对中断函数的设置和端点功能的设置 。
    第二步:创建一个端点0的控制处理任务函数。这个任务的优先级最好设置为最高优先级,以便能够及时处理USB的枚举。在任务函数中,我们通过请求信号量的方式来等待中断服务程序发来的信号,当中断服务程序检测到是端点0的中断,即发送一个信号。端点0的控制任务函数接收到此信号,便开始进入端点0的控制传输。如果没有接收到信号,则此任务函数一直处于堵塞状态。便于其他任务的调度执行。这里还有一点需要注意的是:在进入中断函数时,要使用OSIntEnter()和OSIntExit()这两个配套函数。我开始的时候没有加入这两个函数,结果导致一进入枚举就会导致程序跑飞。

1 //摘要来自http://blog.sina.com.cn/u/1093812390 2 //USB控制传输任务函数 3  4 void TaskUsb(void *pdata) 5 { 6 #if OS_CRITICAL_METHOD == 3 7 OS_CPU_SR  cpu_sr; 8 #endif 9 INT8U err;10 while(1){11 OSSemPend(pSetup_Event,0,&err); //等待信号12 if (err == OS_NO_ERR){13 OS_ENTER_CRITICAL(); //关中断14 Ep0Handler(); //进行控制传输处理15 OS_EXIT_CRITICAL(); //开中断16 }17 }18 }19 20 //中断函数如下:21 22 void IsrUsbd(void)23 {24 #if OS_CRITICAL_METHOD == 3            OS_CPU_SR  cpu_sr;25 #endif26 27 28 U8 usbdIntpnd,epIntpnd;29     U8 saveIndexReg = rINDEX_REG;30     OS_ENTER_CRITICAL();   //关中断31 OSIntEnter(); //通知UCOS系统,已进入中断处理程序 usbdIntpnd = rUSB_INT_REG; //读取USB中断寄存器32 epIntpnd = rEP_INT_REG; //读取端点中断寄存器33 ....34 if (epIntpnd & EP0_INT) {35     rEP_INT_REG = EP0_INT;36     OSSemPost(pSetup_Event); //通知控制端口处理任务37  }38 ClearPending(BIT_USBD); rINDEX_REG = saveIndexReg;39  OS_EXIT_CRITICAL(); //开中断40  OSIntExit(); //通知系统,已处理结束中断服务程序。任务调度41 }

 

转载于:https://www.cnblogs.com/swack/p/3487633.html

你可能感兴趣的文章
安卓学习资料推荐-25
查看>>
Mysql数据库备份和还原常用的命令
查看>>
关于退出当前页面在火狐的一些问题
查看>>
【项目实施】项目考核标准
查看>>
spring-aop AnnotationAwareAspectJAutoProxyCreator类
查看>>
经典入门_排序
查看>>
Redis Cluster高可用集群在线迁移操作记录【转】
查看>>
二、spring中装配bean
查看>>
VIM工具
查看>>
javascript闭包
查看>>
@Column标记持久化详细说明
查看>>
创建本地yum软件源,为本地Package安装Cloudera Manager、Cloudera Hadoop及Impala做准备...
查看>>
mysql8.0.13下载与安装图文教程
查看>>
站立会议08(冲刺2)
查看>>
url查询参数解析
查看>>
http://coolshell.cn/articles/10910.html
查看>>
[转]jsbsim基础概念
查看>>
DIV和SPAN的区别
查看>>
第一次使用cnblogs
查看>>
C#语法糖之 session操作类 asp.net
查看>>