From ae079c1fc5d990ba55714d4b3a51b19f96edaec4 Mon Sep 17 00:00:00 2001 From: WXK <287788329@qq.com> Date: 星期四, 24 四月 2025 16:01:43 +0800 Subject: [PATCH] 改为中断来低电平触发发送当前扫描数据,3s内扫描不到的会退出,串口来55 AA 75 70 64 61 74 65,进入升级模式 --- 01_SDK/modules/hal/panchip/panplat/pan1070/bsp/peripheral/src/pan_hal_uart.c | 892 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 649 insertions(+), 243 deletions(-) diff --git a/01_SDK/modules/hal/panchip/panplat/pan1070/bsp/peripheral/src/pan_hal_uart.c b/01_SDK/modules/hal/panchip/panplat/pan1070/bsp/peripheral/src/pan_hal_uart.c index ec40d7a..e71ce10 100644 --- a/01_SDK/modules/hal/panchip/panplat/pan1070/bsp/peripheral/src/pan_hal_uart.c +++ b/01_SDK/modules/hal/panchip/panplat/pan1070/bsp/peripheral/src/pan_hal_uart.c @@ -7,81 +7,91 @@ * @note * Copyright (C) 2023 Panchip Technology Corp. All rights reserved. *****************************************************************************/ - #include "pan_hal.h" +#if (BLE_EN == 1) +#define PAN_HAL_BLE_IRQ_SPLIT_CALLBACK 1 +#endif -UART_HandleTypeDef UART_Handle_Array[2] = - { - {.pUartx = UART0, - .initObj = {0}, - .interruptObj = {0}, - .pTxBuffPtr = NULL, - .txXferSize = 0, - .txXferCount = 0, - .pRxBuffPtr = NULL, - .rxXferSize = 0, - .rxXferCount = 0, - .IRQn = UART0_IRQn, - .rxIntCallback = NULL, - .txIntCallback = NULL, - .dmaSrc = DMAC_Peripheral_UART0_Rx, - .dmaDst = DMAC_Peripheral_UART0_Tx, - .errorCode = 0}, - {.pUartx = UART1, - .initObj = {0}, - .interruptObj = {0}, - .pTxBuffPtr = NULL, - .txXferSize = 0, - .txXferCount = 0, - .pRxBuffPtr = NULL, - .rxXferSize = 0, - .rxXferCount = 0, - .IRQn = UART1_IRQn, - .rxIntCallback = NULL, - .txIntCallback = NULL, - .dmaSrc = DMAC_Peripheral_UART1_Rx, - .dmaDst = DMAC_Peripheral_UART1_Tx, - .errorCode = 0}}; - -void HAL_DelayMs(uint32_t t) +HAL_UART_HandleTypeDef UART_Handle_Array[PAN_HAL_UART_INST_COUNT] = { - for (uint32_t i = 0; i < t; i++) { - SYS_delay_10nop(0x1080); + .pUartx = UART0, + .initObj = {0}, + .interruptObj = + { + .txTrigLevel = HAL_UART_TX_FIFO_HALF_FULL, + .rxTrigLevel = HAL_UART_RX_FIFO_HALF_FULL, + .IrqPriority = 2, + .IRQn = UART0_IRQn, + }, + .pTxBuffPtr = NULL, + .txXferSize = 0, + .txXferCount = 0, + .pRxBuffPtr = NULL, + .rxXferSize = 0, + .rxXferCount = 0, + .isTxBusy = false, + .isRxBusy = false, + .dmaSrc = DMAC_Peripheral_UART0_Rx, + .dmaDst = DMAC_Peripheral_UART0_Tx, + }, + { + .pUartx = UART1, + .initObj = {0}, + .interruptObj = + { + .txTrigLevel = HAL_UART_TX_FIFO_HALF_FULL, + .rxTrigLevel = HAL_UART_RX_FIFO_HALF_FULL, + .IrqPriority = 2, + .IRQn = UART1_IRQn, + }, + .pTxBuffPtr = NULL, + .txXferSize = 0, + .txXferCount = 0, + .pRxBuffPtr = NULL, + .rxXferSize = 0, + .rxXferCount = 0, + .isTxBusy = false, + .isRxBusy = false, + .dmaSrc = DMAC_Peripheral_UART1_Rx, + .dmaDst = DMAC_Peripheral_UART1_Tx, } -} +}; - - -bool HAL_UART_Init(UART_HandleTypeDef *pUart) +HAL_Status HAL_UART_Init(HAL_UART_HandleTypeDef *pUart) { + if (pUart == NULL) + { + return HAL_ERROR; + } + uint32_t tmpreg = 0x00; uint32_t integerdivider = 0x00; uint32_t fractionaldivider = 0x00; uint64_t apbclock = 0x00; - if(pUart->pUartx == UART0) - { - CLK_APB1PeriphClockCmd(CLK_APB1Periph_UART0, ENABLE); - } - else if(pUart->pUartx == UART1) - { - CLK_APB2PeriphClockCmd(CLK_APB2Periph_UART1, ENABLE); - } - + if(pUart->pUartx == UART0) + { + CLK_APB1PeriphClockCmd(CLK_APB1Periph_UART0, ENABLE); + } + else if(pUart->pUartx == UART1) + { + CLK_APB2PeriphClockCmd(CLK_APB2Periph_UART1, ENABLE); + } + /*---------------------------- UART BRR Configuration -----------------------*/ /* Configure the UART Baud Rate */ apbclock = CLK_GetPeripheralFreq((void *)pUart->pUartx); - /*unlock to enable write & read divisor register*/ + /* Unlock to enable write & read divisor register */ pUart->pUartx->LCR |= UART_LCR_DLAB_Msk; - /* Determine the integer part baud_rate_divisor = PCLK*100 / (16*required_baud_rate)*/ + /* Determine the integer part baud_rate_divisor = PCLK*100 / (16*required_baud_rate) */ integerdivider = ((25 * apbclock) / (4 * (pUart->initObj.baudRate))); // Too high baudrate (too small divider) would cause DLL/DLH be all 0 which means UART disabled, // thus return false if this happens. if (integerdivider < 100) - return false; + return HAL_ERROR; tmpreg = (integerdivider / 100); pUart->pUartx->RBR_THR_DLL = tmpreg & 0xFF; @@ -101,239 +111,621 @@ pUart->pUartx->LCR = tmpreg; /*-------------------------------enable fifo----------------------------------*/ - pUart->pUartx->SCR |= UART_FCR_FIFOE_Msk; - pUart->pUartx->IIR_FCR = pUart->pUartx->SCR; UART_EnableFifo(pUart->pUartx); - return true; + return HAL_OK; } -void HAL_UART_SendData(UART_HandleTypeDef *pUart, uint8_t *pbuf, size_t size) +HAL_Status HAL_UART_SendData(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t size, uint32_t timeout) { - pUart->pTxBuffPtr = pbuf; + if (pUart->isTxBusy) + { + return HAL_BUSY; + } + + if ((pUart == NULL) || (pBuf == NULL) || (size == 0U)) + { + return HAL_ERROR; + } + + uint32_t timeout_tick = HAL_TimeConvMsToTick(timeout); + uint32_t uptime_ref = HAL_TimeGetCurrTick(); + + pUart->isTxBusy = true; + pUart->pTxBuffPtr = pBuf; pUart->txXferSize = size; pUart->txXferCount = 0; + while (pUart->txXferCount < pUart->txXferSize) { - UART_SendData(pUart->pUartx, pUart->pTxBuffPtr[pUart->txXferCount++]); + // Wait until Transmitter Shift Register and Tx FIFO are both empty while (!(UART_GetLineStatus(pUart->pUartx) & UART_LSR_TEMT_Msk)) - ; + { + if (timeout_tick != HAL_TIME_FOREVER) + { + if (HAL_TimeGetCurrTick() - uptime_ref >= timeout_tick) + { + pUart->isTxBusy = false; + return HAL_TIMEOUT; + } + } + } + // Put a byte to Tx FIFO + UART_SendData(pUart->pUartx, pUart->pTxBuffPtr[pUart->txXferCount++]); } + + pUart->isTxBusy = false; + + return HAL_OK; } -void HAL_UART_ReceiveData(UART_HandleTypeDef *pUart, uint8_t *pbuf, size_t size, uint32_t timeout) +HAL_Status HAL_UART_ReceiveData(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t size, uint32_t timeout) { - UART_SetRxTrigger(pUart->pUartx, UART_RX_FIFO_HALF_FULL); + if (pUart->isRxBusy) + { + return HAL_BUSY; + } - pUart->pRxBuffPtr = pbuf; + if ((pUart == NULL) || (pBuf == NULL) || (size == 0U)) + { + return HAL_ERROR; + } + + uint32_t timeout_tick = HAL_TimeConvMsToTick(timeout); + uint32_t uptime_ref = HAL_TimeGetCurrTick(); + + pUart->isRxBusy = true; + pUart->pRxBuffPtr = pBuf; pUart->rxXferSize = size; pUart->rxXferCount = 0; + while (pUart->rxXferCount < pUart->rxXferSize) { - while ((UART_GetLineStatus(pUart->pUartx) & UART_LSR_DR_Msk)) + // Check if there is at least one byte in Rx Data Register or Rx FIFO + if (UART_GetLineStatus(pUart->pUartx) & UART_LSR_DR_Msk) { + // Get a byte from Rx FIFO pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx); + } + if (timeout_tick != HAL_TIME_FOREVER) + { + if (HAL_TimeGetCurrTick() - uptime_ref >= timeout_tick) + { + pUart->isRxBusy = false; + return HAL_TIMEOUT; + } + } + } + + pUart->isRxBusy = false; + + return HAL_OK; +} + +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK +#include "pan_ble_stack.h" +void ble_irq_split_callback(void) +{ + HAL_UART_HandleTypeDef *pUart; + + for (size_t i = 0; i < PAN_HAL_UART_INST_COUNT; i++) + { + pUart = &UART_Handle_Array[i]; + if (pUart->isRxBusy) + { + __disable_irq(); // To avoid swiching to the possible higher priority UART ISR + if (pUart->interruptObj.continuousRxMode) + { + while (UART_GetRxFifoLevel(pUart->pUartx) > 1) + { + if (pUart->rxXferCount < pUart->rxXferSize) + { + pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx); + } + else + { + // Set UART pending irq manually to trigger uart rx continuous buff full error callback + NVIC_SetPendingIRQ(pUart->interruptObj.IRQn); + break; + } + } + } + else + { + while (!UART_IsRxFifoEmpty(pUart->pUartx)) + { + if (pUart->rxXferCount < pUart->rxXferSize) + { + pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx); + } + else + { + break; + } + } + + if (pUart->rxXferCount == pUart->rxXferSize) + { + // Set UART pending irq manually to trigger uart rx finish callback + NVIC_SetPendingIRQ(pUart->interruptObj.IRQn); + } + } + __enable_irq(); } } } +#endif // PAN_HAL_BLE_IRQ_SPLIT_CALLBACK -void HAL_UART_SendData_INT(UART_HandleTypeDef *pUart, uint8_t *pbuf, size_t size, UART_CallbackFunc callback) +HAL_Status HAL_UART_Init_INT(HAL_UART_HandleTypeDef *pUart) { - pUart->pTxBuffPtr = pbuf; - pUart->txXferSize = size; - pUart->txXferCount = 0; - pUart->txIntCallback = callback; - UART_SetTxTrigger(pUart->pUartx, UART_TX_FIFO_EMPTY); + if (pUart == NULL) + { + return HAL_ERROR; + } - pUart->interruptObj.switchFlag = ENABLE; - pUart->interruptObj.interruptMode = HAL_UART_INT_THR_EMPTY; - HAL_UART_Init_INT(pUart); - NVIC_EnableIRQ(pUart->IRQn); -} +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK + pan_misc_register_app_irq_handler_cb(ble_irq_split_callback); +#endif // PAN_HAL_BLE_IRQ_SPLIT_CALLBACK -void HAL_UART_ReceiveData_INT(UART_HandleTypeDef *pUart, uint8_t *pbuf, size_t size,uint32_t timeout,UART_CallbackFunc callback) -{ - pUart->pRxBuffPtr = pbuf; - pUart->rxXferSize = size; - pUart->rxXferCount = 0; - pUart->rxIntCallback = callback; - UART_SetRxTrigger(pUart->pUartx, UART_RX_FIFO_TWO_LESS_THAN_FULL); - - pUart->interruptObj.switchFlag = ENABLE; - pUart->interruptObj.interruptMode = HAL_UART_INT_RECV_DATA_AVL; - HAL_UART_Init_INT(pUart); - pUart->interruptObj.interruptMode = HAL_UART_INT_LINE_STATUS; - HAL_UART_Init_INT(pUart); - pUart->interruptObj.interruptMode = HAL_UART_INT_ALL; - HAL_UART_Init_INT(pUart); - NVIC_EnableIRQ(pUart->IRQn); -} - - - -void HAL_UART_SendData_DMA(UART_HandleTypeDef *pUart, uint8_t *pbuf, size_t size, UART_CallbackFunc callback) -{ - pUart->interruptObj.switchFlag = ENABLE; - pUart->interruptObj.interruptMode = HAL_UART_INT_THR_EMPTY; - HAL_UART_Init_INT(pUart); - - pUart->pTxBuffPtr = pbuf; - pUart->txXferSize = size; - pUart->txXferCount = 0; - + // Flush UART FIFOs UART_ResetTxFifo(pUart->pUartx); - UART_SetTxTrigger(pUart->pUartx, UART_TX_FIFO_HALF_FULL); - UART_EnablePtime(pUart->pUartx); //Enable Programmable THRE Interrupt Mode - - uint32_t txChNum = 0xFF; - // Initialize the DMA controller - DMAC_Init(DMA); - NVIC_EnableIRQ(DMA_IRQn); - - /* Get free DMA channel */ - txChNum = DMAC_AcquireChannel(DMA); - /* Enable DMA transfer interrupt */ - DMAC_ClrIntFlagMsk(DMA, txChNum, DMAC_FLAG_INDEX_TFR); - DMAC_ClrIntFlagMsk(DMA, txChNum, DMAC_FLAG_INDEX_DSTTFR); - DMAC_ClrIntFlagMsk(DMA, txChNum, DMAC_FLAG_INDEX_BLK); - DMAC_ClrIntFlagMsk(DMA, txChNum, DMAC_FLAG_INDEX_ERR); - dma_mem2uart_config.PeripheralDst = pUart->dmaDst; - DMAC_Channel_Array[txChNum].ConfigTmp = dma_mem2uart_config; - DMAC_Channel_Array[txChNum].CallbackUart = callback; - DMAC_Channel_Array[txChNum].PeriMode = DMAC_Peri_UART; - DMAC_Channel_Array[txChNum].pBuffPtr = (uint32_t*)pUart->pTxBuffPtr; - DMAC_Channel_Array[txChNum].XferSize = pUart->txXferSize; - DMAC_SetChannelConfig(DMA, txChNum, &DMAC_Channel_Array[txChNum].ConfigTmp); - - /* Condition check */ - uint32_t DataWidthInByteSrc = 1 << DMAC_Channel_Array[txChNum].ConfigTmp.DataWidthSrc; - uint32_t BlockSize = size / DataWidthInByteSrc; // BlockSize = DataLen / DataWidthInByteSrc - - /* Start DMA Tx channel */ - DMAC_StartChannel(DMA, txChNum, pbuf, (void *)&(pUart->pUartx->RBR_THR_DLL), BlockSize); -} - -void HAL_UART_ReceiveData_DMA(UART_HandleTypeDef *pUart, uint8_t *pbuf, size_t size, uint32_t timeout,UART_CallbackFunc callback) -{ - pUart->pRxBuffPtr = pbuf; - pUart->rxXferSize = size; - pUart->rxXferCount = 0; UART_ResetRxFifo(pUart->pUartx); - UART_SetRxTrigger(pUart->pUartx, UART_RX_FIFO_HALF_FULL); - uint32_t rxChNum = 0xFF; - // Initialize the DMA controller - DMAC_Init(DMA); - NVIC_EnableIRQ(DMA_IRQn); - rxChNum = DMAC_AcquireChannel(DMA); - /* Enable DMA transfer interrupt */ - DMAC_ClrIntFlagMsk(DMA, rxChNum, DMAC_FLAG_INDEX_TFR); - DMAC_ClrIntFlagMsk(DMA, rxChNum, DMAC_FLAG_INDEX_SRCTFR); - DMAC_ClrIntFlagMsk(DMA, rxChNum, DMAC_FLAG_INDEX_BLK); - DMAC_ClrIntFlagMsk(DMA, rxChNum, DMAC_FLAG_INDEX_ERR); + // Set UART IRQ trigger level + UART_SetTxTrigger(pUart->pUartx, (UART_TxTriggerDef)pUart->interruptObj.txTrigLevel); + UART_SetRxTrigger(pUart->pUartx, (UART_RxTriggerDef)pUart->interruptObj.rxTrigLevel); - // dma_uart2mem_config.PeripheralDst = pUart->dmaSrc; - DMAC_Channel_Array[rxChNum].ConfigTmp = dma_uart2mem_config; - DMAC_Channel_Array[rxChNum].ConfigTmp.PeripheralSrc = pUart->dmaSrc; - DMAC_Channel_Array[rxChNum].CallbackUart = callback; - DMAC_Channel_Array[rxChNum].PeriMode = DMAC_Peri_UART; - DMAC_Channel_Array[rxChNum].pBuffPtr = (uint32_t*)pUart->pRxBuffPtr; - DMAC_Channel_Array[rxChNum].XferSize = pUart->rxXferSize; - DMAC_SetChannelConfig(DMA, rxChNum, &DMAC_Channel_Array[rxChNum].ConfigTmp); + // Enable THRE Interrupt Mode + UART_EnablePtime(pUart->pUartx); - /* Condition check */ - uint32_t dataWidthInByteSrc = 1 <<DMAC_Channel_Array[rxChNum].ConfigTmp.DataWidthSrc; - uint32_t blockSize = size / dataWidthInByteSrc; //blockSize = DataLen / dataWidthInByteSrc - /* Start DMA Rx channel */ - DMAC_StartChannel(DMA, rxChNum, (void*)&(pUart->pUartx->RBR_THR_DLL), pUart->pRxBuffPtr, blockSize); + // Set UART IRQ Priority and enable UART IRQ + NVIC_SetPriority(pUart->interruptObj.IRQn, pUart->interruptObj.IrqPriority); + NVIC_EnableIRQ(pUart->interruptObj.IRQn); + + return HAL_OK; } - -void HAL_UART_Init_INT(UART_HandleTypeDef *pUart) +HAL_Status HAL_UART_SendData_INT(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t size) { - if (pUart->interruptObj.switchFlag == ENABLE) + if (pUart->isTxBusy) { - pUart->pUartx->IER_DLH |= ((pUart->interruptObj.interruptMode << UART_IER_ALL_IRQ_Pos) & UART_IER_ALL_IRQ_Msk); + return HAL_BUSY; } - else if (pUart->interruptObj.switchFlag == DISABLE) + + if ((pUart == NULL) || (pBuf == NULL) || (size == 0U)) { - pUart->pUartx->IER_DLH &= ~((pUart->interruptObj.interruptMode << UART_IER_ALL_IRQ_Pos) & UART_IER_ALL_IRQ_Msk); + return HAL_ERROR; } + + pUart->isTxBusy = true; + pUart->pTxBuffPtr = pBuf; + pUart->txXferSize = size; + pUart->txXferCount = 0; + + // Enable Transmit Trigger interupt to start sending + UART_EnableIrq(pUart->pUartx, UART_IRQ_THR_EMPTY); + + return HAL_OK; } -static void UART_HandleLineStatus(UART_HandleTypeDef *pUart) +HAL_Status HAL_UART_ReceiveData_INT(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t size) +{ + if (pUart->isRxBusy) + { + return HAL_BUSY; + } + + if ((pUart == NULL) || (pBuf == NULL) || (size == 0U)) + { + return HAL_ERROR; + } + + pUart->isRxBusy = true; + pUart->pRxBuffPtr = pBuf; + pUart->rxXferSize = size; + pUart->rxXferCount = 0; + + // Enable Data Available and Rx Line Status interrupt to start receiving + UART_EnableIrq(pUart->pUartx, UART_IRQ_RECV_DATA_AVL); + UART_EnableIrq(pUart->pUartx, UART_IRQ_LINE_STATUS); + + return HAL_OK; +} + +HAL_Status HAL_UART_ReceiveDataContinuously_INT(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t bufSize) +{ + if (pUart->isRxBusy) + { + return HAL_BUSY; + } + + if ((pUart == NULL) || (pBuf == NULL) || (bufSize == 0U)) + { + return HAL_ERROR; + } + + // The continuous Rx mode does not support Rx FIFO trigger level set to 1 char + if ((UART_RxTriggerDef)pUart->interruptObj.rxTrigLevel == UART_RX_FIFO_ONE_CHAR) + { + return HAL_ERROR; + } + + pUart->interruptObj.continuousRxMode = true; + pUart->isRxBusy = true; + pUart->pRxBuffPtr = pBuf; + pUart->rxXferSize = bufSize; + pUart->rxXferCount = 0; + + // Enable Data Available and Rx Line Status interrupt to start receiving + UART_EnableIrq(pUart->pUartx, UART_IRQ_RECV_DATA_AVL); + UART_EnableIrq(pUart->pUartx, UART_IRQ_LINE_STATUS); + + return HAL_OK; +} + +HAL_Status HAL_UART_SendDataAbort_INT(HAL_UART_HandleTypeDef *pUart) +{ + if (pUart == NULL) + { + return HAL_ERROR; + } + + // Disable Transmit Trigger interupt to abort sending + UART_DisableIrq(pUart->pUartx, UART_IRQ_THR_EMPTY); + + // Flush Tx FIFO + UART_ResetTxFifo(pUart->pUartx); + + pUart->isTxBusy = false; + + return HAL_OK; +} + +HAL_Status HAL_UART_ReceiveDataAbort_INT(HAL_UART_HandleTypeDef *pUart) +{ + if (pUart == NULL) + { + return HAL_ERROR; + } + + // Disable Data Available and Rx Line Status interrupt to abort receiving + UART_DisableIrq(pUart->pUartx, UART_IRQ_RECV_DATA_AVL); + UART_DisableIrq(pUart->pUartx, UART_IRQ_LINE_STATUS); + + // Flush Rx FIFO + UART_ResetRxFifo(pUart->pUartx); + + pUart->isRxBusy = false; + pUart->interruptObj.continuousRxMode = false; + + return HAL_OK; +} + +HAL_Status HAL_UART_Init_DMA(HAL_UART_HandleTypeDef *pUart, HAL_UART_DmaDirOpt dmaDir, UART_CallbackFunc callback) +{ + uint32_t dmaCh; + + if ((pUart == NULL) || (callback == NULL)) + { + return HAL_ERROR; + } + + if (dmaDir == HAL_UART_DMA_TX) + { + // Configure UART Tx FIFO + UART_ResetTxFifo(pUart->pUartx); + UART_SetTxTrigger(pUart->pUartx, UART_TX_FIFO_HALF_FULL); + UART_EnablePtime(pUart->pUartx); //Enable Programmable THRE Interrupt Mode + + /* Get free DMA channel */ + dmaCh = DMAC_AcquireChannel(DMA); + if (dmaCh == DMA_INVLID_CHANNEL) + { + return HAL_ERROR; + } + + pUart->txDmaCh = dmaCh; + DMAC_Channel_Array[dmaCh].ConfigTmp = dma_mem2uart_config; + DMAC_Channel_Array[dmaCh].ConfigTmp.PeripheralDst = pUart->dmaDst; + } + else if (dmaDir == HAL_UART_DMA_RX) + { + // Configure UART Rx FIFO + UART_ResetRxFifo(pUart->pUartx); + UART_SetRxTrigger(pUart->pUartx, UART_RX_FIFO_HALF_FULL); + + /* Get free DMA channel */ + dmaCh = DMAC_AcquireChannel(DMA); + if (dmaCh == DMA_INVLID_CHANNEL) + { + return HAL_ERROR; + } + + pUart->rxDmaCh = dmaCh; + DMAC_Channel_Array[dmaCh].ConfigTmp = dma_uart2mem_config; + DMAC_Channel_Array[dmaCh].ConfigTmp.PeripheralSrc = pUart->dmaSrc; + } + + /* Enable DMA transfer interrupt */ + DMAC_ClrIntFlagMsk(DMA, dmaCh, DMAC_FLAG_INDEX_TFR); +// DMAC_ClrIntFlagMsk(DMA, dmaCh, DMAC_FLAG_INDEX_ERR); + + DMAC_Channel_Array[dmaCh].periph = pUart; + DMAC_Channel_Array[dmaCh].CallbackUart = callback; + DMAC_Channel_Array[dmaCh].PeriMode = DMAC_Peri_UART; + DMAC_SetChannelConfig(DMA, dmaCh, &DMAC_Channel_Array[dmaCh].ConfigTmp); + + return HAL_OK; +} + +HAL_Status HAL_UART_SendData_DMA(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t size) +{ + if (pUart->isTxBusy) + { + return HAL_BUSY; + } + + if ((pUart == NULL) || (pBuf == NULL) || (size == 0U)) + { + return HAL_ERROR; + } + + pUart->isTxBusy = true; + DMAC_Channel_Array[pUart->txDmaCh].pBuffPtr = (uint32_t*)pBuf; + DMAC_Channel_Array[pUart->txDmaCh].XferSize = size; + DMAC_Channel_Array[pUart->txDmaCh].XferCount = 0; + + if (size < 1024) + { + DMAC_StartChannel(DMA, pUart->txDmaCh, pBuf, (void *)&(pUart->pUartx->RBR_THR_DLL), size); + } + else + { + DMAC_StartChannel(DMA, pUart->txDmaCh, pBuf, (void *)&(pUart->pUartx->RBR_THR_DLL), 1023); + } + + return HAL_OK; +} + +HAL_Status HAL_UART_ReceiveData_DMA(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t size) +{ + if (pUart->isRxBusy) + { + return HAL_BUSY; + } + + if ((pUart == NULL) || (pBuf == NULL) || (size == 0U)) + { + return HAL_ERROR; + } + + pUart->isRxBusy = true; + DMAC_Channel_Array[pUart->rxDmaCh].pBuffPtr = (uint32_t*)pBuf; + DMAC_Channel_Array[pUart->rxDmaCh].XferSize = size; + DMAC_Channel_Array[pUart->rxDmaCh].XferCount = 0; + + if (size < 1024) + { + DMAC_StartChannel(DMA, pUart->rxDmaCh, (void*)&(pUart->pUartx->RBR_THR_DLL), pBuf, size); + } + else + { + DMAC_StartChannel(DMA, pUart->rxDmaCh, (void*)&(pUart->pUartx->RBR_THR_DLL), pBuf, 1023); + } + + return HAL_OK; +} + +HAL_Status HAL_UART_SendDataAbort_DMA(HAL_UART_HandleTypeDef *pUart) +{ + if (pUart == NULL) + { + return HAL_ERROR; + } + + // Stop current DMA channel + DMAC_StopChannel(DMA, pUart->txDmaCh); + + // Flush Tx FIFO + UART_ResetTxFifo(pUart->pUartx); + + pUart->isTxBusy = false; + + return HAL_OK; +} + +HAL_Status HAL_UART_ReceiveDataAbort_DMA(HAL_UART_HandleTypeDef *pUart) +{ + if (pUart == NULL) + { + return HAL_ERROR; + } + + // Stop current DMA channel + DMAC_StopChannel(DMA, pUart->rxDmaCh); + + // Flush Rx FIFO + UART_ResetRxFifo(pUart->pUartx); + + pUart->isRxBusy = false; + + return HAL_OK; +} + +static void UART_HandleLineStatus(HAL_UART_HandleTypeDef *pUart) { uint32_t lineStatus = UART_GetLineStatus(pUart->pUartx); - // Filter line error - if ((lineStatus & (UART_LINE_OVERRUN_ERR | UART_LINE_PARITY_ERR | UART_LINE_FRAME_ERR | UART_LINE_RECV_FIFO_EMPTY)) != 0x0) + if (pUart->isRxBusy) { - - } - - // Handle THRE event - if (lineStatus & UART_LINE_THRE) - { - if ((pUart->pUartx->IER_DLH & UART_IER_EPTI_Msk) == 0) + // Report Rx error event + if (pUart->interruptObj.callbackFunc != NULL) { - - } - - else if ((pUart->pUartx->IIR_FCR & UART_IIR_FIFOSE_Msk) != 0) - { - - } - } -} - -static void UART_HandleModemStatus(UART_HandleTypeDef *pUart) -{ - uint32_t modemStatus = UART_GetModemStatus(pUart->pUartx); -} - -static void UART_HandleReceivedData(UART_HandleTypeDef *pUart,UART_Cb_Flag_Opt flag) -{ - while (!UART_IsRxFifoEmpty(pUart->pUartx)) - { - pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx); - } - - if (flag == UART_CB_FLAG_RX_TIMEOUT) - { - if(pUart->rxXferCount >= pUart->rxXferSize) - { - pUart->rxXferCount = pUart->rxXferSize; - } - - if (pUart->rxIntCallback != NULL) - { - pUart->rxIntCallback(flag,pUart->pRxBuffPtr,pUart->rxXferCount); - } - pUart->rxXferCount = 0; - } -} - -static void UART_HandleTransmittingData(UART_HandleTypeDef *pUart) -{ - while (!UART_IsTxFifoFull(pUart->pUartx)) - { - if (pUart->txXferCount < pUart->txXferSize) - { - UART_SendData(pUart->pUartx, pUart->pTxBuffPtr[pUart->txXferCount++]); - } - else - { - UART_DisableIrq(pUart->pUartx, UART_IRQ_THR_EMPTY); // Disable THRE Interrupt after transmitting done - if (pUart->txIntCallback != NULL) + if (lineStatus & UART_LINE_PARITY_ERR) { - pUart->txIntCallback(UART_CB_FLAG_TX_FINISH, pUart->pTxBuffPtr,pUart->txXferCount); + pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_RX_ERR_PARITY, pUart->pRxBuffPtr, pUart->rxXferCount); } - break; + if (lineStatus & UART_LINE_FRAME_ERR) + { + pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_RX_ERR_FRAME, pUart->pRxBuffPtr, pUart->rxXferCount); + } + if (lineStatus & UART_LINE_OVERRUN_ERR) + { + pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_RX_ERR_OVERRUN, pUart->pRxBuffPtr, pUart->rxXferCount); + } } - } + } } -static void UART_HandleProc(UART_HandleTypeDef *pUart) +static void UART_HandleReceivedData(HAL_UART_HandleTypeDef *pUart, UART_EventDef flag) +{ + if (pUart->isRxBusy) + { + if (pUart->interruptObj.continuousRxMode) + { + if (flag != UART_EVENT_TIMEOUT) + { +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK + __disable_irq(); // To avoid swiching to higher priority LL IRQ +#endif + // Read data from UART Rx FIFO and remains 1 byte in it + while (UART_GetRxFifoLevel(pUart->pUartx) > 1) + { + if (pUart->rxXferCount < pUart->rxXferSize) + { + pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx); + } + else + { + break; + } + } +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK + __enable_irq(); +#endif + } + else + { +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK + __disable_irq(); // To avoid swiching to higher priority LL IRQ +#endif + // Read all data from UART Rx FIFO due to timeout occurred + while (!UART_IsRxFifoEmpty(pUart->pUartx)) + { + if (pUart->rxXferCount < pUart->rxXferSize) + { + pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx); + } + else + { + break; + } + } +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK + __enable_irq(); +#endif + // End current rx flow and trigger Continuous Rx Timeout callback if Rx FIFO is already empty + if (UART_IsRxFifoEmpty(pUart->pUartx)) + { + // Disable Data Available and Rx Line Status interrupt to abort receiving + UART_DisableIrq(pUart->pUartx, UART_IRQ_RECV_DATA_AVL); + UART_DisableIrq(pUart->pUartx, UART_IRQ_LINE_STATUS); +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK + __disable_irq(); // To avoid swiching to higher priority LL IRQ +#endif + pUart->isRxBusy = false; + pUart->interruptObj.continuousRxMode = false; +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK + __enable_irq(); +#endif + // Trigger Continuous Rx Timeout callback + if (pUart->interruptObj.callbackFunc != NULL) + { + pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_CONTI_RX_TIMEOUT, pUart->pRxBuffPtr, pUart->rxXferCount); + } + } + } + if (pUart->rxXferCount >= pUart->rxXferSize) + { + // Trigger Rx Buffer Full callback + if (pUart->interruptObj.callbackFunc != NULL) + { + pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_CONTI_RX_BUFF_FULL, pUart->pRxBuffPtr, pUart->rxXferCount); + } + } + } + else // Normal Rx Mode (Not Continuous Rx Mode) + { +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK + __disable_irq(); // To avoid swiching to higher priority LL IRQ +#endif + while (!UART_IsRxFifoEmpty(pUart->pUartx)) + { + if (pUart->rxXferCount < pUart->rxXferSize) + { + pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx); + } + else + { + break; + } + } +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK + __enable_irq(); +#endif + if (pUart->rxXferCount == pUart->rxXferSize) + { + // Disable Data Available and Rx Line Status interrupt to abort receiving + UART_DisableIrq(pUart->pUartx, UART_IRQ_RECV_DATA_AVL); + UART_DisableIrq(pUart->pUartx, UART_IRQ_LINE_STATUS); +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK + __disable_irq(); // To avoid swiching to higher priority LL IRQ +#endif + pUart->isRxBusy = false; +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK + __enable_irq(); +#endif + // Report Rx finish event + if (pUart->interruptObj.callbackFunc != NULL) + { + pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_RX_FINISH, pUart->pRxBuffPtr, pUart->rxXferCount); + } + } + } + } +} + +static void UART_HandleTransmittingData(HAL_UART_HandleTypeDef *pUart) +{ + if (pUart->isTxBusy) + { + while (!UART_IsTxFifoFull(pUart->pUartx)) + { + if (pUart->txXferCount < pUart->txXferSize) + { + UART_SendData(pUart->pUartx, pUart->pTxBuffPtr[pUart->txXferCount++]); + } + else + { + break; + } + } + + if (pUart->txXferCount == pUart->txXferSize) + { + // Disable Transmit Trigger interupt after transmitting done + UART_DisableIrq(pUart->pUartx, UART_IRQ_THR_EMPTY); + pUart->isTxBusy = false; + // Report Tx finish event + if (pUart->interruptObj.callbackFunc != NULL) + { + pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_TX_FINISH, pUart->pTxBuffPtr, pUart->txXferCount); + } + } + } +} + +static void UART_HandleProc(HAL_UART_HandleTypeDef *pUart) { UART_EventDef event = UART_GetActiveEvent(pUart->pUartx); @@ -343,34 +735,48 @@ UART_HandleLineStatus(pUart); break; case UART_EVENT_DATA: - UART_HandleReceivedData(pUart,UART_CB_FLAG_RX_FINISH); + UART_HandleReceivedData(pUart, UART_EVENT_DATA); break; case UART_EVENT_TIMEOUT: - UART_HandleReceivedData(pUart,UART_CB_FLAG_RX_TIMEOUT); + UART_HandleReceivedData(pUart, UART_EVENT_TIMEOUT); break; case UART_EVENT_THR_EMPTY: UART_HandleTransmittingData(pUart); break; - case UART_EVENT_MODEM: - UART_HandleModemStatus(pUart); - break; case UART_EVENT_NONE: - /* Just ignore this event. */ +#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK + UART_HandleReceivedData(pUart, UART_EVENT_NONE); +#endif // PAN_HAL_BLE_IRQ_SPLIT_CALLBACK break; default: break; } } -void UART0_IRQHandler(void) +__WEAK void UART0_IRQHandlerOverlay(void) { UART_HandleProc(&UART_Handle_Array[0]); } -void UART1_IRQHandler(void) +__WEAK void UART1_IRQHandlerOverlay(void) { UART_HandleProc(&UART_Handle_Array[1]); } +void UART0_IRQHandler(void) +{ + PAN_IO_TIMING_TRACK_LEVEL(CONFIG_TRACK_PIN_UART0_IRQ, 1); -/*** (C) COPYRIGHT 2023 Panchip Technology Corp. ***/ + UART0_IRQHandlerOverlay(); + + PAN_IO_TIMING_TRACK_LEVEL(CONFIG_TRACK_PIN_UART0_IRQ, 0); +} + +void UART1_IRQHandler(void) +{ + PAN_IO_TIMING_TRACK_LEVEL(CONFIG_TRACK_PIN_UART1_IRQ, 1); + + UART1_IRQHandlerOverlay(); + + PAN_IO_TIMING_TRACK_LEVEL(CONFIG_TRACK_PIN_UART1_IRQ, 0); +} -- Gitblit v1.9.3