最近在写一个串口通讯的程序,软件、硬件平台如下:
硬件: 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 */
简单总结如下:
使用了FreeRtos操作系统后,外设中断优先级值不能设置小于configMAX_SYSCALL_INTERRUPT_PRIORITY,否则会导致了宏configASSERT的条件成立,进而卡住了。
|