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

724 lines
28 KiB
C

/**
******************************************************************************
* @file ivec_mcal_mcan.c
* @brief This file provides APIs for MCAN peripheral.
* @date 15-feb-2024
* @Author Vecmocon Technology
******************************************************************************
*/
#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;
/* MCAN Interrupt Line 1 Status */
volatile uint32_t u32MCAL_InterruptLine1Status;
/* MCAN Error Interrupt Status */
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)
{
}
/*=======================================================================================PRIVATE_MEMBERS======================================================================================*/
static const DL_MCAN_ClockConfig gMCAN0ClockConf = {
.clockSel = DL_MCAN_FCLK_HFCLK,////DL_MCAN_FCLK_SYSPLLCLK1,DL_MCAN_FCLK_HFCLK,
.divider = DL_MCAN_FCLK_DIV_1,
};
static DL_MCAN_InitParams gMCAN0InitParams= {
/* Initialize MCAN Init parameters. */
.fdMode = false,
.brsEnable = false,
.txpEnable = false,
.efbi = false,
.pxhddisable = false,
.darEnable = false,
.wkupReqEnable = true,
.autoWkupEnable = true,
.emulationEnable = true,
.tdcEnable = true,
.wdcPreload = 255,
/* Transmitter Delay Compensation parameters. */
.tdcConfig.tdcf = 10,
.tdcConfig.tdco = 6,
};
static DL_MCAN_ConfigParams gMCAN0ConfigParams={
/* Initialize MCAN Config parameters. */
.monEnable = false,
.asmEnable = false,
.tsPrescalar = 15,
.tsSelect = 0,
.timeoutSelect = DL_MCAN_TIMEOUT_SELECT_CONT,
.timeoutPreload = 65535,
.timeoutCntEnable = false,
.filterConfig.rrfs = false,
.filterConfig.rrfe = false,
.filterConfig.anfe = 0,
.filterConfig.anfs = 0,
};
static DL_MCAN_MsgRAMConfigParams gMCAN0MsgRAMConfigParams = {
/* Standard ID Filter List Start Address. */
.flssa = 0x0,
/* List Size: Standard ID. */
.lss = 10,
/* Extended ID Filter List Start Address. */
.flesa = 10 ,
/* List Size: Extended ID. */
.lse = 10 ,
/* Tx Buffers Start Address. */
.txStartAddr = 40 + 80 ,
/* Number of Dedicated Transmit Buffers. */
.txBufNum = 0 ,
.txFIFOSize = 3,
/* Tx Buffer Element Size. */
.txBufMode = 0,
.txBufElemSize = DL_MCAN_ELEM_SIZE_8BYTES,
/* Tx Event FIFO Start Address. */
.txEventFIFOStartAddr = 0 ,
/* Event FIFO Size. */
.txEventFIFOSize = 0 ,
/* Level for Tx Event FIFO watermark interrupt. */
.txEventFIFOWaterMark = 0,
/* Rx FIFO0 Start Address. */
.rxFIFO0startAddr = 40 + 80 + 36 ,
/* Number of Rx FIFO elements. */
.rxFIFO0size = 3 ,
/* Rx FIFO0 Watermark. */
.rxFIFO0waterMark = 0,
.rxFIFO0OpMode = 0,
/* Rx FIFO1 Start Address. */
.rxFIFO1startAddr = 40 + 80 + 36 + 36 ,
/* Number of Rx FIFO elements. */
.rxFIFO1size = 3 ,
/* Level for Rx FIFO 1 watermark interrupt. */
.rxFIFO1waterMark = 0,
/* FIFO blocking mode. */
.rxFIFO1OpMode = 0,
/* Rx Buffer Start Address. */
.rxBufStartAddr = 0 ,
/* Rx Buffer Element Size. */
.rxBufElemSize = DL_MCAN_ELEM_SIZE_8BYTES,
/* Rx FIFO0 Element Size. */
.rxFIFO0ElemSize = DL_MCAN_ELEM_SIZE_8BYTES,
/* Rx FIFO1 Element Size. */
.rxFIFO1ElemSize = DL_MCAN_ELEM_SIZE_8BYTES,
};
static DL_MCAN_BitTimingParams gMCAN0BitTimes_500 = {
/* Arbitration Baud Rate Pre-scaler. */
.nomRatePrescalar = 0,
/* Arbitration Time segment before sample point. */
.nomTimeSeg1 = 41,
/* Arbitration Time segment after sample point. */
.nomTimeSeg2 = 4,
/* Arbitration (Re)Synchronization Jump Width Range. */
.nomSynchJumpWidth = 4,
/* Data Baud Rate Pre-scaler. */
.dataRatePrescalar = 0,
/* Data Time segment before sample point. */
.dataTimeSeg1 = 0,
/* Data Time segment after sample point. */
.dataTimeSeg2 = 0,
/* Data (Re)Synchronization Jump Width. */
.dataSynchJumpWidth = 0,
};
static const DL_MCAN_BitTimingParams gMCAN0BitTimes_250 = {
/* Arbitration Baud Rate Pre-scaler. */
.nomRatePrescalar = 0,
/* Arbitration Time segment before sample point. */
.nomTimeSeg1 = 82,
/* Arbitration Time segment after sample point. */
.nomTimeSeg2 = 11,
/* Arbitration (Re)Synchronization Jump Width Range. */
.nomSynchJumpWidth = 11,
/* Data Baud Rate Pre-scaler. */
.dataRatePrescalar = 0,
/* Data Time segment before sample point. */
.dataTimeSeg1 = 0,
/* Data Time segment after sample point. */
.dataTimeSeg2 = 0,
/* Data (Re)Synchronization Jump Width. */
.dataSynchJumpWidth = 0,
};
volatile DL_MCAN_TxBufElement txMsg = {
.id = ((uint32_t)(0x00)) << 18U,
.rtr = 0U,
.xtd = 0U,
.esi = 0U,
.dlc = 8U,
.brs = 0U,
.fdf = 0U,
.efc = 1U,
.mm = 0xAAU,
.data = {0},
};
/*____________________________________________________________________________________________________________________________________________________________________________________________*/
/*=============================================================================================================================================================================================
PRIVATE_DECLARATIONS
==============================================================================================================================================================================================*/
/**
* @brief Static Function to store RX data in a static buffer
* @retval void
*/
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)
{
can_interrupt = u32InterruptStatus;
uint32_t u32IntrStatus = u32InterruptStatus;
if (u32IntrStatus & (DL_MCAN_INTERRUPT_RF1F | DL_MCAN_INTERRUPT_RF0N | DL_MCAN_INTERRUPT_RF0F | DL_MCAN_INTERRUPT_RF1N)) {
volatile DL_MCAN_RxFIFOStatus xMCAL_RxFIFOStatus;
if (u32IntrStatus & (DL_MCAN_INTERRUPT_RF0F | DL_MCAN_INTERRUPT_RF0N))
xMCAL_RxFIFOStatus.num = DL_MCAN_RX_FIFO_NUM_0;
else
xMCAL_RxFIFOStatus.num = DL_MCAN_RX_FIFO_NUM_1;
DL_MCAN_getRxFIFOStatus(CANFD0, &xMCAL_RxFIFOStatus);
while ((xMCAL_RxFIFOStatus.fillLvl) != 0)
{
volatile DL_MCAN_RxBufElement xMCAL_TempRxMsg;
DL_MCAN_readMsgRam(CANFD0, DL_MCAN_MEM_TYPE_FIFO, 0, xMCAL_RxFIFOStatus.num, &xMCAL_TempRxMsg);
DL_MCAN_writeRxFIFOAck(CANFD0, xMCAL_RxFIFOStatus.num, xMCAL_RxFIFOStatus.getIdx);
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;
}
vMCAL_CanReceiveFifoCallback(xMCAL_TempRxMsg.id, &xMCAL_TempRxMsg.data[0], xMCAL_TempRxMsg.dlc);
DL_MCAN_getRxFIFOStatus(CANFD0, &xMCAL_RxFIFOStatus);
}
}
if(u32IntrStatus & (DL_MCAN_INTR_SRC_MSG_RAM_ACCESS_FAILURE|DL_MCAN_INTR_SRC_TIMEOUT|DL_MCAN_INTR_SRC_ERR_LOG_OVRFLW|DL_MCAN_INTR_SRC_ERR_PASSIVE|DL_MCAN_INTR_SRC_ERR_PASSIVE|DL_MCAN_INTR_SRC_WARNING_STATUS|DL_MCAN_INTR_SRC_BUS_OFF_STATUS|DL_MCAN_INTR_SRC_WATCHDOG|DL_MCAN_INTR_SRC_PROTOCOL_ERR_ARB|DL_MCAN_INTR_SRC_PROTOCOL_ERR_DATA|DL_MCAN_INTR_SRC_RES_ADDR_ACCESS) ) {
can_interrupt = 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
*
*/
void CANFD0_IRQHandler(void)
{
/* Get the pending interrupt source */
switch (DL_MCAN_getPendingInterrupt(CANFD0))
{
case DL_MCAN_IIDX_LINE1:
{
/* Get interrupt status for Line 1 */
uint32_t u32IntrStatus = DL_MCAN_getIntrStatus(CANFD0);
/* Process the interrupt */
__prv_CANInterruptProcess(u32IntrStatus);
/* Clear the interrupt status for Line 1 */
DL_MCAN_clearIntrStatus(MCAN0_INST, u32IntrStatus, DL_MCAN_INTR_SRC_MCAN_LINE_1);
break;
}
case DL_MCAN_IIDX_LINE0:
{
/* Get interrupt status for Line 0 */
uint32_t u32IntrStatus = DL_MCAN_getIntrStatus(CANFD0);
/* Process the interrupt */
__prv_CANInterruptProcess(u32IntrStatus);
/* Clear the interrupt status for Line 0 */
DL_MCAN_clearIntrStatus(MCAN0_INST, u32IntrStatus, DL_MCAN_INTR_SRC_MCAN_LINE_0);
break;
}
default:
{
/* Get interrupt status for external timestamp */
uint32_t u32IntrStatus = DL_MCAN_getIntrStatus(CANFD0);
/* Clear the interrupt status for external timestamp */
DL_MCAN_clearIntrStatus(MCAN0_INST, u32IntrStatus, DL_MCAN_INTR_SRC_MCAN_EXT_TS);
break;
}
}
}
/*=============================================================================================================================================================================================
API
==============================================================================================================================================================================================*/
/**
* @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
*/
IVEC_McalStatus_e vMCAL_MCAN_Init(MCAN_Regs* pMCAN, IVEC_CanBaud_e eBaudRate)
{
assert(pMCAN == CANFD0);
assert(eBaudRate == IVEC_CAN_BAUD_500 || eBaudRate == IVEC_CAN_BAUD_250);
assert(bMCAL_MCAN_InitFlag == 0);
DL_MCAN_RevisionId revid_MCAN0;
DL_MCAN_enableModuleClock(pMCAN);
DL_MCAN_setClockConfig(pMCAN, (DL_MCAN_ClockConfig *) &gMCAN0ClockConf);
/* Get MCANSS Revision ID. */
DL_MCAN_getRevisionId(pMCAN, &revid_MCAN0);
/* Wait for Memory initialization to be completed. */
while (false == DL_MCAN_isMemInitDone(pMCAN));
/* Put MCAN in SW initialization mode. */
DL_MCAN_setOpMode(pMCAN, DL_MCAN_OPERATION_MODE_SW_INIT);
/* Wait till MCAN is not initialized. */
while (DL_MCAN_OPERATION_MODE_SW_INIT != DL_MCAN_getOpMode(pMCAN));
/* Initialize MCAN module. */
DL_MCAN_init(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)) {
gMCAN0ConfigParams.filterConfig.anfe = 3;
}
else
{
gMCAN0ConfigParams.filterConfig.anfs = 3;
}
}
/* Configure MCAN module. */
DL_MCAN_config(pMCAN, (DL_MCAN_ConfigParams*)&gMCAN0ConfigParams);
/* Configure Bit timings. */
if (eBaudRate == IVEC_CAN_BAUD_500)
{
DL_MCAN_setBitTime(pMCAN, (DL_MCAN_BitTimingParams*)&gMCAN0BitTimes_500);
}
else if (eBaudRate == IVEC_CAN_BAUD_250)
{
DL_MCAN_setBitTime(pMCAN, (DL_MCAN_BitTimingParams*)&gMCAN0BitTimes_250);
}
else
{
DL_MCAN_setBitTime(pMCAN, (DL_MCAN_BitTimingParams*)&gMCAN0BitTimes_500);
}
/* Configure Message RAM Sections */
DL_MCAN_msgRAMConfig(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)) {
// Extended ID filter
DL_MCAN_ExtMsgIDFilterElement extFilterElement;
extFilterElement.efid1 = g_u32FilterValues[u32Index];
extFilterElement.efid2 = g_u32MaskValues[u32Index];
extFilterElement.efec = 001;
extFilterElement.eft = 2;
DL_MCAN_addExtMsgIDFilter(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.sfec = 001;
stdFilterElement.sft = 2;
DL_MCAN_addStdMsgIDFilter(pMCAN, l_u8StandardFilterCount, (DL_MCAN_StdMsgIDFilterElement*)&stdFilterElement);
l_u8StandardFilterCount++;
}
}
DL_MCAN_setExtIDAndMask(pMCAN, (0x1FFFFFFFU));
/* Take MCAN out of the SW initialization mode */
DL_MCAN_setOpMode(pMCAN, DL_MCAN_OPERATION_MODE_NORMAL);
while (DL_MCAN_OPERATION_MODE_NORMAL != DL_MCAN_getOpMode(pMCAN));
/* Enable MCAN mopdule Interrupts */
DL_MCAN_enableIntr(pMCAN, (MCAN_IR_RF0N_MASK | \
MCAN_IR_RF0F_MASK | \
MCAN_IR_RF1N_MASK | \
MCAN_IR_RF1F_MASK | \
MCAN_IR_TSW_MASK | \
MCAN_IR_MRAF_MASK | \
MCAN_IR_TOO_MASK | \
MCAN_IR_DRX_MASK | \
MCAN_IR_BEU_MASK | \
MCAN_IR_ELO_MASK | \
MCAN_IR_EP_MASK | \
MCAN_IR_EW_MASK | \
MCAN_IR_BO_MASK | \
MCAN_IR_WDI_MASK | \
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);
/* Enable MSPM0 MCAN interrupt */
DL_MCAN_clearInterruptStatus(pMCAN, (DL_MCAN_MSP_INTERRUPT_LINE0));
DL_MCAN_enableInterrupt(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;
return IVEC_MCAL_STATUS_SUCCESS;
}
/**
* @brief Function to De-Initialize MCAN peripheral
* @param MCAN Pointer to the register overlay for the peripheral
* @retval IVEC MCAL status
*/
IVEC_McalStatus_e vMCAL_MCAN_DeInit(MCAN_Regs* const pMCAN)
{
/* Assert that the MCAN module pointer is valid */
assert(pMCAN == CANFD0);
assert(bMCAL_MCAN_InitFlag != 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);
/* Wait until the operation mode is set to initialization mode */
while (DL_MCAN_OPERATION_MODE_SW_INIT != DL_MCAN_getOpMode(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_INTERRUPT_BO | \
DL_MCAN_INTERRUPT_ELO | \
DL_MCAN_INTERRUPT_EP | \
DL_MCAN_INTERRUPT_EW | \
DL_MCAN_INTERRUPT_PEA | \
DL_MCAN_INTERRUPT_PED | \
DL_MCAN_INTERRUPT_RF0N | \
DL_MCAN_INTERRUPT_RF1N | \
DL_MCAN_INTERRUPT_TC | \
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);
/* 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(pMCAN, DL_MCAN_MSP_INTERRUPT_LINE1);
DL_MCAN_disableInterrupt(pMCAN, DL_MCAN_MSP_INTERRUPT_LINE1);
/* Set the operation mode back to normal */
DL_MCAN_setOpMode(pMCAN, DL_MCAN_OPERATION_MODE_NORMAL);
/* Reset the initialization flag */
bMCAL_MCAN_InitFlag = 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);
/* Wait for power down to complete */
delay_cycles(16);
return IVEC_MCAL_STATUS_SUCCESS;
}
/**
* @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
*/
IVEC_McalStatus_e vMCAL_MCAN_Tx(MCAN_Regs* const pMCAN, uint32_t u32Id,
uint16_t* pu16TxData, uint32_t u32BufNum,
uint32_t u32Bytes)
{
/* Ensure that the MCAN instance is CANFD0 */
assert(pMCAN == CANFD0);
/* Ensure that the MCAN is initialized */
assert(bMCAL_MCAN_InitFlag != 0);
/* Validate the byte size */
assert(u32Bytes <= 8);
/* Set the message type (standard or extended ID) */
if (u32Id > 0x7FF)
{
txMsg.xtd = 1; /* Extended ID */
txMsg.id = u32Id; /* Set the extended ID */
}
else
{
txMsg.xtd = 0; /* Standard ID */
txMsg.id = ((uint32_t)(u32Id)) << 18U; /* Adjust for standard ID format */
}
/* Copy the data bytes to the message */
for (int i = 0; i < u32Bytes; i++)
{
txMsg.data[i] = pu16TxData[i];
}
txMsg.dlc = u32Bytes; /* Set the Data Length Code (DLC) */
__asm("nop"); /* No operation for synchronization */
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
if (sMcalTxFifoStatus_x.freeLvl) // Variable renamed for clarity and prefixed with 'u32' for uint32_t
{
DL_MCAN_writeMsgRam(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'
{
return IVEC_MCAL_STATUS_ERROR;
}
}
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
*/
IVEC_McalStatus_e vMCAL_MCAN_Rx(MCAN_Regs *pMCAN, 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);
/* 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;
}
/**
* @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
*/
IVEC_McalStatus_e vMCAL_MCAN_GetErrorStatus(char *pcErrorStatus)
{
/* Assert that the MCAN initialization flag is set */
assert(bMCAL_MCAN_InitFlag != 0);
/* Copy the error interrupt status to the provided buffer */
strcpy(pcErrorStatus, cMCAL_ErrorInterruptStatus);
/* Retrieve the current protocol status of the MCAN module */
DL_MCAN_getProtocolStatus(CANFD0, &xMCAL_HeaderStat);
/* Declare and initialize the error counter status structure */
volatile DL_MCAN_ErrCntStatus lErrCounter = {0};
DL_MCAN_getErrCounters(CANFD0, &lErrCounter);
/* Return the status based on various error conditions */
return (
(xMCAL_HeaderStat.busOffStatus)) ? IVEC_MCAL_STATUS_ERROR : IVEC_MCAL_STATUS_SUCCESS;
}
/**
* @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
*/
IVEC_McalStatus_e vMCAL_MCAN_GetInterruptLine1Status(uint32_t *pu32InterruptStatus)
{
// Ensure CAN module is initialized (optional assertion, can be uncommented as needed)
// assert(b_MCAN_InitFlag != 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;
}