问题1:利用现有的HC32F448的例程ADC_DMA,按照FreeRTOS的步骤增加于现有程序,但是一运行程序就跑飞了,调试栏中点击暂停会发现程序卡在configASSERT(pxQueue)【来自于文件queue.c的函数xQueueSendFromISR的第一行】。
void DMA_IRQ_HANDLER(void)
{BaseType_t pxHigherPriorityTaskWoken;
uint32_t ulReturn;
/* 进入临界段,临界段可以嵌套 */
ulReturn = taskENTER_CRITICAL_FROM_ISR();
if (DMA_GetTransCompleteStatus(DMA_UNIT, DMA_INT_FLAG) == SET)
{
DMA_ClearTransCompleteStatus(DMA_UNIT, DMA_INT_FLAG);
m_u8AdcValUpdated = 1U;
xQueueSendFromISR(Test_Queue, /* 消息队列的句柄 */
(void *)&m_u8AdcValUpdated,/* 发送的消息内容 */
&pxHigherPriorityTaskWoken);
portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
}
taskEXIT_CRITICAL_FROM_ISR(ulReturn);
}
static void AppTaskCreate(void)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
taskENTER_CRITICAL(); //进入临界区
Test_Queue=xQueueCreate(1,sizeof(uint32_t));
if(NULL != Test_Queue)
printf("创建Test_Queue消息队列成功!\r\n");
xReturn = xTaskCreate((TaskFunction_t )ADC_Task, /* 任务入口函数 */
(const char* )"ADC_Task",/* 任务名字 */
(uint16_t )100, /* 任务栈大小 */
(void* )NULL, /* 任务入口函数参数 */
(UBaseType_t )3, /* 任务的优先级 */
(TaskHandle_t* )&ADC_Task_Handle);/* 任务控制块指针 */
if(pdPASS == xReturn)
vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务
taskEXIT_CRITICAL(); //退出临界区
}
分析:pxQueue即消息队列没有创建成功,但是任务内的确使用了函数xQueueCreate(),两者矛盾。可能的原因是DMA中断服务函数早于消息队列的创建。
解决方法:函数void DMA_IRQ_HANDLER(void)在发送消息时先判断是否存在消息队列。
if(Test_Queue!=NULL)
{ xQueueSendFromISR(Test_Queue, /* 消息队列的句柄 */
(void *)&m_u8AdcValUpdated,/* 发送的消息内容 */
&pxHigherPriorityTaskWoken);
}
问题2:解决问题1后,再次运行程序,结果程序再次卡死于configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );【来自于文件port.c的函数void vPortValidateInterruptPriority(void)】
分析:下面的文章表述很清楚,DMA中断的优先级和FreeRTOS管理中断的矛盾。
嵌入式FreeRTOS操作系统中断优先级配置(重要)_freertos nvic_irqchannelsubpriority-CSDN博客
解决方法:FreeRTOSConfig.h文件的configMAX_SYSCALL_INTERRUPT_PRIORITY数值为0x50左移动4位后仍然为5.DMA的中断优先级数值为3(低于5),导致它不受FreeRTOS管理。
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
直接将 configMAX_SYSCALL_INTERRUPT_PRIORITY改为2(或者1)。再次运行结果正常。
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 2