838 lines
29 KiB
C
838 lines
29 KiB
C
/*
|
|
* ivec_mcal_uart.c
|
|
*
|
|
* Created on: 28-Oct-2024
|
|
* Author: altam
|
|
*/
|
|
#include "../Core/Include/ivec_mcal_uart.h"
|
|
#include "string.h"
|
|
#include "../../utils/utils.h"
|
|
#define LOG_STRING "ivec-mcal-uart"
|
|
|
|
/* Global UART Handles Array */
|
|
static IVEC_McalUartHandle_s* __gprv_pIVEC_McalUartHandle_ss[IVEC_MCAL_UART_PORT_MAX] = { 0 };
|
|
|
|
/* Static Variables */
|
|
static uint32_t __gprv_u32DataCount = 0; /* Data count for tracking received bytes */
|
|
|
|
/* Static Function Prototypes */
|
|
static IVEC_McalUartPort_e __prv_McalGetUartPort(UART_Regs* pxUartInstance);
|
|
|
|
/**
|
|
* @brief UART read callback function.
|
|
*
|
|
* This function is triggered upon receiving data via UART. It increments a data
|
|
* counter, logs the reception event, and invokes the appropriate user-defined
|
|
* callback for handling the received data.
|
|
*
|
|
* @param[in] pxUartInstance Pointer to the UART instance triggering the callback.
|
|
* @param[in] pu8Buffer Pointer to the buffer containing the received data.
|
|
* @param[in] bStatus Boolean indicating the success of the receive operation:
|
|
* - `true`: Data received successfully.
|
|
* - `false`: Data reception failed.
|
|
*
|
|
* @details
|
|
* - If `bStatus` is true:
|
|
* 1. Increments the `prv_u32DataCount` variable to track received data events.
|
|
* 2. Logs the data count using the `IVEC_MCAL_LOG` macro.
|
|
* 3. Iterates through `gpIVEC_McalUartHandle_ss` to find a valid UART handle.
|
|
* 4. If a valid user-defined receive callback (`pvUartRecvCallback`) is found,
|
|
* it is invoked with the received data.
|
|
* - If `bStatus` is false, the function performs no additional operations.
|
|
*/
|
|
|
|
void vMCAL_UartReadCallback(UART_Regs* pxUartInstance, uint8_t* pu8Buffer, bool bStatus)
|
|
{
|
|
if (bStatus)
|
|
{
|
|
__gprv_u32DataCount++;
|
|
|
|
IVEC_MCAL_LOG(LOG_STRING, "UART Receive Callback: %d", prv_u32DataCount);
|
|
|
|
for (uint32_t i = 0; i < IVEC_MCAL_UART_PORT_MAX; i++)
|
|
{
|
|
if (__gprv_pIVEC_McalUartHandle_ss[i] != NULL)
|
|
{
|
|
if (__gprv_pIVEC_McalUartHandle_ss[i]->pvUartRecvCallback != NULL)
|
|
{
|
|
__gprv_pIVEC_McalUartHandle_ss[i]->pvUartRecvCallback(__prv_McalGetUartPort(pxUartInstance),IVEC_MCAL_UART_EVENT_RX_ARRIVED,(char*)pu8Buffer,1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* @brief Handles UART RX events and errors.
|
|
*
|
|
* Processes received data, clears interrupt flags, and handles specific
|
|
* error conditions such as overrun, framing, and parity errors.
|
|
*
|
|
* @param[in] pxUartInstance Pointer to the UART instance triggering the callback.
|
|
* @param[in] u32Event Event type indicating the RX or error condition.
|
|
*/
|
|
|
|
|
|
void prv_vRxCallback(UART_Regs* pxUartInstance, uint32_t u32Event)
|
|
{
|
|
switch (u32Event)
|
|
{
|
|
case DL_UART_MAIN_IIDX_RX:
|
|
{
|
|
uint8_t u8RxBuffer[64] = { 0 }; // Adjust size as needed
|
|
uint32_t u32BytesRead = 0;
|
|
|
|
// Drain the RX FIFO and store the data in buffer
|
|
u32BytesRead = DL_UART_drainRXFIFO(pxUartInstance, u8RxBuffer, sizeof(u8RxBuffer));
|
|
|
|
// Clear the RX interrupt flag
|
|
DL_UART_clearInterruptStatus(pxUartInstance, DL_UART_MAIN_IIDX_RX);
|
|
|
|
// Process each byte of received data
|
|
for (uint32_t u32Index = 0; u32Index < u32BytesRead; u32Index++)
|
|
{
|
|
vMCAL_UartReadCallback(pxUartInstance, &u8RxBuffer[u32Index], 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));
|
|
}
|
|
|
|
void UART3_IRQHandler()
|
|
{
|
|
prv_vRxCallback(UART3, DL_UART_Main_getPendingInterrupt(UART3));
|
|
}
|
|
|
|
/**
|
|
* @brief Retrieves the UART instance for the specified port number.
|
|
*
|
|
* Maps a UART port number to its corresponding hardware instance.
|
|
*
|
|
* @param[in] eUartPortNumber UART port number to retrieve the instance for.
|
|
* @return Pointer to the UART instance, or `eMcalUartPortMax` for invalid input.
|
|
*/
|
|
|
|
static UART_Regs* __prv_McalGetUartInstance(IVEC_McalUartPort_e eUartPortNumber)
|
|
{
|
|
switch (eUartPortNumber)
|
|
{
|
|
case IVEC_MCAL_UART_PORT_1:
|
|
return UART0;
|
|
case IVEC_MCAL_UART_PORT_2:
|
|
return UART1;
|
|
case IVEC_MCAL_UART_PORT_3:
|
|
return UART2;
|
|
case IVEC_MCAL_UART_PORT_4:
|
|
return UART3;
|
|
default:
|
|
return NULL; // Invalid UART port
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Maps UART instance to a corresponding port number.
|
|
*
|
|
* Returns the appropriate `eMcalUartPortNumber` based on the given UART
|
|
* instance. If the instance is not recognized, returns `eMcalUartPortMax`.
|
|
*
|
|
* @param[in] pxUartInstance Pointer to the UART instance.
|
|
* @return Corresponding `eMcalUartPortNumber` or `eMcalUartPortMax` if invalid.
|
|
*/
|
|
|
|
static IVEC_McalUartPort_e __prv_McalGetUartPort(UART_Regs* pxUartInstance)
|
|
{
|
|
switch ((uint32_t)pxUartInstance)
|
|
{
|
|
case (uint32_t)UART0:
|
|
return IVEC_MCAL_UART_PORT_1;
|
|
case (uint32_t)UART1:
|
|
return IVEC_MCAL_UART_PORT_2;
|
|
case (uint32_t)UART2:
|
|
return IVEC_MCAL_UART_PORT_3;
|
|
case (uint32_t)UART3:
|
|
return IVEC_MCAL_UART_PORT_4;
|
|
default:
|
|
return IVEC_MCAL_UART_PORT_MAX; // Invalid UART port
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Deinitializes a UART instance.
|
|
*
|
|
* Disables the specified UART instance, clears interrupt flags, and disables
|
|
* interrupt requests. Optionally resets the UART clock configuration.
|
|
*
|
|
* @param[in] pxUartHandle Pointer to the UART handle containing the port number.
|
|
* @return `IVEC_CORE_STATUS_SUCCESS` if deinitialization is successful,
|
|
* `IVEC_CORE_STATUS_ERROR` if the UART instance is invalid.
|
|
*/
|
|
|
|
static IVEC_McalCommonErr_e _prvMCAL_UartDeInitInstance(IVEC_McalUartHandle_s* pxUartHandle)
|
|
{
|
|
// Get the UART instance based on the port number in the handle
|
|
UART_Regs* pxUartInstance = __prv_McalGetUartInstance(pxUartHandle->eUartPortNumber);
|
|
|
|
// Check if the UART instance is valid
|
|
if (pxUartInstance == NULL)
|
|
{
|
|
return commonMCAL_INVALID_PARAM;
|
|
}
|
|
|
|
// Disable UART instance
|
|
DL_UART_Main_disable(pxUartInstance );
|
|
|
|
// Disable interrupts for the UART instance
|
|
DL_UART_Main_disableInterrupt(pxUartInstance ,
|
|
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 (pxUartInstance == 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 (pxUartInstance == 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 (pxUartInstance == UART2)
|
|
{
|
|
NVIC_DisableIRQ(UART2_INT_IRQn);
|
|
NVIC_ClearPendingIRQ(UART2_INT_IRQn);
|
|
// Reset the UART2 init flag if needed (b_UART2_init_flag = 0)
|
|
}
|
|
else if (pxUartInstance == UART3)
|
|
{
|
|
NVIC_DisableIRQ(UART3_INT_IRQn);
|
|
NVIC_ClearPendingIRQ(UART3_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(pxUartInstance, NULL);
|
|
|
|
return commonMCAL_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Deinitializes the specified UART instance.
|
|
*
|
|
* This function validates the UART handle and port, then calls a private function
|
|
* to deinitialize the UART instance. It logs the status and returns an error code
|
|
* if the deinitialization fails.
|
|
*
|
|
* @param[in] pxUartHandle Pointer to the UART handle containing the port number.
|
|
* @return `commonMCAL_SUCCESS` if deinitialization is successful,
|
|
* `commonMCAL_INVALID_PARAM` if the input parameters are invalid,
|
|
* `commonMCAL_DEINIT_FAIL` if deinitialization fails.
|
|
*/
|
|
|
|
IVEC_McalCommonErr_e xMCAL_UartDeInit(IVEC_McalUartHandle_s* pxUartHandle)
|
|
{
|
|
if (pxUartHandle == NULL || pxUartHandle->eUartPortNumber >= IVEC_MCAL_UART_PORT_MAX)
|
|
{
|
|
return commonMCAL_INIT_FAIL;
|
|
}
|
|
|
|
IVEC_McalCommonErr_e xRetStatus;
|
|
IVEC_MCAL_FUNC_ENTRY(LOG_STRING);
|
|
IVEC_McalCommonErr_e eFuncStatus = commonMCAL_SUCCESS;
|
|
|
|
// Check for null pointer
|
|
if (pxUartHandle == NULL)
|
|
{
|
|
eFuncStatus = commonMCAL_INVALID_PARAM;
|
|
goto exit;
|
|
}
|
|
|
|
// Call the private deinit function
|
|
xRetStatus = _prvMCAL_UartDeInitInstance(pxUartHandle);
|
|
IVEC_MCAL_LOG(LOG_STRING, "Deinitializing UART status: %d", xRetStatus);
|
|
|
|
// Check the return status
|
|
if (xRetStatus != commonMCAL_SUCCESS)
|
|
{
|
|
eFuncStatus = commonMCAL_DEINIT_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
IVEC_MCAL_FUNC_EXIT(LOG_STRING);
|
|
return eFuncStatus;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* @brief Reads a byte of data from the UART port.
|
|
*
|
|
* This function attempts to read a single byte of data from the specified UART
|
|
* instance. It waits until data is received or a timeout occurs. If no data is
|
|
* received within the timeout, it returns an error.
|
|
*
|
|
* @param[in] pxUartHandle Pointer to the UART handle containing the port number.
|
|
* @param[out] pucData Pointer to the buffer where the received data will be stored.
|
|
* @return `commonMCAL_SUCCESS` if the data is read successfully,
|
|
* `commonMCAL_FAIL` if no data was received or an error occurred.
|
|
*/
|
|
|
|
static IVEC_McalCommonErr_e __prv_McalUartReadByte(IVEC_McalUartHandle_s* pxUartHandle, uint8_t* pucData)
|
|
{
|
|
/* Get the UART instance based on the port number in the handle */
|
|
UART_Regs* pUartInstance = __prv_McalGetUartInstance(pxUartHandle->eUartPortNumber);
|
|
|
|
/* Check if the UART instance is valid */
|
|
if (pUartInstance == NULL)
|
|
{
|
|
return commonMCAL_FAIL;
|
|
}
|
|
|
|
bool bDataReceived = false;
|
|
uint32_t u32StartTick = i32MCAL_getTicks();
|
|
|
|
/* Wait until data is received or timeout occurs */
|
|
while (!DL_UART_isTXFIFOEmpty(pUartInstance) &&
|
|
((i32MCAL_getTicks() - u32StartTick) < 50))
|
|
{
|
|
*pucData = DL_UART_Main_receiveData(pUartInstance);
|
|
bDataReceived = true;
|
|
}
|
|
|
|
/* Return error if no data was received */
|
|
if (!bDataReceived)
|
|
{
|
|
return commonMCAL_FAIL;
|
|
}
|
|
|
|
return commonMCAL_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Reads multiple bytes of data from the UART port.
|
|
*
|
|
* This function validates the UART handle, attempts to read data from the UART port,
|
|
* and returns the appropriate status. If the UART handle is invalid or the read
|
|
* operation fails, it returns an error status.
|
|
*
|
|
* @param[in] pxUartHandle Pointer to the UART handle containing the port number.
|
|
* @param[out] pucData Pointer to the buffer where the received data will be stored.
|
|
* @param[in] u32DataLength The length of data to read.
|
|
* @return `commonMCAL_INIT_FAIL` if the UART handle is invalid,
|
|
* `commonMCAL_INVALID_PARAM` if input parameters are incorrect,
|
|
* `commonMCAL_FAIL` if the read operation fails.
|
|
*/
|
|
IVEC_McalCommonErr_e xMCAL_UartRead(IVEC_McalUartHandle_s* pxUartHandle, uint8_t* pucData, uint32_t u32DataLength)
|
|
{
|
|
if (pxUartHandle == NULL || pxUartHandle->eUartPortNumber >= IVEC_MCAL_UART_PORT_MAX)
|
|
{
|
|
return commonMCAL_INIT_FAIL;
|
|
}
|
|
int32_t i32RetVal;
|
|
IVEC_McalCommonErr_e eFuncStatus = commonMCAL_SUCCESS;
|
|
|
|
IVEC_MCAL_FUNC_ENTRY(LOG_STRING);
|
|
|
|
/* Validate the UART handle */
|
|
if (pxUartHandle == NULL)
|
|
{
|
|
eFuncStatus = commonMCAL_INVALID_PARAM;
|
|
goto exit;
|
|
}
|
|
|
|
/* Attempt to read a single byte from UART */
|
|
i32RetVal = __prv_McalUartReadByte(pxUartHandle, pucData);
|
|
|
|
/* Log the read operation status */
|
|
IVEC_MCAL_LOG(LOG_STRING, "UART read status: %d", i32RetVal);
|
|
|
|
/* Check if the read operation failed */
|
|
if (i32RetVal == commonMCAL_SUCCESS)
|
|
{
|
|
eFuncStatus = commonMCAL_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
IVEC_MCAL_FUNC_EXIT(LOG_STRING);
|
|
return eFuncStatus;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* @brief Transmits data over the specified UART port.
|
|
*
|
|
* This function writes a specified number of bytes to the UART port, checking for
|
|
* transmission timeout. If the transmission is successful, it returns a success
|
|
* status, otherwise, it returns an error.
|
|
*
|
|
* @param[in] pxUartHandle Pointer to the UART handle containing the port number.
|
|
* @param[in] pu8TxData Pointer to the buffer containing the data to transmit.
|
|
* @param[in] u32Size Number of bytes to transmit.
|
|
* @return `IVEC_CORE_STATUS_SUCCESS` if data is transmitted successfully,
|
|
* `IVEC_CORE_STATUS_ERROR` if an error occurs.
|
|
*/
|
|
static IVEC_McalCommonErr_e __prv_McalUartTransmit(IVEC_McalUartHandle_s* pxUartHandle, uint8_t* pu8TxData, uint32_t u32Size)
|
|
{
|
|
/* Retrieve UART instance based on the port number */
|
|
UART_Regs* pxUartInstance = __prv_McalGetUartInstance(pxUartHandle->eUartPortNumber);
|
|
|
|
/* Validate the UART instance and data size */
|
|
if (pxUartInstance == NULL || u32Size == 0)
|
|
{
|
|
return commonMCAL_INVALID_PARAM;
|
|
}
|
|
|
|
/* Track transmission timeout */
|
|
uint32_t u32TickStart = i32MCAL_getTicks();
|
|
for (uint32_t u32Index = 0; u32Index < u32Size; u32Index++)
|
|
{
|
|
/* Transmit data byte */
|
|
DL_UART_transmitData(pxUartInstance, pu8TxData[u32Index]);
|
|
|
|
/* Wait for TX FIFO to become available, with timeout */
|
|
while (DL_UART_isTXFIFOFull(pxUartInstance) &&
|
|
((i32MCAL_getTicks() - u32TickStart) < 100));
|
|
}
|
|
|
|
return commonMCAL_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Writes data to the UART port.
|
|
*
|
|
* This function validates the UART handle, checks if the UART is initialized, and
|
|
* calls the static function to transmit data. It logs the status and handles errors
|
|
* related to the UART transmission.
|
|
*
|
|
* @param[in] pxUartHandle Pointer to the UART handle structure.
|
|
* @param[in] pu8Data Pointer to the data buffer to send.
|
|
* @param[in] u32DataLength Length of the data to be sent.
|
|
* @return `commonMCAL_INIT_FAIL` if the UART handle is invalid,
|
|
* `commonMCAL_INVALID_PARAM` if input parameters are invalid,
|
|
* `commonMCAL_WRITE_FAIL` if the write operation fails.
|
|
*/
|
|
IVEC_McalCommonErr_e xMCAL_UartWrite(IVEC_McalUartHandle_s* pxUartHandle, uint8_t* pu8Data, uint32_t u32DataLength)
|
|
{
|
|
if (pxUartHandle == NULL || pxUartHandle->eUartPortNumber >= IVEC_MCAL_UART_PORT_MAX)
|
|
{
|
|
return commonMCAL_INIT_FAIL;
|
|
}
|
|
|
|
IVEC_McalCommonErr_e eFuncStatus = commonMCAL_SUCCESS;
|
|
int32_t i32Ret;
|
|
|
|
/* Log function entry */
|
|
IVEC_MCAL_FUNC_ENTRY(LOG_STRING);
|
|
|
|
/* Validate input parameters */
|
|
if (pxUartHandle == NULL)
|
|
{
|
|
eFuncStatus = commonMCAL_INVALID_PARAM;
|
|
goto exit;
|
|
}
|
|
|
|
/* Call static transmit function */
|
|
i32Ret = __prv_McalUartTransmit(pxUartHandle, pu8Data, u32DataLength);
|
|
|
|
/* Log transmit status */
|
|
IVEC_MCAL_LOG(LOG_STRING, "UART write status: %d", i32Ret);
|
|
|
|
/* Handle transmit errors */
|
|
if (i32Ret != IVEC_CORE_STATUS_SUCCESS)
|
|
{
|
|
eFuncStatus = commonMCAL_WRITE_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
/* Log function exit */
|
|
IVEC_MCAL_FUNC_EXIT(LOG_STRING);
|
|
return eFuncStatus;
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
* @brief Initializes a UART instance based on the given configuration.
|
|
*
|
|
* This function configures the specified UART port by initializing the
|
|
* required GPIO pins for TX and RX, configuring the UART settings such
|
|
* as baud rate, word length, stop bits, parity, and clock settings.
|
|
* It also enables interrupts for error handling and sets FIFO thresholds
|
|
* for efficient data transmission and reception.
|
|
*
|
|
* @param [in] pxUartHandle Pointer to a structure that holds the UART
|
|
* configuration parameters.
|
|
* @param [in] xBaud The desired baud rate for the UART communication.
|
|
* Supported values include various baud rates like
|
|
* 115200, 9600, 2400, etc.
|
|
*
|
|
* @return IVEC_CoreStatus_e Returns `commonMCAL_SUCCESS` if initialization
|
|
* was successful, otherwise returns `commonMCAL_FAIL` in case of errors.
|
|
*/
|
|
|
|
|
|
static IVEC_McalCommonErr_e __prv_McalUartInitInstance(IVEC_McalUartHandle_s* pxUartHandle, IVEC_McalUartBaudRate_e xBaud)
|
|
{
|
|
if (pxUartHandle->eUartPortNumber == IVEC_MCAL_UART_PORT_2)
|
|
{
|
|
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 == IVEC_MCAL_UART_PORT_3)
|
|
{
|
|
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);
|
|
|
|
}
|
|
else if (pxUartHandle->eUartPortNumber == IVEC_MCAL_UART_PORT_4)
|
|
{
|
|
DL_UART_Main_reset(UART3);
|
|
DL_UART_Main_enablePower(UART3);
|
|
DL_GPIO_initPeripheralOutputFunction(IOMUX_PINCM36, IOMUX_PINCM36_PF_UART3_TX);
|
|
DL_GPIO_initPeripheralInputFunction(IOMUX_PINCM35, IOMUX_PINCM35_PF_UART3_RX);
|
|
}
|
|
|
|
UART_Regs* pxUartInstance = __prv_McalGetUartInstance(pxUartHandle->eUartPortNumber);
|
|
|
|
if (pxUartInstance == NULL)
|
|
{
|
|
return commonMCAL_FAIL;
|
|
}
|
|
|
|
DL_UART_Config xUartConfig = { 0 };
|
|
xUartConfig.direction = DL_UART_MAIN_DIRECTION_TX_RX;
|
|
xUartConfig.mode = DL_UART_MAIN_MODE_NORMAL;
|
|
|
|
uint8_t u8DataLength = pxUartHandle->xUartConfig.eUartDataBit;
|
|
if (u8DataLength == IVEC_MCAL_UART_DATA_BIT_7)
|
|
{
|
|
xUartConfig.wordLength = DL_UART_WORD_LENGTH_7_BITS;
|
|
}
|
|
else if (u8DataLength == IVEC_MCAL_UART_DATA_BIT_8)
|
|
{
|
|
xUartConfig.wordLength = DL_UART_WORD_LENGTH_8_BITS;
|
|
}
|
|
|
|
uint8_t u8StopBit = pxUartHandle->xUartConfig.eUartStopBit;
|
|
if (u8StopBit == IVEC_MCAL_UART_STOP_BIT_1)
|
|
{
|
|
xUartConfig.stopBits = DL_UART_STOP_BITS_ONE;
|
|
}
|
|
else if (u8StopBit == IVEC_MCAL_UART_STOP_BIT_2)
|
|
{
|
|
xUartConfig.stopBits = DL_UART_STOP_BITS_TWO;
|
|
}
|
|
|
|
uint8_t u8ParityBit = pxUartHandle->xUartConfig.eUartParityBit;
|
|
if (u8ParityBit == IVEC_MCAL_UART_PARITY_NONE)
|
|
{
|
|
xUartConfig.parity = DL_UART_PARITY_NONE;
|
|
}
|
|
else if (u8ParityBit == IVEC_MCAL_UART_PARITY_ODD)
|
|
{
|
|
xUartConfig.parity = DL_UART_PARITY_ODD;
|
|
}
|
|
else if (u8ParityBit == IVEC_MCAL_UART_PARITY_EVEN)
|
|
{
|
|
xUartConfig.parity = DL_UART_PARITY_EVEN;
|
|
}
|
|
|
|
xUartConfig.flowControl = DL_UART_FLOW_CONTROL_NONE;
|
|
|
|
DL_UART_ClockConfig xUartClockConfig = { 0 };
|
|
xUartClockConfig.clockSel = DL_UART_CLOCK_BUSCLK;
|
|
xUartClockConfig.divideRatio = DL_UART_MAIN_CLOCK_DIVIDE_RATIO_1;
|
|
|
|
DL_UART_Main_setClockConfig(pxUartInstance, (DL_UART_Main_ClockConfig*) &xUartClockConfig);
|
|
DL_UART_Main_init(pxUartInstance, (DL_UART_Main_Config*) &xUartConfig);
|
|
|
|
DL_UART_Main_setOversampling(pxUartInstance, DL_UART_OVERSAMPLING_RATE_16X);
|
|
|
|
|
|
if (xBaud == IVEC_MCAL_UART_BAUD_115200)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 19, 34);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_9600)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 234, 24);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_2400)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 937, 32);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_4800)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 468, 48);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_14400)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 156, 16);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_19200)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 117, 12);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_28800)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 78, 8);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_33600)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 66, 62);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_38400)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 58, 38);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_57600)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 39, 4);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_230400)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 9, 49);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_460800)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 4, 57);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_921600)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 2, 28);
|
|
}
|
|
else if (xBaud == IVEC_MCAL_UART_BAUD_1000000)
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 2, 16);
|
|
}
|
|
else
|
|
{
|
|
DL_UART_Main_setBaudRateDivisor(pxUartInstance, 13, 1);
|
|
}
|
|
|
|
if (pxUartInstance == UART0)
|
|
{
|
|
DL_UART_Main_enableInterrupt(pxUartInstance,
|
|
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(pxUartInstance);
|
|
NVIC_ClearPendingIRQ(UART0_INT_IRQn);
|
|
NVIC_EnableIRQ(UART0_INT_IRQn);
|
|
}
|
|
else if (pxUartInstance == UART1)
|
|
{
|
|
DL_UART_Main_enableInterrupt(pxUartInstance,
|
|
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(pxUartInstance);
|
|
NVIC_ClearPendingIRQ(UART1_INT_IRQn);
|
|
NVIC_EnableIRQ(UART1_INT_IRQn);
|
|
}
|
|
else if (pxUartInstance == UART2)
|
|
{
|
|
DL_UART_Main_enableInterrupt(pxUartInstance,
|
|
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_enable(pxUartInstance);
|
|
NVIC_ClearPendingIRQ(UART2_INT_IRQn);
|
|
NVIC_EnableIRQ(UART2_INT_IRQn);
|
|
}
|
|
else if (pxUartInstance == UART3)
|
|
{
|
|
DL_UART_Main_enableInterrupt(pxUartInstance,
|
|
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(UART3);
|
|
DL_UART_Main_setRXFIFOThreshold(UART3, DL_UART_RX_FIFO_LEVEL_ONE_ENTRY);
|
|
DL_UART_Main_setTXFIFOThreshold(UART3, DL_UART_TX_FIFO_LEVEL_1_2_EMPTY);
|
|
|
|
DL_UART_Main_enable(pxUartInstance);
|
|
NVIC_ClearPendingIRQ(UART3_INT_IRQn);
|
|
NVIC_EnableIRQ(UART3_INT_IRQn);
|
|
}
|
|
|
|
|
|
return commonMCAL_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @brief UART receive callback function for notifying when data is received.
|
|
*
|
|
* This function is called when data is received on the specified UART port. It logs the
|
|
* event type and calls the appropriate user-defined callback function if registered.
|
|
* The callback is invoked with the event type, a NULL pointer for data (as no data is
|
|
* passed here), and the size of the received data.
|
|
*
|
|
* @param [in] ind_type The type of interrupt or event that occurred (e.g., data received).
|
|
* @param [in] port The UART port number on which the receive event occurred.
|
|
* @param [in] size The size of the data that was received on the UART port.
|
|
*/
|
|
#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 Registers a UART handle for a specified UART port.
|
|
*
|
|
* This function stores the given UART handle in the UART handles (`gpIVEC_McalUartHandle_ss`)
|
|
* at the index corresponding to the specified UART port number. It ensures that the handle can be accessed
|
|
* later for operations like configuring or handling UART events.
|
|
*
|
|
* @param [in] pxUartHandle Pointer to the UART handle to be registered. The handle should contain
|
|
* valid configuration and state information for the corresponding UART port.
|
|
*/
|
|
static void prvMCAL_UartRegisterHandle(IVEC_McalUartHandle_s* pxUartHandle)
|
|
{
|
|
__gprv_pIVEC_McalUartHandle_ss[pxUartHandle->eUartPortNumber] = pxUartHandle;
|
|
}
|
|
/**
|
|
* @brief Initializes the UART peripheral based on the provided configuration.
|
|
*
|
|
* This function initializes the UART instance by registering the handle,
|
|
* configuring the UART instance with the settings specified in the
|
|
* `IVEC_McalUartHandle_s`, and setting the UART's baud rate. If the provided handle
|
|
* is invalid or if initialization fails, an appropriate error code is returned.
|
|
*
|
|
* @param [in] pxUartHandle Pointer to the UART handle, containing the port number and configuration
|
|
* (such as baud rate, data bits, stop bits, etc.) for the UART instance.
|
|
*
|
|
* @return IVEC_McalCommonErr_e Returns the status of the UART initialization:
|
|
* - `commonMCAL_SUCCESS` if the initialization is successful.
|
|
* - `commonMCAL_INVALID_PARAM` if the provided handle is invalid (NULL or incorrect port number).
|
|
* - `commonMCAL_INIT_FAIL` if initialization of the UART instance fails.
|
|
*/
|
|
IVEC_McalCommonErr_e xMCAL_UartInit(IVEC_McalUartHandle_s* pxUartHandle)
|
|
{
|
|
|
|
IVEC_MCAL_FUNC_ENTRY(LOG_STRING);
|
|
IVEC_McalCommonErr_e l_xFuncStatus = commonMCAL_SUCCESS;
|
|
if (pxUartHandle == NULL || pxUartHandle->eUartPortNumber >= IVEC_MCAL_UART_PORT_MAX)
|
|
{
|
|
return commonMCAL_INVALID_PARAM;
|
|
goto exit;
|
|
}
|
|
|
|
prvMCAL_UartRegisterHandle(pxUartHandle);
|
|
|
|
int l_i32Ret = __prv_McalUartInitInstance(pxUartHandle, pxUartHandle->xUartConfig.eUartBaudrate);
|
|
if (l_i32Ret != IVEC_CORE_STATUS_SUCCESS)
|
|
{
|
|
l_xFuncStatus = commonMCAL_INIT_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
IVEC_MCAL_FUNC_EXIT(LOG_STRING);
|
|
return l_xFuncStatus;
|
|
}
|