赞
踩
MCU平台还是S32K146,开发环境是S32DS 用官方的SDK3.0.0,PE配置外设,生成generation code。在SDK上边封装函数,第三库用的ringbuf循环队列,代码实现如下:
hal_uart.c
#include "../inc/hal_uart.h" extern void LPUART_DRV_StopTxDma(uint32_t instance); extern void LPUART_DRV_SetIntMode(uint32_t instance, uint32_t intSrc, bool enable); /* func:set_hard_flow_ctrl * prara:Device instance number * return:none */ static void hal_uart_set_hard_flow_ctrl(INT32U instance) { hal_uart_hard_flowctrl_reg_t reg = {1, 0, 0, 1, 0}; LPUART_Type* const s_lpuartBase[LPUART_INSTANCE_COUNT] = LPUART_BASE_PTRS; LPUART_Type* base = s_lpuartBase[instance]; base->MODIR = (base->MODIR & ~LPUART_MODIR_TXCTSE_MASK) | ((reg.TXCTSE ? 1UL : 0UL) << LPUART_MODIR_TXCTSE_SHIFT); base->MODIR = (base->MODIR & ~LPUART_MODIR_TXRTSE_MASK) | ((reg.TXRTSE ? 1UL : 0UL) << LPUART_MODIR_TXRTSE_SHIFT); base->MODIR = (base->MODIR & ~LPUART_MODIR_TXRTSPOL_MASK) | ((reg.TXRTSPOL ? 1UL : 0UL) << LPUART_MODIR_TXRTSPOL_SHIFT); base->MODIR = (base->MODIR & ~LPUART_MODIR_RXRTSE_MASK) | ((reg.RXRTSE ? 1UL : 0UL) << LPUART_MODIR_RXRTSE_SHIFT); base->MODIR = (base->MODIR & ~LPUART_MODIR_RXRTSE_MASK) | ((reg.RXRTSE ? 1UL : 0UL) << LPUART_MODIR_RXRTSE_SHIFT); } /* func: hal_uart_get_context * prara: UART_CH_E * return: hal_uart_contex_t */ static hal_uart_contex_t* hal_uart_get_context(UART_CH_E ch) { hal_uart_contex_t* ctx = &g_uart_ctx[ch]; return ctx; } /* func: uart dcb to config * prara: uart_dcb_t/lpuart_user_config_t * return: BOOLEAN */ static BOOLEAN hal_uart_dcb2conf(uart_dcb_t* dcb, lpuart_user_config_t* conf) { switch (dcb->databit) { case UART_DATABIT_8: conf->bitCountPerChar = LPUART_8_BITS_PER_CHAR; break; case UART_DATABIT_9: conf->bitCountPerChar = LPUART_9_BITS_PER_CHAR; break; case UART_DATABIT_10: conf->bitCountPerChar = LPUART_10_BITS_PER_CHAR; break; default: return FALSE; break; } /* convert parity check mode */ switch (dcb->parity) { case UART_PARITY_NONE: conf->parityMode = LPUART_PARITY_DISABLED; break; case UART_PARITY_EVEN: conf->parityMode = LPUART_PARITY_EVEN; break; case UART_PARITY_ODD: conf->parityMode = LPUART_PARITY_ODD; break; default: return FALSE; break; } /* convert stop bit mode */ switch (dcb->stopbit) { case UART_STOPBIT_ONE: conf->stopBitCount = LPUART_ONE_STOP_BIT; break; case UART_STOPBIT_TWO: conf->stopBitCount = LPUART_TWO_STOP_BIT; break; default: return FALSE; break; } /* convert band rate */ conf->baudRate = dcb->baudrate; return TRUE; } /* func: uart free * prara: hal_uart_contex_t * return: none */ static void hal_uart_free(hal_uart_contex_t* ctx) { if (ctx->instance == INST_LPUART1) { PINS_DRV_WritePin(PTB, 11, 0); } if (ctx->tx_task_hdl) { vTaskSuspend(ctx->tx_task_hdl); vTaskDelete(ctx->tx_task_hdl); ctx->tx_task_hdl = NULL; } if (ctx->rb_rx) { ringbuf_free(ctx->rb_rx); ctx->rb_rx = NULL; } if (ctx->rb_tx) { ringbuf_free(ctx->rb_tx); ctx->rb_tx = NULL; } if (ctx->bf_rx) { vPortFree(ctx->bf_rx); ctx->bf_rx = NULL; } if (ctx->rb_tx_sem) { vSemaphoreDelete(ctx->rb_tx_sem); ctx->rb_tx_sem = NULL; } if (ctx->rb_tx_mutex) { vSemaphoreDelete(ctx->rb_tx_mutex); ctx->rb_tx_mutex = NULL; } if (ctx->tx_mutex) { vSemaphoreDelete(ctx->tx_mutex); ctx->tx_mutex = NULL; } } static void hal_uart_rx_callback(void* driverState, uart_event_t event, void* userData) { /* Unused parameters */ (void)driverState; INT32U remain_bytes = 0; INT32U recv_bytes = 0; //hw_sys_task_msg_e hw_sys_msg = 0xff; portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; hal_uart_contex_t* ctx = (hal_uart_contex_t*)userData; /* Check the event type */ if (event == UART_EVENT_RX_FULL) { LPUART_DRV_GetReceiveStatus(ctx->instance, (uint32_t*)&remain_bytes); /* calculate receive data bytes */ if (remain_bytes == ctx->bf_rx_size) { /* complete receive interrupt */ recv_bytes = remain_bytes; } else { /* idle interrupt */ recv_bytes = ctx->bf_rx_size - remain_bytes; } ctx->hw_recv_bytes += recv_bytes; ctx->rb_recv_bytes += MIN(ringbuf_free_size(ctx->rb_rx), recv_bytes); ringbuf_write(ctx->rb_rx, ctx->bf_rx, recv_bytes); // if (ctx->ch == UART_CH_DEBUG) // { // hw_sys_msg = HW_SYS_MSG_UART_DEBUG; // } //else if (ctx->ch == UART_CH_COMM) //{ // uart_receive_detect = HAL_UART_DETECT_TIMEOUT; // hw_sys_msg = HW_SYS_MSG_UART_COMM; // } // else if (ctx->ch == UART_CH_IVI) // { // hw_sys_msg = HW_SYS_MSG_UART_IVI; // } //if (hw_sys_queue) //{ // xQueueSendFromISR(hw_sys_queue, (void*)&hw_sys_msg, &xHigherPriorityTaskWoken); //} LPUART_DRV_SetRxBuffer(ctx->instance, ctx->bf_rx, ctx->bf_rx_size); if (xHigherPriorityTaskWoken) { portYIELD_FROM_ISR(pdTRUE); } } else if (event == UART_EVENT_ERROR) { if (ctx->ch == UART_CH_COMM) { //if (hal_pio_get_invalue(WK_MCU) == 1) //{ // LPUART_DRV_StopRxDma(ctx->instance); // LPUART_DRV_ReceiveData(ctx->instance, ctx->bf_rx, ctx->bf_rx_size); //} //else // { // mpu_ready_flag = FALSE; // } } else { LPUART_DRV_StopRxDma(ctx->instance); LPUART_DRV_ReceiveData(ctx->instance, ctx->bf_rx, ctx->bf_rx_size); } } else { } } /* func: uart write API * prara: UART_CH_E/pdata/len * return: BOOLEAN */ BOOLEAN hal_uart_write(UART_CH_E ch, INT8U* pdata, INT16U len) { INT32S left = len; hal_uart_contex_t* ctx; if (!(ch < MAX_UART_INDEX && pdata != NULL && len > 0)) { return FALSE; } ctx = hal_uart_get_context(ch); if (!(ctx != NULL && ctx->rb_tx_mutex != NULL && ctx->rb_tx != NULL && ctx->rb_tx_sem != NULL)) { return FALSE; } xSemaphoreTake(ctx->tx_mutex, 10000); // 处理多线程并发访问一个硬件通道导致数据乱序问题 /* james 20210526 增加retry次数,防止一直占用CPU */ INT8S retry_cnt = 10; while (left > 0 && retry_cnt-- > 0) { xSemaphoreTake(ctx->rb_tx_mutex, 1000); if (!ringbuf_is_full(ctx->rb_tx)) { len = ringbuf_write(ctx->rb_tx, pdata, MIN(ringbuf_free_size(ctx->rb_tx), left)); if (len > 0) { left -= len; pdata += len; } xSemaphoreGive(ctx->rb_tx_mutex); xSemaphoreGive(ctx->rb_tx_sem); } else { xSemaphoreGive(ctx->rb_tx_mutex); xSemaphoreGive(ctx->rb_tx_sem); vTaskDelay(2);//现在参数不对 } } xSemaphoreGive(ctx->tx_mutex); if (left > 0) { return FALSE; } return TRUE; } /* func: uart tx task os * prara: args * return: none */ static void hal_uart_tx_task(void* args) { hal_uart_contex_t* ctx = (hal_uart_contex_t*)args; INT32S txsize = 0; char txbuf[HAL_UART_TX_TASK_STACK_SIZE - 384]; for (;;) { if (xSemaphoreTake(ctx->rb_tx_sem, HAL_UART_TX_WAIT_TIMEOUT)) { xSemaphoreTake(ctx->rb_tx_mutex, 1000); while (!ringbuf_is_empty(ctx->rb_tx)) { txsize = ringbuf_read(txbuf, ctx->rb_tx, sizeof(txbuf)); if (txsize > 0) { xSemaphoreGive(ctx->rb_tx_mutex); if (LPUART_DRV_SendDataBlocking(ctx->instance, txbuf, txsize, 100)) { LPUART_DRV_StopTxDma(ctx->instance); } xSemaphoreTake(ctx->rb_tx_mutex, 1000); } } xSemaphoreGive(ctx->rb_tx_mutex); } } } /* func: hal uart open * prara: UART_CH_E/uart_dcb_t * return: none */ BOOLEAN hal_uart_open(UART_CH_E ch, uart_dcb_t* dcb) { LPUART_Type* s_lpuartBase[LPUART_INSTANCE_COUNT] = LPUART_BASE_PTRS; hal_uart_contex_t* ctx; ctx = hal_uart_get_context(ch); //得到hal_uart_contex_t类型数组里面的配置 hal_uart_dcb2conf(dcb, ctx->conf); //把调用传参的配置转换成CTX类型 ctx->ch = ch; //赋值通道号 ctx->rb_rx = ringbuf_malloc(dcb->rbuf_size); //申请调用传参时的buf空间 ctx->rb_tx_sem = xSemaphoreCreateCounting(255,0); //申请发送的计数型信号量 ctx->rb_tx_mutex = xSemaphoreCreateMutex(); //队列申请互斥信号量 ctx->rb_tx = ringbuf_malloc(dcb->tbuf_size); //申请调用传参时的buf空间 ctx->bf_rx = (INT8U*)os_malloc(ctx->bf_rx_size); //申请DMA缓存空间 ctx->tx_mutex = xSemaphoreCreateMutex(); //发送锁 LPUART_DRV_Init(ctx->instance, ctx->state, ctx->conf);//初始化函数 INT_SYS_DisableIRQGlobal(); //关闭全局中断 LPUART_DRV_SetIntMode(ctx->instance, LPUART_INT_IDLE_LINE, true);//使能空闲中断 s_lpuartBase[ctx->instance]->CTRL = s_lpuartBase[ctx->instance]->CTRL | 0x0700;//设置空闲字数128个字节 if (dcb->flowctrl == UART_FLOWCTRL_RTSCTS) //设置硬件流控 { hal_uart_set_hard_flow_ctrl(ctx->instance); } INT_SYS_SetPriority(ctx->irq_num, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);//收发中断优先级 if (ctx->instance == INST_LPUART1)//DMA通道优先级 { INT_SYS_SetPriority(DMA1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1); INT_SYS_SetPriority(DMA2_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1); } LPUART_DRV_InstallRxCallback(ctx->instance, hal_uart_rx_callback, ctx);//配置回调函数 if (ctx->instance == INST_LPUART1)//唤醒232en { PINS_DRV_WritePin(PTB, 11, 1); } INT_SYS_EnableIRQGlobal();//打开全局中断 //ctx->tx_task_hdl = xTaskCreate(hal_uart_tx_task,ctx->tx_task_name, HAL_UART_TX_TASK_STACK_SIZE,ctx,HAL_UART_TX_TASK_PRIORITY,NULL) ; /* start receive data from UART */ //LPUART_DRV_ReceiveData(ctx->instance, ctx->bf_rx, ctx->bf_rx_size); //放开上边两个函数后 程序进入DefaultISR:急需排查问题 return TRUE; } void test_uart(void) { const uint8_t sbuf[20] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; for (;;) { hal_uart_write(UART_CH_DEBUG, sbuf, sizeof(sbuf)); vTaskDelay(100 / portTICK_RATE_MS); } }
hardwaremanage.c
#include "hardwareManage.h"
void hw_uart_open(void)
{
uart_dcb_t hal_dcb;
hal_dcb.rbuf_size = HW_UART_DBG_BUFF_SIZE;
hal_dcb.tbuf_size = HW_UART_DBG_BUFF_SIZE;
hal_uart_open(TO_HW_UART_CH(HW_UART_CH_DEBUG), &hal_dcb);
}
void vSystemHardwareHalInit(void)
{
hw_uart_open();
}
//上边vSystemHardwareHalInit在主函数初始化
main.c 小灯1S闪烁任务代表系统运行
void vSystemHardwareWorkTask(void *p) { while(1) { PINS_DRV_TogglePins(PTE,1<<3); vTaskDelay(1000); } } int main(void) { /* Write your local variable definition here */ /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/ #ifdef PEX_RTOS_INIT PEX_RTOS_INIT(); /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */ #endif /*** End of Processor Expert internal initialization. ***/ CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT, g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT); CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT); PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr); vSystemHardwareHalInit(); xTaskCreate( vSystemHardwareWorkTask, "SystemHardwareWorkTask", 310, 0, 1,0);//系统硬件工作任务 优先级1 vTaskStartScheduler(); }
上边代码的要做的就是打开uart 配置回调函数及创建发送任务,hal_uart_write作为发送API,test_uart测试是否能发送,大概这么个流程。
1. 问题1:程序进入DefaultISR
调试方法1:屏蔽部分代码找到进入硬件中断的问题点。
分析:LPUART_DRV_ReceiveData(ctx->instance, ctx->bf_rx, ctx->bf_rx_size);开启接收函数屏蔽不进入硬件中断,打开进入硬件中断。
调试方法2:论坛的方案
尝试:根据方案描述定义函数DefaultISR,但我的问题是串口实际不能打印,但是仍然重写DefaultISR看一下效果
void DefaultISR(void)
{
#define VECTORNUM (*(volatile uint8_t*)(0xE000ED04))
printf("\n****default_isr entered on vector %d*****\r\n\n", VECTORNUM);
return;
}
效果:工程不卡在DefaultISR中,但是由于是串口初始化导致的DefaultISR,打断点不能看到是哪个中断号出现的问题。换成下边这个
void DefaultISR(void)
{
#define VECTORNUM (*(volatile uint8_t*)(0xE000ED04))
//printf("\n****default_isr entered on vector %d*****\r\n\n", VECTORNUM);
sprintf(buf,"\n****default_isr entered on vector %d %x *****\r\n\n", (uint8_t)VECTORNUM, (uint32_t)VECTORNUM);
return;
}
根据下边这张图定位到vector 3 根据打印出来的数据,判断VECTOR,是怎么原因触发中断的。这里我的值为3,查对应芯片向量表,得知是Hard_Fault导致的。还得接着往下找具体是什么引起的硬件中断。
调试方法3:只要重写函数HardFault_Handler,然后在函数HardFault_Handler里面执行语句“asm(“bx lr”)”可以让程序执行到进入函数HardFault_Handler中断之前的函数,这样是不是就很容易定位到这个地址啦?
void HardFault_Handler(void) { // LR provides information of the return stack PSP/MSP //__asm("MOVS R0, #4"); ///__asm("MOV R1, LR"); //__asm("TST R0, R1"); //__asm("BEQ _MSP"); // __asm("MRS R0, PSP"); /// //__asm("B getStackFrame"); // __asm("_MSP:"); // __asm("MRS R0, MSP"); //__asm("B getStackFrame"); __asm("bx lr"); //SystemSoftwareReset(); //return; }
问题点好像定位到EDMA_DRV_InstallCallback函数,当通过BL或BLX指令调用子程序时,硬件自动将子程序返回地址保存在R14寄存器中。在子程序返回时,把LR的值复制到程序计数器PC即可实现子程序返回。我在__asm(“bx lr”);打的断点然后单步运行的定位到EDMA_DRV_InstallCallback不知道是不是返回调用处。但是LPUART_DRV_StartReceiveDataUsingDma调用EDMA_DRV_InstallCallback;LPUART_DRV_ReceiveData调用LPUART_DRV_StartReceiveDataUsingDma,这也证实了问题出现在LPUART_DRV_ReceiveData函数。
调试方法4:
uint32_t r0; uint32_t r1; uint32_t r2; uint32_t r3; uint32_t r12; uint32_t lr; uint32_t pc; uint32_t psr; void getStackFrame(uint32_t *stackFrame) { r0 = stackFrame[0]; r1 = stackFrame[1]; r2 = stackFrame[2]; r3 = stackFrame[3]; r12 = stackFrame[4]; lr = stackFrame[5]; pc = stackFrame[6];//程序计数器(pc)保存导致异常的指令的地址。 psr = stackFrame[7]; __asm("BKPT"); //断点中断指令 } void HardFault_Handler(void) { // LR provides information of the return stack PSP/MSP __asm("MOVS R0, #4"); __asm("MOV R1, LR"); __asm("TST R0, R1"); __asm("BEQ _MSP"); __asm("MRS R0, PSP"); __asm("B getStackFrame"); __asm("_MSP:"); __asm("MRS R0, MSP"); __asm("B getStackFrame"); //__asm("bx lr"); //SystemSoftwareReset(); return; }
得到PC指针为6926 16进制0x1B0E也就是进EDMA_DRV_ConfigSingleBlockTransfer之后发生的硬件故障,本来试图定位代码但是没有找到相关方法。先分析一下这个函数是否有问题。
调试方法5:CmBacktrace(有点麻烦没有用)
解决:是我粗心。。。调用DMA没有初始化DMA,才发生的硬件中断。加上EDMA_DRV_Init(&dmaController1_State,&dmaController1_InitConfig0,edmaChnStateArray,edmaChnConfigArray,EDMA_CONFIGURED_CHANNELS_COUNT);就好了,这一天如同梦游,还是对S32平台不熟悉的缘故。
修改后的源码:
hal_uart.c
/* func: hal uart open * prara: UART_CH_E/uart_dcb_t * return: none */ BOOLEAN hal_uart_open(UART_CH_E ch, uart_dcb_t* dcb) { LPUART_Type* s_lpuartBase[LPUART_INSTANCE_COUNT] = LPUART_BASE_PTRS; hal_uart_contex_t* ctx; ctx = hal_uart_get_context(ch); //得到hal_uart_contex_t类型数组里面的配置 hal_uart_dcb2conf(dcb, ctx->conf); //把调用传参的配置转换成CTX类型 ctx->ch = ch; //赋值通道号 ctx->rb_rx = ringbuf_malloc(dcb->rbuf_size); //申请调用传参时的buf空间 ctx->rb_tx_sem = xSemaphoreCreateCounting(255,0); //申请发送的计数型信号量 ctx->rb_tx_mutex = xSemaphoreCreateMutex(); //队列申请互斥信号量 ctx->rb_tx = ringbuf_malloc(dcb->tbuf_size); //申请调用传参时的buf空间 ctx->bf_rx = (INT8U*)os_malloc(ctx->bf_rx_size); //申请DMA缓存空间 ctx->tx_mutex = xSemaphoreCreateMutex(); //发送锁 LPUART_DRV_Init(ctx->instance, ctx->state, ctx->conf);//初始化函数 INT_SYS_DisableIRQGlobal(); //关闭全局中断 LPUART_DRV_SetIntMode(ctx->instance, LPUART_INT_IDLE_LINE, true);//使能空闲中断 s_lpuartBase[ctx->instance]->CTRL = s_lpuartBase[ctx->instance]->CTRL | 0x0700;//设置空闲字数128个字节 if (dcb->flowctrl == UART_FLOWCTRL_RTSCTS) //设置硬件流控 { hal_uart_set_hard_flow_ctrl(ctx->instance); } INT_SYS_SetPriority(ctx->irq_num, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);//收发中断优先级 if (ctx->instance == INST_LPUART1)//DMA通道优先级 { INT_SYS_SetPriority(DMA1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1); INT_SYS_SetPriority(DMA2_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1); } LPUART_DRV_InstallRxCallback(ctx->instance, hal_uart_rx_callback, ctx);//配置回调函数 if (ctx->instance == INST_LPUART1)//唤醒232en { PINS_DRV_WritePin(PTB, 11, 1); } INT_SYS_EnableIRQGlobal();//打开全局中断 ctx->tx_task_hdl = xTaskCreate(hal_uart_tx_task,ctx->tx_task_name, HAL_UART_TX_TASK_STACK_SIZE,ctx,HAL_UART_TX_TASK_PRIORITY,NULL) ; LPUART_DRV_ReceiveData(ctx->instance, ctx->bf_rx, ctx->bf_rx_size); //开启接收 for (INT8U i = 0; i < sizeof(g_uart_save_status) / sizeof(g_uart_save_status[0]); i++) {//初始化状态相关的全局变量 if (g_uart_save_status[i].ch == ch) { g_uart_save_status[i].dcb.baudrate = dcb->baudrate; g_uart_save_status[i].dcb.databit = dcb->databit; g_uart_save_status[i].dcb.flowctrl = dcb->flowctrl; g_uart_save_status[i].dcb.parity = dcb->parity; g_uart_save_status[i].dcb.rbuf_size = dcb->rbuf_size; g_uart_save_status[i].dcb.stopbit = dcb->stopbit; g_uart_save_status[i].dcb.tbuf_size = dcb->tbuf_size; g_uart_save_status[i].staus = HAL_UART_OPEN; break; } } return TRUE; }
增肌hal_board.c
#include "../inc/hal_board.h"
BOOLEAN hal_board_init(void)
{
CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT, g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);
PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);
//增加没有初始化的DMA
EDMA_DRV_Init(&dmaController1_State, &dmaController1_InitConfig0, edmaChnStateArray, edmaChnConfigArray, EDMA_CONFIGURED_CHANNELS_COUNT);
}
hardwaremanage.c
#include "hardwareManage.h"
void hw_uart_open(void)
{
uart_dcb_t hal_dcb;
hal_dcb.rbuf_size = HW_UART_DBG_BUFF_SIZE;
hal_dcb.tbuf_size = HW_UART_DBG_BUFF_SIZE;
hal_uart_open(TO_HW_UART_CH(HW_UART_CH_DEBUG), &hal_dcb);
}
void vSystemHardwareHalInit(void)
{
hal_board_init();
hw_uart_open();
}
main.c
void vSystemHardwareWorkTask(void *p) { while(1) { PINS_DRV_TogglePins(PTE,1<<3); vTaskDelay(1000); } } int main(void) { /* Write your local variable definition here */ /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/ #ifdef PEX_RTOS_INIT PEX_RTOS_INIT(); /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */ #endif /*** End of Processor Expert internal initialization. ***/ vSystemHardwareHalInit(); xTaskCreate( vSystemHardwareWorkTask, "SystemHardwareWorkTask", 310, 0, 1,0);//系统硬件工作任务 优先级1 vTaskStartScheduler(); /*** Don't write any code pass this line, or it will be deleted during code generation. ***/ /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/ #ifdef PEX_RTOS_START PEX_RTOS_START(); /* Startup of the selected RTOS. Macro is defined by the RTOS component. */ #endif /*** End of RTOS startup code. ***/ /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/ for(;;) { if(exit_code != 0) { break; } } return exit_code; } /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/
继续调试!!!!
现象:小灯不闪烁了,但是没有进Hard_Fault,而是卡死在下边的代码里
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI;
__asm volatile
(
" mov %0, %1 \n" \
" msr basepri, %0 \n" \
" isb \n" \
" dsb \n" \
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
);
}
函数vPortRaiseBASEPRI是向寄存器BASEPRI写入宏configMAX_SYSCALL_INTERRUPT_PRIORITY,那么优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断就会被屏蔽。但是为什么一直卡在这里呢?
照例还是把上边uart任务关闭,看看小灯是否能闪烁,只留一个任务是能运行的,接着两个任务都是小灯闪烁,继续调试。
void vSystemHardwareWorkTask(void *p) { while(1) { PINS_DRV_TogglePins(PTE,1<<3); vTaskDelay(1000); } } void vUartDataProcessingTask(void *p) { while(1) { PINS_DRV_TogglePins(PTE,1<<12); vTaskDelay(200); } }
没有问题,两个灯都能正常闪烁。看这个函数被什么地方调用,放三个全局变量在三个任务里,仿真发现都为0,即都一次没执行就进了vPortRaiseBASEPRI,那应该是在开启调度器时发生的问题。把断点打在vTaskStartScheduler();然后单步仿真,动态申请一个空闲任务进入任务创建;portSTACK_GROWTH进入pvPortMalloc,申请失败返回xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY,应该是内存不够,HAL_UART_TX_TASK_STACK_SIZE我写了1024,太大了?改成300就好了。小等正常闪烁。把其中一个小灯的任务改成调用串口接口发送的任务。
void vUartDataProcessingTask(void *p)
{
const uint8_t sbuf[20] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
while(1)
{
hal_uart_write(UART_CH_DEBUG, sbuf, sizeof(sbuf));
vTaskDelay(500);
count2++;
}
}
效果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。