NXP S32K146 FREERTOS工程配置UART底层驱动(一)

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++;
	  }
  }

效果:
在这里插入图片描述

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值