中断中使用FreeRtos API注意事项

1.优先级问题

 

                                              图一

 

 

 

                                              图二

 

                                               图三


在stm32cube中FreeRTOS有以上两个配置,其代表了RTOS可以调用的最高和最低中断优先级,若在优先级不属于该定义的中断中调用FreeRTOS相关函数,则有可能调用vPortValidateInterruptPriority安全函数,导致程序停止运行。中断的优先级不能设置的过高(对应数字过小)!即中断优先级设置范围为5~15。
 1 void vPortValidateInterruptPriority( void )
 2 {
 3     uint32_t ulCurrentInterrupt;
 4     uint8_t ucCurrentPriority;
 5     //参考内核指南,这个命令是获取当前的中断号
 6     ulCurrentInterrupt = vPortGetIPSR();
 7     /*portFIRST_USER_INTERRUPT_NUMBER 是一个和芯片相关的用户中断号
 8     在M3、M4的芯片上就是15以后是外部中断的中断号所以这里配置成16
 9     判断是不是在外部中断中调用的API函数,如果是执行if里的内容*/
10     if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
11     {
12         /*根据中断服务函数的中断号获取当前中断的优先级设置*/
13         ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
14         /*如果当前执行的中断优先级数字小于配置ucMaxSysCallPriority这个值实际上是
15         configMAX_SYSCALL_INTERRUPT_PRIORITY,也就是当前中断优先级高于配置最高优先级
16         断言将会失败,程序将停止在这里*/
17         configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
18     }
19     /*当前中断优先级分组组大于配置分组(也就是表示抢占优先级的位数少于配置)则断言失败,程序停止*/
20     configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
21 }

中断函数中必须使用带FromISR后缀的API函数!
使用xTaskResumeFromISR()函数,如果改成vTaskResume(),实测发现程序会卡死在这里。

 1 //port.c的429~443行
 2 void vPortEnterCritical( void )
 3 {
 4     portDISABLE_INTERRUPTS();
 5     uxCriticalNesting++;
 6 
 7     /* This is not the interrupt safe version of the enter critical function so
 8     assert() if it is being called from an interrupt context.  Only API
 9     functions that end in "FromISR" can be used in an interrupt.  Only assert if
10     the critical nesting count is 1 to protect against recursive calls if the
11     assert function also uses a critical section. */
12     if( uxCriticalNesting == 1 )
13     {
14         configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
15     }
16 }

2.挂起(xTaskSuspend())恢复(xTaskResume())(xTaskResumeFromISR())使用

带FromISR的API才能在中断中调用;

如果函数xTaskResumeFromISR()返回值为pdTRUE,那么说明要恢复的这个任务的任务优先级等于或者高于正在运行的任务(被中断打断的任务),所以在退出中断前一定要进行上下文切换!

1             status = xTaskResumeFromISR(dataTaskHandle);//恢复任务
2              if(status==pdTRUE)
3              {
4                  portYIELD_FROM_ISR(status);
5              }

xTaskSuspend(NULL)挂起自身,存在对耗时有要求的任务时,其它同优先级任务可以挂起的尽量挂起。



posted @ 2022-05-07 16:29  妖岭  阅读(792)  评论(0)    收藏  举报