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++;
}
}
效果: