chen
2025-05-15 67ca69985af9109a0603a1cde71f21b940c059ff
keil/include/components/hal/UART.c
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,472 @@
/*******************************************************************************
 * File Name         : Uart.c
 * Description       :
 * Created on        : 2018å¹´4月24日
 * Author            : æœé”®
 *******************************************************************************/
/*******************************************************************************
 *                              Include Files                                  *
 *******************************************************************************/
#include "string.h"
#ifdef _USE_OS_
#include "cmsis_os.h"
#endif
#include <stdio.h>
#include "HIDO_Util.h"
#include "HIDO_VLQueue.h"
#include "HIDO_ArraryQueue.h"
#include "HIDO_Lock.h"
#include "HIDO_ATLite.h"
#include "UART.h"
/*******************************************************************************
 *                                  Macro                                      *
 *******************************************************************************/
/*******************************************************************************
 *                             Type Definition                                 *
 *******************************************************************************/
typedef struct
{
#ifdef _USE_OS_
    osMutexId m_mutexLock;
#endif
    E_UartID m_eUartID;
    enum UART_DEV_T m_eUartPort;
    E_UartTxMode m_eTxMode;
    E_UartRxMode m_eRxMode;
    HIDO_UINT8 *m_pu8RxBuf;
    HIDO_UINT32 m_u32RxBufSize;
    HIDO_UINT8 *m_pu8RxLastPos;
    HIDO_UINT8 *m_pu8RxBufEnd;
    HIDO_ArraryQueueStruct m_stRxArraryQueue;
    HIDO_UINT8 *m_pu8TxBuf;
    HIDO_UINT32 m_u32TxBufSize;
    HIDO_UINT32 m_u32TxQueueMemberCnt;
    HIDO_VLQStruct m_stTxVLQueue;
    HIDO_UINT8 m_u8RxValue;
    HIDO_UINT32 m_u32Flag;
    FN_RxISR m_fnRxISR;
} ST_UartInfo;
/*******************************************************************************
 *                             Local Variable                                  *
 *******************************************************************************/
static ST_UartInfo l_astUartInfo[UART_ID_LAST];
/*******************************************************************************
 *                        Local Function Declaration                           *
 *******************************************************************************/
static void uart_receive_callback(void *dev, uint32_t err_code);
const static struct baud_map
{
    enum UART_BAUD_T baud;
    HIDO_UINT32 u32Baud;
} baud_map[] =
{
    {BAUD_1200,    1200},
    {BAUD_2400,    2400},
    {BAUD_4800,    4800},
    {BAUD_9600,    9600},
    {BAUD_19200,   19200},
    {BAUD_38400,   38400},
    {BAUD_57600,   57600},
    {BAUD_115200,  115200},
    {BAUD_230400,  230400},
    {BAUD_460800,  460800},
    {BAUD_921600,  921600},
    {BAUD_1843200, 1843200},
    {BAUD_1000000, 1000000},
    {BAUD_2000000, 2000000},
};
/*******************************************************************************
 *                             Local Function                                  *
 *******************************************************************************/
static enum UART_BAUD_T get_baud(HIDO_UINT32 u32Baud)
{
    for(HIDO_UINT32 i = 0; i < HIDO_ARRARY_COUNT(baud_map); i++)
    {
        if(u32Baud == baud_map[i].u32Baud)
        {
            return baud_map[i].baud;
        }
    }
    return BAUD_115200;
}
/*******************************************************************************
 *                             Global Function                                 *
 *******************************************************************************/
/*******************************************************************************
 * Function Name     :
 * Description       :
 * Input             :
 * Output            :
 * Return            :
 * Author            : æœé”®
 * Modified Date:    : 2018å¹´4月24日
 *******************************************************************************/
HIDO_INT32 Uart_Register(E_UartID _eUartID, enum UART_DEV_T _ePort)
{
    /* åˆå§‹åŒ–参数 */
    HIDO_UtilBzero(&l_astUartInfo[_eUartID], sizeof(ST_UartInfo));
    l_astUartInfo[_eUartID].m_eUartPort = _ePort;
    return HIDO_OK;
}
/*******************************************************************************
 * Function Name     :
 * Description       :
 * Input             :
 * Output            :
 * Return            :
 * Author            : æœé”®
 * Modified Date:    : 2018å¹´4月24日
 *******************************************************************************/
HIDO_INT32 Uart_Init(E_UartID _eUartID, ST_UartInit *_pstInit)
{
    if((HIDO_NULL == _pstInit) || (_eUartID >= UART_ID_LAST))
    {
        return HIDO_ERR;
    }
#ifdef _USE_OS_
    l_astUartInfo[_eUartID].m_mutexLock =  osMutexCreate(HIDO_NULL);
#endif
    struct UART_CFG_T uart_cfg =
    {
        .parity = UART_PARITY_NONE,
        .stop = UART_STOP_BITS_1,
        .data = UART_DATA_BITS_8,
        .flow = UART_FLOW_CONTROL_NONE,
        .rx_level = UART_RXFIFO_CHAR_1,
        .tx_level = UART_TXFIFO_EMPTY,
        .baud = get_baud(_pstInit->m_u32BaudRate),
        .dma_en = false,
        .int_rx = true,
        .int_tx = false,
    };
    l_astUartInfo[_eUartID].m_eUartID = _eUartID;
    l_astUartInfo[_eUartID].m_eTxMode = _pstInit->m_eTxMode;
    l_astUartInfo[_eUartID].m_eRxMode = _pstInit->m_eRxMode;
    l_astUartInfo[_eUartID].m_pu8RxBuf = _pstInit->m_pu8RxBuf;
    l_astUartInfo[_eUartID].m_u32RxBufSize = _pstInit->m_u32RxBufSize;
    if(UART_RX_MODE_DMA == _pstInit->m_eRxMode)
    {
        l_astUartInfo[_eUartID].m_pu8RxLastPos= l_astUartInfo[_eUartID].m_pu8RxBuf;
        l_astUartInfo[_eUartID].m_pu8RxBufEnd = l_astUartInfo[_eUartID].m_pu8RxBuf + l_astUartInfo[_eUartID].m_u32RxBufSize - 1;
    }
    else if(UART_RX_MODE_INT == _pstInit->m_eRxMode)
    {
        HIDO_ArraryQueueInit(
                &l_astUartInfo[_eUartID].m_stRxArraryQueue,
                _pstInit->m_pu8RxBuf,
                _pstInit->m_u32RxBufSize,
                sizeof(HIDO_UINT8));
    }
    l_astUartInfo[_eUartID].m_pu8TxBuf = _pstInit->m_pu8TxBuf;
    l_astUartInfo[_eUartID].m_u32TxBufSize = _pstInit->m_u32TxBufSize;
    l_astUartInfo[_eUartID].m_fnRxISR = _pstInit->m_fnRxISR;
    l_astUartInfo[_eUartID].m_u32TxQueueMemberCnt = _pstInit->m_u32TxQueueMemberCnt;
    uart_open(l_astUartInfo[_eUartID].m_eUartPort, &uart_cfg);
    if((UART_TX_MODE_DMA == _pstInit->m_eTxMode) || (UART_TX_MODE_INT == _pstInit->m_eTxMode))
    {
        HIDO_VLQInit(
                &(l_astUartInfo[_eUartID].m_stTxVLQueue),
                _pstInit->m_pu8TxBuf,
                _pstInit->m_u32TxBufSize,
                _pstInit->m_u32TxQueueMemberCnt);
    }
    if (UART_RX_MODE_INT == _pstInit->m_eRxMode)
    {
        uart_receive(l_astUartInfo[_eUartID].m_eUartPort, &l_astUartInfo[_eUartID].m_u8RxValue, 1, uart_receive_callback);
    }
    return HIDO_OK;
}
/*******************************************************************************
 * Function Name     :
 * Description       :
 * Input             :
 * Output            :
 * Return            :
 * Author            : æœé”®
 * Modified Date:    : 2018å¹´4月24日
 *******************************************************************************/
HIDO_INT32 Uart_ReInit(E_UartID _eUartID)
{
    if(UART_RX_MODE_DMA == l_astUartInfo[_eUartID].m_eRxMode)
    {
        l_astUartInfo[_eUartID].m_pu8RxLastPos= l_astUartInfo[_eUartID].m_pu8RxBuf;
        l_astUartInfo[_eUartID].m_pu8RxBufEnd = l_astUartInfo[_eUartID].m_pu8RxBuf + l_astUartInfo[_eUartID].m_u32RxBufSize - 1;
    }
    else if(UART_RX_MODE_INT ==  l_astUartInfo[_eUartID].m_eRxMode)
    {
        HIDO_ArraryQueueInit(
                &l_astUartInfo[_eUartID].m_stRxArraryQueue,
                l_astUartInfo[_eUartID].m_pu8RxBuf,
                l_astUartInfo[_eUartID].m_u32RxBufSize,
                sizeof(HIDO_UINT8));
    }
    if((UART_TX_MODE_DMA == l_astUartInfo[_eUartID].m_eTxMode) || (UART_TX_MODE_INT == l_astUartInfo[_eUartID].m_eTxMode))
    {
        HIDO_VLQInit(
                &(l_astUartInfo[_eUartID].m_stTxVLQueue),
                l_astUartInfo[_eUartID].m_pu8TxBuf,
                l_astUartInfo[_eUartID].m_u32TxBufSize,
                l_astUartInfo[_eUartID].m_u32TxQueueMemberCnt);
    }
    uart_receive(l_astUartInfo[_eUartID].m_eUartPort, &l_astUartInfo[_eUartID].m_u8RxValue, 1, uart_receive_callback);
    return HIDO_OK;
}
/*******************************************************************************
 * Function Name     :
 * Description       :
 * Input             :
 * Output            :
 * Return            :
 * Author            : æœé”®
 * Modified Date:    : 2018å¹´4月24日
 *******************************************************************************/
HIDO_INT32 Uart_ReConfigBaudRate(E_UartID _eUartID, HIDO_UINT32 _u32BaudRate)
{
    uart_close(l_astUartInfo[_eUartID].m_eUartPort);
    struct UART_CFG_T uart_cfg =
    {
        .parity = UART_PARITY_NONE,
        .stop = UART_STOP_BITS_1,
        .data = UART_DATA_BITS_8,
        .flow = UART_FLOW_CONTROL_NONE,
        .rx_level = UART_RXFIFO_CHAR_1,
        .tx_level = UART_TXFIFO_EMPTY,
        .baud = get_baud(_u32BaudRate),
        .dma_en = false,
        .int_rx = true,
        .int_tx = false,
    };
    uart_open(l_astUartInfo[_eUartID].m_eUartPort, &uart_cfg);
    return HIDO_OK;
}
/*******************************************************************************
 * Function Name     :
 * Description       :
 * Input             :
 * Output            :
 * Return            :
 * Author            : æœé”®
 * Modified Date:    : 2018å¹´4月24日
 *******************************************************************************/
static void uart_send_callback(void *dev, uint32_t err_code)
{
    E_UartID eUartID = (E_UartID) 0;
    for (eUartID = (E_UartID) 0; eUartID < UART_ID_LAST; eUartID++)
    {
        if (l_astUartInfo[eUartID].m_eUartPort == *(enum UART_DEV_T *)dev)
        {
            if(UART_TX_MODE_DMA == l_astUartInfo[eUartID].m_eTxMode)
            {
                HIDO_VLQMemberStruct *pstMember = HIDO_NULL;
                pstMember = HIDO_VLQGetDequeueMember(&(l_astUartInfo[eUartID].m_stTxVLQueue));
                HIDO_VLQDequeue(&(l_astUartInfo[eUartID].m_stTxVLQueue), pstMember);
                pstMember = HIDO_VLQGetDequeueMember(&(l_astUartInfo[eUartID].m_stTxVLQueue));
                if (pstMember)
                {
                    uart_send(l_astUartInfo[eUartID].m_eUartPort, pstMember->m_pDataAddr, pstMember->m_u32DataLen, uart_send_callback);
                }
            }
            else if(UART_TX_MODE_INT == l_astUartInfo[eUartID].m_eTxMode)
            {
                HIDO_VLQMemberStruct *pstMember = HIDO_NULL;
                pstMember = HIDO_VLQGetDequeueMember(&(l_astUartInfo[eUartID].m_stTxVLQueue));
                HIDO_VLQDequeue(&(l_astUartInfo[eUartID].m_stTxVLQueue), pstMember);
                pstMember = HIDO_VLQGetDequeueMember(&(l_astUartInfo[eUartID].m_stTxVLQueue));
                if (pstMember)
                {
                    uart_send(l_astUartInfo[eUartID].m_eUartPort, pstMember->m_pDataAddr, pstMember->m_u32DataLen, uart_send_callback);
                }
            }
            break;
        }
    }
}
/*******************************************************************************
 * Function Name     : Uart_RxOverFromISR
 * Description       :
 * Input             :
 * Output            :
 * Return            :
 * Author            : æœé”®
 * Modified Date:    : 2018å¹´4月24日
 *******************************************************************************/
static void uart_receive_callback(void *dev, uint32_t err_code)
{
    E_UartID eUartID = UART_ID_4G;
    HIDO_UINT8 u8RecvByte = l_astUartInfo[eUartID].m_u8RxValue;
    HIDO_ArraryQueueIn(&l_astUartInfo[eUartID].m_stRxArraryQueue, &u8RecvByte);
    /* å¯åЍINT接收 */
    uart_receive(l_astUartInfo[eUartID].m_eUartPort, &l_astUartInfo[eUartID].m_u8RxValue, 1, uart_receive_callback);
}
/*******************************************************************************
 * Function Name     :
 * Description       :
 * Input             :
 * Output            :
 * Return            :
 * Author            : æœé”®
 * Modified Date:    : 2018å¹´4月24日
 *******************************************************************************/
HIDO_INT32 Uart_GetChar(E_UartID _eUartID, HIDO_UINT8 *_pu8Char)
{
    HIDO_INT32 i32Result = HIDO_ERR;
    if (HIDO_NULL == _pu8Char || _eUartID >= UART_ID_LAST)
    {
        return HIDO_ERR;
    }
#ifdef _USE_OS_
    osMutexWait(l_astUartInfo[_eUartID].m_mutexLock, osWaitForever);
#endif
    if (UART_RX_MODE_INT == l_astUartInfo[_eUartID].m_eRxMode)
    {
        if (HIDO_ArraryQueueOut(&l_astUartInfo[_eUartID].m_stRxArraryQueue, _pu8Char) == HIDO_OK)
        {
            i32Result = HIDO_OK;
        }
    }
#ifdef _USE_OS_
    osMutexRelease(l_astUartInfo[_eUartID].m_mutexLock);
#endif
    return i32Result;
}
/*******************************************************************************
 * Function Name     :
 * Description       :
 * Input             :
 * Output            :
 * Return            :
 * Author            : æœé”®
 * Modified Date:    : 2018å¹´4月24日
 *******************************************************************************/
HIDO_INT32 Uart_Send(E_UartID _eUartID, HIDO_UINT8 *_pu8Data, HIDO_UINT32 _u32Len)
{
    HIDO_INT32 i32Result = HIDO_OK;
    if (HIDO_NULL == _pu8Data || 0 == _u32Len || _eUartID >= UART_ID_LAST)
    {
        return HIDO_ERR;
    }
#ifdef _USE_OS_
    osMutexWait(l_astUartInfo[_eUartID].m_mutexLock, osWaitForever);
#endif
    if (UART_TX_MODE_DMA == l_astUartInfo[_eUartID].m_eTxMode)
    {
        HIDO_VLQMemberStruct *pstMember = HIDO_NULL;
        HIDO_Lock();
        pstMember = HIDO_VLQGetEnqueueMember(&(l_astUartInfo[_eUartID].m_stTxVLQueue), _u32Len);
        if (HIDO_NULL == pstMember)
        {
            HIDO_UnLock();
            i32Result = HIDO_ERR;
        }
        else
        {
            HIDO_VLQEnqueue(&(l_astUartInfo[_eUartID].m_stTxVLQueue), pstMember);
            memcpy(pstMember->m_pDataAddr, _pu8Data, _u32Len);
            pstMember = HIDO_VLQGetDequeueMember(&(l_astUartInfo[_eUartID].m_stTxVLQueue));
            HIDO_UnLock();
            uart_send(l_astUartInfo[_eUartID].m_eUartPort, pstMember->m_pDataAddr, pstMember->m_u32DataLen, uart_send_callback);
        }
    }
    else if (UART_TX_MODE_INT == l_astUartInfo[_eUartID].m_eTxMode)
    {
        HIDO_VLQMemberStruct *pstMember = HIDO_NULL;
        HIDO_Lock();
        pstMember = HIDO_VLQGetEnqueueMember(&(l_astUartInfo[_eUartID].m_stTxVLQueue), _u32Len);
        if (HIDO_NULL == pstMember)
        {
            HIDO_UnLock();
            i32Result = HIDO_ERR;
        }
        else
        {
            HIDO_VLQEnqueue(&(l_astUartInfo[_eUartID].m_stTxVLQueue), pstMember);
            memcpy(pstMember->m_pDataAddr, _pu8Data, _u32Len);
            pstMember = HIDO_VLQGetDequeueMember(&(l_astUartInfo[_eUartID].m_stTxVLQueue));
            HIDO_UnLock();
            uart_send(l_astUartInfo[_eUartID].m_eUartPort, pstMember->m_pDataAddr, pstMember->m_u32DataLen, uart_send_callback);
        }
    }
    else if (UART_TX_MODE_POLL == l_astUartInfo[_eUartID].m_eTxMode)
    {
        uart_send(l_astUartInfo[_eUartID].m_eUartPort, _pu8Data, _u32Len, NULL);
    }
#ifdef _USE_OS_
    osMutexRelease(l_astUartInfo[_eUartID].m_mutexLock);
#endif
    return i32Result;
}
HIDO_VOID HIDO_Lock(void)
{
    int_lock();
}
HIDO_VOID HIDO_UnLock(void)
{
    uint32_t lock = int_lock();
    int_unlock(lock);
}