chg-stn-motherboard-ti-mcu/Core/Source/ivec_mcal_uart.c

620 lines
20 KiB
C

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