#include "../Core/Include/ivec_mcal_uart.h" #include "string.h" #include "../../utils/utils.h" //#include "ivec_mcal_uart.h" #define LOG_STRING "ivec-mcal-uart" McalUartHandle_s* g_pxUartHandles[IVEC_MCAL_UART_MAX_PORT] = { 0 }; static uint32_t __gprv_u32DataCount = 0; static volatile uint8_t u8rxbuffer1 = 0; static McalUartPortNumber_e GetUartPort(UART_Regs* pxUartInstance); void UART_ReadCallback(UART_Regs* uart, uint8_t* buf, bool status) { if (status == true) { __gprv_u32DataCount += 1; IVEC_MCAL_LOG(LOG_STRING, "Uart Recv Callback:%d", ind_type); for (int i = 0;i < IVEC_MCAL_UART_MAX_PORT; i++) { if (g_pxUartHandles[i] != NULL) { if (g_pxUartHandles[i]->pvUartRecvCallback != NULL) g_pxUartHandles[i]->pvUartRecvCallback(GetUartPort(uart), IVEC_MCAL_UART_EVENT_RX_ARRIVED, (char*)buf, 1); break; } } } } void _prv_vrxcallback(UART_Regs* pxUartInstance, uint32_t event) { switch (event) { case DL_UART_MAIN_IIDX_RX: { uint8_t l_pu8Buffer[64] = { 0 }; // Adjust size as needed uint32_t bytesRead; // Drain the RX FIFO and store the data in buffer bytesRead = DL_UART_drainRXFIFO(pxUartInstance, l_pu8Buffer, sizeof(l_pu8Buffer)); DL_UART_clearInterruptStatus(pxUartInstance, DL_UART_MAIN_IIDX_RX); for (int ijk = 0; ijk < bytesRead; ijk++) UART_ReadCallback(pxUartInstance, &l_pu8Buffer[ijk], true); break; } case DL_UART_MAIN_IIDX_OVERRUN_ERROR: DL_UART_clearInterruptStatus(pxUartInstance, DL_UART_MAIN_IIDX_OVERRUN_ERROR); __asm("nop"); break; case DL_UART_MAIN_IIDX_BREAK_ERROR: DL_UART_clearInterruptStatus(pxUartInstance, DL_UART_MAIN_IIDX_BREAK_ERROR); __asm("nop"); break; case DL_UART_MAIN_IIDX_PARITY_ERROR: DL_UART_clearInterruptStatus(pxUartInstance, DL_UART_MAIN_IIDX_PARITY_ERROR); __asm("nop"); break; case DL_UART_MAIN_IIDX_FRAMING_ERROR: DL_UART_clearInterruptStatus(pxUartInstance, DL_UART_MAIN_IIDX_FRAMING_ERROR); __asm("nop"); break; case DL_UART_MAIN_IIDX_RX_TIMEOUT_ERROR: DL_UART_clearInterruptStatus(pxUartInstance, DL_UART_MAIN_IIDX_RX_TIMEOUT_ERROR); __asm("nop"); break; case DL_UART_MAIN_IIDX_NOISE_ERROR: DL_UART_clearInterruptStatus(pxUartInstance, DL_UART_MAIN_IIDX_NOISE_ERROR); __asm("nop"); break; default: break; } } void UART0_IRQHandler() { _prv_vrxcallback(UART0, DL_UART_Main_getPendingInterrupt(UART0)); } void UART1_IRQHandler() { _prv_vrxcallback(UART1, DL_UART_Main_getPendingInterrupt(UART1)); } void UART2_IRQHandler() { _prv_vrxcallback(UART2, DL_UART_Main_getPendingInterrupt(UART2)); } // Get the UART instance based on the enum static UART_Regs* GetUartInstance(McalUartPortNumber_e eUartPortNumber) { switch (eUartPortNumber) { case mcalUART_PORT1: return UART0; case mcalUART_PORT2: return UART1; case mcalUART_PORT3: return UART2; default: return NULL; // Invalid UART port } } static McalUartPortNumber_e GetUartPort(UART_Regs* pxUartInstance) { switch ((uint32_t)pxUartInstance) { case (uint32_t)UART0: return mcalUART_PORT1; case (uint32_t)UART1: return mcalUART_PORT2; case (uint32_t)UART2: return mcalUART_PORT3; default: return mcalUART_PORT_MAX; // Invalid UART port } } static xCoreStatus_t uart_deinit(McalUartHandle_s* pxUartHandle) { // Get the UART instance based on the port number in the handle UART_Regs* uart_inst = GetUartInstance(pxUartHandle->eUartPortNumber); // Check if the UART instance is valid if (uart_inst == NULL) { return STATUS_ERROR; } // Disable UART instance DL_UART_Main_disable(uart_inst); // Disable interrupts for the UART instance DL_UART_Main_disableInterrupt(uart_inst, DL_UART_MAIN_INTERRUPT_BREAK_ERROR | DL_UART_MAIN_INTERRUPT_FRAMING_ERROR | DL_UART_MAIN_INTERRUPT_NOISE_ERROR | DL_UART_MAIN_INTERRUPT_OVERRUN_ERROR | DL_UART_MAIN_INTERRUPT_PARITY_ERROR | DL_UART_MAIN_INTERRUPT_RX | DL_UART_MAIN_INTERRUPT_RX_TIMEOUT_ERROR); // Clear and disable NVIC interrupt requests based on UART instance if (uart_inst == UART0) { NVIC_DisableIRQ(UART0_INT_IRQn); NVIC_ClearPendingIRQ(UART0_INT_IRQn); // Reset the UART0 init flag if needed (b_UART0_init_flag = 0) } else if (uart_inst == UART1) { NVIC_DisableIRQ(UART1_INT_IRQn); NVIC_ClearPendingIRQ(UART1_INT_IRQn); // Reset the UART1 init flag if needed (b_UART1_init_flag = 0) } else if (uart_inst == UART2) { NVIC_DisableIRQ(UART2_INT_IRQn); NVIC_ClearPendingIRQ(UART2_INT_IRQn); // Reset the UART2 init flag if needed (b_UART2_init_flag = 0) } // Optionally, reset the UART clock configuration if needed DL_UART_Main_setClockConfig(uart_inst, NULL); return STATUS_SUCCESS; } /** * @brief Function to De-init UART Peripheral. * @warning Donot call if UART is not initilized earlier. * @param pxUartHandle pointer to \link McalUartHandle_s \endlink * @return \link IVEC_McalCommonErr_e \endlink returns a status based on the success or failure of the UART De-Init operation. */ IVEC_McalCommonErr_e xMCAL_UartDeInit(McalUartHandle_s* pxUartHandle) { int l_i32Ret; IVEC_MCAL_FUNC_ENTRY(LOG_STRING); IVEC_McalCommonErr_e l_xFuncStatus = commonMCAL_SUCCESS; if (pxUartHandle == NULL) { l_xFuncStatus = commonMCAL_INVALID_PARAM; goto exit; } l_i32Ret = uart_deinit(pxUartHandle); IVEC_MCAL_LOG(LOG_STRING, "DeInitilising UART status %d", l_i32Ret); if (l_i32Ret != STATUS_SUCCESS) { l_xFuncStatus = commonMCAL_DEINIT_FAIL; goto exit; } exit: IVEC_MCAL_FUNC_EXIT(LOG_STRING); return l_xFuncStatus; } /////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// static xCoreStatus_t uart_read(McalUartHandle_s* pxUartHandle, unsigned char* pucData) { // Get the UART instance based on the port number in the handle UART_Regs* uart_inst = GetUartInstance(pxUartHandle->eUartPortNumber); // Check if the UART instance is valid if (uart_inst == NULL) { return STATUS_ERROR; } bool status = false; uint32_t l_u32Tick = i32MCAL_getTicks(); while (!DL_UART_Main_isRXFIFOEmpty(uart_inst) && ((i32MCAL_getTicks() - l_u32Tick) < 50)) { *pucData = DL_UART_Main_receiveData(uart_inst); status = true; } //*pucData = DL_UART_receiveData(uart_inst); if (status == false) { return STATUS_ERROR; } return STATUS_SUCCESS; } /** * @brief Function to Read data at from UART Port * @pre UART should be initilized first. * @param [in] pxUartHandle pointer to \link McalUartHandle_s \endlink * @param [in] pucData pointer to unsigned char. Used to read data from UART. * @param [in] u32DataLength Length of the data to read. * @return \link IVEC_McalCommonErr_e \endlink returns a status based on the success or failure of the UART Read operation. */ IVEC_McalCommonErr_e xMCAL_UartRead(McalUartHandle_s* pxUartHandle, unsigned char* pucData, unsigned int u32DataLength) { int l_i32Ret; IVEC_MCAL_FUNC_ENTRY(LOG_STRING); IVEC_McalCommonErr_e l_xFuncStatus = commonMCAL_SUCCESS; if (pxUartHandle == NULL) { l_xFuncStatus = commonMCAL_INVALID_PARAM; goto exit; } l_i32Ret = uart_read(pxUartHandle, pucData); IVEC_MCAL_LOG(LOG_STRING, "Reading UART status %d", l_i32Ret); if (l_i32Ret == STATUS_ERROR) { l_xFuncStatus = commonMCAL_READ_FAIL; goto exit; } exit: IVEC_MCAL_FUNC_EXIT(LOG_STRING); return l_xFuncStatus; } /////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// static xCoreStatus_t uart_transmit(McalUartHandle_s* pxUartHandle, uint8_t* u8txdata, uint32_t u32size) { // Get the UART instance based on the port number in the handle UART_Regs* uart_inst = GetUartInstance(pxUartHandle->eUartPortNumber); // Check if the UART instance is valid if (uart_inst == NULL || u32size == 0) { return STATUS_ERROR; } uint32_t l_u32Tick = i32MCAL_getTicks(); for (int j = 0; j < u32size; j++) { DL_UART_transmitData(uart_inst, u8txdata[j]); while (DL_UART_isTXFIFOFull(uart_inst) && ((i32MCAL_getTicks() - l_u32Tick) < 100)); } return STATUS_SUCCESS; } /** * @brief Function to Write data at UART Port * @pre UART should be initilized first. * @param [in] pxUartHandle pointer to \link McalUartHandle_s \endlink * @param [in] pucData pointer to unsigned char. Used to send data to UART. * @param [in] u32DataLength Length of the Data that need to be write. * @return \link IVEC_McalCommonErr_e \endlink returns a status based on the success or failure of the UART Write operation. */ IVEC_McalCommonErr_e xMCAL_UartWrite(McalUartHandle_s* pxUartHandle, unsigned char* pucData, unsigned int u32DataLength) { int l_i32Ret; IVEC_MCAL_FUNC_ENTRY(LOG_STRING); IVEC_McalCommonErr_e l_xFuncStatus = commonMCAL_SUCCESS; if (pxUartHandle == NULL) { l_xFuncStatus = commonMCAL_INVALID_PARAM; goto exit; } l_i32Ret = uart_transmit(pxUartHandle, pucData, u32DataLength); IVEC_MCAL_LOG(LOG_STRING, "Writing UART status %d", l_i32Ret); if (l_i32Ret != STATUS_SUCCESS) { l_xFuncStatus = commonMCAL_WRITE_FAIL; goto exit; } exit: IVEC_MCAL_FUNC_EXIT(LOG_STRING); return l_xFuncStatus; } ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// static xCoreStatus_t uart_init(McalUartHandle_s* pxUartHandle, McalUartBaudRate_e xBaud) { if (pxUartHandle->eUartPortNumber== mcalUART_PORT2) { DL_UART_Main_reset(UART1); DL_UART_Main_enablePower(UART1); DL_GPIO_initPeripheralOutputFunction(IOMUX_PINCM19, IOMUX_PINCM19_PF_UART1_TX); DL_GPIO_initPeripheralInputFunction(IOMUX_PINCM20, IOMUX_PINCM20_PF_UART1_RX); } else if (pxUartHandle->eUartPortNumber== mcalUART_PORT3) { DL_UART_Main_reset(UART2); DL_UART_Main_enablePower(UART2); DL_GPIO_initPeripheralOutputFunction(IOMUX_PINCM32, IOMUX_PINCM32_PF_UART2_TX); DL_GPIO_initPeripheralInputFunction(IOMUX_PINCM33, IOMUX_PINCM33_PF_UART2_RX); } // Get the UART instance based on the port number in the handle UART_Regs* uart_inst = GetUartInstance(pxUartHandle->eUartPortNumber); // Check if the UART instance is valid if (uart_inst == NULL) { return STATUS_ERROR; } DL_UART_Config xprvUartConfig = { 0 }; xprvUartConfig.direction = DL_UART_MAIN_DIRECTION_TX_RX; xprvUartConfig.mode = DL_UART_MAIN_MODE_NORMAL; //xprvUartConfig.wordLength = pxUartHandle->xUartConfig.eUartDataBit; uint8_t datalength = pxUartHandle->xUartConfig.eUartDataBit; if (datalength == mcalUART_DATABIT_7) { xprvUartConfig.wordLength = DL_UART_WORD_LENGTH_7_BITS; } else if (datalength == mcalUART_DATABIT_8) { xprvUartConfig.wordLength = DL_UART_WORD_LENGTH_8_BITS; } //xprvUartConfig.stopBits = pxUartHandle->xUartConfig.eUartStopBit; uint8_t stopbit = pxUartHandle->xUartConfig.eUartStopBit; if (stopbit == mcalUART_STOP_1) { xprvUartConfig.stopBits = DL_UART_STOP_BITS_ONE; } else if (stopbit == mcalUART_STOP_2) { xprvUartConfig.stopBits = DL_UART_STOP_BITS_TWO; } //xprvUartConfig.parity = pxUartHandle->xUartConfig.eUartParityBit; uint8_t paritybit = pxUartHandle->xUartConfig.eUartParityBit; if (paritybit == mcalUART_PARITY_NONE) { xprvUartConfig.parity = DL_UART_PARITY_NONE; } else if (paritybit == mcalUART_PARITY_ODD) { xprvUartConfig.parity = DL_UART_PARITY_ODD; } else if (paritybit == mcalUART_PARITY_EVEN) { xprvUartConfig.parity = DL_UART_PARITY_EVEN; } xprvUartConfig.flowControl = DL_UART_FLOW_CONTROL_NONE; DL_UART_ClockConfig gUART_0ClockConfig = { 0 }; gUART_0ClockConfig.clockSel = DL_UART_CLOCK_BUSCLK; gUART_0ClockConfig.divideRatio = DL_UART_MAIN_CLOCK_DIVIDE_RATIO_1; DL_UART_Main_setClockConfig(uart_inst, (DL_UART_Main_ClockConfig*)&gUART_0ClockConfig); DL_UART_Main_init(uart_inst, (DL_UART_Main_Config*)&xprvUartConfig); /* Configure baud rate by setting oversampling and baud rate divisors.*/ DL_UART_Main_setOversampling(uart_inst, DL_UART_OVERSAMPLING_RATE_16X); if (xBaud == 115200) { /* * Target baud rate: 115200 * Actual baud rate: 115211.52 */ // DL_UART_Main_setBaudRateDivisor(uart_inst, 13, 1); //DL_UART_Main_setBaudRateDivisor(uart_inst, 19, 20); DL_UART_Main_setBaudRateDivisor(uart_inst, 19, 34); } else if (xBaud == 9600) { DL_UART_Main_setBaudRateDivisor(uart_inst, 234, 24); } else if (xBaud == 2400) { DL_UART_Main_setBaudRateDivisor(uart_inst, 937, 32); } else if (xBaud == 4800) { DL_UART_Main_setBaudRateDivisor(uart_inst, 468, 48); } else if (xBaud == 14400) { DL_UART_Main_setBaudRateDivisor(uart_inst, 156, 16); } else if (xBaud == 19200) { DL_UART_Main_setBaudRateDivisor(uart_inst, 117, 12); } else if (xBaud == 28800) { DL_UART_Main_setBaudRateDivisor(uart_inst, 78, 8); } else if (xBaud == 33600) { DL_UART_Main_setBaudRateDivisor(uart_inst, 66, 62); } else if (xBaud == 38400) { DL_UART_Main_setBaudRateDivisor(uart_inst, 58, 38); } else if (xBaud == 57600) { DL_UART_Main_setBaudRateDivisor(uart_inst, 39, 4); } else if (xBaud == 230400) { DL_UART_Main_setBaudRateDivisor(uart_inst, 9, 49); } else if (xBaud == 460800) { DL_UART_Main_setBaudRateDivisor(uart_inst, 4, 57); } else if (xBaud == 921600) { DL_UART_Main_setBaudRateDivisor(uart_inst, 2, 28); } else if (xBaud == 1000000) { DL_UART_Main_setBaudRateDivisor(uart_inst, 2, 16); } else { /* * Target baud rate: 115200 * Actual baud rate: 115211.52 */ DL_UART_Main_setBaudRateDivisor(uart_inst, 13, 1); } /* Configure Interrupts */ if (uart_inst == UART0) { DL_UART_Main_enableInterrupt(uart_inst, DL_UART_MAIN_INTERRUPT_BREAK_ERROR | DL_UART_MAIN_INTERRUPT_FRAMING_ERROR | DL_UART_MAIN_INTERRUPT_NOISE_ERROR | DL_UART_MAIN_INTERRUPT_OVERRUN_ERROR | DL_UART_MAIN_INTERRUPT_PARITY_ERROR | DL_UART_MAIN_INTERRUPT_RX | DL_UART_MAIN_INTERRUPT_RX_TIMEOUT_ERROR); DL_UART_Main_enableFIFOs(UART0); DL_UART_Main_setRXFIFOThreshold(UART0, DL_UART_RX_FIFO_LEVEL_ONE_ENTRY); DL_UART_Main_setTXFIFOThreshold(UART0, DL_UART_TX_FIFO_LEVEL_1_2_EMPTY); DL_UART_Main_enable(uart_inst); /*Clearing and Enabling Interrupt Requests*/ NVIC_ClearPendingIRQ(UART0_INT_IRQn); NVIC_EnableIRQ(UART0_INT_IRQn); //b_UART0_init_flag=1; } if (uart_inst == UART1) { DL_UART_Main_enableInterrupt(uart_inst, DL_UART_MAIN_INTERRUPT_BREAK_ERROR | DL_UART_MAIN_INTERRUPT_FRAMING_ERROR | DL_UART_MAIN_INTERRUPT_NOISE_ERROR | DL_UART_MAIN_INTERRUPT_OVERRUN_ERROR | DL_UART_MAIN_INTERRUPT_PARITY_ERROR | DL_UART_MAIN_INTERRUPT_RX | DL_UART_MAIN_INTERRUPT_RX_TIMEOUT_ERROR); DL_UART_Main_enableFIFOs(UART1); DL_UART_Main_setRXFIFOThreshold(UART1, DL_UART_RX_FIFO_LEVEL_ONE_ENTRY); DL_UART_Main_setTXFIFOThreshold(UART1, DL_UART_TX_FIFO_LEVEL_1_2_EMPTY); DL_UART_Main_enable(uart_inst); /*Clearing and Enabling Interrupt Requests*/ NVIC_ClearPendingIRQ(UART1_INT_IRQn); NVIC_EnableIRQ(UART1_INT_IRQn); //b_UART1_init_flag=1; } else if (uart_inst == UART2) { DL_UART_Main_enableInterrupt(uart_inst, DL_UART_MAIN_INTERRUPT_BREAK_ERROR | DL_UART_MAIN_INTERRUPT_FRAMING_ERROR | DL_UART_MAIN_INTERRUPT_NOISE_ERROR | DL_UART_MAIN_INTERRUPT_OVERRUN_ERROR | DL_UART_MAIN_INTERRUPT_PARITY_ERROR | DL_UART_MAIN_INTERRUPT_RX | DL_UART_MAIN_INTERRUPT_RX_TIMEOUT_ERROR); DL_UART_Main_enableFIFOs(UART2); DL_UART_Main_setRXFIFOThreshold(UART2, DL_UART_RX_FIFO_LEVEL_ONE_ENTRY); DL_UART_Main_setTXFIFOThreshold(UART2, DL_UART_TX_FIFO_LEVEL_1_2_EMPTY); // DL_UART_Main_setRXInterruptTimeout(UART2, 15); DL_UART_Main_enable(uart_inst); /*Clearing and Enabling Interrupt Requests*/ NVIC_ClearPendingIRQ(UART2_INT_IRQn); NVIC_EnableIRQ(UART2_INT_IRQn); } return STATUS_SUCCESS;//TODO: FIX RETURN BUG } /** * @brief Function to trigger the UART interrupt that is configured in the function pointer pvUartRecvCallback in \link McalUartHandle_s \endlink handle. * @param [in] ind_type This is used as indication to the uart callback function. See \link IVEC_McalUartEvents_e \endlink * @param [in] port UART Port number. * @param [in] size Size of Data. * @return nothing. */ #if 0 static void __prvMCAL_UartNotifyRecvCb(uint32 ind_type, ql_uart_port_number_e port, uint32 size) { IVEC_MCAL_LOG(LOG_STRING, "Uart Recv Callback:%d", ind_type); for (int i = 0;i < IVEC_MCAL_UART_MAX_PORT; i++) { if (g_pxUartHandles[i] != NULL && port == (ql_uart_port_number_e)g_pxUartHandles[i]->eUartPortNumber) { if (g_pxUartHandles[i]->pvUartRecvCallback != NULL) g_pxUartHandles[i]->pvUartRecvCallback((IVEC_McalUartEvents_e)ind_type & 0xffff, NULL, size); break; } } } #endif /** * @brief Function to register UART handle used for registering UART receive callback fucntion. * @warning This is a private function. It should not be call outside the file \link ivec_mcal_uart.c \endlink. * @param pxUartHandle pointer to \link McalUartHandle_s \endlink * @return Nothing */ static void __prvMCAL_UartRegisterHandle(McalUartHandle_s* pxUartHandle) { g_pxUartHandles[pxUartHandle->eUartPortNumber] = pxUartHandle; } /** * @brief Function to Init UART peripheral * @pre Need to configure UART configuration/properties in \link McalUartHandle_s \endlink * @param pxUartHandle pointer to \link McalUartHandle_s \endlink * @return \link IVEC_McalCommonErr_e \endlink returns a status based on the success or failure of the UART Init operation. */ IVEC_McalCommonErr_e xMCAL_UartInit(McalUartHandle_s* pxUartHandle) { IVEC_MCAL_FUNC_ENTRY(LOG_STRING); IVEC_McalCommonErr_e l_xFuncStatus = commonMCAL_SUCCESS; if (pxUartHandle == NULL) { l_xFuncStatus = commonMCAL_INVALID_PARAM; goto exit; } __prvMCAL_UartRegisterHandle(pxUartHandle); int l_i32Ret = uart_init(pxUartHandle, pxUartHandle->xUartConfig.eUartBaudrate); if (l_i32Ret != STATUS_SUCCESS) { l_xFuncStatus = commonMCAL_INIT_FAIL; goto exit; } exit: IVEC_MCAL_FUNC_EXIT(LOG_STRING); return l_xFuncStatus; }