/** ****************************************************************************** * @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; }