refactor: Improve CAN and UART handling, add documentation and checks

- Fixed UART speed inside handle and CAN speed inside handle for runtime configuration.
- Moved CAN filter setup inside the handle for more centralized control.
- Added documentation above functions for better readability.
- Included argument checks at function entry to ensure valid parameters.
- Added runtime checks to prevent memory corruption where values can change dynamically.
- Removed unnecessary `extern` declarations to improve code clarity.
- Fixed `vMCAL_MCAN_Tx()` to return success even if `if (sMcalTxFifoStatus_x.freeLvl)` fails.
- Removed unused functions to clean up the codebase.
- Fixed `xMCAL_VrefInit()` by calling vMCAL_SoftReset.
stable
Rakshita 2025-01-20 15:20:15 +05:30
parent 1c6fff8d24
commit b1fa1129af
11 changed files with 1184 additions and 463 deletions

View File

@ -3,6 +3,7 @@
#include "..\utils\utils.h"
#include "ti_msp_dl_config.h"
#define ivMCAL_MAX_FILTERS 10
/* Enum for CAN ID Types */
typedef enum {
@ -11,30 +12,47 @@ typedef enum {
IVEC_MCAL_CAN_ID_ERROR = 0x02 /* Error ID */
} xMCAL_CanIdType_e;
/* CAN Baud Rate Options */
typedef enum
{
IVEC_CAN_BAUD_500 = 500,
IVEC_CAN_BAUD_250 = 250,
IVEC_CAN_BAUD_150 = 150,
IVEC_CAN_BAUD_1000 = 1000,
IVEC_CAN_BAUD_125 = 125,
}xMCAL_CanBaud_e;
typedef struct
{
MCAN_Regs *pMCAN;
uint8_t __u8Init;
xMCAL_CanBaud_e u16Speed;
int32_t i32MaskCount;
int32_t i32FilterCount;
uint32_t u32MaskValues[ivMCAL_MAX_FILTERS];
uint32_t u32FilterValues[ivMCAL_MAX_FILTERS];
} xMcalCanHandle;
/* Function Prototypes for MCAN MCAL Layer */
/* Initialize the MCAN module */
IVEC_McalStatus_e vMCAL_MCAN_Init(MCAN_Regs* pMCAN, IVEC_CanBaud_e eBaudRate);
IVEC_McalStatus_e xMCAL_MCANInit(xMcalCanHandle* pxCanHandle);
/* Deinitialize the MCAN module */
IVEC_McalStatus_e vMCAL_MCAN_DeInit(MCAN_Regs* const pMCAN);
IVEC_McalStatus_e xMCAL_MCANDeInit(xMcalCanHandle* pxCanHandle);
/* Transmit data via MCAN */
IVEC_McalStatus_e vMCAL_MCAN_Tx(MCAN_Regs* const pMCAN, uint32_t u32Id, uint16_t* pu16TxData, uint32_t u32BufNum, uint32_t u32Bytes);
/* Transmit data via MCAN in blocking mode */
IVEC_McalStatus_e vMCAL_MCAN_TxBlocking(MCAN_Regs* const pMCAN, uint32_t u32Id, uint16_t* pu16TxData, uint32_t u32BufNum, int iBytes);
IVEC_McalStatus_e xMCAL_MCANTx(xMcalCanHandle* pxCanHandle, uint32_t u32Id, uint16_t* pu16TxData, uint32_t u32BufNum, uint32_t u32Bytes);
/* Receive data via MCAN */
IVEC_McalStatus_e vMCAL_MCAN_Rx(MCAN_Regs* const pMCAN, uint32_t* pu32Id, uint8_t* pu8RxData, int iDLC);
IVEC_McalStatus_e xMCAL_MCANRx(xMcalCanHandle* pxCanHandle, uint32_t* pu32Id, uint8_t* pu8RxData, int iDLC);
/* Get the error status of the MCAN module */
IVEC_McalStatus_e vMCAL_MCAN_GetErrorStatus(char* pcErrorStatus);
IVEC_McalStatus_e xMCAL_MCANGetErrorStatus(xMcalCanHandle* pxCanHandle, char* pcErrorStatus);
/* Get interrupt status of MCAN Interrupt Line 1 */
IVEC_McalStatus_e vMCAL_MCAN_GetInterruptLine1Status(uint32_t* pu32InterruptStatus);
/* Reset the MCAN module */
IVEC_McalStatus_e vMCAL_MCAN_Reset(MCAN_Regs* const pMCAN, IVEC_CanBaud_e eBaudRate);
IVEC_McalStatus_e xMCAL_MCANGetInterruptLine1Status(xMcalCanHandle* pxCanHandle, uint32_t* pu32InterruptStatus);
#endif /* CORE_INCLUDE_IVEc_MCAL_MCAN_H_ */

View File

@ -99,6 +99,5 @@ IVEC_McalCommonErr_e xMCAL_UartInit(xMcalUartHandle* pxUartHandle);
IVEC_McalCommonErr_e xMCAL_UartDeInit(xMcalUartHandle* pxUartHandle);
IVEC_McalCommonErr_e xMCAL_UartRead(xMcalUartHandle* pxUartHandle, uint8_t* pu8Data, uint32_t u32DataLength);
IVEC_McalCommonErr_e xMCAL_UartWrite(xMcalUartHandle* pxUartHandle, uint8_t* pu8Data, uint32_t u32DataLength);
IVEC_McalCommonErr_e _prvMCAL_UartPinInit(xMcalUartHandle* pxUartHandle);
#endif /* CORE_INCLUDE_IVEC_MCAL_UART_H_ */

View File

@ -11,19 +11,13 @@
#include <../Core/Include/ivec_mcal_mcan.h>
#include "string.h"
/* MCAN Initialization Flag */
volatile bool bMCAL_MCAN_InitFlag = false;
/* MCAN Status Flag */
volatile uint8_t u8MCAL_MCAN_StatusFlag = IVEC_MCAL_STATUS_ERROR;
/* Service Interrupt Flag */
volatile bool bMCAL_ServiceInterrupt = true;
/* MCAN Protocol Status Header */
volatile DL_MCAN_ProtocolStatus xMCAL_HeaderStat;
extern IVEC_CanBaud_e g_eCanSpeed;
extern xMCAL_CanBaud_e g_eCanSpeed;
/* MCAN Interrupt Line 1 Status */
volatile uint32_t u32MCAL_InterruptLine1Status;
@ -33,15 +27,10 @@ volatile char cMCAL_ErrorInterruptStatus[50];
volatile uint32_t can_interrupt = 0;
#define ivMCAL_MAX_FILTERS 10
extern int32_t g_i32FilterCount;
extern int32_t g_i32MaskCount;
extern uint32_t g_u32MaskValues[ivMCAL_MAX_FILTERS];
extern uint32_t g_u32FilterValues[ivMCAL_MAX_FILTERS];
volatile DL_MCAN_RxBufElement xMCAL_TempRxMsgInFunction;
__attribute__((weak)) void vMCU_FDCAN_RxFifo_Callback(uint32_t Identifier, uint8_t *data, uint16_t DataLength)
__attribute__((weak)) void vMCU_FDCANRxFifoCallback(uint32_t Identifier, uint8_t *data, uint16_t DataLength)
{
}
@ -193,18 +182,23 @@ volatile DL_MCAN_TxBufElement txMsg = {
/*=============================================================================================================================================================================================
PRIVATE_DECLARATIONS
==============================================================================================================================================================================================*/
/**
* @brief Static Function to store RX data in a static buffer
* @retval void
* @brief Processes CAN interrupt events.
*
* Handles CAN RX FIFO events, reads messages from the RX FIFO, and invokes a callback
* for each received message. It also processes error conditions and manages the interrupt status.
*
* @param[in] u32InterruptStatus The interrupt status indicating which event triggered the interrupt.
*
* @details
* - If the interrupt is related to RX FIFO events (RF0F, RF0N, RF1F, RF1N):
* - Retrieves the FIFO status and reads messages from the corresponding RX FIFO.
* - Acknowledges the read message and processes the message ID and data payload.
* - Calls `vMCAL_CanReceiveFifoCallback` with the received message.
* - If the interrupt is related to errors (e.g., timeout, bus off, protocol errors):
* - The interrupt status is saved for further processing (currently no action is taken for errors).
*/
static void _prv_vMCAL_MCAN_StoreRxData(const DL_MCAN_RxBufElement* pRxMsg, uint32_t* pu32Id, uint8_t* pu8RxData, int iDLC)
{
/* Extract data from the RX message into the buffer */
for (int i = 0; i < iDLC; i++) {
pu8RxData[i] = (pRxMsg->data[i] & 0xFF);
}
}
void __prv_CANInterruptProcess(uint32_t u32InterruptStatus)
{
@ -236,7 +230,7 @@ void __prv_CANInterruptProcess(uint32_t u32InterruptStatus)
au8DataArr[i] = xMCAL_TempRxMsg.data[i] & 0xFF;
}
vMCAL_CanReceiveFifoCallback(xMCAL_TempRxMsg.id, &xMCAL_TempRxMsg.data[0], xMCAL_TempRxMsg.dlc);
vMCAL_CanReceiveFifoCallback(xMCAL_TempRxMsg.id, &au8DataArr[0], xMCAL_TempRxMsg.dlc);
DL_MCAN_getRxFIFOStatus(CANFD0, &xMCAL_RxFIFOStatus);
}
}
@ -245,75 +239,6 @@ void __prv_CANInterruptProcess(uint32_t u32InterruptStatus)
}
}
//void vMCAL_MCAN_InterruptProcess(uint32_t u32InterruptStatus)
//{
// uint32_t u32IntrStatus = u32InterruptStatus;
//
//// /* Retrieve protocol status */
//// DL_MCAN_getProtocolStatus(CANFD0, &xMCAL_HeaderStat);
////
//// /* Handle Transmission Complete Interrupt */
//// if (u32IntrStatus & DL_MCAN_INTERRUPT_TC) {
//// bMCAL_ServiceInterrupt = true;
//// u8MCAL_MCAN_StatusFlag = IVEC_MCAL_STATUS_SUCCESS;
//// }
////
//// /* Handle Bus Off Interrupt */
//// if (u32IntrStatus & DL_MCAN_INTERRUPT_BO) {
//// DL_MCAN_setOpMode(CANFD0, DL_MCAN_OPERATION_MODE_NORMAL);
//// }
//
// /* Handle Receive FIFO New Message Interrupt */
// if (u32IntrStatus & (DL_MCAN_INTERRUPT_RF0N | DL_MCAN_INTERRUPT_RF1N)) {
// while (!bMCAL_ServiceInterrupt);
//
// bMCAL_ServiceInterrupt = false;
//
// /* MCAN RX FIFO Status */
// volatile DL_MCAN_RxFIFOStatus xMCAL_RxFIFOStatus;
//
// /* Determine which FIFO triggered the interrupt */
// xMCAL_RxFIFOStatus.fillLvl = 0;
// xMCAL_RxFIFOStatus.num = (u32IntrStatus & DL_MCAN_INTERRUPT_RF0N)
// ? DL_MCAN_RX_FIFO_NUM_0
// : DL_MCAN_RX_FIFO_NUM_1;
//
// /* Wait until the FIFO has data */
// while (xMCAL_RxFIFOStatus.fillLvl == 0) {
// DL_MCAN_getRxFIFOStatus(CANFD0, &xMCAL_RxFIFOStatus);
// }
//
// /* Read the message from the FIFO */
// DL_MCAN_readMsgRam(CANFD0, DL_MCAN_MEM_TYPE_FIFO, 0,
// xMCAL_RxFIFOStatus.num, &xMCAL_TempRxMsg);
//
// /* Acknowledge the message */
// DL_MCAN_writeRxFIFOAck(CANFD0, xMCAL_RxFIFOStatus.num,
// xMCAL_RxFIFOStatus.getIdx);
//
// bMCAL_ServiceInterrupt = true;
//
// /* Handle Bus Off Recovery */
// if (xMCAL_HeaderStat.busOffStatus == 1) {
// DL_MCAN_setOpMode(CANFD0, DL_MCAN_OPERATION_MODE_NORMAL);
// }
//
// /* Process Standard or Extended ID */
// if (!xMCAL_TempRxMsg.xtd) {
// xMCAL_TempRxMsg.id = (uint32_t)(xMCAL_TempRxMsg.id >> 18);
// }
//
// /* Extract data payload */
// uint8_t au8DataArr[8] = {0};
// for (int i = 0; i < 8; i++) {
// au8DataArr[i] = xMCAL_TempRxMsg.data[i] & 0xFF;
// }
//
// /* Call the RX FIFO callback function */
// vMCU_FDCAN_RxFifo_Callback(xMCAL_TempRxMsg.id, au8DataArr, xMCAL_TempRxMsg.dlc);
// }
//}
/**
* @brief Default Interrupt Handler for MCAN
*
@ -364,49 +289,63 @@ void CANFD0_IRQHandler(void)
==============================================================================================================================================================================================*/
/**
* @brief Function to initialize MCAN Peripheral
* @note Interrupts are enabled in this function itself
* @param MCAN Pointer to the register overlay for the peripheral
* @param BAUD Param to set Baud rate of MCAN
* @retval IVEC_McalStatus_e
* @brief Initializes the MCAN module with specified configurations.
*
* This function configures the MCAN module with the following:
* - Enables the module clock and sets the clock configuration.
* - Initializes the MCAN in software initialization mode and waits for completion.
* - Configures bit timings and message RAM.
* - Sets up the filter configurations for both extended and standard IDs based on the provided filter values and masks.
* - Enables necessary interrupts for CAN operation and sets interrupt priorities.
*
* @param[in] pxCanHandle Pointer to the CAN handle structure containing the configuration parameters.
*
* @return IVEC_MCAL_STATUS_SUCCESS if the initialization is successful, or an error status if failed.
*
* @details
* The function performs the following steps:
* 1. Validates the CAN instance and speed.
* 2. Initializes the MCAN module by enabling the module clock, configuring the clock, and setting the operation mode to software initialization.
* 3. Waits for memory initialization to complete, then sets the MCAN operation mode to normal.
* 4. Configures the MCAN module parameters, including bit timings and message RAM.
* 5. Sets up CAN filters for extended and standard IDs based on the provided filter and mask values.
* 6. Enables CAN interrupts and configures interrupt lines for CAN events.
* 7. Clears and enables interrupts in the NVIC for the CAN module.
*/
IVEC_McalStatus_e vMCAL_MCAN_Init(MCAN_Regs* pMCAN, IVEC_CanBaud_e eBaudRate)
IVEC_McalStatus_e xMCAL_MCANInit(xMcalCanHandle* pxCanHandle)
{
assert(pMCAN == CANFD0);
assert(eBaudRate == IVEC_CAN_BAUD_500 || eBaudRate == IVEC_CAN_BAUD_250);
assert(bMCAL_MCAN_InitFlag == 0);
assert(pxCanHandle->pMCAN == CANFD0);
assert(pxCanHandle->u16Speed == IVEC_CAN_BAUD_500 || pxCanHandle->u16Speed == IVEC_CAN_BAUD_250);
// g_xEcuCanHandle.__xCanHandle.u16Speed = eMcalUartBaud115200;
DL_MCAN_RevisionId revid_MCAN0;
DL_MCAN_enableModuleClock(pMCAN);
DL_MCAN_enableModuleClock(pxCanHandle->pMCAN);
DL_MCAN_setClockConfig(pMCAN, (DL_MCAN_ClockConfig *) &gMCAN0ClockConf);
DL_MCAN_setClockConfig(pxCanHandle->pMCAN, (DL_MCAN_ClockConfig *) &gMCAN0ClockConf);
/* Get MCANSS Revision ID. */
DL_MCAN_getRevisionId(pMCAN, &revid_MCAN0);
DL_MCAN_getRevisionId(pxCanHandle->pMCAN, &revid_MCAN0);
/* Wait for Memory initialization to be completed. */
while (false == DL_MCAN_isMemInitDone(pMCAN));
while (false == DL_MCAN_isMemInitDone(pxCanHandle->pMCAN));
/* Put MCAN in SW initialization mode. */
DL_MCAN_setOpMode(pMCAN, DL_MCAN_OPERATION_MODE_SW_INIT);
DL_MCAN_setOpMode(pxCanHandle->pMCAN, DL_MCAN_OPERATION_MODE_SW_INIT);
/* Wait till MCAN is not initialized. */
while (DL_MCAN_OPERATION_MODE_SW_INIT != DL_MCAN_getOpMode(pMCAN));
while (DL_MCAN_OPERATION_MODE_SW_INIT != DL_MCAN_getOpMode(pxCanHandle->pMCAN));
/* Initialize MCAN module. */
DL_MCAN_init(pMCAN, (DL_MCAN_InitParams*)&gMCAN0InitParams);
DL_MCAN_init(pxCanHandle->pMCAN, (DL_MCAN_InitParams*)&gMCAN0InitParams);
gMCAN0ConfigParams.filterConfig.anfe = 0;
gMCAN0ConfigParams.filterConfig.anfs = 0;
// g_u32FilterValues[0]=1312;
// g_u32MaskValues[0]=2047;
// g_i32MaskCount=0;
// g_i32FilterCount=0;
for (int u32Index = 0; u32Index <= g_i32MaskCount; u32Index++) {
if ((g_u32FilterValues[u32Index] > 0x7FF) || (g_u32MaskValues[u32Index] > 0x7FF)) {
for (int u32Index = 0; u32Index <= pxCanHandle->i32MaskCount; u32Index++) {
if ((pxCanHandle->u32FilterValues[u32Index] > 0x7FF) || (pxCanHandle->u32MaskValues[u32Index] > 0x7FF)) {
gMCAN0ConfigParams.filterConfig.anfe = 3;
}
else
@ -415,62 +354,62 @@ IVEC_McalStatus_e vMCAL_MCAN_Init(MCAN_Regs* pMCAN, IVEC_CanBaud_e eBaudRate)
}
}
/* Configure MCAN module. */
DL_MCAN_config(pMCAN, (DL_MCAN_ConfigParams*)&gMCAN0ConfigParams);
DL_MCAN_config(pxCanHandle->pMCAN, (DL_MCAN_ConfigParams*)&gMCAN0ConfigParams);
/* Configure Bit timings. */
if (eBaudRate == IVEC_CAN_BAUD_500)
if (pxCanHandle->u16Speed == IVEC_CAN_BAUD_500)
{
DL_MCAN_setBitTime(pMCAN, (DL_MCAN_BitTimingParams*)&gMCAN0BitTimes_500);
DL_MCAN_setBitTime(pxCanHandle->pMCAN, (DL_MCAN_BitTimingParams*)&gMCAN0BitTimes_500);
}
else if (eBaudRate == IVEC_CAN_BAUD_250)
else if (pxCanHandle->u16Speed == IVEC_CAN_BAUD_250)
{
DL_MCAN_setBitTime(pMCAN, (DL_MCAN_BitTimingParams*)&gMCAN0BitTimes_250);
DL_MCAN_setBitTime(pxCanHandle->pMCAN, (DL_MCAN_BitTimingParams*)&gMCAN0BitTimes_250);
}
else
{
DL_MCAN_setBitTime(pMCAN, (DL_MCAN_BitTimingParams*)&gMCAN0BitTimes_500);
DL_MCAN_setBitTime(pxCanHandle->pMCAN, (DL_MCAN_BitTimingParams*)&gMCAN0BitTimes_500);
}
/* Configure Message RAM Sections */
DL_MCAN_msgRAMConfig(pMCAN, (DL_MCAN_MsgRAMConfigParams*)&gMCAN0MsgRAMConfigParams);
DL_MCAN_msgRAMConfig(pxCanHandle->pMCAN, (DL_MCAN_MsgRAMConfigParams*)&gMCAN0MsgRAMConfigParams);
uint8_t l_u8ExtendedFilterCount = 0;
uint8_t l_u8StandardFilterCount = 0;
for (int u32Index = 0; u32Index <= g_i32MaskCount; u32Index++) {
if ((g_u32FilterValues[u32Index] > 0x7FF) || (g_u32MaskValues[u32Index] > 0x7FF)) {
for (int u32Index = 0; u32Index <= pxCanHandle->i32MaskCount; u32Index++) {
if ((pxCanHandle->u32FilterValues[u32Index] > 0x7FF) || (pxCanHandle->u32MaskValues[u32Index] > 0x7FF)) {
// Extended ID filter
DL_MCAN_ExtMsgIDFilterElement extFilterElement;
extFilterElement.efid1 = g_u32FilterValues[u32Index];
extFilterElement.efid2 = g_u32MaskValues[u32Index];
extFilterElement.efid1 = pxCanHandle->u32FilterValues[u32Index];
extFilterElement.efid2 = pxCanHandle->u32MaskValues[u32Index];
extFilterElement.efec = 001;
extFilterElement.eft = 2;
DL_MCAN_addExtMsgIDFilter(pMCAN, l_u8ExtendedFilterCount, (DL_MCAN_StdMsgIDFilterElement*)&extFilterElement);
DL_MCAN_addExtMsgIDFilter(pxCanHandle->pMCAN, l_u8ExtendedFilterCount, (DL_MCAN_StdMsgIDFilterElement*)&extFilterElement);
l_u8ExtendedFilterCount++;
}
else {
// Standard ID filter
DL_MCAN_StdMsgIDFilterElement stdFilterElement;
stdFilterElement.sfid1 = g_u32FilterValues[u32Index];
stdFilterElement.sfid2 = g_u32MaskValues[u32Index];
stdFilterElement.sfid1 = pxCanHandle->u32FilterValues[u32Index];
stdFilterElement.sfid2 = pxCanHandle->u32MaskValues[u32Index];
stdFilterElement.sfec = 001;
stdFilterElement.sft = 2;
DL_MCAN_addStdMsgIDFilter(pMCAN, l_u8StandardFilterCount, (DL_MCAN_StdMsgIDFilterElement*)&stdFilterElement);
DL_MCAN_addStdMsgIDFilter(pxCanHandle->pMCAN, l_u8StandardFilterCount, (DL_MCAN_StdMsgIDFilterElement*)&stdFilterElement);
l_u8StandardFilterCount++;
}
}
DL_MCAN_setExtIDAndMask(pMCAN, (0x1FFFFFFFU));
DL_MCAN_setExtIDAndMask(pxCanHandle->pMCAN, (0x1FFFFFFFU));
/* Take MCAN out of the SW initialization mode */
DL_MCAN_setOpMode(pMCAN, DL_MCAN_OPERATION_MODE_NORMAL);
DL_MCAN_setOpMode(pxCanHandle->pMCAN, DL_MCAN_OPERATION_MODE_NORMAL);
while (DL_MCAN_OPERATION_MODE_NORMAL != DL_MCAN_getOpMode(pMCAN));
while (DL_MCAN_OPERATION_MODE_NORMAL != DL_MCAN_getOpMode(pxCanHandle->pMCAN));
/* Enable MCAN mopdule Interrupts */
DL_MCAN_enableIntr(pMCAN, (MCAN_IR_RF0N_MASK | \
DL_MCAN_enableIntr(pxCanHandle->pMCAN, (MCAN_IR_RF0N_MASK | \
MCAN_IR_RF0F_MASK | \
MCAN_IR_RF1N_MASK | \
MCAN_IR_RF1F_MASK | \
@ -487,17 +426,17 @@ IVEC_McalStatus_e vMCAL_MCAN_Init(MCAN_Regs* pMCAN, IVEC_CanBaud_e eBaudRate)
MCAN_IR_ARA_MASK), 1);
DL_MCAN_selectIntrLine(pMCAN, DL_MCAN_INTR_MASK_ALL, DL_MCAN_INTR_LINE_NUM_0);
DL_MCAN_enableIntrLine(pMCAN, DL_MCAN_INTR_LINE_NUM_0, 1U);
DL_MCAN_selectIntrLine(pxCanHandle->pMCAN, DL_MCAN_INTR_MASK_ALL, DL_MCAN_INTR_LINE_NUM_0);
DL_MCAN_enableIntrLine(pxCanHandle->pMCAN, DL_MCAN_INTR_LINE_NUM_0, 1U);
/* Enable MSPM0 MCAN interrupt */
DL_MCAN_clearInterruptStatus(pMCAN, (DL_MCAN_MSP_INTERRUPT_LINE0));
DL_MCAN_enableInterrupt(pMCAN, (DL_MCAN_MSP_INTERRUPT_LINE0));
DL_MCAN_clearInterruptStatus(pxCanHandle->pMCAN, (DL_MCAN_MSP_INTERRUPT_LINE0));
DL_MCAN_enableInterrupt(pxCanHandle->pMCAN, (DL_MCAN_MSP_INTERRUPT_LINE0));
NVIC_SetPriority(CANFD0_INT_IRQn, 1);
NVIC_ClearPendingIRQ(CANFD0_INT_IRQn);
NVIC_EnableIRQ(CANFD0_INT_IRQn);
bMCAL_MCAN_InitFlag = 1;
pxCanHandle->__u8Init = 1;
return IVEC_MCAL_STATUS_SUCCESS;
}
@ -509,23 +448,23 @@ IVEC_McalStatus_e vMCAL_MCAN_Init(MCAN_Regs* pMCAN, IVEC_CanBaud_e eBaudRate)
* @retval IVEC MCAL status
*/
IVEC_McalStatus_e vMCAL_MCAN_DeInit(MCAN_Regs* const pMCAN)
IVEC_McalStatus_e xMCAL_MCANDeInit(xMcalCanHandle* pxCanHandle)
{
/* Assert that the MCAN module pointer is valid */
assert(pMCAN == CANFD0);
assert(bMCAL_MCAN_InitFlag != 0); /* Ensure the module was initialized before deinitializing. */
assert(pxCanHandle->pMCAN == CANFD0);
assert(pxCanHandle->__u8Init != 0); /* Ensure the module was initialized before deinitializing. */
/* Reset the CAN module to initialization mode */
DL_MCAN_setOpMode(pMCAN, DL_MCAN_OPERATION_MODE_SW_INIT);
DL_MCAN_setOpMode(pxCanHandle->pMCAN, DL_MCAN_OPERATION_MODE_SW_INIT);
/* Wait until the operation mode is set to initialization mode */
while (DL_MCAN_OPERATION_MODE_SW_INIT != DL_MCAN_getOpMode(pMCAN));
while (DL_MCAN_OPERATION_MODE_SW_INIT != DL_MCAN_getOpMode(pxCanHandle->pMCAN));
/* Disable the CAN interrupt */
NVIC_DisableIRQ(CANFD0_INT_IRQn);
/* Disable interrupts on CAN module */
DL_MCAN_enableIntr(pMCAN, (DL_MCAN_INTERRUPT_BEU | \
DL_MCAN_enableIntr(pxCanHandle->pMCAN, (DL_MCAN_INTERRUPT_BEU | \
DL_MCAN_INTERRUPT_BO | \
DL_MCAN_INTERRUPT_ELO | \
DL_MCAN_INTERRUPT_EP | \
@ -538,29 +477,29 @@ IVEC_McalStatus_e vMCAL_MCAN_DeInit(MCAN_Regs* const pMCAN)
DL_MCAN_INTERRUPT_TOO), false);
/* Disable interrupt lines */
DL_MCAN_enableIntrLine(pMCAN, DL_MCAN_INTR_LINE_NUM_0, false);
DL_MCAN_enableIntrLine(pMCAN, DL_MCAN_INTR_LINE_NUM_1, false);
DL_MCAN_enableIntrLine(pxCanHandle->pMCAN, DL_MCAN_INTR_LINE_NUM_0, false);
DL_MCAN_enableIntrLine(pxCanHandle->pMCAN, DL_MCAN_INTR_LINE_NUM_1, false);
/* Clear interrupt statuses for lines 0 and 1 */
DL_MCAN_clearInterruptStatus(pMCAN, DL_MCAN_MSP_INTERRUPT_LINE0);
DL_MCAN_disableInterrupt(pMCAN, DL_MCAN_MSP_INTERRUPT_LINE0);
DL_MCAN_clearInterruptStatus(pxCanHandle->pMCAN, DL_MCAN_MSP_INTERRUPT_LINE0);
DL_MCAN_disableInterrupt(pxCanHandle->pMCAN, DL_MCAN_MSP_INTERRUPT_LINE0);
DL_MCAN_clearInterruptStatus(pMCAN, DL_MCAN_MSP_INTERRUPT_LINE1);
DL_MCAN_disableInterrupt(pMCAN, DL_MCAN_MSP_INTERRUPT_LINE1);
DL_MCAN_clearInterruptStatus(pxCanHandle->pMCAN, DL_MCAN_MSP_INTERRUPT_LINE1);
DL_MCAN_disableInterrupt(pxCanHandle->pMCAN, DL_MCAN_MSP_INTERRUPT_LINE1);
/* Set the operation mode back to normal */
DL_MCAN_setOpMode(pMCAN, DL_MCAN_OPERATION_MODE_NORMAL);
DL_MCAN_setOpMode(pxCanHandle->pMCAN, DL_MCAN_OPERATION_MODE_NORMAL);
/* Reset the initialization flag */
bMCAL_MCAN_InitFlag = 0;
pxCanHandle->__u8Init = 0;
/* Disable the CAN module's GPIO peripheral function */
DL_GPIO_initPeripheralOutputFunction(IOMUX_PINCM59, 0);
DL_GPIO_initPeripheralInputFunction(IOMUX_PINCM60, 0);
/* Disable the module clock and power */
DL_MCAN_disableModuleClock(pMCAN);
DL_MCAN_disablePower(pMCAN);
DL_MCAN_disableModuleClock(pxCanHandle->pMCAN);
DL_MCAN_disablePower(pxCanHandle->pMCAN);
/* Wait for power down to complete */
delay_cycles(16);
@ -569,23 +508,41 @@ IVEC_McalStatus_e vMCAL_MCAN_DeInit(MCAN_Regs* const pMCAN)
}
/**
* @brief Function to Transmit CAN message
* @param MCAN Pointer to the register overlay for the peripheral
* @param ID Message ID for TxMsg Object.
* @param TxData Array of Data to be transmitted
* @param BufNum Tx Buffer Number
* @param Bytes Number of bytes to be transmitted
* @retval IVEC_McalStatus_e
* @brief Deinitializes the MCAN module and disables associated resources.
*
* This function performs the necessary steps to safely deinitialize the MCAN module, including:
* - Resetting the MCAN to initialization mode.
* - Disabling CAN interrupts and interrupt lines.
* - Clearing interrupt statuses.
* - Setting the MCAN operation mode back to normal.
* - Disabling the CAN module clock and powering down the module.
* - Disabling the GPIO peripheral functions for CAN.
*
* @param[in] pxCanHandle Pointer to the CAN handle structure containing the configuration parameters.
*
* @return IVEC_MCAL_STATUS_SUCCESS if the deinitialization is successful, or an error status if failed.
*
* @details
* The function performs the following steps:
* 1. Validates the CAN module pointer and checks if the module was initialized.
* 2. Resets the CAN module to the software initialization mode and waits for completion.
* 3. Disables interrupts for the CAN module and the interrupt lines associated with CAN events.
* 4. Clears interrupt statuses for both interrupt lines and disables the interrupts in the NVIC.
* 5. Sets the CAN operation mode back to normal.
* 6. Resets the initialization flag and disables the GPIO peripheral functions for CAN pins.
* 7. Disables the CAN module's clock and power, waiting for the power down process to complete.
*/
IVEC_McalStatus_e vMCAL_MCAN_Tx(MCAN_Regs* const pMCAN, uint32_t u32Id,
IVEC_McalStatus_e xMCAL_MCANTx(xMcalCanHandle* pxCanHandle, uint32_t u32Id,
uint16_t* pu16TxData, uint32_t u32BufNum,
uint32_t u32Bytes)
{
/* Ensure that the MCAN instance is CANFD0 */
assert(pMCAN == CANFD0);
assert(pxCanHandle->pMCAN == CANFD0);
assert(pxCanHandle->u16Speed == IVEC_CAN_BAUD_500 || pxCanHandle->u16Speed == IVEC_CAN_BAUD_250);
/* Ensure that the MCAN is initialized */
assert(bMCAL_MCAN_InitFlag != 0);
assert(pxCanHandle->__u8Init != 0);
/* Validate the byte size */
assert(u32Bytes <= 8);
@ -613,70 +570,70 @@ IVEC_McalStatus_e vMCAL_MCAN_Tx(MCAN_Regs* const pMCAN, uint32_t u32Id,
volatile DL_MCAN_TxFIFOStatus sMcalTxFifoStatus_x = { 0 }; // Structure variable prefixed with 's' for structure type and 'x' for typedef suffix
DL_MCAN_getTxFIFOQueStatus(pMCAN, &sMcalTxFifoStatus_x); // Function name prefixed with layer (MCAL) and descriptive
DL_MCAN_getTxFIFOQueStatus(pxCanHandle->pMCAN, &sMcalTxFifoStatus_x); // Get the FIFO status
if (sMcalTxFifoStatus_x.freeLvl) // Variable renamed for clarity and prefixed with 'u32' for uint32_t
if (sMcalTxFifoStatus_x.freeLvl) // Check if there is space in the FIFO
{
DL_MCAN_writeMsgRam(pMCAN, DL_MCAN_MEM_TYPE_FIFO, u32BufNum, &txMsg); // Function and variable name updated
DL_MCAN_writeMsgRam(pxCanHandle->pMCAN, DL_MCAN_MEM_TYPE_FIFO, u32BufNum, &txMsg); // Function and variable name updated
if (DL_MCAN_TXBufAddReq(pMCAN, sMcalTxFifoStatus_x.putIdx) == IVEC_MCAL_STATUS_ERROR) // Function return type 'x'
if (DL_MCAN_TXBufAddReq(pxCanHandle->pMCAN, sMcalTxFifoStatus_x.putIdx) == IVEC_MCAL_STATUS_ERROR) // Function return type 'x'
{
return IVEC_MCAL_STATUS_ERROR;
}
}
else
{
/* If no space in FIFO, return busy */
return IVEC_MCAL_STATUS_BUSY;
}
bMCAL_ServiceInterrupt = true;
return IVEC_MCAL_STATUS_SUCCESS;
}
/**
* @brief Function to Receive CAN message
* @param MCAN Pointer to the register overlay for the peripheral
* @param RxMsg Message Object.
* @param FifoNum Fifo Number to be used
* @param RxData Array where received data is to be stored
* @param DLC length of received data
* @retval IVEC_McalStatus_e
* @brief Receives a message from the CAN bus.
*
* Retrieves the received CAN message, including the message ID and data.
* Handles bus-off recovery and copies the received data into the provided buffer.
*
* @param[in] pxCanHandle Pointer to the CAN handle.
* @param[out] pu32ID Pointer to store the received message ID.
* @param[out] pu8RxData Pointer to the buffer to store the received message data.
* @param[in] iDLC The Data Length Code (DLC), specifying the number of bytes in the data field.
*
* @return IVEC_MCAL_STATUS_SUCCESS on successful reception.
*/
IVEC_McalStatus_e vMCAL_MCAN_Rx(MCAN_Regs *pMCAN, uint32_t *pu32ID, uint8_t *pu8RxData, int iDLC)
IVEC_McalStatus_e xMCAL_MCANRx(xMcalCanHandle* pxCanHandle, uint32_t *pu32ID, uint8_t *pu8RxData, int iDLC)
{
/* Assert that the CAN module is CANFD0 and that the MCAL initialization flag is set */
assert(pMCAN == CANFD0);
assert(bMCAL_MCAN_InitFlag != 0);
assert(pxCanHandle->pMCAN == CANFD0);
assert(pxCanHandle->u16Speed == IVEC_CAN_BAUD_500 || pxCanHandle->u16Speed == IVEC_CAN_BAUD_250);
assert(pxCanHandle->__u8Init != 0);
/* If the bus-off status is set, change to normal operation mode */
if (xMCAL_HeaderStat.busOffStatus == 1)
{
DL_MCAN_setOpMode(CANFD0, DL_MCAN_OPERATION_MODE_NORMAL);
}
/* Temporary RX ID */
volatile uint32_t u32MCAL_TempRxID;
/* Store the received ID */
*pu32ID = u32MCAL_TempRxID;
/* Copy the received message data into the RxData buffer */
for (int i = 0; i < iDLC; i++)
{
pu8RxData[i] = xMCAL_TempRxMsgInFunction.data[i];
}
return IVEC_MCAL_STATUS_SUCCESS;
return IVEC_MCAL_STATUS_ERROR;
}
/**
* @brief Function to check current Error Status of MCAN peripheral
* @param ErrorStatus Pointer to array where current status will be stored
* @retval IVEC_McalStatus_e
* @brief Retrieves the error status of the MCAN module.
*
* Copies the current error interrupt status and protocol status into a buffer and returns
* an appropriate status based on error conditions.
*
* @param[in] pxCanHandle Pointer to the CAN handle.
* @param[out] pcErrorStatus Buffer to store the error status string.
*
* @return IVEC_MCAL_STATUS_SUCCESS if no errors, IVEC_MCAL_STATUS_ERROR if errors are detected.
*/
IVEC_McalStatus_e vMCAL_MCAN_GetErrorStatus(char *pcErrorStatus)
IVEC_McalStatus_e xMCAL_MCANGetErrorStatus(xMcalCanHandle* pxCanHandle, char *pcErrorStatus)
{
/* Assert that the MCAN initialization flag is set */
assert(bMCAL_MCAN_InitFlag != 0);
assert(pxCanHandle->__u8Init != 0);;
/* Copy the error interrupt status to the provided buffer */
strcpy(pcErrorStatus, cMCAL_ErrorInterruptStatus);
@ -695,29 +652,23 @@ IVEC_McalStatus_e vMCAL_MCAN_GetErrorStatus(char *pcErrorStatus)
/**
* @brief Function to check Interrupt Line1 Status of MCAN peripheral
* @param Interrupt_Status Pointer to variable where current status will be stored
* @retval IVEC_McalStatus_e
* @brief Retrieves the status of interrupt line 1 for the MCAN module.
*
* Copies the current interrupt status for line 1 into the provided status buffer.
*
* @param[in] pxCanHandle Pointer to the CAN handle.
* @param[out] pu32InterruptStatus Pointer to store the interrupt status.
*
* @return IVEC_MCAL_STATUS_SUCCESS if successful.
*/
IVEC_McalStatus_e vMCAL_MCAN_GetInterruptLine1Status(uint32_t *pu32InterruptStatus)
IVEC_McalStatus_e xMCAL_MCANGetInterruptLine1Status(xMcalCanHandle* pxCanHandle, uint32_t *pu32InterruptStatus)
{
// Ensure CAN module is initialized (optional assertion, can be uncommented as needed)
// assert(b_MCAN_InitFlag != 0);
assert(pxCanHandle->__u8Init != 0);;
*pu32InterruptStatus = u32MCAL_InterruptLine1Status;
return IVEC_MCAL_STATUS_SUCCESS;
}
IVEC_McalStatus_e vMCAL_MCAN_Reset(MCAN_Regs* const pMCAN, IVEC_CanBaud_e eBaudRate)
{
// Ensure MCAN is initialized and that the pointer is valid
assert(bMCAL_MCAN_InitFlag != 0);
assert(pMCAN == CANFD0); // Or check for valid CAN register base address
// Reset the MCAN module and re-initialize it
vMCAL_MCAN_DeInit(pMCAN); // De-initialize CAN
vMCAL_MCAN_Init(pMCAN, eBaudRate); // Re-initialize CAN with the provided baud rate
return IVEC_MCAL_STATUS_SUCCESS;
}

View File

@ -18,6 +18,29 @@ static uint32_t prv_u32DataCount = 0; /* Data count for tracking received bytes
/* Static Function Prototypes */
static eMcalUartPortNumber _prvMCAL_GetUartPort(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 `gpxMcalUartHandles` 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)
@ -39,6 +62,16 @@ void vMCAL_UartReadCallback(UART_Regs* pxUartInstance, uint8_t* pu8Buffer, bool
}
}
}
/**
* @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)
{
@ -107,11 +140,14 @@ void UART2_IRQHandler()
}
/**
* @brief Get the UART instance based on the enum.
* @brief Retrieves the UART instance for the specified port number.
*
* @param eUartPortNumber UART port number enumeration.
* @return UART_Regs* Pointer to the UART registers.
* 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* _prvMCAL_GetUartInstance(eMcalUartPortNumber eUartPortNumber)
{
switch (eUartPortNumber)
@ -123,16 +159,20 @@ static UART_Regs* _prvMCAL_GetUartInstance(eMcalUartPortNumber eUartPortNumber)
case eMcalUartPort3:
return UART2;
default:
return NULL; // Invalid UART port
return eMcalUartPortMax; // Invalid UART port
}
}
/**
* @brief Get the UART port based on the instance.
* @brief Maps UART instance to a corresponding port number.
*
* @param pxUartInstance Pointer to the UART registers.
* @return eMcalUartPortNumber UART port number enumeration.
* 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 eMcalUartPortNumber _prvMCAL_GetUartPort(UART_Regs* pxUartInstance)
{
switch ((uint32_t)pxUartInstance)
@ -149,11 +189,17 @@ static eMcalUartPortNumber _prvMCAL_GetUartPort(UART_Regs* pxUartInstance)
}
/**
* @brief Private function to deinitialize UART instance.
/**
* @brief Deinitializes a UART instance.
*
* @param pxUartHandle Pointer to \link xMcalUartHandle \endlink.
* @return IVEC_CoreStatus_e Status of the UART deinitialization.
* 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_CoreStatus_e _prvMCAL_UartDeInitInstance(xMcalUartHandle* pxUartHandle)
{
// Get the UART instance based on the port number in the handle
@ -205,13 +251,25 @@ static IVEC_CoreStatus_e _prvMCAL_UartDeInitInstance(xMcalUartHandle* pxUartHand
}
/**
* @brief Function to deinitialize the UART peripheral.
* @brief Deinitializes the specified UART instance.
*
* @param pxUartHandle Pointer to \link xMcalUartHandle \endlink.
* @return IVEC_McalCommonErr_e Returns a status based on the success or failure of the UART deinitialization operation.
* 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(xMcalUartHandle* pxUartHandle)
{
if (pxUartHandle == NULL || pxUartHandle->eUartPortNumber >= IVEC_MCAL_UART_MAX_PORT)
{
return commonMCAL_INIT_FAIL;
}
IVEC_CoreStatus_e xRetStatus;
IVEC_MCAL_FUNC_ENTRY(LOG_STRING);
IVEC_McalCommonErr_e eFuncStatus = commonMCAL_SUCCESS;
@ -243,11 +301,18 @@ exit:
//////////////////////////////////////////////////////////////////////
/**
* @brief Internal function to read a single byte from UART.
* @param [in] pxUartHandle Pointer to \link McalUartHandle_t \endlink.
* @param [out] pucData Pointer to store the received byte.
* @return \link CoreStatus_t \endlink Returns CORE_STATUS_SUCCESS on success or CORE_STATUS_ERROR on failure.
* @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 prvIvecMcalUart_ReadByte(xMcalUartHandle* pxUartHandle, uint8_t* pucData)
{
/* Get the UART instance based on the port number in the handle */
@ -280,15 +345,25 @@ static IVEC_McalCommonErr_e prvIvecMcalUart_ReadByte(xMcalUartHandle* pxUartHan
}
/**
* @brief Reads data from the UART port.
* @pre UART should be initialized before calling this function.
* @param [in] pxUartHandle Pointer to \link McalUartHandle_t \endlink.
* @param [out] pucData Pointer to buffer for storing received data.
* @param [in] u32DataLength Length of the data to read.
* @return \link IvecMcalCommonErr_t \endlink Returns the status of the UART read operation.
* @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 xIvecMcalUart_Read(xMcalUartHandle* pxUartHandle, uint8_t* pucData, uint32_t u32DataLength)
{
if (pxUartHandle == NULL || pxUartHandle->eUartPortNumber >= IVEC_MCAL_UART_MAX_PORT)
{
return commonMCAL_INIT_FAIL;
}
int32_t i32RetVal;
IVEC_McalCommonErr_e eFuncStatus = commonMCAL_SUCCESS;
@ -324,11 +399,17 @@ exit:
////////////////////////////////////////////////////////////////////////////////////
/**
* @brief Static function to transmit data over UART.
* @param [in] pxUartHandle Pointer to UART handle structure.
* @param [in] pu8TxData Pointer to the data buffer to transmit.
* @param [in] u32Size Number of bytes to transmit.
* @return xCoreStatus_t Status of the transmission (STATUS_SUCCESS or STATUS_ERROR).
* @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_CoreStatus_e _prvMCAL_UartTransmit(xMcalUartHandle* pxUartHandle, uint8_t* pu8TxData, uint32_t u32Size)
{
@ -355,17 +436,27 @@ static IVEC_CoreStatus_e _prvMCAL_UartTransmit(xMcalUartHandle* pxUartHandle, ui
return IVEC_CORE_STATUS_SUCCESS;
}
/**
* @brief Function to write data to the UART port.
* @pre UART must be initialized before calling this function.
* @param [in] pxUartHandle Pointer to UART handle structure.
* @param [in] pu8Data Pointer to the data buffer to send.
* @param [in] u32DataLength Length of the data to be sent.
* @return IVEC_McalCommonErr_e Status of the write operation.
* @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(xMcalUartHandle* pxUartHandle, uint8_t* pu8Data, uint32_t u32DataLength)
{
if (pxUartHandle == NULL || pxUartHandle->eUartPortNumber >= IVEC_MCAL_UART_MAX_PORT)
{
return commonMCAL_INIT_FAIL;
}
IVEC_McalCommonErr_e eFuncStatus = commonMCAL_SUCCESS;
int32_t i32Ret;
@ -402,7 +493,27 @@ exit:
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
static IVEC_CoreStatus_e prvMCAL_UART_InitInstance(xMcalUartHandle* pxUartHandle, eMcalUartBaudRate xBaud)
/**
* @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_CoreStatus_e prvMCAL_UARTInitInstance(xMcalUartHandle* pxUartHandle, eMcalUartBaudRate xBaud)
{
if (pxUartHandle->eUartPortNumber == eMcalUartPort2)
{
@ -601,11 +712,16 @@ static IVEC_CoreStatus_e prvMCAL_UART_InitInstance(xMcalUartHandle* pxUartHandle
/**
* @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.
* @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)
@ -624,35 +740,49 @@ static void __prvMCAL_UartNotifyRecvCb(uint32 ind_type, ql_uart_port_number_e po
#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
* @brief Registers a UART handle for a specified UART port.
*
* This function stores the given UART handle in the UART handles (`gpxMcalUartHandles`)
* 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(xMcalUartHandle* pxUartHandle)
{
gpxMcalUartHandles[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.
* @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
* `xMcalUartHandle`, 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(xMcalUartHandle* pxUartHandle)
{
IVEC_MCAL_FUNC_ENTRY(LOG_STRING);
IVEC_McalCommonErr_e l_xFuncStatus = commonMCAL_SUCCESS;
if (pxUartHandle == NULL)
if (pxUartHandle == NULL || pxUartHandle->eUartPortNumber >= IVEC_MCAL_UART_MAX_PORT)
{
l_xFuncStatus = commonMCAL_INVALID_PARAM;
return commonMCAL_INVALID_PARAM;
goto exit;
}
prvMCAL_UartRegisterHandle(pxUartHandle);
int l_i32Ret = prvMCAL_UART_InitInstance(pxUartHandle, pxUartHandle->xUartConfig.eUartBaudrate);
int l_i32Ret = prvMCAL_UARTInitInstance(pxUartHandle, pxUartHandle->xUartConfig.eUartBaudrate);
if (l_i32Ret != IVEC_CORE_STATUS_SUCCESS)
{
l_xFuncStatus = commonMCAL_INIT_FAIL;

View File

@ -9,6 +9,8 @@
#include <stdlib.h>
#include <string.h>
#define ivECU_MAX_FILTERS ivMCAL_MAX_FILTERS
// Macro Definitions
#define IVEC_ECU_CAN_QUEUE(name, buff) \
volatile IVEC_ECU_CANQueue_s name = { \
@ -56,16 +58,39 @@ typedef struct {
IVEC_ECU_CANBuff_s *buffer;
} IVEC_ECU_CANQueue_s;
// Function Prototypes
void vMCU_FDCAN_RxFifo_Callback(uint32_t ulIdentifier, uint8_t *pucData, uint16_t usDataLength);
uint8_t vMCAL_StoreMsgFromISRToQueue(uint32_t ulId, uint8_t *pucData, uint8_t ucLen);
typedef enum
{
/* data */
IVEC_ECU_CAN_SPEED_125 = 125,
IVEC_ECU_CAN_SPEED_150 = 150,
IVEC_ECU_CAN_SPEED_250 = 250,
IVEC_ECU_CAN_SPEED_500 = 500,
IVEC_ECU_CAN_SPEED_1000 = 1000,
}IVEC_EcuCANSpeed_s;
IVEC_EcuCommonErr_e vECU_CAN_Init(MCAN_Regs *pMCAN, IVEC_CanBaud_e eBaud);
IVEC_EcuCommonErr_e vECU_CAN_DeInit(MCAN_Regs *pMCAN);
IVEC_EcuCommonErr_e vECU_WriteDataOverCAN(uint8_t *pucBuf, uint32_t ulId, int iRetCode, uint32_t ulBufNum);
IVEC_EcuCommonErr_e vECU_CAN_GetData(IVEC_ECU_CANBuff_s *pxBuff);
IVEC_EcuCommonErr_e vECU_CAN_ReInit(MCAN_Regs *pMCAN, uint16_t usSpeed);
IVEC_EcuCommonErr_e vECU_CAN_GetStatus(MCAN_Regs *pMCAN, uint16_t usSpeed);
typedef struct
{
xMcalCanHandle __xCanHandle;
MCAN_Regs *pMCAN;
uint8_t __u8Init;
IVEC_EcuCANSpeed_s u16Speed;
int32_t i32MaskCount;
int32_t i32FilterCount;
uint8_t __u8MaxFilter;
uint32_t u32MaskValues[ivECU_MAX_FILTERS];
uint32_t u32FilterValues[ivECU_MAX_FILTERS];
}IVEC_EcuCANHandle_s;
// Function Prototypes
void vMCU_FDCANRxFifoCallback(uint32_t ulIdentifier, uint8_t *pucData, uint16_t usDataLength);
uint8_t u8MCAL_StoreMsgFromISRToQueue(uint32_t ulId, uint8_t *pucData, uint8_t ucLen);
IVEC_EcuCommonErr_e xECU_CANInit(IVEC_EcuCANHandle_s *xCANhandle);
IVEC_EcuCommonErr_e xECU_CANDeInit(IVEC_EcuCANHandle_s *xCANhandle);
IVEC_EcuCommonErr_e xECU_WriteDataOverCAN(IVEC_EcuCANHandle_s *xCANhandle,uint8_t *pucBuf, uint32_t ulId, int iRetCode, uint32_t ulBufNum);
IVEC_EcuCommonErr_e xECU_CANGetData(IVEC_EcuCANHandle_s *xCANhandle, IVEC_ECU_CANBuff_s *pxBuff);
IVEC_EcuCommonErr_e xECU_CANReInit(IVEC_EcuCANHandle_s *xCANhandle);
IVEC_EcuCommonErr_e xECU_CANGetStatus(IVEC_EcuCANHandle_s *xCANhandle);
#endif /* IVEC_ECU_CAN_H_ */
//

View File

@ -8,25 +8,40 @@ static IVEC_ECU_CANBuff_s g_xCanBuffer[1024] = {0}; /* All the CAN ID, length,
/* Queue for CAN messages */
IVEC_ECU_CAN_QUEUE(g_xCanQueue_x, g_xCanBuffer);
/**
* @brief Callback function for receiving CAN messages and storing them in a queue.
*
* This function is called when a CAN message is received. It checks if the CAN
* queue is full and stores the message in the queue if there is space available.
*
* @param[in] u32Identifier CAN ID of the received message.
* @param[in] pu8Data Pointer to the data of the received CAN message.
* @param[in] u16DataLength Length of the received CAN message data.
*/
/* CAN Receive FIFO Callback function */
void vMCAL_CanReceiveFifoCallback(uint32_t u32Identifier, uint8_t* pu8Data, uint16_t u16DataLength)
{
/* Check if the CAN queue is full */
if (!IVEC_ECU_CAN_IS_FULL(g_xCanQueue_x)) {
/* Store the received message in the queue from the interrupt */
vMCAL_StoreMsgFromISRToQueue(u32Identifier, pu8Data, u16DataLength);
u8MCAL_StoreMsgFromISRToQueue(u32Identifier, pu8Data, u16DataLength);
}
}
/**
* @brief Stores a CAN message from ISR to a queue.
* @brief Stores a CAN message from an interrupt service routine (ISR) to a queue.
*
* @param ulId CAN ID of the message.
* @param pucData Pointer to the CAN data.
* @param ucLen Length of the CAN data.
* This function stores a CAN message with the specified ID and data length into
* the CAN queue.
*
* @param[in] ulId CAN ID of the message.
* @param[in] pucData Pointer to the CAN message data.
* @param[in] ucLen Length of the CAN message data.
* @return uint8_t Status (0 for success, non-zero for failure).
*/
uint8_t vMCAL_StoreMsgFromISRToQueue(uint32_t ulId, uint8_t* pucData, uint8_t ucLen)
uint8_t u8MCAL_StoreMsgFromISRToQueue(uint32_t ulId, uint8_t* pucData, uint8_t ucLen)
{
IVEC_ECU_CANBuff_s xBuff = {0};
xBuff.ulId = ulId;
@ -37,18 +52,30 @@ uint8_t vMCAL_StoreMsgFromISRToQueue(uint32_t ulId, uint8_t* pucData, uint8_t uc
}
/**
* @brief Sends data over CAN.
* @brief Writes data over CAN.
*
* @param pucBuf Pointer to the data buffer.
* @param ulId CAN ID to send the data.
* @param iRetCode Number of bytes to transmit.
* @param ulBufNum CAN buffer number.
* @return IVEC_EcuCommonErr_e Status of the transmission.
* This function writes a data buffer to the CAN bus using the provided CAN
* handle and ID. It processes the buffer, applies a transformation (XOR with 0x0000),
* and attempts to send the data using `xMCAL_MCANTx`.
*
* @param[in] xCANhandle Pointer to the CAN handle structure.
* @param[in] pucBuf Pointer to the buffer containing data to be sent.
* @param[in] u32Id CAN ID for the message.
* @param[in] iRetCode Number of bytes to be written.
* @param[in] u32BufNum Buffer number to be used for transmission.
* @return IVEC_EcuCommonErr_e Status of the operation (`commonECU_SUCCESS` or `commonECU_WRITE_FAIL`).
*/
// Function to write data over CAN
IVEC_EcuCommonErr_e vECU_WriteDataOverCAN(uint8_t* pucBuf, uint32_t u32Id, int iRetCode, uint32_t u32BufNum)
IVEC_EcuCommonErr_e xECU_WriteDataOverCAN(IVEC_EcuCANHandle_s *xCANhandle, uint8_t* pucBuf, uint32_t u32Id, int iRetCode, uint32_t u32BufNum)
{
IVEC_EcuCommonErr_e eFuncStatus = commonECU_WRITE_FAIL;
IVEC_EcuCommonErr_e l_xFuncStatus = commonECU_WRITE_FAIL;
/* Ensure that the MCAN instance is CANFD0 */
if (xCANhandle->__xCanHandle.__u8Init == 0)
{
l_xFuncStatus = commonMCAL_FAIL;
return l_xFuncStatus;
}
uint8_t u8RetCode;
uint16_t au16TxData[8] = {0}; // Define a buffer for the CAN payload data.
@ -57,43 +84,82 @@ IVEC_EcuCommonErr_e vECU_WriteDataOverCAN(uint8_t* pucBuf, uint32_t u32Id, int i
}
int iBytes = iRetCode;
u8RetCode = vMCAL_MCAN_Tx(CANFD0, u32Id, au16TxData, u32BufNum, iBytes);
u8RetCode = xMCAL_MCANTx(&xCANhandle->__xCanHandle, u32Id, au16TxData, u32BufNum, iBytes);
if (u8RetCode == IVEC_MCAL_STATUS_SUCCESS) {
eFuncStatus = commonECU_SUCCESS;
l_xFuncStatus = commonECU_SUCCESS;
}
return eFuncStatus;
return l_xFuncStatus;
}
// Function to get data from the CAN buffer queue
IVEC_EcuCommonErr_e vECU_CAN_GetData(IVEC_ECU_CANBuff_s *pxBuff)
/**
* @brief Retrieves data from the CAN buffer queue.
*
* This function checks if the CAN queue is not empty and, if so, retrieves
* the next CAN message from the queue and copies it into the provided buffer.
*
* @param[in] xCANhandle Pointer to the CAN handle structure.
* @param[out] pxBuff Pointer to the buffer to store the retrieved CAN message.
* @return IVEC_EcuCommonErr_e Status of the operation (`commonECU_SUCCESS` or `commonECU_FAIL`).
*/
IVEC_EcuCommonErr_e xECU_CANGetData(IVEC_EcuCANHandle_s *xCANhandle, IVEC_ECU_CANBuff_s *pxBuff)
{
IVEC_EcuCommonErr_e eFuncStatus = commonECU_FAIL;
IVEC_EcuCommonErr_e l_xFuncStatus = commonECU_FAIL;
/* Ensure that the MCAN instance is CANFD0 */
if (xCANhandle->__xCanHandle.__u8Init == 0)
{
l_xFuncStatus = commonMCAL_FAIL;
return l_xFuncStatus;
}
if (!IVEC_ECU_CAN_IS_EMPTY(g_xCanQueue_x)) {
IVEC_ECU_CANBuff_s xBuff = { 0x00 };
IVEC_ECU_CAN_DEQUEUE(g_xCanQueue_x, xBuff);
memcpy(pxBuff, &xBuff, sizeof(IVEC_ECU_CANBuff_s));
eFuncStatus = commonECU_SUCCESS;
l_xFuncStatus = commonECU_SUCCESS;
}
return eFuncStatus;
return l_xFuncStatus;
}
/* Function to reinitialize the CAN module */
IVEC_EcuCommonErr_e vECU_CAN_ReInit(MCAN_Regs* pMCAN, uint16_t u16Speed)
/**
* @brief Reinitializes the CAN module.
*
* This function attempts to deinitialize and then reinitialize the CAN module,
* ensuring the correct configuration of power, GPIO, and CAN settings. It handles
* errors in the initialization and deinitialization process.
*
* @param[in] xCANhandle Pointer to the CAN handle structure.
* @return IVEC_EcuCommonErr_e Status of the operation (`commonECU_SUCCESS`, `commonECU_ALREADY_DEINIT`,
* `commonECU_DEINIT_FAIL`, or `commonECU_INIT_FAIL`).
*/
IVEC_EcuCommonErr_e xECU_CANReInit(IVEC_EcuCANHandle_s *xCANhandle)
{
IVEC_EcuCommonErr_e l_eFuncStatus = commonECU_SUCCESS;
IVEC_EcuCommonErr_e l_xFuncStatus = commonECU_SUCCESS;
/* Ensure that the MCAN instance is CANFD0 */
assert(xCANhandle->pMCAN == CANFD0);
assert(xCANhandle->u16Speed == IVEC_ECU_CAN_SPEED_250 || xCANhandle->u16Speed == IVEC_ECU_CAN_SPEED_500);
if (xCANhandle->__xCanHandle.__u8Init == 0)
{
l_xFuncStatus = commonECU_ALREADY_DEINIT;
return l_xFuncStatus;
}
IVEC_McalStatus_e l_xMCALStatus;
/* Deinitialize the MCAN module */
l_xMCALStatus = vMCAL_MCAN_DeInit(pMCAN);
l_xMCALStatus = xMCAL_MCANDeInit(&xCANhandle->__xCanHandle);
if (l_xMCALStatus != IVEC_MCAL_STATUS_SUCCESS) {
l_eFuncStatus = commonECU_DEINIT_FAIL;
return l_eFuncStatus;
l_xFuncStatus = commonECU_DEINIT_FAIL;
return l_xFuncStatus;
}
/* Enable power to the MCAN module */
DL_MCAN_enablePower(pMCAN);
DL_MCAN_enablePower(xCANhandle->pMCAN);
delay_cycles(POWER_STARTUP_DELAY);
/* Configure GPIO for CAN TX and RX */
@ -101,61 +167,122 @@ IVEC_EcuCommonErr_e vECU_CAN_ReInit(MCAN_Regs* pMCAN, uint16_t u16Speed)
DL_GPIO_initPeripheralInputFunction(GPIO_MCAN0_IOMUX_CAN_RX, GPIO_MCAN0_IOMUX_CAN_RX_FUNC);
/* Reinitialize the MCAN module */
l_xMCALStatus = vMCAL_MCAN_Init(pMCAN, u16Speed);
l_xMCALStatus = xMCAL_MCANInit(&xCANhandle->__xCanHandle);
/* Check if reinitialization was successful */
if (l_xMCALStatus != IVEC_MCAL_STATUS_SUCCESS) {
l_eFuncStatus = commonECU_INIT_FAIL;
l_xFuncStatus = commonECU_INIT_FAIL;
}
return l_eFuncStatus;
return l_xFuncStatus;
}
/* Function to initialize the CAN module */
IVEC_EcuCommonErr_e vECU_CAN_Init(MCAN_Regs *pMCAN, IVEC_CanBaud_e eBaud)
/**
* @brief Initializes the CAN module.
*
* This function initializes the CAN module with the provided handle and settings.
* It ensures the correct speed configuration and performs the necessary hardware
* initializations.
*
* @param[in] xCANhandle Pointer to the CAN handle structure.
* @return IVEC_EcuCommonErr_e Status of the operation (`commonECU_SUCCESS` or `commonECU_INIT_FAIL`).
*/
IVEC_EcuCommonErr_e xECU_CANInit(IVEC_EcuCANHandle_s *xCANhandle)
{
IVEC_EcuCommonErr_e l_eFuncStatus = commonECU_SUCCESS;
IVEC_EcuCommonErr_e l_xFuncStatus = commonECU_SUCCESS;
/* Ensure that the MCAN instance is CANFD0 */
assert(xCANhandle->pMCAN == CANFD0);
assert(xCANhandle->u16Speed == IVEC_ECU_CAN_SPEED_250 || xCANhandle->u16Speed == IVEC_ECU_CAN_SPEED_500);
if (xCANhandle->__xCanHandle.__u8Init == 1)
{
l_xFuncStatus = commonECU_ALREADY_INIT;
return l_xFuncStatus;
}
xCANhandle->__xCanHandle.pMCAN = xCANhandle->pMCAN;
xCANhandle->__xCanHandle.u16Speed = xCANhandle->u16Speed;
IVEC_McalStatus_e eMcalStatus;
/* Call MCAL initialization function */
eMcalStatus = vMCAL_MCAN_Init(pMCAN, eBaud);
eMcalStatus = xMCAL_MCANInit(&xCANhandle->__xCanHandle);
/* Check if initialization was successful */
if (eMcalStatus != IVEC_MCAL_STATUS_SUCCESS)
{
l_eFuncStatus = commonECU_INIT_FAIL;
l_xFuncStatus = commonECU_INIT_FAIL;
}
return l_eFuncStatus;
return l_xFuncStatus;
}
/* Function to deinitialize the CAN module */
IVEC_EcuCommonErr_e vECU_CAN_DeInit(MCAN_Regs *pMCAN)
/**
* @brief Deinitializes the CAN module.
*
* This function deinitializes the CAN module if it has been initialized.
* It ensures that the CAN module is properly deinitialized by calling the
* MCAL deinitialization function and checks for errors during the process.
*
* @param[in] xCANhandle Pointer to the CAN handle structure.
* @return IVEC_EcuCommonErr_e Status of the operation (`commonECU_SUCCESS`, `commonECU_ALREADY_DEINIT`,
* or `commonECU_INIT_FAIL`).
*/
IVEC_EcuCommonErr_e xECU_CANDeInit(IVEC_EcuCANHandle_s *xCANhandle)
{
IVEC_EcuCommonErr_e l_eFuncStatus = commonECU_SUCCESS;
/* Assert that the MCAN module pointer is valid */
assert(xCANhandle->pMCAN == CANFD0);
IVEC_EcuCommonErr_e l_xFuncStatus = commonECU_SUCCESS;
if (xCANhandle->__xCanHandle.__u8Init == 0)
{
l_xFuncStatus = commonECU_ALREADY_DEINIT;
return l_xFuncStatus;
}
IVEC_McalStatus_e eMcalStatus;
/* Call MCAL deinitialization function */
eMcalStatus = vMCAL_MCAN_DeInit(pMCAN);
eMcalStatus = xMCAL_MCANDeInit(&xCANhandle->__xCanHandle);
/* Check if deinitialization was successful */
if (eMcalStatus != IVEC_MCAL_STATUS_SUCCESS)
{
l_eFuncStatus = commonECU_INIT_FAIL;
l_xFuncStatus = commonECU_INIT_FAIL;
}
return l_eFuncStatus;
return l_xFuncStatus;
}
/* Function to get the status of the CAN module */
IVEC_EcuCommonErr_e vECU_CAN_GetStatus(MCAN_Regs* const pMCAN, uint16_t u16Speed)
/**
* @brief Retrieves the status of the CAN module.
*
* This function checks the current status of the CAN module. If the module is
* initialized, it retrieves the error status. If an error is detected, it attempts
* to reinitialize the CAN module.
*
* @param[in] xCANhandle Pointer to the CAN handle structure.
* @return IVEC_EcuCommonErr_e Status of the operation (`commonECU_SUCCESS`, `commonMCAL_FAIL`).
*/
IVEC_EcuCommonErr_e xECU_CANGetStatus(IVEC_EcuCANHandle_s *xCANhandle)
{
IVEC_EcuCommonErr_e l_eFuncStatus = commonECU_SUCCESS;
/* Ensure that the MCAN instance is CANFD0 */
assert(xCANhandle->pMCAN == CANFD0);
assert(xCANhandle->u16Speed == IVEC_ECU_CAN_SPEED_250 || xCANhandle->u16Speed == IVEC_ECU_CAN_SPEED_500);
IVEC_EcuCommonErr_e l_xFuncStatus = commonECU_SUCCESS;
if (xCANhandle->__xCanHandle.__u8Init == 0)
{
l_xFuncStatus = commonMCAL_FAIL;
return l_xFuncStatus;
}
char cErrorString[32] = {0};
/* Retrieve the MCAN error status */
if (vMCAL_MCAN_GetErrorStatus(cErrorString) == IVEC_MCAL_STATUS_ERROR)
if (xMCAL_MCANGetErrorStatus(&xCANhandle->__xCanHandle, cErrorString) == IVEC_MCAL_STATUS_ERROR)
{
/* Reinitialize CAN if an error is detected */
l_eFuncStatus = vECU_CAN_ReInit(pMCAN, u16Speed);
l_xFuncStatus = xECU_CANReInit(xCANhandle);
}
return l_eFuncStatus;
return l_xFuncStatus;
}

View File

@ -24,6 +24,30 @@
/*Private Variables*/
typedef int IVEC_ECU_UartPacketRetCode_e;/*SERVICE_SUCESS or SERVICE_FAIL*/
typedef enum
{
eEcuUartBaudAuto = 0,
eEcuUartBaud2400 = 2400,
eEcuUartBaud4800 = 4800,
eEcuUartBaud9600 = 9600,
eEcuUartBaud14400 = 14400,
eEcuUartBaud19200 = 19200,
eEcuUartBaud28800 = 28800,
eEcuUartBaud33600 = 33600,
eEcuUartBaud38400 = 38400,
eEcuUartBaud57600 = 57600,
eEcuUartBaud115200 = 115200,
eEcuUartBaud230400 = 230400,
eEcuUartBaud460800 = 460800,
eEcuUartBaud921600 = 921600,
eEcuUartBaud1000000 = 1000000,
eEcuUartBaud1843200 = 1843200,
eEcuUartBaud2000000 = 2000000,
eEcuUartBaud2100000 = 2100000,
eEcuUartBaud3686400 = 3686400,
eEcuUartBaud4000000 = 4000000,
eEcuUartBaud4468750 = 4468750
} eEcuUartBaudRate;
typedef enum
@ -48,6 +72,7 @@ typedef struct
volatile uint8_t* u8Qbuffer;
uint16_t u16QbufSize;
uint16_t u16len;
eEcuUartBaudRate u32BaudRate;
void (*pvUartRecvCallback)(IVEC_ECU_UartPortNumber_e, IVEC_ECU_UartEvent_e , char *, uint32_t);
} IVEC_ECU_UartHandle_s;
@ -55,14 +80,13 @@ typedef struct
* Functions declaration
===========================================================================*/
IVEC_EcuCommonErr_e xECU_UartInit(IVEC_ECU_UartHandle_s* uartHandle);
IVEC_EcuCommonErr_e xECU_UartDeinit(IVEC_ECU_UartHandle_s *uartHandle);
IVEC_EcuCommonErr_e xECU_UartReinit(IVEC_ECU_UartHandle_s *uartHandle);
IVEC_EcuCommonErr_e xECU_UartTransmit(IVEC_ECU_UartHandle_s *uartHandle, uint8_t* buffer, uint16_t len);
IVEC_EcuCommonErr_e xECU_UartGetData(IVEC_ECU_UartHandle_s *uartHandle, uint8_t* buffer, uint16_t len, uint16_t timeout);
IVEC_EcuCommonErr_e IVEC_ECU_Uart_Init(IVEC_ECU_UartHandle_s* uartHandle, uint32_t speed);
IVEC_EcuCommonErr_e IVEC_ECU_Uart_Deinit(IVEC_ECU_UartHandle_s *uartHandle);
IVEC_EcuCommonErr_e IVEC_ECU_Uart_Reinit(IVEC_ECU_UartHandle_s *uartHandle, uint32_t speed);
IVEC_EcuCommonErr_e IVEC_ECU_Uart_Transmit(IVEC_ECU_UartHandle_s *uartHandle, uint8_t* buffer, uint16_t len);
IVEC_EcuCommonErr_e IVEC_ECU_Uart_GetData(IVEC_ECU_UartHandle_s *uartHandle, uint8_t* buffer, uint16_t len, uint16_t timeout);
IVEC_ECU_UartPacketRetCode_e IVEC_ECU_Uart_FormatPacket(IVEC_ECU_UartHandle_s *uartHandle, uint8_t* data, uint8_t dlc, uint32_t id);
IVEC_ECU_UartPacketRetCode_e IVEC_ECU_Uart_ReadCANDataLenOverUART(IVEC_ECU_UartHandle_s *uartHandle, uint8_t* buffer, uint32_t *id);
IVEC_ECU_UartPacketRetCode_e IVEC_ECU_Uart_ReadCANDataOverUART(IVEC_ECU_UartHandle_s* uartHandle, uint8_t* buffer, uint32_t *id);
int IVEC_ECU_Uart_InitiateTransmit(IVEC_ECU_UartHandle_s* uartHandle, uint32_t id, uint8_t *data, uint8_t len);
IVEC_ECU_UartPacketRetCode_e xECU_UartFormatPacket(IVEC_ECU_UartHandle_s *uartHandle, uint8_t* data, uint8_t dlc, uint32_t id);
IVEC_ECU_UartPacketRetCode_e xECU_UartReadCANDataLenOverUART(IVEC_ECU_UartHandle_s *uartHandle, uint8_t* buffer, uint32_t *id);
IVEC_ECU_UartPacketRetCode_e xECU_UartReadCANDataOverUART(IVEC_ECU_UartHandle_s* uartHandle, uint8_t* buffer, uint32_t *id);
int32_t iECU_UartInitiateTransmit(IVEC_ECU_UartHandle_s* uartHandle, uint32_t id, uint8_t *data, uint8_t len);

View File

@ -1,4 +1,4 @@
#include "../ivec_ECU/ivec_ecu_uart/inc/ivec_ecu_uart.h"
#include "../ivec_ECU/ivec_ecu_uart/inc/ivec_ecu_uart.h"
#include "ivec_cmplx_queue.h"
#include "../Core/Include/ivec_mcal_uart.h"
@ -9,9 +9,19 @@
volatile static CmplxFifoQueueHandle_s __gprv_EcuUartResponseQueue[IVEC_MCAL_UART_MAX_PORT] = { 0 };
//static uint8_t __gprv_u8NFCUartDataBuffer[NFC_UART_BUFFER_MAX_SIZE];
/**
* @brief UART receive callback for processing received data.
*
* This function is invoked when data is received over UART on different UART ports.
* The received data is enqueued into the appropriate FIFO queue based on the UART port.
*
* @param[in] uartPort The UART port number where the data was received.
* @param[in] eventType The event type indicating the status of the UART reception.
* @param[in] pucBuffer Pointer to the received data buffer.
* @param[in] u32Size Size of the received data buffer.
*/
static void __prv_vEcu_CANOverUartMsgCallback(eMcalUartPortNumber uartPort, IVEC_ECU_UartEvent_e eventType, char* pucBuffer, uint32_t u32Size)
static void __prvEcu_CANOverUartMsgCallback(eMcalUartPortNumber uartPort, IVEC_ECU_UartEvent_e eventType, char* pucBuffer, uint32_t u32Size)
{
switch (uartPort)
{
@ -29,8 +39,20 @@ static void __prv_vEcu_CANOverUartMsgCallback(eMcalUartPortNumber uartPort, IVEC
break;
}
}
/**
* @brief Calculates the checksum for the given packet.
*
* This function computes a two-byte checksum for the provided data packet. The
* checksum is calculated by summing the bytes of the packet (excluding the sync data),
* with each byte of the checksum being constrained to 8 bits.
*
* @param[in] pkt Pointer to the packet data for which the checksum is to be calculated.
* @param[in] len Length of the packet data.
* @param[out] checksum Pointer to a buffer where the calculated checksum will be stored.
* The checksum consists of two bytes.
*/
static void IVEC_ECU_CalculateChecksum(uint8_t* pkt, int len, uint8_t* checksum) {
static void _prvECU_CalculateChecksum(uint8_t* pkt, int len, uint8_t* checksum) {
uint8_t checksum_a = 0, checksum_b = 0;
/* Incremented to ignore Sync data */
for (int i = 2; i < len - 2; i++) {
@ -43,10 +65,38 @@ static void IVEC_ECU_CalculateChecksum(uint8_t* pkt, int len, uint8_t* checksum)
checksum[1] = checksum_b;
}
//IVEC_EcuCommonErr_e
/**
* @brief Initializes UART with specified configurations and a FIFO queue.
*
* This function initializes the UART interface by configuring the UART port,
* setting up the receive callback, and initializing the FIFO queue for the
* specified UART port. It also sets the UART parameters such as baud rate,
* flow control, data bits, stop bits, and parity bits.
*
* @param[in] prvUartHandle Pointer to the UART handle structure containing
* UART port configuration and queue settings.
*
* @return IVEC_EcuCommonErr_e Status of the initialization process:
* - `commonECU_SUCCESS`: Initialization was successful.
* - `commonECU_INIT_FAIL`: Initialization failed.
*
* @details
* - The function validates the UART port number and configures the appropriate
* FIFO queue for receiving data.
* - Initializes the UART configuration with provided parameters (baud rate, flow control,
* data bits, stop bits, and parity).
* - Sets the UART receive callback to `__prvEcu_CANOverUartMsgCallback`.
* - If the initialization of the FIFO queue or UART fails, the function returns
* `commonECU_INIT_FAIL`.
*/
IVEC_EcuCommonErr_e IVEC_ECU_Uart_Init(IVEC_ECU_UartHandle_s* prvUartHandle, uint32_t speed)
IVEC_EcuCommonErr_e xECU_UartInit(IVEC_ECU_UartHandle_s* prvUartHandle)
{
if (prvUartHandle->eUartPortNumber >= IVEC_MCAL_UART_MAX_PORT)
{
return commonMCAL_INIT_FAIL;
}
IVEC_ECU_FUNC_ENTRY(LOG_STRING);
IVEC_EcuCommonErr_e l_xFuncStatus = commonECU_SUCCESS;
uint8_t l_i32Ret = 0;
@ -83,9 +133,8 @@ IVEC_EcuCommonErr_e IVEC_ECU_Uart_Init(IVEC_ECU_UartHandle_s* prvUartHandle, uin
IVEC_ECU_LOG(LOG_STRING, "Initializing UART");
prvUartHandle->__xUartHandle.pvUartRecvCallback = __prv_vEcu_CANOverUartMsgCallback;
prvUartHandle->__xUartHandle.xUartConfig.eUartBaudrate = speed;
prvUartHandle->__xUartHandle.pvUartRecvCallback = __prvEcu_CANOverUartMsgCallback;
prvUartHandle->__xUartHandle.xUartConfig.eUartBaudrate = prvUartHandle->u32BaudRate;
prvUartHandle->__xUartHandle.eUartPortNumber = prvUartHandle->eUartPortNumber;
prvUartHandle->__xUartHandle.xUartConfig.eUartFlowCtrl = eMcalUartFcNone;
prvUartHandle->__xUartHandle.xUartConfig.eUartDataBit = eMcalUartDataBit8;
@ -103,11 +152,34 @@ exit:
IVEC_ECU_FUNC_EXIT(LOG_STRING, 0);
return l_xFuncStatus;
}
/**
* @brief Deinitializes the UART interface.
*
* This function deinitializes the UART interface by flushing the associated FIFO
* queue and calling the `xMCAL_UartDeInit` function. If the UART port number is invalid
* or the UART handle is NULL, it returns an initialization failure status.
*
* @param[in] prvUartHandle Pointer to the UART handle structure to be deinitialized.
*
* @return IVEC_EcuCommonErr_e Status of the deinitialization:
* - `commonECU_SUCCESS`: Deinitialization was successful.
* - `commonECU_INIT_FAIL`: UART port is invalid or initialization failed.
* - `commonECU_DEINIT_FAIL`: UART deinitialization failed.
* - `commonECU_ALREADY_DEINIT`: UART handle is NULL, indicating it's already deinitialized.
*
* @details
* - The function first validates the UART handle and port number.
* - It then calls `xMCAL_UartDeInit` to deinitialize the UART hardware.
* - If the deinitialization fails, it returns `commonECU_DEINIT_FAIL`.
* - If successful, it flushes the UART response queue.
*/
IVEC_EcuCommonErr_e IVEC_ECU_Uart_Deinit(IVEC_ECU_UartHandle_s* prvUartHandle)
IVEC_EcuCommonErr_e xECU_UartDeinit(IVEC_ECU_UartHandle_s* prvUartHandle)
{
if (prvUartHandle == NULL || prvUartHandle->eUartPortNumber >= IVEC_MCAL_UART_MAX_PORT)
{
return commonECU_INIT_FAIL;
}
IVEC_ECU_FUNC_ENTRY(LOG_STRING);
uint8_t l_i32Ret;
IVEC_EcuCommonErr_e l_xFuncStatus = commonECU_SUCCESS;
@ -122,7 +194,7 @@ IVEC_EcuCommonErr_e IVEC_ECU_Uart_Deinit(IVEC_ECU_UartHandle_s* prvUartHandle)
l_i32Ret = xMCAL_UartDeInit(&prvUartHandle->__xUartHandle);
if (l_i32Ret != IVEC_MCAL_STATUS_SUCCESS)
{
l_xFuncStatus = commonECU_INIT_FAIL;
l_xFuncStatus = commonECU_DEINIT_FAIL;
goto exit;
}
@ -135,14 +207,36 @@ exit:
IVEC_ECU_FUNC_EXIT(LOG_STRING, 0);
return l_xFuncStatus;
}
/**
* @brief Reinitializes the UART interface.
*
* This function first deinitializes the UART interface using `xECU_UartDeinit`,
* and then reinitializes it with the new configuration using `xECU_UartInit`.
*
* @param[in] prvUartHandle Pointer to the UART handle structure to be reinitialized.
*
* @return IVEC_EcuCommonErr_e Status of the reinitialization:
* - `commonECU_SUCCESS`: Reinitialization was successful.
* - `commonECU_INIT_FAIL`: UART initialization failed.
* - `commonECU_DEINIT_FAIL`: UART deinitialization failed.
*
* @details
* - The function first deinitializes the UART by calling `xECU_UartDeinit`.
* - If the deinitialization is successful, it then calls `xECU_UartInit` to reinitialize the UART.
* - If any step fails, the function returns an appropriate error status.
*/
IVEC_EcuCommonErr_e IVEC_ECU_Uart_Reinit(IVEC_ECU_UartHandle_s* prvUartHandle, uint32_t speed)
IVEC_EcuCommonErr_e xECU_UartReinit(IVEC_ECU_UartHandle_s* prvUartHandle)
{
if (prvUartHandle == NULL || prvUartHandle->eUartPortNumber >= IVEC_MCAL_UART_MAX_PORT)
{
return commonECU_INIT_FAIL;
}
IVEC_EcuCommonErr_e l_xFuncStatus = commonECU_SUCCESS;
uint8_t l_i32Ret;
// Deinitialize UART
l_i32Ret = IVEC_ECU_Uart_Deinit(prvUartHandle);
l_i32Ret = xECU_UartDeinit(prvUartHandle);
if (l_i32Ret != IVEC_MCAL_STATUS_SUCCESS)
{
l_xFuncStatus = commonECU_DEINIT_FAIL;
@ -150,7 +244,7 @@ IVEC_EcuCommonErr_e IVEC_ECU_Uart_Reinit(IVEC_ECU_UartHandle_s* prvUartHandle, u
}
// Reinitialize UART with the new speed
l_i32Ret = IVEC_ECU_Uart_Init(prvUartHandle, speed);
l_i32Ret = xECU_UartInit(prvUartHandle);
if (l_i32Ret != IVEC_MCAL_STATUS_SUCCESS)
{
l_xFuncStatus = commonECU_INIT_FAIL;
@ -159,69 +253,182 @@ IVEC_EcuCommonErr_e IVEC_ECU_Uart_Reinit(IVEC_ECU_UartHandle_s* prvUartHandle, u
exit:
return l_xFuncStatus;
}
/**
* @brief Transmits data over UART.
*
* This function is a placeholder and currently does not transmit data.
* It returns a failure status as the implementation is not provided.
*
* @param[in] prvUartHandle Pointer to the UART handle structure.
* @param[in] pucBuffer Pointer to the data buffer to be transmitted.
* @param[in] len Length of the data to be transmitted.
*
* @return IVEC_EcuCommonErr_e Status of the transmission:
* - `commonECU_FAIL`: Transmission is not implemented.
*/
IVEC_EcuCommonErr_e IVEC_ECU_Uart_Transmit(IVEC_ECU_UartHandle_s* prvUartHandle, uint8_t* pucBuffer, uint16_t len)
IVEC_EcuCommonErr_e xECU_UartTransmit(IVEC_ECU_UartHandle_s* prvUartHandle, uint8_t* pucBuffer, uint16_t len)
{
return commonECU_SUCCESS;
return commonECU_FAIL;
}
/**
* @brief Flushes the UART response queue.
*
* This function clears the response queue associated with the specified UART port.
*
* @param[in] prvUartHandle Pointer to the UART handle structure.
*
* @return IVEC_EcuCommonErr_e Status of the flush operation:
* - `commonECU_SUCCESS`: Queue was flushed successfully.
* - `commonECU_FAIL`: The UART handle is invalid or the port number is out of range.
*
* @details
* - The function checks if the UART handle is valid and if the port number is within the allowed range.
* - It then flushes the FIFO queue associated with the UART response queue for the specified port.
*/
IVEC_EcuCommonErr_e IVEC_ECU_UART_Flush(IVEC_ECU_UartHandle_s* prvUartHandle)
IVEC_EcuCommonErr_e xECU_UartFlush(IVEC_ECU_UartHandle_s* prvUartHandle)
{
if (prvUartHandle == NULL || prvUartHandle->eUartPortNumber >= IVEC_MCAL_UART_MAX_PORT)
{
vCMPLX_FifoQueueFlush((CmplxFifoQueueHandle_s*)&__gprv_EcuUartResponseQueue[prvUartHandle->eUartPortNumber]);
return commonECU_FAIL;
}
vCMPLX_FifoQueueFlush((CmplxFifoQueueHandle_s*)&__gprv_EcuUartResponseQueue[prvUartHandle->eUartPortNumber]);
return commonECU_SUCCESS;
}
/**
* @brief Retrieves data from the UART response queue.
*
* This function retrieves data from the UART response queue within a specified timeout period.
* If the data is available, it copies the data into the provided buffer. If data is not available
* within the timeout, it returns an error.
*
* @param[in] prvUartHandle Pointer to the UART handle structure.
* @param[out] pucBuffer Pointer to the buffer where the received data will be stored.
* @param[in] len Length of the data to be received.
* @param[in] timeout Timeout period in milliseconds.
*
* @return IVEC_EcuCommonErr_e Status of the data retrieval:
* - `commonECU_SUCCESS`: Data was retrieved successfully.
* - `commonECU_INVALID_PARAM`: Invalid UART handle or port number.
* - `commonECU_READ_FAIL`: Data could not be read within the timeout.
*
* @details
* - The function validates the UART handle and port number.
* - It checks the FIFO queue for available data and retrieves it into the provided buffer.
* - If data is not available within the timeout period, it returns `commonECU_READ_FAIL`.
* - Interrupts are disabled during the dequeue operation to ensure data integrity.
*/
IVEC_EcuCommonErr_e IVEC_ECU_Uart_GetData(IVEC_ECU_UartHandle_s* prvUartHandle, uint8_t* pucBuffer, uint16_t len, uint16_t timeout)
IVEC_EcuCommonErr_e xECU_UartGetData(IVEC_ECU_UartHandle_s* prvUartHandle, uint8_t* pucBuffer, uint16_t len, uint16_t timeout)
{
IVEC_ECU_FUNC_ENTRY(LOG_STRING);
IVEC_EcuCommonErr_e l_xFuncStatus = commonECU_SUCCESS;
// Validate parameters
if (prvUartHandle == NULL || prvUartHandle->eUartPortNumber >= IVEC_MCAL_UART_MAX_PORT)
{
l_xFuncStatus = commonECU_INVALID_PARAM;
goto exit;
}
uint8_t ijk = 0;
int l_u32Len = 0;
uint16_t l_u16Len = 0;
uint32_t u32CommTimestamp = i32MCAL_GetTicks();
// Loop until timeout or buffer is filled
while (((i32MCAL_GetTicks() - u32CommTimestamp) <= timeout + 1) && (ijk < len))
while(((i32MCAL_GetTicks() - u32CommTimestamp) <= timeout+1) && (l_u16Len < len))
{
if (!u8CMPLX_FifoQueueEmpty((CmplxFifoQueueHandle_s*)&__gprv_EcuUartResponseQueue[prvUartHandle->eUartPortNumber]))
{
if (u8CMPLX_FifoDequeue((CmplxFifoQueueHandle_s*)&__gprv_EcuUartResponseQueue[prvUartHandle->eUartPortNumber], &pucBuffer[ijk], &l_u32Len, 0) == 1)
ijk++;
}
l_u16Len = i32CMPLX_FifoCounts((CmplxFifoQueueHandle_s*)&__gprv_EcuUartResponseQueue[prvUartHandle->eUartPortNumber]);
}
// Check if all requested data was received
if (ijk != len)
if (l_u16Len < len)
{
l_xFuncStatus = commonECU_READ_FAIL;
goto exit;
}
else
{
int i32Len = 0;
__disable_irq();//disabling interrupt to avoid enqueing while dequeing
for(int i=0;i<len;i++)
{
u8CMPLX_FifoDequeue((CmplxFifoQueueHandle_s*)&__gprv_EcuUartResponseQueue[prvUartHandle->eUartPortNumber], &pucBuffer[i], &i32Len, 0);
exit:
}
__enable_irq();
}
exit:
IVEC_ECU_FUNC_EXIT(LOG_STRING, 0);
return l_xFuncStatus;
}
//IVEC_EcuCommonErr_e xECU_UartGetData(IVEC_ECU_UartHandle_s* prvUartHandle, uint8_t* pucBuffer, uint16_t len, uint16_t timeout)
//{
// IVEC_ECU_FUNC_ENTRY(LOG_STRING);
//
// IVEC_EcuCommonErr_e l_xFuncStatus = commonECU_SUCCESS;
//
// // Validate parameters
// if (prvUartHandle == NULL || prvUartHandle->eUartPortNumber >= IVEC_MCAL_UART_MAX_PORT)
// {
// l_xFuncStatus = commonECU_INVALID_PARAM;
// goto exit;
// }
//
// uint8_t ijk = 0;
// int l_u32Len = 0;
// uint32_t u32CommTimestamp = i32MCAL_GetTicks();
//
// // Loop until timeout or buffer is filled
// while (((i32MCAL_GetTicks() - u32CommTimestamp) <= timeout + 1) && (ijk < len))
// {
// if (!u8CMPLX_FifoQueueEmpty((CmplxFifoQueueHandle_s*)&__gprv_EcuUartResponseQueue[prvUartHandle->eUartPortNumber]))
// {
// if (u8CMPLX_FifoDequeue((CmplxFifoQueueHandle_s*)&__gprv_EcuUartResponseQueue[prvUartHandle->eUartPortNumber], &pucBuffer[ijk], &l_u32Len, 0) == 1)
// ijk++;
// }
// }
//
// // Check if all requested data was received
// if (ijk != len)
// {
// l_xFuncStatus = commonECU_READ_FAIL;
// goto exit;
// }
//
//exit:
// IVEC_ECU_FUNC_EXIT(LOG_STRING, 0);
// return l_xFuncStatus;
//}
IVEC_ECU_UartPacketRetCode_e IVEC_ECU_Uart_ReadCANDataLenOverUART(IVEC_ECU_UartHandle_s* prvUartHandle, uint8_t* pucBuf, uint32_t* ulId)
/**
* @brief Reads and validates CAN data length over UART.
*
* This function reads data from the UART, checks packet synchronization, calculates
* the packet length, and verifies the checksum. It handles various conditions and
* returns the packet length or failure code.
*
* @param[in] prvUartHandle Pointer to the UART handle for communication.
* @param[out] pucBuf Buffer to store the received data.
* @param[out] ulId Pointer to store the extracted CAN ID.
*
* @return The packet length on success, or a failure code:
* - `commonECU_READ_FAIL` if the read operation or checksum validation fails.
* - `IVEC_ECU_UART_PACKET_FAIL` if the packet synchronization is lost.
*/
IVEC_ECU_UartPacketRetCode_e xECU_UartReadCANDataLenOverUART(IVEC_ECU_UartHandle_s* prvUartHandle, uint8_t* pucBuf, uint32_t* ulId)
{
int PktLen = commonECU_READ_FAIL;
if ((IVEC_ECU_Uart_GetData(prvUartHandle, (uint8_t*)&pucBuf[0], 1, 0) == commonECU_SUCCESS))
if ((xECU_UartGetData(prvUartHandle, (uint8_t*)&pucBuf[0], 1, 0) == commonECU_SUCCESS))
{
if (pucBuf[0] == 0xB5)
{
if (IVEC_ECU_Uart_GetData(prvUartHandle, (uint8_t*)&pucBuf[1], 1, 5) == commonECU_SUCCESS) {
if (xECU_UartGetData(prvUartHandle, (uint8_t*)&pucBuf[1], 1, 5) == commonECU_SUCCESS) {
if (pucBuf[1] != 0x62) {
PktLen = commonECU_READ_FAIL;
goto EXIT; // 0x62 not found, OUT OF SYNC
@ -232,7 +439,7 @@ IVEC_ECU_UartPacketRetCode_e IVEC_ECU_Uart_ReadCANDataLenOverUART(IVEC_ECU_UartH
PktLen = commonECU_READ_FAIL;
goto EXIT;
}
if (IVEC_ECU_Uart_GetData(prvUartHandle, (uint8_t*)&pucBuf[2], 5, DATA_PACKET_TIMEOUT_MS) != commonECU_SUCCESS) {
if (xECU_UartGetData(prvUartHandle, (uint8_t*)&pucBuf[2], 5, DATA_PACKET_TIMEOUT_MS) != commonECU_SUCCESS) {
PktLen = commonECU_READ_FAIL;
goto EXIT;
}
@ -240,13 +447,13 @@ IVEC_ECU_UartPacketRetCode_e IVEC_ECU_Uart_ReadCANDataLenOverUART(IVEC_ECU_UartH
*(ulId) = (uint32_t)((pucBuf[6] << 24) | (pucBuf[5] << 16) | (pucBuf[4] << 8) | (pucBuf[3]));
uint8_t l_ucTempLen = pucBuf[2];
PktLen = IVEC_ECU_UART_PKT_HEADER_FOOTER + l_ucTempLen;
if (IVEC_ECU_Uart_GetData(prvUartHandle, (uint8_t*)&pucBuf[IVEC_ECU_UART_PKT_HEADER], (uint32_t)(PktLen - IVEC_ECU_UART_PKT_HEADER), DATA_PACKET_TIMEOUT_MS) != commonECU_SUCCESS)
if (xECU_UartGetData(prvUartHandle, (uint8_t*)&pucBuf[IVEC_ECU_UART_PKT_HEADER], (uint32_t)(PktLen - IVEC_ECU_UART_PKT_HEADER), DATA_PACKET_TIMEOUT_MS) != commonECU_SUCCESS)
{
PktLen = commonECU_READ_FAIL;
goto EXIT;
}
uint8_t checksum[2];
IVEC_ECU_CalculateChecksum(pucBuf, PktLen, checksum);
_prvECU_CalculateChecksum(pucBuf, PktLen, checksum);
/* TODO: (Python Script) Sometimes fails due to bad checksum */
if ((checksum[0] == pucBuf[PktLen - 2]) && (checksum[1] == pucBuf[PktLen - 1])) {
@ -267,14 +474,46 @@ IVEC_ECU_UartPacketRetCode_e IVEC_ECU_Uart_ReadCANDataLenOverUART(IVEC_ECU_UartH
EXIT:
return PktLen;
}
IVEC_ECU_UartPacketRetCode_e IVEC_ECU_Uart_ReadCANDataOverUART(IVEC_ECU_UartHandle_s* prvUartHandle, uint8_t* pucBuf, uint32_t* ulId)
/**
* @brief Reads CAN data over UART and returns the packet length.
*
* This function first validates the UART handle and checks the packet
* length over UART by calling `xECU_UartReadCANDataLenOverUART`.
* It returns the result based on the outcome of that function.
*
* @param[in] prvUartHandle Pointer to the UART handle for communication.
* @param[out] pucBuf Buffer to store the received data.
* @param[out] ulId Pointer to store the extracted CAN ID.
*
* @return The result of reading the CAN data over UART.
* - `IVEC_ECU_UART_PACKET_FAIL` if the UART handle is invalid or the
* packet read fails.
*/
IVEC_ECU_UartPacketRetCode_e xECU_UartReadCANDataOverUART(IVEC_ECU_UartHandle_s* prvUartHandle, uint8_t* pucBuf, uint32_t* ulId)
{
if (prvUartHandle == NULL || prvUartHandle->eUartPortNumber >= IVEC_MCAL_UART_MAX_PORT)
{
return IVEC_ECU_UART_PACKET_FAIL;
}
IVEC_ECU_UartPacketRetCode_e retCode = IVEC_ECU_UART_PACKET_FAIL;
retCode = IVEC_ECU_Uart_ReadCANDataLenOverUART(prvUartHandle, pucBuf, ulId);
retCode = xECU_UartReadCANDataLenOverUART(prvUartHandle, pucBuf, ulId);
return retCode;
}
/**
* @brief Writes data to UART.
*
* This function writes a buffer of data to the UART, returning a success
* or failure status based on the outcome of the write operation.
*
* @param[in] prvUartHandle Pointer to the UART handle for communication.
* @param[in] pucBuffer Pointer to the buffer containing the data to send.
* @param[in] len Length of the data to send.
*
* @return Status of the write operation:
* - `commonECU_SUCCESS` if successful.
* - `commonECU_INVALID_PARAM` if the UART handle is invalid.
* - `commonECU_WRITE_FAIL` if the write operation fails.
*/
IVEC_EcuCommonErr_e IVEC_ECU_Uart_Write(IVEC_ECU_UartHandle_s* prvUartHandle, uint8_t* pucBuffer, uint16_t len)
{
IVEC_EcuCommonErr_e l_xFuncStatus = commonECU_WRITE_FAIL;
@ -293,15 +532,29 @@ IVEC_EcuCommonErr_e IVEC_ECU_Uart_Write(IVEC_ECU_UartHandle_s* prvUartHandle, ui
return l_xFuncStatus;
}
IVEC_ECU_UartPacketRetCode_e IVEC_ECU_Uart_FormatPacket(IVEC_ECU_UartHandle_s* prvUartHandle, uint8_t* pucData, uint8_t ucDlc, uint32_t ulId)
/**
* @brief Formats and prepares a UART packet for transmission.
*
* This function formats a packet with a sync character, data length, CAN ID,
* and checksum, and then sends it via UART using `IVEC_ECU_Uart_Write`.
*
* @param[in] prvUartHandle Pointer to the UART handle for communication.
* @param[in] pucData Pointer to the data buffer to format.
* @param[in] ucDlc Data length code (DLC) for the packet.
* @param[in] ulId CAN ID to be included in the packet.
*
* @return Status of the packet formatting:
* - `IVEC_ECU_UART_PACKET_SUCCESS` if successful.
* - `IVEC_ECU_UART_PACKET_FAIL` if the packet formatting or write fails.
*/
IVEC_ECU_UartPacketRetCode_e xECU_UartFormatPacket(IVEC_ECU_UartHandle_s* prvUartHandle, uint8_t* pucData, uint8_t ucDlc, uint32_t ulId)
{
pucData[0] = 0xb5; // SYNC_CHAR[0]
pucData[1] = 0x62; // SYNC_CHAR[1]
pucData[2] = ucDlc;
memcpy(&pucData[3], &ulId, sizeof(uint32_t));
unsigned char checksum[2] = { 0 };
IVEC_ECU_CalculateChecksum(pucData, (ucDlc + IVEC_ECU_UART_PKT_HEADER_FOOTER), checksum);
_prvECU_CalculateChecksum(pucData, (ucDlc + IVEC_ECU_UART_PKT_HEADER_FOOTER), checksum);
pucData[(ucDlc + IVEC_ECU_UART_PKT_HEADER_FOOTER) - 2] = checksum[0];
pucData[(ucDlc + IVEC_ECU_UART_PKT_HEADER_FOOTER) - 1] = checksum[1];
if (IVEC_ECU_Uart_Write(prvUartHandle, pucData, (ucDlc + IVEC_ECU_UART_PKT_HEADER_FOOTER)) != commonECU_SUCCESS) {
@ -309,10 +562,28 @@ IVEC_ECU_UartPacketRetCode_e IVEC_ECU_Uart_FormatPacket(IVEC_ECU_UartHandle_s* p
}
return IVEC_ECU_UART_PACKET_SUCCESS;
}
int IVEC_ECU_Uart_InitiateTransmit(IVEC_ECU_UartHandle_s* prvUartHandle, uint32_t id, uint8_t* pucData, uint8_t ucLen)
/**
* @brief Initiates UART data transmission.
*
* This function prepares a data packet with the given CAN ID and data,
* formats the packet, and sends it via UART.
*
* @param[in] prvUartHandle Pointer to the UART handle for communication.
* @param[in] id CAN ID for the packet.
* @param[in] pucData Pointer to the data to send.
* @param[in] ucLen Length of the data to send.
*
* @return Status of the transmission:
* - `0` on success.
* - `-1` on failure.
*/
int32_t iECU_UartInitiateTransmit(IVEC_ECU_UartHandle_s* prvUartHandle, uint32_t id, uint8_t* pucData, uint8_t ucLen)
{
if (prvUartHandle == NULL || prvUartHandle->eUartPortNumber >= IVEC_MCAL_UART_MAX_PORT)
{
return commonECU_INIT_FAIL;
}
uint8_t pucBuf[IVEC_ECU_UART_MAX_PACKET_LENGTH] = { 0 };
memcpy(&pucBuf[IVEC_ECU_UART_PKT_HEADER], pucData, ucLen);
return (IVEC_ECU_Uart_FormatPacket(prvUartHandle, pucBuf, ucLen, id) == IVEC_ECU_UART_PACKET_SUCCESS) ? 0 : -1;
return (xECU_UartFormatPacket(prvUartHandle, pucBuf, ucLen, id) == IVEC_ECU_UART_PACKET_SUCCESS) ? 0 : -1;
}

View File

@ -19,6 +19,7 @@
// UART Handles
IVEC_ECU_UartHandle_s g_xEcuUartHandle;
IVEC_ECU_UartHandle_s g_xEcuUart2Handle;
IVEC_EcuCANHandle_s g_xEcuCanHandle;
// Configuration Macros
#define ivECU_CONFIG_BASIL_BATTERY_SMART 1
@ -28,8 +29,7 @@ IVEC_ECU_UartHandle_s g_xEcuUart2Handle;
#define ivECU_UART_PIN_SELECTION ivECU_CONFIG_BASIL_BATTERY_SMART
// Global Variables
uint32_t g_u32UartSpeed = 0;
IVEC_CanBaud_e g_eCanSpeed = 0;
xMCAL_CanBaud_e g_eCanSpeed = 0;
uint8_t g_pu8UartBuffer[IVEC_ECU_UART_MAX_PACKET_LENGTH] = {0};
volatile uint32_t g_u32CanId = 0x1FFFFFFF;
@ -38,14 +38,8 @@ volatile uint32_t g_u32CanId = 0x1FFFFFFF;
volatile uint8_t g_prvU8CanUartDataBuffer[ivECU_CAN_UART_BUFFER_MAX_SIZE];
// CAN Filters
#define ivECU_MAX_FILTERS 10
uint32_t g_u32MaskValues[ivECU_MAX_FILTERS];
uint32_t g_u32FilterValues[ivECU_MAX_FILTERS];
bool g_bIsExtendedId[ivECU_MAX_FILTERS];
// Filter Counters
int32_t g_i32MaskCount = -1;
int32_t g_i32FilterCount = -1;
// Filter Information
uint16_t g_u16ExtendedFilter = 0;
@ -63,12 +57,15 @@ extern volatile bool g_bMcalMcanInitFlag; /*!< CAN initialization flag */
#define ivECU_MCAN_FILTER_SIZE 0U
/**
* @brief Function to use SDA pin of TM1650
* @brief Sets the state of the MCU temperature data pin (SDA) for TM1650.
*
* @param state the value to write on SDA pin (0 or 1)
* @returns none
* @param[in] u8State The state to set on the SDA pin (0 for low, 1 for high).
*
* @note This function controls the SDA pin of the TM1650 by setting it to
* either low or high based on the input state.
*/
void vRTE_SetMcuTempDataPin(uint8_t u8State)
{
if(u8State == 0){
@ -80,11 +77,14 @@ void vRTE_SetMcuTempDataPin(uint8_t u8State)
}
/**
* @brief Function to use SCL pin of TM1650
* @brief Sets the state of the MCU temperature clock pin (SCL) for TM1650.
*
* @param state the value to write on SDA pin (0 or 1)
* @returns none
* @param[in] u8State The state to set on the SCL pin (0 for low, 1 for high).
*
* @note This function controls the SCL pin of the TM1650 by setting it to
* either low or high based on the input state.
*/
void vRTE_McuSetTempClkPin(uint8_t u8State)
{
if(u8State == 0){
@ -96,12 +96,17 @@ void vRTE_McuSetTempClkPin(uint8_t u8State)
}
/**
* @brief Function to read SDA pin of TM1650
* @brief Reads the state of the MCU temperature data pin (SDA) for TM1650.
*
* @param none
* @returns Value of GPIO (0 or 1)
* This function configures the SDA pin as an input, reads the pin state,
* and then restores the pin's direction to output.
*
* @returns The state of the SDA pin (0 for low, 1 for high).
*
* @note The pin direction is temporarily set to input to read the pin state.
*/
static uint8_t _prvRteReadMcuTempPin(void) {
static uint8_t _prvRTE_ReadMcuTempPin(void) {
uint8_t l_u8ReadBuffer = 0;
vMCAL_set_gpioDirection(TM1650_SDA_PIN_IOMUX,false);
l_u8ReadBuffer = u32MCAL_gpioRead(TM1650_PORT, TM1650_SDA_PIN_PIN);
@ -109,11 +114,25 @@ static uint8_t _prvRteReadMcuTempPin(void) {
return l_u8ReadBuffer;
}
/**
* @brief Initializes the MATLAB interface for MCU and TM1650.
*
* This function performs the following initialization steps:
* - Initializes GPIO pins for communication.
* - Initializes the TM1650 display with the specified parameters.
* - Turns off the TM1650 screen, waits for a short delay, and then hides the
* decimal points on the digits.
* - Initializes the touch display for user interaction.
*
* @returns None
*
* @note The function uses `vMCAL_DelayTicks` for a delay after turning off the display.
*/
void vRTE_MatlabInit(void)
{
u8MCAL_gpioInit();
tm1650_Init(TM_1650_BRIGHT_8, TM_1650_Segment_8, TM_1650_Normal_Mode, TM_1650_Screen_ON, TM_1650_DIG_3, (void*)&vRTE_SetMcuTempDataPin , (void*)&vRTE_McuSetTempClkPin , &_prvRteReadMcuTempPin);
tm1650_Init(TM_1650_BRIGHT_8, TM_1650_Segment_8, TM_1650_Normal_Mode, TM_1650_Screen_ON, TM_1650_DIG_3, (void*)&vRTE_SetMcuTempDataPin , (void*)&vRTE_McuSetTempClkPin , &_prvRTE_ReadMcuTempPin);
tm1650_displaySwitch(TM_1650_Screen_OFF);
vMCAL_DelayTicks(500);
tm1650_showDot(TM_1650_DIG_1,false);
@ -121,6 +140,20 @@ void vRTE_MatlabInit(void)
tm1650_showDot(TM_1650_DIG_3,false);
socTouchDisplay_initialize();
}
/**
* @brief Runs the MATLAB interface for MCU and TM1650 during operation.
*
* This function performs several actions:
* - Detects if a touch input is active and sets display and touch durations.
* - Executes the display update step with `socTouchDisplay_step()`.
* - Clears and resets the CAN message buffer.
* - Based on the display and error statuses, it updates the TM1650 display:
* - If display status is active, it shows the appropriate digits or alphabet.
* - If an error is detected, it displays an error message on the TM1650.
* - If neither status is active, it turns off the display.
*
* @returns None
*/
void vRTE_MatlabRun(void)
{
@ -177,6 +210,15 @@ void vRTE_MatlabRun(void)
tm1650_displaySwitch(TM_1650_Screen_OFF);
}
}
/**
* @brief Initializes the application run processes.
*
* This function processes UART and CAN data to perform necessary tasks during
* the application runtime.
*
* @returns None
*/
void vRTE_AppInit(void)
{
@ -186,32 +228,64 @@ void vRTE_AppInit(void)
vRTE_InitUartCanEcho();
}
/**
* @brief Callback function for timer interrupt.
*
* This function is triggered by a timer interrupt and performs the following actions:
* - Calls the `vRTE_MatlabRun()` function if the battery smart configuration is enabled.
* - Clears the interrupt flag for Timer 1.
*
* @returns None
*/
void vRTE_InitUartCanEcho(void)
{
g_u32UartSpeed = eMcalUartBaud115200;
g_eCanSpeed = IVEC_CAN_BAUD_500;
g_xEcuUartHandle.u8Qbuffer = g_prvU8CanUartDataBuffer;
g_xEcuUartHandle.u16QbufSize = ivECU_CAN_UART_BUFFER_MAX_SIZE;
#if (ivECU_UART_PIN_SELECTION == 1)
#if (ivECU_UART_PIN_SELECTION == 1)
g_xEcuUartHandle.eUartPortNumber = IVEC_ECU_UART_PORT3;
#elif (ivECU_UART_PIN_SELECTION == 2)
g_xEcuUartHandle.u32BaudRate = eEcuUartBaud115200;
#elif (ivECU_UART_PIN_SELECTION == 2)
g_xEcuUartHandle.eUartPortNumber = IVEC_ECU_UART_PORT2;
#endif
g_xEcuUartHandle.u32BaudRate = eEcuUartBaud115200;
#endif
IVEC_ECU_Uart_Init(&g_xEcuUartHandle, g_u32UartSpeed);
xECU_UartInit(&g_xEcuUartHandle);
vECU_CAN_Init(CANFD0,g_eCanSpeed);
g_xEcuCanHandle.u16Speed = IVEC_ECU_CAN_SPEED_500;
g_xEcuCanHandle.pMCAN = CANFD0;
g_xEcuCanHandle.i32MaskCount = -1;
g_xEcuCanHandle.i32FilterCount = -1;
xECU_CANInit(&g_xEcuCanHandle);
}
/**
* @brief Initializes the application run processes.
*
* This function processes UART and CAN data to perform necessary tasks during
* the application runtime.
*
* @returns None
*/
void vRTE_AppRunInit(void)
{
vRTE_ProcessUartData();
vRTE_ProcessCanData();
}
/**
* @brief Callback function for timer interrupt.
*
* This function is triggered by a timer interrupt and performs the following actions:
* - Calls the `vRTE_MatlabRun()` function if the battery smart configuration is enabled.
* - Clears the interrupt flag for Timer 1.
*
* @returns None
*/
void vMCAL_TimerCallback(void)
{
@ -221,25 +295,61 @@ void vMCAL_TimerCallback(void)
DL_TimerA_clearInterruptStatus(TIMER_1_INST, GPTIMER_CPU_INT_IMASK_Z_SET);
}
/**
* @brief Saves the CAN filter mask value.
*
* This function saves the mask value at the specified index in the CAN handle,
* allowing for the configuration of the CAN filters based on the given
* extended ID and mask value.
*
* @param[in] u8Idx The index where the mask value is saved.
* @param[in] u32Mask The mask value to be stored.
* @param[in] bIsExtended Flag indicating whether the mask applies to extended IDs.
*
* @returns None
*/
void vRTE_CanFilterMaskSaveVal(uint8_t u8Idx, uint32_t u32Mask, bool bIsExtended)
{
g_i32MaskCount = u8Idx;
g_u32MaskValues[g_i32MaskCount] = u32Mask;
g_xEcuCanHandle.i32MaskCount = u8Idx;
g_xEcuCanHandle.u32MaskValues[g_xEcuCanHandle.i32MaskCount] = u32Mask;
}
/**
* @brief Saves the CAN filter value.
*
* This function saves the CAN filter value at the specified index in the CAN handle,
* allowing for dynamic configuration of the CAN filters at runtime.
*
* @param[in] u8Idx The index where the filter value is stored.
* @param[in] u32Filter The filter value to be stored.
* @param[in] bIsExtended Flag indicating whether the filter applies to extended IDs.
*
* @returns None
*/
void vRTE_CanFilterSaveVal(uint8_t u8Idx, uint32_t u32Filter, bool bIsExtended)
{
g_i32FilterCount = u8Idx;
g_xEcuCanHandle.i32FilterCount = u8Idx;
// Store filter value
g_u32FilterValues[g_i32FilterCount] = u32Filter;
g_xEcuCanHandle.u32FilterValues[g_xEcuCanHandle.i32FilterCount] = u32Filter;
}
/**
* @brief Processes UART data to manage CAN and UART communication.
*
* This function reads data from UART, interprets the data to determine the mode,
* and performs appropriate actions like adjusting UART or CAN baud rates, saving
* filter and mask values, or reinitializing CAN with new configurations.
* It handles different modes (0, 1, 2, 3, and 100) for runtime configurations.
*
* @returns None
*/
void vRTE_ProcessUartData(void)
{
IVEC_ECU_UartPacketRetCode_e eRetCode = IVEC_ECU_UART_PACKET_FAIL;
uint32_t l_u32Id = 0x1fffffff;
eRetCode= IVEC_ECU_Uart_ReadCANDataOverUART(&g_xEcuUartHandle,g_pu8UartBuffer,&l_u32Id);
eRetCode= xECU_UartReadCANDataOverUART(&g_xEcuUartHandle,g_pu8UartBuffer,&l_u32Id);
l_u32Id &= 0x1fffffff;
if(eRetCode > -1)
{
@ -248,16 +358,16 @@ void vRTE_ProcessUartData(void)
uint32_t l_u32Baudrate = 0;
uint8_t l_u8Mode = g_pu8UartBuffer[IVEC_ECU_UART_PKT_HEADER];
memcpy(&l_u32Baudrate, &g_pu8UartBuffer[IVEC_ECU_UART_PKT_HEADER+1], (uint32_t)eRetCode);
IVEC_ECU_Uart_InitiateTransmit(&g_xEcuUartHandle, 0x01, g_pu8UartBuffer, 0);
iECU_UartInitiateTransmit(&g_xEcuUartHandle, 0x01, g_pu8UartBuffer, 0);
if( l_u8Mode == 0 )
{
g_u32UartSpeed = l_u32Baudrate;
IVEC_ECU_Uart_Reinit(&g_xEcuUartHandle, g_u32UartSpeed);
g_xEcuUartHandle.u32BaudRate = l_u32Baudrate;
xECU_UartReinit(&g_xEcuUartHandle);
}
else if( l_u8Mode == 1 )
{
g_eCanSpeed = (uint16_t)l_u32Baudrate;
vECU_CAN_ReInit(CANFD0, g_eCanSpeed);
g_xEcuCanHandle.u16Speed = (uint16_t)l_u32Baudrate;;
xECU_CANReInit(&g_xEcuCanHandle);
}
else if( l_u8Mode == 2 )
{
@ -270,13 +380,13 @@ void vRTE_ProcessUartData(void)
vRTE_CanFilterSaveVal((g_pu8UartBuffer[IVEC_ECU_UART_PKT_HEADER+1] - 1), filterId, isExtended);
if( g_pu8UartBuffer[IVEC_ECU_UART_PKT_HEADER+2] )//All filter received. Trigger Filter Settings
{
vECU_CAN_ReInit(CANFD0,g_eCanSpeed);
xECU_CANReInit(&g_xEcuCanHandle);
}
else
return;
}
else{
vECU_CAN_ReInit(CANFD0,g_eCanSpeed);
xECU_CANReInit(&g_xEcuCanHandle);
}
}
else if ( l_u8Mode == 3 )
@ -296,32 +406,43 @@ void vRTE_ProcessUartData(void)
}
vMCAL_DelayTicks(100);
IVEC_ECU_Uart_InitiateTransmit(&g_xEcuUartHandle, 0x01, g_pu8UartBuffer, 0);
iECU_UartInitiateTransmit(&g_xEcuUartHandle, 0x01, g_pu8UartBuffer, 0);
}
if ( eRetCode == 0 && l_u32Id == 0){
IVEC_ECU_Uart_InitiateTransmit(&g_xEcuUartHandle, 0x0, g_pu8UartBuffer, 0); //interface okay response
iECU_UartInitiateTransmit(&g_xEcuUartHandle, 0x0, g_pu8UartBuffer, 0); //interface okay response
}
if ( eRetCode >= 0 && (l_u32Id > 0x00 && l_u32Id < 0xffffffff) )
{
//_prvU8Buffer = (_prvU8Buffer + 1) % 2;
vECU_WriteDataOverCAN(&g_pu8UartBuffer[IVEC_ECU_UART_PKT_HEADER], l_u32Id, eRetCode, 0);
xECU_WriteDataOverCAN(&g_xEcuCanHandle, &g_pu8UartBuffer[IVEC_ECU_UART_PKT_HEADER], l_u32Id, eRetCode, 0);
}
}
}
/**
* @brief Processes CAN data and handles CAN communication.
*
* This function reads incoming CAN data, checks the data for specific conditions (e.g.,
* the CAN ID `0x16` and specific data values `V`, `E`, and `C`), and takes actions accordingly,
* such as initiating a soft reset. If the data matches the conditions, it is transmitted over UART.
* The function also stores received CAN messages in a buffer and tracks the number of messages sent in bursts.
* Once the burst limit is reached, it stops processing additional messages.
*
* @returns None
*/
void vRTE_ProcessCanData(void)
{
IVEC_ECU_CANBuff_s l_xCanBuff = { 0x00 };
volatile uint8_t l_u8TxBurstMessages = 0;
while( vECU_CAN_GetData(&l_xCanBuff) == commonECU_SUCCESS )
while( xECU_CANGetData(&g_xEcuCanHandle, &l_xCanBuff) == commonECU_SUCCESS )
{
if( (l_xCanBuff.ulId == 0x16) && (l_xCanBuff.ucData[0] = 'V') && \
(l_xCanBuff.ucData[1] == 'E') && (l_xCanBuff.ucData[2] == 'C'))
{
xMCAL_VrefInit();
vMCAL_SoftReset();
}
IVEC_ECU_Uart_InitiateTransmit(&g_xEcuUartHandle, (uint32_t)l_xCanBuff.ulId, (uint8_t*)&l_xCanBuff.ucData[0], (uint8_t)l_xCanBuff.ucLength);
iECU_UartInitiateTransmit(&g_xEcuUartHandle, (uint32_t)l_xCanBuff.ulId, (uint8_t*)&l_xCanBuff.ucData[0], (uint8_t)l_xCanBuff.ucLength);
socTouchDisplay_U.Input[_prvU8Index].ID = l_xCanBuff.ulId;
socTouchDisplay_U.Input[_prvU8Index].Length = l_xCanBuff.ucLength;
memcpy(&socTouchDisplay_U.Input[_prvU8Index].Data[0], &l_xCanBuff.ucData[0], 8);
@ -331,6 +452,6 @@ void vRTE_ProcessCanData(void)
else
break;
}
vECU_CAN_GetStatus(CANFD0, g_eCanSpeed);
xECU_CANGetStatus(&g_xEcuCanHandle);
}

View File

@ -23,7 +23,16 @@ static const DL_VREF_ClockConfig g_dlVrefClockConfig = {
.divideRatio = DL_VREF_CLOCK_DIVIDE_1,
};
/* Systick Initialization */
/**
* @brief Initializes the SysTick timer.
*
* Configures the SysTick timer with the specified period and sets the interrupt priority.
*
* @param[in] eTick The period for the SysTick timer.
*
* @return IVEC_CORE_STATUS_SUCCESS if initialization is successful.
*/
IVEC_CoreStatus_e xMCAL_SystickInit(IVEC_SystickPeriod_e eTick)
{
SysTick_Config(eTick);
@ -47,8 +56,19 @@ static const DL_SYSCTL_SYSPLLConfig g_dlSysPllConfig = {
.qDiv = 5,
.pDiv = DL_SYSCTL_SYSPLL_PDIV_1,
};
/**
* @brief Initializes the system control settings, including clock source and low power mode.
*
* Configures the power policy, BOR threshold, and flash wait state based on the specified
* low power mode and clock source. It also sets up system PLL and HFCLK parameters accordingly.
*
* @param[in] u8ClkSrc The clock source to use (e.g., HFXT or SYSOSC).
* @param[in] u8LowPowerMode The low power mode to configure (e.g., STANDBY0 or SLEEP0).
*
* @return IVEC_CORE_STATUS_SUCCESS if initialization is successful,
* IVEC_CORE_STATUS_INIT_FAIL if invalid parameters are provided.
*/
/* System Control Initialization */
IVEC_CoreStatus_e xMCAL_SysctlInit(uint8_t u8ClkSrc, uint8_t u8LowPowerMode)
{
if ((u8LowPowerMode != IVEC_STANDBY0) && (u8LowPowerMode != IVEC_SLEEP0))
@ -96,16 +116,33 @@ IVEC_CoreStatus_e xMCAL_SysctlInit(uint8_t u8ClkSrc, uint8_t u8LowPowerMode)
return IVEC_CORE_STATUS_SUCCESS;
}
/**
* @brief SysTick interrupt handler.
*
* Increments the global tick counter (`g_i32TickCnt`) each time the SysTick interrupt occurs.
*/
void SysTick_Handler(void)
{
g_i32TickCnt++;
}
/**
* @brief Retrieves the current tick count.
*
* @return The current tick count stored in `g_i32TickCnt`.
*/
int32_t i32MCAL_GetTicks()
{
return g_i32TickCnt;
}
/**
* @brief Delays execution for a specified number of milliseconds based on tick count.
*
* Waits until the number of ticks has passed corresponding to the input delay (in milliseconds).
*
* @param[in] i32DelayMs The delay in milliseconds to wait.
*/
void vMCAL_DelayTicks(int32_t i32DelayMs)
{
@ -116,17 +153,38 @@ void vMCAL_DelayTicks(int32_t i32DelayMs)
/* Wait */
}
}
/**
* @brief Initializes the MCU by configuring power and GPIO settings.
*
* Calls the necessary functions to initialize power and GPIO configurations for the MCU.
*/
void vMCAL_McuInit(void)
{
SYSCFG_DL_initPower();
SYSCFG_DL_GPIO_init();
}
/**
* @brief Delays execution for a specified number of microseconds.
*
* Uses a cycle-based delay function to wait for the specified duration in microseconds.
*
* @param[in] u32Us The delay duration in microseconds.
*/
void vMCAL_DelayUs(uint32_t u32Us)
{
delay_cycles(32 * u32Us);
}
/**
* @brief Initializes the voltage reference (VREF) system.
*
* Configures the clock and reference settings for the VREF system. If already initialized,
* it returns a failure status.
*
* @return IVEC_MCAL_STATUS_SUCCESS if initialization is successful,
* IVEC_MCAL_STATUS_INIT_FAIL if VREF is already initialized.
*/
IVEC_McalStatus_e xMCAL_VrefInit(void)
{
@ -143,6 +201,11 @@ IVEC_McalStatus_e xMCAL_VrefInit(void)
return IVEC_MCAL_STATUS_INIT_FAIL;
}
}
/**
* @brief Performs a soft reset on the MCU.
*
* Resets the MCU's CPU by calling the appropriate system control function.
*/
void vMCAL_SoftReset(void)
{

View File

@ -51,15 +51,7 @@ typedef enum
IVEC_UART_BAUD_9600 = 1,
} IVEC_UartBaud_e;
/* CAN Baud Rate Options */
typedef enum
{
IVEC_CAN_BAUD_500 = 500,
IVEC_CAN_BAUD_250 = 250,
IVEC_CAN_BAUD_150 = 150,
IVEC_CAN_BAUD_1000 = 1000,
IVEC_CAN_BAUD_125 = 125,
} IVEC_CanBaud_e;
/* SPI Clock Speed Options */
typedef enum