724 lines
28 KiB
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;
|
|
}
|