在线时间137 小时
UID1721340
ST金币2315
蝴蝶豆4
注册时间2015-8-6
该用户从未签到
金牌会员
- 最后登录
- 2021-3-26
|
本帖最后由 power568 于 2019-4-16 16:07 编辑
最近在写一个串口通讯的程序,软件、硬件平台如下:
硬件: STM32F429ZG
系统: FreeRtos、HAL库
工具: Iar7.6
计划是利用串口DMA+IDLE空闲中断的方式接收数据,在中断内将接收到的数据通过队列的方式发送出去,在任务内部等待接收队列,串口中断配置及ISR如下:- HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);//// 中断配置,优先级大小不能乱配置
- HAL_NVIC_EnableIRQ(USART1_IRQn);
- void USART1_IRQHandler(void)
- {
- uint32_t flag=0;
- BaseType_t pHigherPriorityTaskWoken = pdFALSE;
-
- flag = __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE);
- if((flag != RESET))
- {
- __HAL_UART_CLEAR_IDLEFLAG(&huart1);
- huart1.Instance->SR;
- huart1.Instance->DR;
- HAL_UART_DMAStop(&huart1);
- xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken);
- portYIELD_FROM_ISR(pHigherPriorityTaskWoken);
- }
- }
复制代码
//// 为什么代码提交后,代码对齐格式变了呢???
调试发现进入中断后,程序卡在了函数xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken)内部configASSERT( ucCurrentPriority >= ucMaxSysCallPriority )处,具体为:
- #if( configASSERT_DEFINED == 1 )
- void vPortValidateInterruptPriority( void )
- {
- uint32_t ulCurrentInterrupt;
- uint8_t ucCurrentPriority;
- /* Obtain the number of the currently executing interrupt. */
- __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
- //// ulCurrentInterrupt 调试显示为53
- /* Is the interrupt number a user defined interrupt? */
- if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
- {
- /* Look up the interrupt's priority. */
- ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
- //// 当串口优先级设置小于5时,ucCurrentPriority的值小于0x50,导致下面的宏断
- //// 言configASSERT条件值"==0",进而卡住
- //// 当串口优先级设置大于等于5时,ucCurrentPriority的值大于等于0x50,下面的
- //// 宏configASSERT条件值"==1",所以不会卡住
- /* The following assertion will fail if a service routine (ISR) for
- an interrupt that has been assigned a priority above
- configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
- function. ISR safe FreeRTOS API functions must *only* be called
- from interrupts that have been assigned a priority at or below
- configMAX_SYSCALL_INTERRUPT_PRIORITY.
- //// 如果一个调用FreeRtos安全ISR API接口的中断ISR优先级分配大于
- //// configMAX_SYSCALL_INTERRUPT_PRIORITY(即中断优先级值小于
- //// configMAX_SYSCALL_INTERRUPT_PRIORITY,因为FreeRtos中值越小优先级越高),
- //// 下面的断言就会失败。FreeRtos安全ISR API接口必须只能在优先级分配大于
- //// configMAX_SYSCALL_INTERRUPT_PRIORITY的中断ISR中调用
-
- Numerically low interrupt priority numbers represent logically high
- interrupt priorities, therefore the priority of the interrupt must
- be set to a value equal to or numerically *higher* than
- configMAX_SYSCALL_INTERRUPT_PRIORITY.
- //// 数值小的中断优先级逻辑上具有高的中断有限权,因此设置时,中断的优先级
- //// 值必须必configMAX_SYSCALL_INTERRUPT_PRIORITY大
- Interrupts that use the FreeRTOS API must not be left at their
- default priority of zero as that is the highest possible priority,
- which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
- and therefore also guaranteed to be invalid.
- //// 使用FreeRTOS API的中断的优先级禁止使用其0的认值,因为此时中断优先级最
- //// 高,0值的优先级必然大于configMAX_SYSCALL_INTERRUPT_PRIORITY,因此也必
- //// 然无效
- FreeRTOS maintains separate thread and ISR API functions to ensure
- interrupt entry is as fast and simple as possible.
- //// FreeRTOS为了确保中断入口尽可能的快和简单,因此分离了线程ISR API接口
- The following links provide detailed information:
- http://www.freertos.org/RTOS-Cortex-M3-M4.html
- http://www.freertos.org/FAQHelp.html */
- configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); //// 程序卡住位置
- //// ucMaxSysCallPriority值为0x50
- }
- /* Priority grouping: The interrupt controller (NVIC) allows the bits
- that define each interrupt's priority to be split between bits that
- define the interrupt's pre-emption priority bits and bits that define
- the interrupt's sub-priority. For simplicity all bits must be defined
- to be pre-emption priority bits. The following assertion will fail if
- this is not the case (if some bits represent a sub-priority).
- If the application only uses CMSIS libraries for interrupt
- configuration then the correct setting can be achieved on all Cortex-M
- devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
- scheduler. Note however that some vendor specific peripheral libraries
- assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
- configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
- }
- #endif /* configASSERT_DEFINED */
复制代码
相关宏定义如下:
- #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
复制代码
- /* The lowest interrupt priority that can be used in a call to a "set priority"
- function. */
- #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
- /* The highest interrupt priority that can be used by any interrupt service
- routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
- INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
- PRIORITY THAN THIS! (higher priorities are lower numeric values. */
- #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
- /* Interrupt priorities used by the kernel port layer itself. These are generic
- to all Cortex-M ports, and do not rely on any particular library functions. */
- #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
- /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
- See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
- #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
- /* Normal assert() semantics without relying on the provision of an assert.h
- header file. */
- /* USER CODE BEGIN 1 */
- #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
- /* USER CODE END 1 */
复制代码- #define configPRIO_BITS 4
复制代码
简单总结如下:
使用了FreeRtos操作系统后,外设中断优先级值不能设置小于configMAX_SYSCALL_INTERRUPT_PRIORITY,否则会导致了宏configASSERT的条件成立,进而卡住了。
|
|