/******************************************************************************* * 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 #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 = true, .int_rx = false, .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); }