/** ****************************************************************************** * @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" volatile bool b_MCAN_InitFlag = 0; /*!< CAN initialization flag */ volatile uint8_t u8_MCAN_StatusFlag = IVEC_MCAL_STATUS_ERROR; volatile bool b_ServiceInt=true; volatile uint32_t u32InterruptLine1Status; volatile char u8ErrorInterruptStatus[50]; volatile DL_MCAN_RxFIFOStatus rxFS; volatile DL_MCAN_RxBufElement TempRxMsg; volatile uint8_t TempRxBuffer[8]; volatile uint32_t TempRxID; volatile uint32_t id; DL_MCAN_ProtocolStatus HeaderStat; volatile uint32_t l_canTransmitTimeout; volatile uint8_t u8CallBack_buff[8]={0}; volatile IVEC_McalStatus_e l_statusFlag = IVEC_MCAL_STATUS_SUCCESS; extern volatile uint8_t u8CANDataAct; #define MCAN_FILTER_SIZE 2u /*REQUIRED MCAN CONFIGS*/ __attribute__((weak)) void mcu_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 = false, .autoWkupEnable = false, .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, .filterConfig.anfe = 3, .filterConfig.anfs = 3, }; //static DL_MCAN_MsgRAMConfigParams gMCAN0MsgRAMConfigParams ={ // // /* Standard ID Filter List Start Address. */ // .flssa = 0 , // /* List Size: Standard ID. */ // .lss = 0 , // /* Extended ID Filter List Start Address. */ // .flesa = 0 , // /* List Size: Extended ID. */ // .lse = 0 , // /* Tx Buffers Start Address. */ // .txStartAddr = 10 , // /* Number of Dedicated Transmit Buffers. */ // .txBufNum = 10 , // .txFIFOSize = 10, // /* Tx Buffer Element Size. */ // .txBufMode = 0, // .txBufElemSize = DL_MCAN_ELEM_SIZE_8BYTES, // /* Tx Event FIFO Start Address. */ // .txEventFIFOStartAddr = 640 , // /* Event FIFO Size. */ // .txEventFIFOSize = 10 , // /* Level for Tx Event FIFO watermark interrupt. */ // .txEventFIFOWaterMark = 0, // /* Rx FIFO0 Start Address. */ // .rxFIFO0startAddr = 170 , // /* Number of Rx FIFO elements. */ // .rxFIFO0size = 10 , // /* Rx FIFO0 Watermark. */ // .rxFIFO0waterMark = 0, // .rxFIFO0OpMode = 0, // /* Rx FIFO1 Start Address. */ // .rxFIFO1startAddr = 190 , // /* Number of Rx FIFO elements. */ // .rxFIFO1size = 10 , // /* Level for Rx FIFO 1 watermark interrupt. */ // .rxFIFO1waterMark = 10, // /* FIFO blocking mode. */ // .rxFIFO1OpMode = 0, // /* Rx Buffer Start Address. */ // .rxBufStartAddr = 208 , // /* 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_MsgRAMConfigParams gMCAN0MsgRAMConfigParams ={ /* Standard ID Filter List Start Address. */ .flssa = 1, /* List Size: Standard ID. */ .lss = MCAN_FILTER_SIZE, /* Extended ID Filter List Start Address. */ .flesa = 48 , /* List Size: Extended ID. */ .lse = 2 , /* Tx Buffers Start Address. */ .txStartAddr = 10 , /* Number of Dedicated Transmit Buffers. */ .txBufNum = 10 , .txFIFOSize = 10, /* Tx Buffer Element Size. */ .txBufMode = 0, .txBufElemSize = DL_MCAN_ELEM_SIZE_8BYTES, /* Tx Event FIFO Start Address. */ .txEventFIFOStartAddr = 640 , /* Event FIFO Size. */ .txEventFIFOSize = 10 , /* Level for Tx Event FIFO watermark interrupt. */ .txEventFIFOWaterMark = 0, /* Rx FIFO0 Start Address. */ .rxFIFO0startAddr = 170 , /* Number of Rx FIFO elements. */ .rxFIFO0size = 10 , /* Rx FIFO0 Watermark. */ .rxFIFO0waterMark = 0, .rxFIFO0OpMode = 0, /* Rx FIFO1 Start Address. */ .rxFIFO1startAddr = 190 , /* Number of Rx FIFO elements. */ .rxFIFO1size = 10 , /* Level for Rx FIFO 1 watermark interrupt. */ .rxFIFO1waterMark = 10, /* FIFO blocking mode. */ .rxFIFO1OpMode = 0, /* Rx Buffer Start Address. */ .rxBufStartAddr = 208 , /* 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 DL_MCAN_BitTimingParams gMCAN0BitTimes_250 = { /* Arbitration Baud Rate Pre-scaler. */ .nomRatePrescalar = 0, /* Arbitration Time segment before sample point. */ .nomTimeSeg1 = 138, /* Arbitration Time segment after sample point. */ .nomTimeSeg2 = 19, /* Arbitration (Re)Synchronization Jump Width Range. */ .nomSynchJumpWidth = 19, /* 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_StdMsgIDFilterElement gMCAN0StdFiltelem1 = { .sfec = 001, .sft = 0x00, .sfid1 = 0, .sfid2 = 100, }; //static const DL_MCAN_StdMsgIDFilterElement gMCAN0StdFiltelem1 = { // .sfec = 001, // .sft = 10, // .sfid1 = 0xc8, // .sfid2 = 0x7fe, //}; // apply mask pass only 200 and 201 id static const DL_MCAN_StdMsgIDFilterElement gMCAN0StdFiltelem2 = { .sfec = 0x1, .sft = 0x00, .sfid1 = 200, .sfid2 = 300, }; static const DL_MCAN_StdMsgIDFilterElement gMCAN0StdFiltelem3 = { .sfec = 0x1, .sft = 0x00, .sfid1 = 0x1A4, .sfid2 = 0x1A4, }; static const DL_MCAN_StdMsgIDFilterElement gMCAN0StdFiltelem4 = { .sfec = 0x1, .sft = 0x00, .sfid1 = 0x521, .sfid2 = 0x521, }; static const DL_MCAN_StdMsgIDFilterElement gMCAN0StdFiltelem5 = { .sfec = 0x1, .sft = 0x00, .sfid1 = 0x16, .sfid2 = 0x16, }; static const DL_MCAN_ExtMsgIDFilterElement gMCAN0ExtFiltelem1 = { .efec = 0x1, .eft = 0x0, .efid1 = 3000, .efid2 = 3500, }; static const DL_MCAN_ExtMsgIDFilterElement gMCAN0ExtFiltelem2 = { .efec = 0x1, .eft = 0x0, .efid1 = 4000, .efid2 = 4500, }; static const DL_MCAN_ExtMsgIDFilterElement gMCAN0ExtFiltelem3 = { .efec = 0x1, .eft = 0x0, .efid1 = 0x1CEBFF23, .efid2 = 0x1CEBFF23, }; volatile DL_MCAN_TxBufElement txMsg = { .id = ((uint32_t)(0x00)) << 18U, .rtr = 0U, .xtd = 0U, .esi = 0U, .dlc = 8U, .brs = 1U, .fdf = 1U, .efc = 1U, .mm = 0xAAU, .data = 0U, }; /*____________________________________________________________________________________________________________________________________________________________________________________________*/ /*============================================================================================================================================================================================= PRIVATE_DECLARATIONS ==============================================================================================================================================================================================*/ /** * @brief Static Function to store RX data in a static buffer * @retval void */ static void _prv_vGetRxMsg(DL_MCAN_RxBufElement *rxMsg,uint32_t *ID,uint8_t *RxData,int DLC) { for (int i =0 ; i < DLC ; i++) { RxData[i] = (rxMsg->data[i] & 0xFF); } } /** * @brief Default Interrupt Handler for MCAN * */ void CANFD0_IRQHandler(void) { uint32_t IntrStatus = DL_MCAN_getIntrStatus(CANFD0); DL_MCAN_getProtocolStatus(CANFD0, &HeaderStat); if (IntrStatus & DL_MCAN_INTERRUPT_TC){ __asm("nop"); DL_MCAN_clearIntrStatus(CANFD0, IntrStatus,DL_MCAN_INTR_SRC_MCAN_LINE_1); b_ServiceInt = true; u8_MCAN_StatusFlag = IVEC_MCAL_STATUS_SUCCESS; __asm("nop"); } else if(IntrStatus & DL_MCAN_INTERRUPT_RF0N){ while (false == b_ServiceInt); b_ServiceInt = false; rxFS.fillLvl = 0; rxFS.num = DL_MCAN_RX_FIFO_NUM_0; while ((rxFS.fillLvl) == 0) { DL_MCAN_getRxFIFOStatus(CANFD0, &rxFS); } DL_MCAN_readMsgRam(CANFD0, DL_MCAN_MEM_TYPE_FIFO, 0, rxFS.num, &TempRxMsg); DL_MCAN_writeRxFIFOAck(CANFD0, rxFS.num, rxFS.getIdx); xCanIdType_t idType = ERROR; // if (TempRxMsg.id >= 0 && TempRxMsg.id <= 0x7FF) // { // idType = STD_ID; // } else if (TempRxMsg.id <= 0x1FFFFFFF) // { // idType = EXT_ID; // } // // for(int i=0;i<8;i++) // { // u8CallBack_buff[i]=(TempRxMsg.data[i] & 0xFF); // } uint64_t idx = 0; idx = TempRxMsg.id; uint32_t value = ((TempRxMsg.id & (uint32_t) 0x1FFC0000) >> (uint32_t) 18); if ((value > 0) && (value <= 0x7FF)) if(TempRxMsg.xtd == 0) { idType = STD_ID; idx = value; idx = ((TempRxMsg.id & (uint32_t) 0x1FFC0000) >> (uint32_t) 18); } __asm("nop"); TempRxID = idx; _prv_vGetRxMsg(&TempRxMsg,&TempRxID ,TempRxBuffer,TempRxMsg.dlc); DL_MCAN_clearIntrStatus(CANFD0, IntrStatus,DL_MCAN_INTR_SRC_MCAN_LINE_1); b_ServiceInt = true; if(HeaderStat.busOffStatus==1) { DL_MCAN_setOpMode(CANFD0, DL_MCAN_OPERATION_MODE_NORMAL); } uint32_t u32RxCANID = 0; uint8_t u8RxData[8] = {0}; xMCAL_MCANRx(CANFD0,&u32RxCANID,u8RxData,8); // vSOC_MeterCallback(u32RxCANID, &u8RxData[0]); mcu_FDCAN_RxFifo_Callback(u32RxCANID, &u8RxData[0], TempRxMsg.dlc); } else if(IntrStatus & MCAN_IR_PEA_MASK) { __asm("nop"); DL_MCAN_clearIntrStatus(CANFD0, IntrStatus,DL_MCAN_INTR_SRC_MCAN_LINE_1); } else if(IntrStatus & MCAN_IR_BO_MASK) { DL_MCAN_clearIntrStatus(CANFD0, IntrStatus,DL_MCAN_INTR_SRC_MCAN_LINE_1); } else{ DL_MCAN_clearIntrStatus(CANFD0, IntrStatus,DL_MCAN_INTR_SRC_MCAN_LINE_1); } } /*============================================================================================================================================================================================= 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 xMCAL_MCANInit(MCAN_Regs* MCAN, xCAN_baud_t BAUD) { assert(MCAN == CANFD0); assert(BAUD == BAUD_500 || BAUD == BAUD_250); assert(b_MCAN_InitFlag == 0); DL_MCAN_RevisionId revid_MCAN0; DL_MCAN_enableModuleClock(MCAN); DL_MCAN_setClockConfig(MCAN, (DL_MCAN_ClockConfig *) &gMCAN0ClockConf); /* Get MCANSS Revision ID. */ DL_MCAN_getRevisionId(MCAN, &revid_MCAN0); /* Wait for Memory initialization to be completed. */ while(false == DL_MCAN_isMemInitDone(MCAN)); /* Put MCAN in SW initialization mode. */ DL_MCAN_setOpMode(MCAN, DL_MCAN_OPERATION_MODE_SW_INIT); /* Wait till MCAN is not initialized. */ while (DL_MCAN_OPERATION_MODE_SW_INIT != DL_MCAN_getOpMode(MCAN)); /* Initialize MCAN module. */ DL_MCAN_init(MCAN, (DL_MCAN_InitParams *) &gMCAN0InitParams); /* Configure MCAN module. */ DL_MCAN_config(MCAN, (DL_MCAN_ConfigParams*) &gMCAN0ConfigParams); /* Configure Bit timings. */ if(BAUD==BAUD_500) { DL_MCAN_setBitTime(MCAN, (DL_MCAN_BitTimingParams*) &gMCAN0BitTimes_500); } else if(BAUD==BAUD_250) { DL_MCAN_setBitTime(MCAN, (DL_MCAN_BitTimingParams*) &gMCAN0BitTimes_250); } /* Configure Message RAM Sections */ DL_MCAN_msgRAMConfig(MCAN, (DL_MCAN_MsgRAMConfigParams*) &gMCAN0MsgRAMConfigParams); /* Configure Standard ID filter element */ DL_MCAN_addStdMsgIDFilter(MCAN, 0U, (DL_MCAN_StdMsgIDFilterElement *) &gMCAN0StdFiltelem1); // DL_MCAN_addStdMsgIDFilter(MCAN, 1U, (DL_MCAN_StdMsgIDFilterElement *) &gMCAN0StdFiltelem2); // // DL_MCAN_addStdMsgIDFilter(MCAN, 2U, (DL_MCAN_StdMsgIDFilterElement *) &gMCAN0StdFiltelem3); // // DL_MCAN_addStdMsgIDFilter(MCAN, 3U, (DL_MCAN_StdMsgIDFilterElement *) &gMCAN0StdFiltelem4); // // DL_MCAN_addStdMsgIDFilter(MCAN, 4U, (DL_MCAN_StdMsgIDFilterElement *) &gMCAN0StdFiltelem5); // DL_MCAN_addExtMsgIDFilter(MCAN, 0U,(DL_MCAN_ExtMsgIDFilterElement *)&gMCAN0ExtFiltelem1); // DL_MCAN_addExtMsgIDFilter(MCAN, 1U,(DL_MCAN_ExtMsgIDFilterElement *)&gMCAN0ExtFiltelem2); // // DL_MCAN_addExtMsgIDFilter(MCAN, 2U,(DL_MCAN_ExtMsgIDFilterElement *)&gMCAN0ExtFiltelem3); /* Set Extended ID Mask. */ DL_MCAN_setExtIDAndMask(MCAN, (0x1FFFFFFFU)); /* Take MCAN out of the SW initialization mode */ DL_MCAN_setOpMode(MCAN, DL_MCAN_OPERATION_MODE_NORMAL); while (DL_MCAN_OPERATION_MODE_NORMAL != DL_MCAN_getOpMode(MCAN)); /* Enable MCAN mopdule Interrupts */ DL_MCAN_enableIntr(MCAN, (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_TC | \ DL_MCAN_INTERRUPT_TOO), 1U); DL_MCAN_selectIntrLine(MCAN, (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_TC | \ DL_MCAN_INTERRUPT_TOO), DL_MCAN_INTR_LINE_NUM_1); DL_MCAN_enableIntrLine(MCAN, DL_MCAN_INTR_LINE_NUM_1, 1U); /* Enable MSPM0 MCAN interrupt */ DL_MCAN_clearInterruptStatus(MCAN,(DL_MCAN_MSP_INTERRUPT_LINE1)); DL_MCAN_enableInterrupt(MCAN,(DL_MCAN_MSP_INTERRUPT_LINE1)); NVIC_SetPriority(CANFD0_INT_IRQn, 1); NVIC_EnableIRQ(CANFD0_INT_IRQn); b_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 xMCAL_MCANDeInit(MCAN_Regs* MCAN) { assert(MCAN == CANFD0); assert(b_MCAN_InitFlag != 0); NVIC_DisableIRQ(CANFD0_INT_IRQn); DL_MCAN_disablePower(MCAN); b_MCAN_InitFlag = 0; 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 xMCAL_MCANTx(MCAN_Regs *MCAN, uint32_t u32ID ,uint16_t *TxData, uint32_t BufNum, uint32_t Bytes) { // xMCAL_MCANTx(CANFD0,0x14FFFC23, timerTxData , 0, 8); assert(MCAN == CANFD0); assert(b_MCAN_InitFlag != 0); assert(Bytes<=8); if (u32ID>0x7FF){ txMsg.xtd = 1; txMsg.id = u32ID; } else{ txMsg.xtd = 0; txMsg.id = ((uint32_t)(u32ID)) << 18U; } for(int i=0;i 2){ __asm("nop"); return IVEC_MCAL_STATUS_TIMEOUT; } } if(HeaderStat.busOffStatus==1) { DL_MCAN_setOpMode(CANFD0, DL_MCAN_OPERATION_MODE_NORMAL); } b_ServiceInt = 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 xMCAL_MCANRx(MCAN_Regs *MCAN,uint32_t *ID ,uint8_t *RxData, int DLC) { assert(MCAN == CANFD0); assert(b_MCAN_InitFlag != 0); if(HeaderStat.busOffStatus==1) { DL_MCAN_setOpMode(CANFD0, DL_MCAN_OPERATION_MODE_NORMAL); } if((((TempRxID&0xFFF)>>1)==0x16)) { xMCAL_SoftReset(); } if((((TempRxID&0xFFF)>>1)==0x1AE)||(((TempRxID&0xFFF)>>1)==0x520)||(((TempRxID&0xFFF)>>1)==0xBB)||(((TempRxID&0xFFF)>>1)==0x1A4)||(((TempRxID&0xFFF)>>1)==0x521))//TODO: CHANGE ID CHECKS AFTER UPDATED CAN MATRIX { *ID=((TempRxID&0xFFF)>>1); } else { *ID=TempRxID; } for(int i=0;i