[应用相关] 笔记---FreeRtos系统中外设中断优先级设置的要点

[复制链接]
4989|11
 楼主| Larm1 发表于 2019-4-16 16:05 | 显示全部楼层 |阅读模式
      最近在写一个串口通讯的程序,软件、硬件平台如下:
硬件: STM32F429ZG
系统: FreeRtos、HAL库
工具:  Iar7.6

      计划是利用串口DMA+IDLE空闲中断的方式接收数据,在中断内将接收到的数据通过队列的方式发送出去,在任务内部等待接收队列,串口中断配置及ISR如下:
  1. //// 中断配置,优先级大小不能乱配置
  2. HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
  3. HAL_NVIC_EnableIRQ(USART1_IRQn);

  4. void USART1_IRQHandler(void)
  5. {
  6.         uint32_t                 flag=0;
  7.         BaseType_t        pHigherPriorityTaskWoken = pdFALSE;
  8.        
  9.         flag = __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE);
  10.         if((flag != RESET))
  11.         {
  12.                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);
  13.                 huart1.Instance->SR;  
  14.                 huart1.Instance->DR;

  15.                 HAL_UART_DMAStop(&huart1);
  16.                 xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken);
  17.                 portYIELD_FROM_ISR(pHigherPriorityTaskWoken);
  18.         }
  19. }
      //// 为什么代码提交后,代码对齐格式变了呢???

      调试发现进入中断后,程序卡在了函数xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken)内部configASSERT( ucCurrentPriority >= ucMaxSysCallPriority )处,具体为:
  1. #if( configASSERT_DEFINED == 1 )

  2.         void vPortValidateInterruptPriority( void )
  3.         {
  4.         uint32_t ulCurrentInterrupt;
  5.         uint8_t ucCurrentPriority;

  6.                 /* Obtain the number of the currently executing interrupt. */
  7.                 __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
  8.                 //// ulCurrentInterrupt 调试显示为53

  9.                 /* Is the interrupt number a user defined interrupt? */
  10.                 if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
  11.                 {
  12.                         /* Look up the interrupt's priority. */
  13.                         ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
  14.                         //// 当串口优先级设置小于5时,ucCurrentPriority的值小于0x50,导致下面的宏断
  15.                         //// 言configASSERT条件值"==0",进而卡住
  16.                         //// 当串口优先级设置大于等于5时,ucCurrentPriority的值大于等于0x50,下面的
  17.                         //// 宏configASSERT条件值"==1",所以不会卡住

  18.                         /* The following assertion will fail if a service routine (ISR) for
  19.                         an interrupt that has been assigned a priority above
  20.                         configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
  21.                         function.  ISR safe FreeRTOS API functions must *only* be called
  22.                         from interrupts that have been assigned a priority at or below
  23.                         configMAX_SYSCALL_INTERRUPT_PRIORITY.
  24.                         //// 如果一个调用FreeRtos安全ISR API接口的中断ISR优先级分配大于
  25.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY(即中断优先级值小于
  26.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY,因为FreeRtos中值越小优先级越高),
  27.                         //// 下面的断言就会失败。FreeRtos安全ISR API接口必须只能在优先级分配大于
  28.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY的中断ISR中调用
  29.                         
  30.                         Numerically low interrupt priority numbers represent logically high
  31.                         interrupt priorities, therefore the priority of the interrupt must
  32.                         be set to a value equal to or numerically *higher* than
  33.                         configMAX_SYSCALL_INTERRUPT_PRIORITY.
  34.                         //// 数值小的中断优先级逻辑上具有高的中断有限权,因此设置时,中断的优先级
  35.                         //// 值必须必configMAX_SYSCALL_INTERRUPT_PRIORITY大

  36.                         Interrupts that        use the FreeRTOS API must not be left at their
  37.                         default priority of        zero as that is the highest possible priority,
  38.                         which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
  39.                         and        therefore also guaranteed to be invalid.
  40.                         //// 使用FreeRTOS API的中断的优先级禁止使用其0的认值,因为此时中断优先级最
  41.                         //// 高,0值的优先级必然大于configMAX_SYSCALL_INTERRUPT_PRIORITY,因此也必
  42.                         //// 然无效

  43.                         FreeRTOS maintains separate thread and ISR API functions to ensure
  44.                         interrupt entry is as fast and simple as possible.
  45.                         //// FreeRTOS为了确保中断入口尽可能的快和简单,因此分离了线程ISR API接口

  46.                         The following links provide detailed information:
  47.                         http://www.freertos.org/RTOS-Cortex-M3-M4.html
  48.                         http://www.freertos.org/FAQHelp.html */
  49.                         configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); //// 程序卡住位置
  50.                         //// ucMaxSysCallPriority值为0x50
  51.                 }

  52.                 /* Priority grouping:  The interrupt controller (NVIC) allows the bits
  53.                 that define each interrupt's priority to be split between bits that
  54.                 define the interrupt's pre-emption priority bits and bits that define
  55.                 the interrupt's sub-priority.  For simplicity all bits must be defined
  56.                 to be pre-emption priority bits.  The following assertion will fail if
  57.                 this is not the case (if some bits represent a sub-priority).

  58.                 If the application only uses CMSIS libraries for interrupt
  59.                 configuration then the correct setting can be achieved on all Cortex-M
  60.                 devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
  61.                 scheduler.  Note however that some vendor specific peripheral libraries
  62.                 assume a non-zero priority group setting, in which cases using a value
  63.                 of zero will result in unpredicable behaviour. */
  64.                 configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
  65.         }

  66. #endif /* configASSERT_DEFINED */


简单总结如下:

      使用了FreeRtos操作系统后,外设中断优先级值不能设置小于configMAX_SYSCALL_INTERRUPT_PRIORITY,否则会导致了宏configASSERT的条件成立,进而卡住了。

mmuuss586 发表于 2019-4-18 09:45 | 显示全部楼层
感谢分享
木木guainv 发表于 2019-5-7 10:09 | 显示全部楼层
非常感谢楼主分享
xiaoqizi 发表于 2019-5-7 10:15 | 显示全部楼层
非常感谢楼主分享
renzheshengui 发表于 2019-5-7 10:52 | 显示全部楼层
感谢楼主分享
paotangsan 发表于 2019-5-7 11:20 | 显示全部楼层
代码非常详细
keaibukelian 发表于 2019-5-7 11:36 | 显示全部楼层
非常感谢楼主分享
guanjiaer 发表于 2019-5-7 11:44 | 显示全部楼层
非常感谢楼主分享
heimaojingzhang 发表于 2019-5-7 11:46 | 显示全部楼层
非常感谢楼主分享
磨砂 发表于 2019-5-8 08:19 | 显示全部楼层
代码好详细啊
晓伍 发表于 2019-5-8 08:26 | 显示全部楼层
是跑的系统吗
八层楼 发表于 2019-5-8 08:36 | 显示全部楼层
非常感谢楼主分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:大爱无疆

53

主题

389

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部