Part Number: TMS320F28388D
Tool/software:
raw 133 - mcan.c
raw 1438 - application.c
#include "f28x_project.h"
#include "application.h"
#include "board.h"
#include "device.h"
#include "mcan.h"
TestDescriptor testDescriptor;
int main(void)
{
Device_init();
//
// Allocate MCAN (a shared peripheral) to CPU1 (C28x)
//
SysCtl_allocateSharedPeripheral();
//
// Configure the divisor for the MCAN bit-clock
//
//SysCtl_setMCANClk();
//
// Board peripheral/module configuration
//
Board_init();
XINT1_enable();
MCANIntrsEnable(true);
//
// Initialize message to transmit and receive.
//
MCAN_TxDataFrame_init(&testDescriptor.txMsg[0], 4);
MCAN_RxDataFrameInit(testDescriptor.rxMsg);
//
// Write Tx Message to the Message RAM.
//
MCAN_writeMsgRam(MCAN_MEM_TYPE_BUF, 1U, &testDescriptor.txMsg[0]);
//
// 4-Enable Transmission interrupt.
//
//MCAN_txBufTransIntrEnable(1U,1U);
#if LOOPBACK_MODE
//
// Add request for transmission.
//
MCAN_txBufAddReq(1U);
while(testDescriptor.isrIntr1Flag)
{
}
//
// Read Message RAM.
//
MCAN_readMsgRam(MCAN_MEM_TYPE_BUF, 0U, MCAN_RX_FIFO_NUM_1,
&testDescriptor.rxMsg[0]);
//
// Get the New Data Status.
//
MCAN_getNewDataStatus(&testDescriptor.newData);
//
// Check that received data matches sent data.
// Device will halt here during debug if data doesn't match.
//
if((testDescriptor.txMsg[0].data[0] != testDescriptor.rxMsg[0].data[0]) ||
(testDescriptor.txMsg[0].data[1] != testDescriptor.rxMsg[0].data[1]) ||
(testDescriptor.txMsg[0].data[2] != testDescriptor.rxMsg[0].data[2]) ||
(testDescriptor.txMsg[0].data[3] != testDescriptor.rxMsg[0].data[3]))
{
//
// Device will halt here if transmitted and received data are
// not same.
//
ESTOP0;
}
else
{
//
// Increment message count if message is received.
//
testDescriptor.msgCount++;
}
#endif
while(1)
{
#if CLASSIC_TRANSMIT
if (testDescriptor.enable)
{
testDescriptor.enable = false;
// Add request for all transmission.
//
MCAN_txBufAddReq(1U);
//
// Wait till all the messages are transmitted.
//
while(MCAN_getTxBufReqPend() == 0)
{
}
testDescriptor.msgCount++;
}
#endif
// Turn on LED
//
GPIO_WritePin(99, 0);
//
// Delay for a bit.
//
DELAY_US(500000);
//
// Turn off LED
//
GPIO_WritePin(99, 1);
//
// Delay for a bit.
//
DELAY_US(500000);
}
}
/***************************mcan.c*************************************/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "mcan.h"
#include "mcan_defines.h"
#include "mcanss.h"
#include "hardware.h"
#include "application.h"
void MCAN_init_config()
{
int i;
MCAN_RevisionId revId;
MCAN_InitParams initParams;
MCAN_ConfigParams configParams;
MCAN_MsgRAMConfigParams msgRAMConfigParams;
MCAN_StdMsgIDFilterElement stdFiltelem[MCAN_STD_ID_FILTER_NUM];
MCAN_BitTimingParams bitTimes;
//
// Initializing all structs to zero to prevent stray values
//
memset(&initParams, 0, sizeof(initParams));
memset(&configParams, 0, sizeof(configParams));
memset(&msgRAMConfigParams, 0, sizeof(msgRAMConfigParams));
memset(&stdFiltelem, 0, sizeof(stdFiltelem));
memset(&bitTimes, 0, sizeof(bitTimes));
//
// Initialize MCAN Init parameters.
//
initParams.fdMode = 0x0U; // FD operation enabled - disabled
initParams.brsEnable = 0x0U; // Bit rate switching for - disabled
// transmissions enabled.
initParams.txpEnable = 0x0U; // Transmit pause disabled.
initParams.efbi = 0x0U; // Edge filtering disabled.
initParams.pxhddisable = 0x0U; // Protocol exception handling enabled
initParams.darEnable = 0x0U; // Enable Automatic retransmission of
// messages not transmitted successfully
initParams.wkupReqEnable = 0x1U; // Wakeup request is enabled.
initParams.autoWkupEnable = 0x1U; // Auto-Wakeup is enabled.
initParams.debugSuspendEnable= 0x1U; // Emulation/Debug Suspend is enabled.
initParams.tdcEnable = 0x1U; // Transmitter Delay Compensation is
// enabled.
initParams.wdcPreload = 0xFFU; // Start value of the Message RAM
// Watchdog Counter preload.
//
// Transmitter Delay Compensation parameters.
//
initParams.tdcConfig.tdcf = 0xAU;
initParams.tdcConfig.tdco = 0x6U;
//
// Initialize MCAN Config parameters.
//
configParams.monEnable = 0x0U; // Bus Monitoring Mode is disabled
configParams.asmEnable = 0x0U; // Normal CAN operation.
configParams.tsPrescalar = 0xFU; // Prescaler Value.
configParams.tsSelect = 0x0U; // Timestamp counter value.
configParams.timeoutSelect = MCAN_TIMEOUT_SELECT_CONT;
// Time-out counter source select.
configParams.timeoutPreload = 0xFFFFU; // Start value of the Timeout
// Counter.
configParams.timeoutCntEnable = 0x0U; // Time-out Counter is disabled.
configParams.filterConfig.rrfs = 0x1U; // Reject all remote frames with
// 29-bit extended IDs.
configParams.filterConfig.rrfe = 0x1U; // Reject all remote frames with
// 11-bit standard IDs.
configParams.filterConfig.anfe = 0x1U; // Accept in Rx FIFO 1.
configParams.filterConfig.anfs = 0x1U; // Accept in Rx FIFO 1.
//
// Initialize Message RAM Sections Configuration Parameters.
//
msgRAMConfigParams.flssa = MCAN_STD_ID_FILT_START_ADDR;
// Standard ID Filter List Start Address.
msgRAMConfigParams.lss = MCAN_STD_ID_FILTER_NUM;
// List Size: Standard ID.
msgRAMConfigParams.flesa = MCAN_EXT_ID_FILT_START_ADDR;
// Extended ID Filter List Start Address.
msgRAMConfigParams.lse = MCAN_EXT_ID_FILTER_NUM;
// List Size: Extended ID.
msgRAMConfigParams.txStartAddr = MCAN_TX_BUFF_START_ADDR;
// Tx Buffers Start Address.
msgRAMConfigParams.txBufNum = MCAN_TX_BUFF_SIZE;
// Number of Dedicated Transmit Buffers.
msgRAMConfigParams.txFIFOSize = 0U; // No Tx FIFO/Queue.
msgRAMConfigParams.txBufMode = 0U; //Tx FIFO operation
msgRAMConfigParams.txBufElemSize = MCAN_TX_BUFF_ELEM_SIZE;
// Tx Buffer Element Size.
msgRAMConfigParams.txEventFIFOStartAddr = MCAN_TX_EVENT_START_ADDR;
// Tx Event FIFO Start Address.
msgRAMConfigParams.txEventFIFOSize = MCAN_TX_BUFF_SIZE;
// Event FIFO Size.
msgRAMConfigParams.txEventFIFOWaterMark = 5U;
// Level for Tx Event FIFO watermark interrupt.
msgRAMConfigParams.rxFIFO0startAddr = MCAN_FIFO_0_START_ADDR;
// Rx FIFO0 Start Address.
msgRAMConfigParams.rxFIFO0size = MCAN_FIFO_0_NUM;
// Number of Rx FIFO elements.
msgRAMConfigParams.rxFIFO0waterMark = 5U; // Rx FIFO0 Watermark.
msgRAMConfigParams.rxFIFO0OpMode = 0U; // FIFO blocking mode.
msgRAMConfigParams.rxFIFO1startAddr = MCAN_FIFO_1_START_ADDR;
// Rx FIFO1 Start Address.
msgRAMConfigParams.rxFIFO1size = MCAN_FIFO_1_NUM;
// Number of Rx FIFO elements.
msgRAMConfigParams.rxFIFO1waterMark = 5U; // Level for Rx FIFO 1
// watermark interrupt.
msgRAMConfigParams.rxFIFO1OpMode = 0U; // FIFO blocking mode.
msgRAMConfigParams.rxBufStartAddr = MCAN_RX_BUFF_START_ADDR;
// Rx Buffer Start Address.
msgRAMConfigParams.rxBufElemSize = MCAN_RX_BUFF_ELEM_SIZE;
// Rx Buffer Element Size.
msgRAMConfigParams.rxFIFO0ElemSize = MCAN_FIFO_0_ELEM_SIZE;
// Rx FIFO0 Element Size.
msgRAMConfigParams.rxFIFO1ElemSize = MCAN_FIFO_1_ELEM_SIZE;
// Rx FIFO1 Element Size.
//Standard ID filters initialize
//Configure Standard ID filter element 0
MCAN_StdIDFilterConfiguration(&stdFiltelem[0], 0, 4, 7, 0 );
//Configure Standard ID filter element 1
MCAN_StdIDFilterConfiguration(&stdFiltelem[1], 1, 5, 7, 0 );
//Configure Standard ID filter element 2
MCAN_StdIDFilterConfiguration(&stdFiltelem[2], 2, 6, 7, 0 );
//Configure Standard ID filter element 3
MCAN_StdIDFilterConfiguration(&stdFiltelem[3], 3, 7, 7, 0 );
//
// Initialize bit timings - source clock 10 MHz
//
bitTimes.nomRatePrescalar = 0x0U; // Nominal Baud Rate Pre-scaler.
bitTimes.nomTimeSeg1 = 0x9U; // Nominal Time segment before SP
bitTimes.nomTimeSeg2 = 0x8U; // Nominal Time segment after SP
bitTimes.nomSynchJumpWidth = 0x8U; // Nominal SJW
bitTimes.dataRatePrescalar = 0x1U; // Data Baud Rate Pre-scaler.
bitTimes.dataTimeSeg1 = 0x9U; // Data Time segment before SP
bitTimes.dataTimeSeg2 = 0x8U; // Data Time segment after SP
bitTimes.dataSynchJumpWidth = 0x8U; // Data SJW
//
// Get MCANSS Revision ID.
//
MCAN_getRevisionId(&revId);
//
// Wait for Memory initialization to be completed.
//
while(false == MCAN_isMemInitDone());
//
// Put MCAN in SW initialization mode.
//
MCAN_setOpMode(MCAN_OPERATION_MODE_SW_INIT);
//
// Wait till MCAN is not initialized.
//
while (MCAN_OPERATION_MODE_SW_INIT != McanaRegs.MCAN_CCCR.bit.INIT);
//
// Initialize MCAN module.
//
MCAN_init(&initParams);
//
// Configure MCAN module.
//
MCAN_config(&configParams);
//
// Configure Bit timings.
//
MCAN_setBitTime(&bitTimes);
//
// Configure Message RAM Sections
//
MCAN_msgRAMConfig(&msgRAMConfigParams);
//
// Configure Standard ID filter element
//
#if !EXT_ID_FILTER
for (i = 0; i<MCAN_STD_ID_FILTER_NUM; i++)
MCAN_addStdMsgIDFilter(i, &stdFiltelem[i]);
#else
//
// Configure Extended ID filter element
//
MCAN_addExtMsgIDFilter(0U, &extFiltelem);
//
// Set Extended ID Mask for acceptance filtering of received frames
// (Mask disabled when all bits are set to 1)
//
MCAN_setExtIDAndMask(MCAN_EXT_ID_AND_MASK);
#endif
#if LOOPBACK_MODE
//
// Enable internal/external loopback mode
//
MCAN_lpbkModeEnable(MCAN_LPBK_MODE_EXTERNAL, true);
#endif
//
// Take MCAN out of the SW initialization mode
//
MCAN_setOpMode(MCAN_OPERATION_MODE_NORMAL);
while (MCAN_OPERATION_MODE_NORMAL != McanaRegs.MCAN_CCCR.bit.INIT);
}
/**
* \brief This API is used get the MCAN revision ID.
*
*
* \param revId Contains Revision ID of MCAN module.
* Refer struct #MCAN_RevisionId.
*
* \return None.
*/
static void MCAN_getRevisionId(MCAN_RevisionId *revId)
{
revId->minor = McanaSsRegs.MCANSS_PID.bit.MINOR; //Minor Revision of the MCAN Subsystem
revId->major = McanaSsRegs.MCANSS_PID.bit.MAJOR; //Major Revision of the MCAN Subsystem
revId->modId = McanaSsRegs.MCANSS_PID.bit.MODULE_ID; //Module Identification Number
revId->scheme = McanaSsRegs.MCANSS_PID.bit.SCHEME; //PID Register Scheme
revId->day = McanaRegs.MCAN_CREL.bit.DAY; //Time Stamp Day. Two digits, BCD-coded
revId->mon = McanaRegs.MCAN_CREL.bit.MON; //Time Stamp Month. Two digits, BCD-coded
revId->year = McanaRegs.MCAN_CREL.bit.YEAR; //Time Stamp Year. One digit, BCD-coded
revId->subStep = McanaRegs.MCAN_CREL.bit.SUBSTEP; //Sub-Step of Core Release. One digit, BCD-coded
revId->step = McanaRegs.MCAN_CREL.bit.STEP; //Step of Core Release. One digit, BCD-coded
revId->rel = McanaRegs.MCAN_CREL.bit.REL; //Core Release. One digit, BCD-coded
}
/**
* \brief This function checks if the memory initialization is done for
* MCAN module.
*
*
*
* \retval state Returns TRUE if memory initialization is done.
* Else returns FALSE.*/
static bool MCAN_isMemInitDone()
{
uint32_t memInit;
bool state = false;
memInit = McanaSsRegs.MCANSS_STAT.bit.MEM_INIT_DONE;
if(1U == memInit)
{
state = true;
}
return state;
}
/**
* \brief This API will set MCAN module mode of operation.
*
*
* \param mode Mode of operation.
* Refer enum #MCAN_OperationMode.
*
* \return None.
*/
static void MCAN_setOpMode(uint32_t mode)
{
McanaRegs.MCAN_CCCR.bit.INIT = mode;
}
/**
* \brief This API will initialize MCAN module.
*
* \param initParams Initialization parameters.
* Refer struct #MCAN_InitParams.
*
* \return status Initialization status.
*/
static bool MCAN_init(const MCAN_InitParams *initParams)
{
bool status;
/* Configure MCAN wakeup and clock stop controls */
McanaSsRegs.MCANSS_CTRL.bit.WAKEUPREQEN = initParams->wkupReqEnable;
McanaSsRegs.MCANSS_CTRL.bit.AUTOWAKEUP = initParams->autoWkupEnable;
McanaSsRegs.MCANSS_CTRL.bit.DBGSUSP_FREE = initParams->debugSuspendEnable;
McanaRegs.MCAN_CCCR.bit.CCE = 1;
/*Configuration Change Enable 0 The CPU has no write
registers
1 The CPU has write acc
hile CCCR.INIT = '1'
*/
/* Configure MCAN mode(FD vs Classic CAN operation) and controls */
McanaRegs.MCAN_CCCR.bit.FDOE = initParams->fdMode;
McanaRegs.MCAN_CCCR.bit.BRSE = initParams->brsEnable;
McanaRegs.MCAN_CCCR.bit.TXP = initParams->txpEnable;
McanaRegs.MCAN_CCCR.bit.EFBI = initParams->efbi;
McanaRegs.MCAN_CCCR.bit.PXHD = initParams->pxhddisable;
McanaRegs.MCAN_CCCR.bit.DAR = initParams->darEnable;
if((MCAN_TDCR_TDCF_MAX >= initParams->tdcConfig.tdcf) &&
(MCAN_TDCR_TDCO_MAX >= initParams->tdcConfig.tdco) &&
(MCAN_RWD_WDC_MAX >= initParams->wdcPreload))
{
/* Configure Transceiver Delay Compensation */
McanaRegs.MCAN_TDCR.bit.TDCF = initParams->tdcConfig.tdcf;
McanaRegs.MCAN_TDCR.bit.TDCO = initParams->tdcConfig.tdco;
/* Configure MSG RAM watchdog counter preload value */
McanaRegs.MCAN_RWD.bit.WDC = initParams->wdcPreload;
/* Enable/Disable Transceiver Delay Compensation */
McanaRegs.MCAN_DBTP.bit.TDC = initParams->tdcEnable;
status = true;
}
else
{
status = false;
}
McanaRegs.MCAN_CCCR.bit.CCE = 0;
return status;
}
/**
* \brief This API will configure MCAN module.
*
* \param configParams configuration parameters.
* Refer struct #MCAN_ConfigParams.
*
* \return status Configuration status.
*/
static bool MCAN_config(const MCAN_ConfigParams *configParams)
{
bool status;
McanaRegs.MCAN_CCCR.bit.CCE = 1;
/* Configure MCAN control registers */
McanaRegs.MCAN_CCCR.bit.MON = configParams->monEnable;
McanaRegs.MCAN_CCCR.bit.ASM = configParams->asmEnable;
/* Configure Global Filter */
McanaRegs.MCAN_GFC.bit.RRFE = configParams->filterConfig.rrfe;
McanaRegs.MCAN_GFC.bit.RRFS = configParams->filterConfig.rrfs;
McanaRegs.MCAN_GFC.bit.ANFE = configParams->filterConfig.anfe;
McanaRegs.MCAN_GFC.bit.ANFS = configParams->filterConfig.anfs;
if((MCAN_TSCC_TCP_MAX >= configParams->tsPrescalar) &&
(MCAN_TOCC_TOP_MAX >= configParams->timeoutPreload))
{
/* Configure Time-stamp counter */
McanaRegs.MCAN_TSCC.bit.TSS = configParams->tsSelect;
McanaRegs.MCAN_TSCC.bit.TCP = (configParams->tsPrescalar - 1U);
/* Configure Time-out counter */
McanaRegs.MCAN_TOCC.bit.TOS = configParams->timeoutSelect;
McanaRegs.MCAN_TOCC.bit.TOP = configParams->timeoutPreload;
/* Enable Time-out counter */
McanaRegs.MCAN_TOCC.bit.ETOC = configParams->timeoutCntEnable;
status = true;
}
else
{
status = false;
}
McanaRegs.MCAN_CCCR.bit.CCE = 0;
return status;
}
/**
* \brief This API will configure a bit timings for MCAN module.
*
* \param configParams Configuration parameters for MCAN bit timing.
* Refer struct #MCAN_BitTimingParams.
*
* \return status Bit Timings configuration status.
*/
static bool MCAN_setBitTime(const MCAN_BitTimingParams *configParams)
{
bool status;
McanaRegs.MCAN_CCCR.bit.CCE = 1;
if((MCAN_NBTP_NSJW_MAX >= configParams->nomSynchJumpWidth) &&
(MCAN_NBTP_NTSEG2_MAX >= configParams->nomTimeSeg2) &&
(MCAN_NBTP_NTSEG1_MAX >= configParams->nomTimeSeg1) &&
(MCAN_NBTP_NBRP_MAX >= configParams->nomRatePrescalar))
{
McanaRegs.MCAN_NBTP.bit.NSJW = configParams->nomSynchJumpWidth;
McanaRegs.MCAN_NBTP.bit.NTSEG2 = configParams->nomTimeSeg2;
McanaRegs.MCAN_NBTP.bit.NTSEG1 = configParams->nomTimeSeg1;
McanaRegs.MCAN_NBTP.bit.NBRP = configParams->nomRatePrescalar;
status = true;
}
else
{
status = false;
}
if(true == status)
{
if((MCAN_DBTP_DSJW_MAX >= configParams->dataSynchJumpWidth) &&
(MCAN_DBTP_DTSEG2_MAX >= configParams->dataTimeSeg2) &&
(MCAN_DBTP_DTSEG1_MAX >= configParams->dataTimeSeg1) &&
(MCAN_DBTP_DBRP_MAX >= configParams->dataRatePrescalar))
{
McanaRegs.MCAN_DBTP.bit.DSJW = configParams->dataSynchJumpWidth;
McanaRegs.MCAN_DBTP.bit.DTSEG2 = configParams->dataTimeSeg2;
McanaRegs.MCAN_DBTP.bit.DTSEG1 = configParams->dataTimeSeg1;
McanaRegs.MCAN_DBTP.bit.DBRP = configParams->dataRatePrescalar;
status = true;
}
else
{
status = false;
}
}
McanaRegs.MCAN_CCCR.bit.CCE = 0;
return status;
}
/**
* \brief This API will configure Different sections of Message RAM.
*
* \param msgRAMConfigParams
* Message RAM Configuration parameters.
* Refer struct #MCAN_MsgRAMConfigParams.
*
* \return status Configuration Status.
*/
static bool MCAN_msgRAMConfig(const MCAN_MsgRAMConfigParams *msgRAMConfigParams)
{
bool status;
uint32_t elemNum = 0U;
McanaRegs.MCAN_CCCR.bit.CCE = 1;
/* Configure Message Filters section */
if(0U != msgRAMConfigParams->lss)
{
McanaRegs.MCAN_SIDFC.bit.FLSSA = (msgRAMConfigParams->flssa >> 2U);
McanaRegs.MCAN_SIDFC.bit.LSS = msgRAMConfigParams->lss;
}
if(0U != msgRAMConfigParams->lse)
{
McanaRegs.MCAN_XIDFC.bit.FLESA = (msgRAMConfigParams->flesa >> 2U);
McanaRegs.MCAN_XIDFC.bit.LSE = msgRAMConfigParams->lse;
}
/* Configure Rx FIFO 0 section */
if(0U != msgRAMConfigParams->rxFIFO0size)
{
McanaRegs.MCAN_RXF0C.bit.F0SA = (msgRAMConfigParams->rxFIFO0startAddr >> 2U);
McanaRegs.MCAN_RXF0C.bit.F0S = msgRAMConfigParams->rxFIFO0size;
McanaRegs.MCAN_RXF0C.bit.F0WM = msgRAMConfigParams->rxFIFO0waterMark;
McanaRegs.MCAN_RXF0C.bit.F0OM = msgRAMConfigParams->rxFIFO0OpMode;
/* Configure Rx FIFO0 elements size */
McanaRegs.MCAN_RXESC.bit.F0DS = msgRAMConfigParams->rxFIFO0ElemSize;
}
/* Configure Rx FIFO 1 section */
if(0U != msgRAMConfigParams->rxFIFO1size)
{
McanaRegs.MCAN_RXF1C.bit.F1SA = (msgRAMConfigParams->rxFIFO1startAddr >> 2U);
McanaRegs.MCAN_RXF1C.bit.F1S = msgRAMConfigParams->rxFIFO1size;
McanaRegs.MCAN_RXF1C.bit.F1WM = msgRAMConfigParams->rxFIFO1waterMark;
McanaRegs.MCAN_RXF1C.bit.F1OM = msgRAMConfigParams->rxFIFO1OpMode;
/* Configure Rx FIFO0 elements size */
McanaRegs.MCAN_RXESC.bit.F1DS = msgRAMConfigParams->rxFIFO1ElemSize;
}
/* Configure Rx Buffer Start Address */
McanaRegs.MCAN_RXBC.bit.RBSA = (msgRAMConfigParams->rxBufStartAddr >> 2U);
/* Configure Rx Buffer elements size */
McanaRegs.MCAN_RXESC.bit.RBDS = msgRAMConfigParams->rxBufElemSize;
/* Configure Tx Event FIFO section */
if(0U != msgRAMConfigParams->txEventFIFOSize)
{
McanaRegs.MCAN_TXEFC.bit.EFSA = (msgRAMConfigParams->txEventFIFOStartAddr >> 2U);
McanaRegs.MCAN_TXEFC.bit.EFS = msgRAMConfigParams->txEventFIFOSize;
McanaRegs.MCAN_TXEFC.bit.EFWM = msgRAMConfigParams->txEventFIFOWaterMark;
}
/* Configure Tx Buffer and FIFO/Q section */
elemNum = msgRAMConfigParams->txBufNum + msgRAMConfigParams->txFIFOSize;
if((MCANSS_TX_BUFFER_MAX >= elemNum) &&
((0U != msgRAMConfigParams->txBufNum) ||
(0U != msgRAMConfigParams->txFIFOSize)))
{
McanaRegs.MCAN_TXBC.bit.TBSA = (msgRAMConfigParams->txStartAddr >> 2U);
McanaRegs.MCAN_TXBC.bit.NDTB = msgRAMConfigParams->txBufNum;
McanaRegs.MCAN_TXBC.bit.TFQS = msgRAMConfigParams->txFIFOSize;
McanaRegs.MCAN_TXBC.bit.TFQM = msgRAMConfigParams->txBufMode;
/* Configure Tx Buffer/FIFO0/FIFO1 elements size */
McanaRegs.MCAN_TXESC.bit.TBDS = msgRAMConfigParams->txBufElemSize;
status = true;
}
else
{
status = false;
}
McanaRegs.MCAN_CCCR.bit.CCE = 0;
return status;
}
/**
* \brief This API is used to add Standard Message ID Filter Element.
*
* \param filtNum Filter number.
* \param elem Filter Object.
* Refer struct #MCAN_StdMsgIDFilterElement.
*
* \return None.
*/
#if !EXT_ID_FILTER
static void MCAN_addStdMsgIDFilter(uint32_t filtNum, const MCAN_StdMsgIDFilterElement *elem)
{
uint32_t startAddr, elemAddr, regVal, newAddr;
startAddr = McanaRegs.MCAN_SIDFC.bit.FLSSA;
startAddr = (uint32_t) (startAddr << 2U);
elemAddr = startAddr + (filtNum * MCANSS_STD_ID_FILTER_SIZE_WORDS * 4U);
elemAddr += MCAN_STD_ID_FILT_START_ADDR;
regVal = 0U;
regVal |= (uint32_t) (elem->sfid2 << MCANSS_STD_ID_FILTER_SFID2_SHIFT);
regVal |= (uint32_t) (elem->sfid1 << MCANSS_STD_ID_FILTER_SFID1_SHIFT);
regVal |= (uint32_t) (elem->sfec << MCANSS_STD_ID_FILTER_SFEC_SHIFT);
regVal |= (uint32_t) (elem->sft << MCANSS_STD_ID_FILTER_SFT_SHIFT);
newAddr = MCANA_MSG_RAM_BASE + elemAddr;
HW_WR_REG32(newAddr, regVal);
}
#endif
/**
* \brief This API will enable/disable Loop Back Test Mode for
* MCAN module.
*
* \param lpbkMode Loopback mode for MCAN.
* Refer #enum MCAN_LpbkMode.
* \param enable Loop Back Mode is enabled if it is TRUE.
* Loop Back Mode is disabled if it is FALSE.
*
* \return None.
* \note This API can be called only when MCAN is in Software
* Initialization mode of operation.
*/
static void MCAN_lpbkModeEnable(uint32_t lpbkMode,uint32_t enable)
{
McanaRegs.MCAN_CCCR.bit.CCE = 1;
if(true == enable)
{
McanaRegs.MCAN_CCCR.bit.TEST = 1;
McanaRegs.MCAN_TEST.bit.LBCK = enable;
if((uint32_t)MCAN_LPBK_MODE_INTERNAL == lpbkMode)
{
McanaRegs.MCAN_CCCR.bit.MON = 1;
}
}
else
{
McanaRegs.MCAN_TEST.bit.LBCK = enable;
McanaRegs.MCAN_CCCR.bit.TEST = 0;
if((uint32_t)MCAN_LPBK_MODE_INTERNAL == lpbkMode)
{
McanaRegs.MCAN_CCCR.bit.MON = 0;
}
}
McanaRegs.MCAN_CCCR.bit.CCE = 0;
}
/**
* \brief This API is used to write Tx message to message RAM.
*
* \param memType Part of message ram to which given message to write.
* Refer enum #MCAN_MemType.
* \param bufNum Buffer number where message to write.
* This parameter will ignored if memType is FIFO/Q.
* \param elem Message Object.
* Refer struct #MCAN_TxBufElement.
*
* \return None.
*/
void MCAN_writeMsgRam(uint32_t memType, uint32_t bufNum, const MCAN_TxBufElement *elem)
{
uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U;
uint32_t idx = 0U, enableMod = 0U;
if((uint32_t)MCAN_MEM_TYPE_BUF == memType)
{
idx = bufNum;
enableMod = 1U;
}
if((uint32_t)MCAN_MEM_TYPE_FIFO == memType)
{
idx = McanaRegs.MCAN_TXFQS.bit.TFQP;
/*
* Tx FIFO/Queue Put Index. Tx FIFO/Queue write index pointer, range
0 to 31.
Note: In case of mixed configurations where dedicated Tx Buffers are
combined with a Tx FIFO or a Tx Queue, the Put and Get Indices
indicate the number of the Tx Buffer starting with the first dedicated
Tx Buffers. Example: For a configuration of 12 dedicated Tx Buffers
and a Tx FIFO of 20 Buffers a Put Index of 15 points to the fourth
buffer of the Tx FIFO.
* */
enableMod = 1U;
}
if(1U == enableMod)
{
startAddr = McanaRegs.MCAN_TXBC.bit.TBSA;
elemSize = McanaRegs.MCAN_TXESC.bit.TBDS;
startAddr = (uint32_t) (startAddr << 2U);
elemSize = MCAN_getMsgObjSize(elemSize);
elemSize *= 4U;
elemAddr = startAddr + (elemSize * idx);
elemAddr += MCAN_MCAN_MSG_MEM;
MCAN_writeMsg(elemAddr, elem);
}
}
/**
* \brief This API will write the message object to Message RAM.
*
* \param elemAddr Address of the message object.
* \param elem Message Object.
* Refer struct #MCAN_TxBufElement.
*
* \return None.
*/
static void MCAN_writeMsg(uint32_t elemAddr, const MCAN_TxBufElement *elem)
{
uint32_t regVal = 0, loopCnt = 0U;
regVal = 0U;
regVal |= (((uint32_t) (elem->id << MCANSS_TX_BUFFER_ELEM_ID_SHIFT)) |
((uint32_t) (elem->rtr << MCANSS_TX_BUFFER_ELEM_RTR_SHIFT)) |
((uint32_t) (elem->xtd << MCANSS_TX_BUFFER_ELEM_XTD_SHIFT)) |
((uint32_t) (elem->esi << MCANSS_TX_BUFFER_ELEM_ESI_SHIFT)));
HW_WR_REG32(MCANA_MSG_RAM_BASE+elemAddr, regVal);
elemAddr += 4U;
regVal = 0U;
regVal |= ((uint32_t) (elem->dlc << MCANSS_TX_BUFFER_ELEM_DLC_SHIFT)) |
((uint32_t) (elem->brs << MCANSS_TX_BUFFER_ELEM_BRS_SHIFT)) |
((uint32_t) (elem->fdf << MCANSS_TX_BUFFER_ELEM_FDF_SHIFT)) |
((uint32_t) (elem->efc << MCANSS_TX_BUFFER_ELEM_EFC_SHIFT)) |
((uint32_t) (elem->mm << MCANSS_TX_BUFFER_ELEM_MM_SHIFT));
HW_WR_REG32(MCANA_MSG_RAM_BASE+elemAddr, regVal);
elemAddr += 4U;
loopCnt = 0U;
/* Framing words out of the payload bytes and writing it to message RAM */
while((4U <= (MCAN_getDataSize(elem->dlc) - loopCnt)) &&
(0U != (MCAN_getDataSize(elem->dlc) - loopCnt)))
{
ASSERT((loopCnt + 3U) < MCAN_MAX_PAYLOAD_BYTES);
regVal = 0U;
regVal |= ((uint32_t)elem->data[loopCnt] |
((uint32_t)elem->data[(loopCnt + 1U)] << 8U) |
((uint32_t)elem->data[(loopCnt + 2U)] << 16U) |
((uint32_t)elem->data[(loopCnt + 3U)] << 24U));
HW_WR_REG32(MCANA_MSG_RAM_BASE+elemAddr, regVal);
elemAddr += 4U;
loopCnt += 4U;
}
/* Framing a word out of remaining payload bytes and writing it to
* message RAM */
if(0U < (MCAN_getDataSize(elem->dlc) - loopCnt))
{
ASSERT((loopCnt + 3U) < MCAN_MAX_PAYLOAD_BYTES);
regVal = 0U;
regVal |= ((uint32_t)elem->data[loopCnt] |
((uint32_t)elem->data[(loopCnt + 1U)] << 8U) |
((uint32_t)elem->data[(loopCnt + 2U)] << 16U) |
((uint32_t)elem->data[(loopCnt + 3U)] << 24U));
HW_WR_REG32(MCANA_MSG_RAM_BASE+elemAddr, regVal);
}
}
static uint32_t MCAN_getDataSize(uint32_t dlc)
{
uint32_t dataSize[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8,
12, 16, 20, 24, 32, 48, 64};
ASSERT(dlc < 16U);
return(dataSize[dlc]);
}
/**
* \brief This API will return Tx Buffer Request Pending status.
*
*
* \return status Tx Buffer Request Pending status.
*/
#if 0
bool MCAN_getTxBufReqPend()
{
bool bufStatus = false;
int i;
uint32_t regValue = McanaRegs.MCAN_TXBRP.all;
for (i = 0; i < 32; i++)
{
bufStatus |= (regValue & (1 << i));
}
return bufStatus;
}
#endif
/**
* \brief This API is used to enable/disable interrupts.
*
* \param intrMask Interrupts to enable.
* Refer enum #MCAN_IntrSrc.
* \param enable Interrupt is enabled if it is TRUE.
* Interrupt is disabled if it is FALSE.
* MCAN Interrupt Enable
* \return None.
*/
void MCAN_enableIntr(uint32_t intrMask, uint32_t enable)
{
uint32_t regVal;
if(true == enable)
{
regVal = McanaRegs.MCAN_IE.all;
regVal |= intrMask;
McanaRegs.MCAN_IE.all = regVal;
}
else
{
regVal = McanaRegs.MCAN_IE.all;
regVal &= ~intrMask;
McanaRegs.MCAN_IE.all = regVal;
}
}
/**
* \brief This API is used to select interrupt line.
*
* \param intrMask Interrupt Number for which interrupt
* line is to be selected. Refer enum #MCAN_IntrSrc.
* \param lineNum Interrupt Line to select.
* Refer enum #MCAN_IntrLineNum,
* MCAN Interrupt Line Select
* \return None.
*/
void MCAN_selectIntrLine(uint32_t intrMask, uint32_t lineNum)
{
uint32_t regVal;
if((uint32_t)MCAN_INTR_LINE_NUM_0 == lineNum)
{
regVal = McanaRegs.MCAN_ILS.all;
regVal &= ~intrMask;
McanaRegs.MCAN_ILS.all = regVal;
}
else
{
regVal = McanaRegs.MCAN_ILS.all;
regVal |= intrMask;
McanaRegs.MCAN_ILS.all = regVal;
}
}
/**
* \brief This API is used to enable/disable selected interrupt line.
*
* \param lineNum Interrupt Line to select.
* Refer enum #MCAN_IntrLineNum,
* \param enable Interrupt Line is enabled if it is 1.
* Interrupt Line is disabled if it is 0.
* MCAN Interrupt Line Enable EINT0, EINT1
* \return None.
*/
void MCAN_enableIntrLine(uint32_t lineNum, uint32_t enable)
{
uint32_t regVal;
lineNum &= MCANSS_INTR_LINE_EN_MASK;
regVal = McanaRegs.MCAN_ILE.all;
regVal &= ~((uint32_t) 0x1U << lineNum);
regVal |= (uint32_t) (enable << lineNum);
McanaRegs.MCAN_ILE.all = regVal;
}
/**
* \brief This API is used to enable/disable Tx Buffer Transmission Interrupt.
*
* \param bufNum Buffer number for which interrupt is to enable.
* \param enable Interrupt is enabled if it is TRUE.
* Interrupt is disabled if it is FALSE.
* MCAN Tx Buffer Transmission Interrupt Enable
* \return status Configuration status.
*/
bool MCAN_txBufTransIntrEnable(uint32_t bufNum, uint32_t enable)
{
bool status = false;
uint32_t regVal;
if(MCANSS_TX_BUFFER_MAX > bufNum)
{
if(true == enable)
{
regVal = McanaRegs.MCAN_TXBTIE.all;
regVal |= ((uint32_t) 1U << bufNum);
McanaRegs.MCAN_TXBTIE.all = regVal;
}
else
{
regVal = McanaRegs.MCAN_TXBTIE.all;
regVal &= ~((uint32_t) 0x1U << bufNum);
McanaRegs.MCAN_TXBTIE.all = regVal;
}
status = true;
}
return status;
}
/**
* \brief This API will set Tx Buffer Add Request.
*
* \param bufNum Tx Buffer number for which request is to be added.
*
* MCAN Tx Buffer Add Request
* \return status Configuration Status.
*/
bool MCAN_txBufAddReq(uint32_t bufNum)
{
bool status = false;
uint32_t regVal;
if(MCANSS_TX_BUFFER_MAX > bufNum)
{
regVal = McanaRegs.MCAN_TXBAR.all;
regVal |= ((uint32_t) 1U << bufNum);
// For writing to TXBAR CCE bit should be '0'. This need not be
// reverted because for other qualified writes this is locked state
// and can't be written.
//McanaRegs.MCAN_CCCR.bit.CCE = 0;
McanaRegs.MCAN_TXBAR.all = regVal;
status = true;
}
return status;
}
/**
* \brief This API is used to read received message form message RAM.
*
* \param memType Part of message ram to which given message to write.
* Refer enum #MCAN_MemType.
* \param bufNum Buffer number from where message is to read.
* This parameter will ignored if memType is FIFO/Q.
* \param fifoNum FIFOs number from where message is to read.
* Refer enum #MCAN_RxFIFONum.
* This parameter will ignored if memType is buffer.
* \param elem Message Object.
* Refer struct #MCAN_RxBufElement.
*
* \return None.
*/
void MCAN_readMsgRam(uint32_t memType, uint32_t bufNum, uint32_t fifoNum, MCAN_RxBufElement *elem)
{
uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U;
uint32_t enableMod = 0U, idx = 0U;
if((uint32_t)MCAN_MEM_TYPE_BUF == memType)
{
startAddr = McanaRegs.MCAN_RXBC.bit.RBSA;
/*Rx Buffer Start Address. Configures the start address of the Rx
Buffers section in the Message RAM (32-bit word address).
*/
elemSize = McanaRegs.MCAN_RXESC.bit.RBDS;
/*
* Rx Buffer Data Field Size
000 8 byte data field
001 12 byte data field
010 16 byte data field
011 20 byte data field
100 24 byte data field
101 32 byte data field
110 48 byte data field
111 64 byte data field
Note: In case the data field size of an accepted CAN frame exceeds
the data field size configured for the matching Rx Buffer or Rx FIFO,
only the number of bytes as configured by RXESC are stored to the
Rx Buffer resp. Rx FIFO element. The rest of the frame's data field is
ignored.
Qualified Write is possible only with CCCR.CCE='1' and
CCCR.INIT='1'.
*/
idx = bufNum;
enableMod = 1U;
}
if((uint32_t)MCAN_MEM_TYPE_FIFO == memType)
{
switch (fifoNum)
{
case MCAN_RX_FIFO_NUM_0:
startAddr = McanaRegs.MCAN_RXF0C.bit.F0SA;
/*Rx FIFO 0 Start Address. Start address of Rx FIFO 0 in Message
RAM (32-bit word address).
Qualified Write is possible only with CCCR.CCE='1' and
CCCR.INIT='1'.
*/
elemSize = McanaRegs.MCAN_RXESC.bit.F0DS;
/*
* Rx FIFO 0 Data Field Size
000 8 byte data field
001 12 byte data field
010 16 byte data field
011 20 byte data field
100 24 byte data field
101 32 byte data field
110 48 byte data field
111 64 byte data field
Note: In case the data field size of an accepted CAN frame exceeds
the data field size configured for the matching Rx Buffer or Rx FIFO,
only the number of bytes as configured by RXESC are stored to the
Rx Buffer resp. Rx FIFO element. The rest of the frame's data field is
ignored.
Qualified Write is possible only with CCCR.CCE='1' and
CCCR.INIT='1'.
*/
idx = McanaRegs.MCAN_RXF0S.bit.F0GI; //Rx FIFO 0 Get Index. Rx FIFO 0 read index pointer, range 0 to 63.
enableMod = 1U;
break;
case MCAN_RX_FIFO_NUM_1:
startAddr = McanaRegs.MCAN_RXF1C.bit.F1SA;
/*Rx FIFO 0 Start Address. Start address of Rx FIFO 0 in Message
RAM (32-bit word address).
Qualified Write is possible only with CCCR.CCE='1' and
CCCR.INIT='1'.
*/
elemSize = McanaRegs.MCAN_RXESC.bit.F1DS;
/*
* Rx FIFO 0 Data Field Size
000 8 byte data field
001 12 byte data field
010 16 byte data field
011 20 byte data field
100 24 byte data field
101 32 byte data field
110 48 byte data field
111 64 byte data field
Note: In case the data field size of an accepted CAN frame exceeds
the data field size configured for the matching Rx Buffer or Rx FIFO,
only the number of bytes as configured by RXESC are stored to the
Rx Buffer resp. Rx FIFO element. The rest of the frame's data field is
ignored.
Qualified Write is possible only with CCCR.CCE='1' and
CCCR.INIT='1'.
*/
idx = McanaRegs.MCAN_RXF1S.bit.F1GI; //Rx FIFO 0 Get Index. Rx FIFO 0 read index pointer, range 0 to 63.
enableMod = 1U;
break;
default:
/* Invalid option */
break;
}
}
if(1U == enableMod)
{
startAddr = (uint32_t) (startAddr << 2U);
elemSize = MCAN_getMsgObjSize(elemSize);
elemSize *= 4U;
elemAddr = startAddr + (elemSize * idx);
elemAddr += MCAN_MCAN_MSG_MEM;
MCAN_readMsg(elemAddr, elem);
}
}
static void MCAN_readMsg(uint32_t elemAddr,MCAN_RxBufElement *elem)
{
uint32_t regVal = 0U, loopCnt = 0U;
regVal = HW_RD_REG32(MCANA_MSG_RAM_BASE + elemAddr);
elem->id = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_ID_MASK)
>> MCANSS_RX_BUFFER_ELEM_ID_SHIFT);
elem->rtr = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_RTR_MASK)
>> MCANSS_RX_BUFFER_ELEM_RTR_SHIFT);
elem->xtd = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_XTD_MASK)
>> MCANSS_RX_BUFFER_ELEM_XTD_SHIFT);
elem->esi = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_ESI_MASK)
>> MCANSS_RX_BUFFER_ELEM_ESI_SHIFT);
elemAddr += 4U;
regVal = HW_RD_REG32(MCANA_MSG_RAM_BASE + elemAddr);
elem->rxts = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_RXTS_MASK)
>> MCANSS_RX_BUFFER_ELEM_RXTS_SHIFT);
elem->dlc = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_DLC_MASK)
>> MCANSS_RX_BUFFER_ELEM_DLC_SHIFT);
elem->brs = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_BRS_MASK)
>> MCANSS_RX_BUFFER_ELEM_BRS_SHIFT);
elem->fdf = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_FDF_MASK)
>> MCANSS_RX_BUFFER_ELEM_FDF_SHIFT);
elem->fidx = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_FIDX_MASK)
>> MCANSS_RX_BUFFER_ELEM_FIDX_SHIFT);
elem->anmf = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_ANMF_MASK)
>> MCANSS_RX_BUFFER_ELEM_ANMF_SHIFT);
elemAddr += 4U;
loopCnt = 0U;
/* Reading words from message RAM and forming payload bytes out of it */
while((4U <= (MCAN_getDataSize(elem->dlc) - loopCnt)) &&
(0U != (MCAN_getDataSize(elem->dlc) - loopCnt)))
{
ASSERT((loopCnt + 3U) < MCAN_MAX_PAYLOAD_BYTES);
regVal = HW_RD_REG32(MCANA_MSG_RAM_BASE + elemAddr);
elem->data[loopCnt] = (uint16_t)(regVal & 0x000000FFU);
elem->data[(loopCnt + 1U)] = (uint16_t)((regVal & 0x0000FF00U) >> 8U);
elem->data[(loopCnt + 2U)] = (uint16_t)((regVal & 0x00FF0000U) >> 16U);
elem->data[(loopCnt + 3U)] = (uint16_t)((regVal & 0xFF000000U) >> 24U);
elemAddr += 4U;
loopCnt += 4U;
}
/* Reading remaining bytes from message RAM */
if(0U < (MCAN_getDataSize(elem->dlc) - loopCnt))
{
ASSERT((loopCnt + 2U) < MCAN_MAX_PAYLOAD_BYTES);
regVal = HW_RD_REG32(MCANA_MSG_RAM_BASE + elemAddr);
elem->data[loopCnt] = (uint16_t)(regVal & 0x000000FFU);
elem->data[(loopCnt + 1U)] = (uint16_t)((regVal & 0x0000FF00U) >> 8U);
elem->data[(loopCnt + 2U)] = (uint16_t)((regVal & 0x00FF0000U) >> 16U);
}
}
/**
* \brief This API will return New Data Message Status.
*
* \param newDataStatus Rx Buffer new data status.
* Refer struct #MCAN_RxNewDataStatus.
*
* \return None.
*/
void MCAN_getNewDataStatus(MCAN_RxNewDataStatus *newDataStatus)
{
newDataStatus->statusLow = McanaRegs.MCAN_NDAT1.all;
newDataStatus->statusHigh = McanaRegs.MCAN_NDAT2.all;
}
/**
* \brief This API is used to add Extended Message ID Filter Element.
*
* \param filtNum Filter number.
* \param elem Filter Object.
* Refer struct #MCAN_ExtMsgIDFilterElement.
*
* \return None.
*/
#if EXT_ID_FILTER
void MCAN_addExtMsgIDFilter(uint32_t filtNum, const MCAN_ExtMsgIDFilterElement *elem)
{
uint32_t startAddr, elemAddr, regVal;
startAddr = McanaRegs.MCAN_XIDFC.bit.FLESA; //Filter List Extended Start Address.
startAddr = (uint32_t) (startAddr << 2U);
elemAddr = startAddr + (filtNum * MCANSS_EXT_ID_FILTER_SIZE_WORDS * 4U);
elemAddr += MCAN_MCAN_MSG_MEM;
regVal = 0U;
regVal |= (uint32_t) (elem->efid1 << MCANSS_EXT_ID_FILTER_EFID1_SHIFT);
regVal |= (uint32_t) (elem->efec << MCANSS_EXT_ID_FILTER_EFEC_SHIFT);
HW_WR_REG32(MCANA_MSG_RAM_BASE + elemAddr, regVal);
elemAddr += 4U;
regVal = 0U;
regVal |= (uint32_t) (elem->efid2 << MCANSS_EXT_ID_FILTER_EFID2_SHIFT);
regVal |= (uint32_t) (elem->eft << MCANSS_EXT_ID_FILTER_EFT_SHIFT);
HW_WR_REG32(MCANA_MSG_RAM_BASE + elemAddr, regVal);
}
/**
* \brief This API will configure Extended ID AND Mask.
*
* \param idMask Configuration parameters for MCAN Extended Id mask.
* This value is 29 bit wide.
*
* \return status Extended ID AND Mask configuration status.
*/
static bool MCAN_setExtIDAndMask(uint32_t idMask)
{
bool status;
if(MCAN_XIDAM_EIDM_MAX >= idMask)
{
McanaRegs.MCAN_CCCR.bit.CCE = 1;
McanaRegs.MCAN_XIDAM.bit.EIDM = idMask;
/*
* Extended ID Mask. For acceptance filtering of extended frames the
Extended ID AND Mask is ANDed with the Message ID of a received
frame. Intended for masking of 29-bit IDs in SAE J1939. With the
reset value of all bits set to one the mask is not active.
Qualified Write is possible only with CCCR.CCE='1' and
CCCR.INIT='1'.
*/
McanaRegs.MCAN_CCCR.bit.CCE = 0;
status = true;
}
else
{
status = false;
}
return status;
}
#endif
/**
* \brief This API will return interrupt status.
*
*
* \return status Interrupt Status.
*/
uint32_t MCAN_getIntrStatus()
{
return( McanaRegs.MCAN_IR.all);
}
/**
* \brief This API is used to clear the interrupt status.
*
* \param intrMask Interrupts to clear status.
*
* \return None.
*/
void MCAN_clearIntrStatus(uint32_t intrMask)
{
McanaRegs.MCAN_IR.all = intrMask;
}
/**
* \brief This API will write Rx FIFO Acknowledgement.
*
* Refer enum #MCAN_RxFIFONum.
* \param fifoNum FIFO Number.
* \param idx Rx FIFO Acknowledge Index
*
* \return status Acknowledgement Status.
*/
bool MCAN_writeRxFIFOAck(uint32_t fifoNum, uint32_t idx)
{
bool status = false;
uint32_t size;
switch (fifoNum)
{
case MCAN_RX_FIFO_NUM_0:
size = McanaRegs.MCAN_RXF0C.bit.F0S;
if(size >= idx)
{
McanaRegs.MCAN_RXF0A.bit.F0AI = idx;
status = true;
}
break;
case MCAN_RX_FIFO_NUM_1:
size = McanaRegs.MCAN_RXF1C.bit.F1S;
if(size >= idx)
{
McanaRegs.MCAN_RXF1A.bit.F1AI = idx;
status = true;
}
break;
default:
break;
}
return status;
}
/**
* \brief This API is used to get interrupt line selected for each interrupt.
*
*
* \return status Interrupt Line Select Status.
*/
uint32_t MCAN_getIntrLineSelectStatus()
{
return(McanaRegs.MCAN_ILS.all);
}
#if 1
/**
* \brief This API will return Tx Buffer Request Pending status.
*
*
* \return None
*/
uint32_t MCAN_getTxBufReqPend()
{
return(McanaRegs.MCAN_TXBRP.all);
}
#endif
/**
* \brief This API will return Tx Buffer Transmission Occurred status.
*
*
* \return status Tx Buffer Transmission Occurred status.
*/
uint32_t MCAN_getTxBufTransmissionStatus()
{
return(McanaRegs.MCAN_TXBTO.all);
}
/**
* \brief This API will be used for configuring the std filter's fields.
*
*
* \return status Tx Buffer Transmission Occurred status.
*/
static void MCAN_StdIDFilterConfiguration(MCAN_StdMsgIDFilterElement *stdFiltelem,
uint32_t sfid2,
uint32_t sfid1,
uint32_t sfec,
uint32_t sft)
{
//
// Initialize Rx Buffer Configuration parameters.
//
stdFiltelem->sfid2 = sfid2; // Standard Filter ID 2.
/*
SFID2[10:0]
Standard Filter ID 2
This bit field has a different meaning depending on the configuration of
SFEC:
• SFEC = 001 - 110: Second ID of standard ID filter element
• SFEC = 111: Filter for Rx buffers
SFID2[10:9]
This filed is decides whether the received message is stored into an Rx
Buffer or treated as message A, B, or C of the debug message sequence.
• 0x0: Store message into an Rx Buffer
• 0x1: Debug Message A
• 0x2: Debug Message B
• 0x3: Debug Message C
Note: Debug feature is not supported.
SFID2[8:6]
This field is used to control the filter event pins at the Extension Interface.
A one at the respective bit position enables generation of a pulse at the
related filter event pin with the duration of one MCAN_ICKL period in case
the filter matches.
Note: Only two filter event pins are supported.
SFID2[5:0] This field defines the offset to the Rx Buffer Start Address
MCAN_RXBC.RBSA field for storage of a matching message
*/
stdFiltelem->sfid1 = sfid1; // Standard Filter ID 1.-------DISABLE
/*
When filtering for Rx buffers this field defines the ID of a standard message
to be stored. The received identifiers must match exactly, no masking
mechanism is used.
*/
stdFiltelem->sfec = sfec; // Store into Rx Buffer
/*
* All enabled filter elements are used for acceptance filtering of standard
frames. Acceptance filtering stops at the first matching enabled filter
element or when the end of the filter list is reached. If SFEC = 100, 101, or
110 match sets interrupt flag MCAN_IR.HPM and, if enabled, an interrupt
is generated. In this case, the MCAN_HPMS register is updated with the
status of the priority match.
• 0x0: Disable filter element
• 0x1: Store in Rx FIFO 0 if filter matches
• 0x2: Store in Rx FIFO 1 if filter matches
• 0x3: Reject ID if filter matches
• 0x4: Set priority if filter matches
• 0x5: Set priority and store in FIFO 0 if filter matches
• 0x6: Set priority and store in FIFO 1 if filter matches
• 0x7: Store into Rx Buffer , configuration of SFT[1:0] ignored
*/
stdFiltelem->sft = sft; // Range filter from SFID1 to SFID2
/*
* Standard Filter Type
• 0x0: Range filter from SFID1 to SFID2 (SFID2 ≥ SFID1)
• 0x1: Dual ID filter for SFID1 or SFID2
• 0x2: Classic filter: SFID1 = filter; SFID2 = mask
• 0x3: Filter element disabled
*/
}
/**
* \brief This API clear New Data Message Status.
*
* \param newDataStatus
* Rx Buffer new data status.
* Refer struct #MCAN_RxNewDataStatus.
* \return None.
*/
void MCAN_clearNewDataStatus(const MCAN_RxNewDataStatus *newDataStatus)
{
McanaRegs.MCAN_NDAT1.all =newDataStatus->statusLow;
McanaRegs.MCAN_NDAT2.all =newDataStatus->statusHigh;
}
/*************************application.c********************/
/*
* application.c
*
* Created on: 16 gen 2025
* Author: d.marsili
*/
#include "application.h"
#include "mcan.h"
#include "mcan_defines.h"
#include "f2838x_examples.h"
void MCAN_TxDataFrame_init(MCAN_TxBufElement *mess, uint16_t identifier)
{
testDescriptor.isrIntr1Flag = 1;
int i;
mess->id = ((uint32_t)(identifier))<< 18U ; // ID value
mess->rtr = 0U; // Transmit data frame.
mess->xtd = 0U; // 11-bit standard identifier.
mess->esi = 0U;
mess->dlc = 4U; // Payload length 4 byte
mess->brs = 0U; // CAN FD frames transmitted with bit rate switching
mess->fdf = 0U; // Frame transmitted in CAN FD format.
mess->efc = 0U; // No-Store Tx events.
mess->mm = 0xAAU; // Message Marker.
mess->data[0] = 0x1;
for(i = 1; i < mess->dlc; i++)
{
mess->data[i] = mess->data[i-1] + 1;
}
}
void MCAN_RxDataFrameInit(MCAN_RxBufElement *rxMsg)
{
int i,j;
for(i = 0; i < NUM_OF_MSG; i++)
{
//
// Initialize message to receive
//
rxMsg[i].id = 0U;
rxMsg[i].rtr = 0U;
rxMsg[i].xtd = 0U;
rxMsg[i].esi = 0U;
rxMsg[i].rxts = 0U; // Rx Timestamp
rxMsg[i].dlc = 0U;
rxMsg[i].brs = 0U;
rxMsg[i].fdf = 0U;
rxMsg[i].fidx = 0U; // Filter Index
// (of matching Rx acceptance filter element)
rxMsg[i].anmf = 0U; // Accepted Non-matching Frame
for(j = 0; j < RX_MSG_PAYLOAD_MAX_LENGTH; j++) // Initialize receive buffer to 0
{
rxMsg[i].data[j] = 0;
}
}
}
/***************************************************************************/
/********************** Interrupts set-up's functions***********************/
/***************************************************************************/
//MCAN interrupts configuration
void MCANIntrConfig()
{
MCAN_ISRHandler();
//
// Enable PIE interrupt
//
PieCtrlRegs.PIEIER9.bit.INTx9 = 1; //MCANSS_INT0
PieCtrlRegs.PIEIER9.bit.INTx10 = 1; //MCANSS_INT1
}
static void MCAN_ISRHandler()
{
EALLOW;
PieVectTable.MCANA_0_INT = &MCANIntr0ISR; //function for MCAN interrupt 0
PieVectTable.MCANA_1_INT = &MCANIntr1ISR; //function for MCAN interrupt 1
EDIS;
}
//XINT1 interrupt configuration
void XINT1IntrConfig()
{
XINT1_ISRHandler();
//
// Enable PIE interrupt
//
PieCtrlRegs.PIEIER1.bit.INTx4 = 1; //Enable PIE Group 1 INT4- XINT1
}
static void XINT1_ISRHandler()
{
EALLOW;
PieVectTable.XINT1_INT = &xint1_ISR; //function for XINT1 interrupt
EDIS;
}
/***************************************************************************/
/********************** Interrupts enable's functions***********************/
/***************************************************************************/
//MCAN interrupts enable
void MCANIntrsEnable(bool enable)
{
if (enable)
{
//
// 1-Enable Interrupts.
//
MCAN_enableIntr(MCAN_IR_DRX_MASK, 1U);
//
// 2-Enable Interrupt Line.
//
MCAN_selectIntrLine(MCAN_IR_DRX_MASK, MCAN_INTR_LINE_NUM_0);
//
// 3-Enable Interrupt Line.
//
MCAN_enableIntrLine(MCAN_INTR_LINE_NUM_0, 1U);
//
// 1-Enable Interrupts.
//
MCAN_enableIntr(MCAN_IR_BO_MASK, 1U);
//
// 2-Enable Interrupt Line.
//
MCAN_selectIntrLine(MCAN_IR_BO_MASK, MCAN_INTR_LINE_NUM_1);
//
// 3-Enable Interrupt Line.
//
MCAN_enableIntrLine(MCAN_INTR_LINE_NUM_1, 1U);
}
else
{
//
// 1-Enable Interrupts.
//
MCAN_enableIntr(MCAN_IR_DRX_MASK, 0U);
//
// 2-Enable Interrupt Line.
//
MCAN_selectIntrLine(MCAN_IR_DRX_MASK, MCAN_INTR_LINE_NUM_0);
//
// 3-Enable Interrupt Line.
//
MCAN_enableIntrLine(MCAN_INTR_LINE_NUM_0, 0U);
//
// 1-Enable Interrupts.
//
MCAN_enableIntr(MCAN_IR_BO_MASK, 0U);
//
// 2-Enable Interrupt Line.
//
MCAN_selectIntrLine(MCAN_IR_BO_MASK, MCAN_INTR_LINE_NUM_1);
//
// 3-Enable Interrupt Line.
//
MCAN_enableIntrLine(MCAN_INTR_LINE_NUM_1, 0U);
}
}
void XINT1_enable()
{
//
// GPIO88 is mapped to XINT1
//
GPIO_SetupXINT1Gpio(62);
//
// Configure XINT1
//
XintRegs.XINT1CR.bit.POLARITY = 0; // Falling edge interrupt
XintRegs.XINT1CR.bit.ENABLE = 1; // Enable XINT1
}
/***************************************************************************/
/********************** Interrupts Service Routine**************************/
/***************************************************************************/
//
// xint1ISR - External Interrupt 1 ISR
//
interrupt void xint1_ISR(void)
{
testDescriptor.enable = true;
//
// Acknowledge this interrupt to get more from group 1
//
PieCtrlRegs.PIEACK.all = 1;
}
//
// This is Interrupt Service Routine for MCAN interrupt 0.
//
__interrupt void MCANIntr0ISR(void)
{
uint32_t intrStatus = MCAN_getIntrStatus();
#if LOOPBACK_MODE
if (0x81200 != intrStatus) //0x81200 - Transmission completed/ Tx FIFO event new entry/ Message Stored in RX buff
{
testDescriptor.error++;
}
//
// Clear the interrupt Status.
//
MCAN_clearIntrStatus(intrStatus);
//
// Update the flag value.
//
testDescriptor.isrIntr1Flag = 1U;
//
// Acknowledge this interrupt located in group 9
//
PieCtrlRegs.PIEACK.bit.ACK9 = 1;
#else
MCAN_RxNewDataStatus newData;
/*
EALLOW;
McanaSsRegs.MCANSS_EOI.bit.EOI = 2;
EDIS;
*/
/* End of Interrupt. A write to this register will clear the associated
interrupt. If the unserviced interrupt counter is > 1, another interrupt
is generated.
0x00 External TS Interrupt is cleared
0x01 MCAN[0] interrupt is cleared
0x02 MCAN[1] interrupt is cleared
Other writes are ignored.
*/
//
// Clear the interrupt Status.
//
MCAN_clearIntrStatus(intrStatus);
//
// Check to see if the interrupt is caused by a message being
// received in dedicated RX Buffers
//
if((MCAN_IR_DRX_MASK & intrStatus) == MCAN_IR_DRX_MASK)
{
//
// Read the NewData registers
//
MCAN_getNewDataStatus(&newData);
// If message is received in buffer element 0
if((newData.statusLow & (1UL << 0U)) != 0)
{
MCAN_readMsgRam(MCAN_MEM_TYPE_BUF, 0U,
0, &testDescriptor.rxMsg[0]);
}
// If message is received in buffer element 1
if((newData.statusLow & (1UL << 1U)) != 0)
{
MCAN_readMsgRam(MCAN_MEM_TYPE_BUF, 1U,
0, &testDescriptor.rxMsg[1]);
}
if((newData.statusLow & (1UL << 2U)) != 0)
{
MCAN_readMsgRam(MCAN_MEM_TYPE_BUF, 2U,
0, &testDescriptor.rxMsg[2]);
}
if((newData.statusLow & (1UL << 3U)) != 0)
{
MCAN_readMsgRam(MCAN_MEM_TYPE_BUF, 3U,
0, &testDescriptor.rxMsg[3]);
}
//
// Clearing the NewData registers
//
MCAN_clearNewDataStatus(&newData);
}
else
{
testDescriptor.error++;
//
// Interrupt handling for other interrupt sources goes here
//
}
//
// Acknowledge this interrupt located in group 9
//
PieCtrlRegs.PIEACK.bit.ACK9 = 1;
#endif
}
//
// This is Interrupt Service Routine for MCAN interrupt 1.
//
__interrupt void MCANIntr1ISR(void)
{
uint32_t intrStatus = MCAN_getIntrStatus();
/*
EALLOW;
McanaSsRegs.MCANSS_EOI.bit.EOI = 2;
EDIS;
*/
//
// Clear the interrupt Status.
//
MCAN_clearIntrStatus(intrStatus);
McanaRegs.MCAN_CCCR.bit.CCE = 1;
McanaRegs.MCAN_CCCR.bit.INIT = MCAN_OPERATION_MODE_NORMAL;
McanaRegs.MCAN_CCCR.bit.CCE = 0;
testDescriptor.error++;
//
// Acknowledge this interrupt located in group 9
//
PieCtrlRegs.PIEACK.bit.ACK9 = 1;
//McanaErrRegs.MCANERR_SEC_EOI.bit.EOI_WR = 1;
}
#if 0
static CommunicationStatus CheckMCANCommunicationStatus()
{
uint32_t intrStatus = MCAN_getIntrStatus();
uint32_t receptionCompl = (intrStatus >> 0 & 1);
CommunicationStatus event = OTHERS;
receptionCompl = receptionCompl || (intrStatus >> 4 & 1);
receptionCompl = receptionCompl|| (intrStatus >> 19 & 1);
if (intrStatus >> 9 & 1)
event =TRASMISSION_COMPLETED;
else if(intrStatus >> 19 & 1)
event = RECECPTION_COMPLETED;
else if (intrStatus >> 24 & 1)
event = BUS_OFF_STATUS;
return event;
}
#endif
Hi experts, I absolutely need your help, I'm in trouble.
This example follows the principle behind the example mcan_ex10_receive_multiple_buffers.
The interrupt is triggered the first time and allows me to read the received texture correctly. After that, it doesn't go off again. Is there any register in addition to those inserted to reset or are there other aspects that I overlook?
For more information please ask.
