Other Parts Discussed in Thread: TCAN4550
Hi Eric Schott1,
Please check following configuration changes made, i think it is almost same as you asked to do.
Please find the changes made as below to receive the CAN messages sent from TCAN4550 to MCU using "RX-Buffer Element - 01"-
1) In init_CAN()-
TCAN4x5x_MCAN_SID_Filter SID_ID = {0};
/* Configure the default CAN packet filtering settings */
TCAN4550_MCAN_Global_Filter_Configuration gfc = {0};
gfc.RRFE = 1; // Reject remote frames (TCAN4550 doesn't support this)
gfc.RRFS = 1; // Reject remote frames (TCAN4550 doesn't support this)
gfc.ANFE = TCAN4550_GFC_REJECT;
gfc.ANFS = TCAN4550_GFC_REJECT;
/* ************************************************************************
* In the next configuration block, we will set the MCAN core up to have:
* - 5 SID filter element
* - 5 XID Filter element
* - 0 RX FIFO 0 elements
* - RX FIFO 0 supports data payloads up to 64 bytes
* - RX Buffer: RxBufNumElements - 5 and RxBufElementSize - 64Bytes
* - No TX Event FIFOs
* - 2 Transmit buffers supporting up to 64 bytes of data payload
*/
TCAN4550_MRAM_Config MRAMConfiguration = {0};
MRAMConfiguration.SIDNumElements = 5; // Standard ID number of elements, you MUST have a filter written to MRAM for each element defined
MRAMConfiguration.XIDNumElements = 5; // Extended ID number of elements, you MUST have a filter written to MRAM for each element defined
MRAMConfiguration.Rx0NumElements = 0; // RX0 Number of elements
MRAMConfiguration.Rx0ElementSize = MRAM_64_Byte_Data; // RX0 data payload size
MRAMConfiguration.Rx1NumElements = 0; // RX1 number of elements
MRAMConfiguration.Rx1ElementSize = MRAM_64_Byte_Data; // RX1 data payload size
MRAMConfiguration.RxBufNumElements = 64; // RX buffer number of elements
MRAMConfiguration.RxBufElementSize = MRAM_64_Byte_Data; // RX buffer data payload size
MRAMConfiguration.TxEventFIFONumElements = 0; // TX Event FIFO number of elements
MRAMConfiguration.TxBufferNumElements = 2; // TX buffer number of elements
MRAMConfiguration.TxBufferElementSize = MRAM_64_Byte_Data; // TX buffer data payload size
/* Configure the MCAN core with the settings above, the changes in this block are write protected registers, *
* so it makes the most sense to do them all at once, so we only unlock and lock once */
TCAN4550_MCAN_EnableProtectedRegisters(); // Start by making protected registers accessible
TCAN4550_MCAN_ConfigureCCCRRegister(&cccrConfig); // Enable FD mode and Bit rate switching
TCAN4550_MCAN_ConfigureGlobalFilter(&gfc); // Configure the global filter configuration (Default CAN message behavior)
TCAN4550_MCAN_ConfigureNominalTiming_Simple(&TCANNomTiming);// Setup nominal/arbitration bit timing
TCAN4550_MCAN_ConfigureDataTiming_Simple(&TCANDataTiming); // Setup CAN FD timing
TCAN4550_MRAM_Clear(); // Clear all of MRAM (Writes 0's to all of it)
TCAN4550_MRAM_Configure(&MRAMConfiguration); // Set up the applicable registers related to MRAM configuration
TCAN4550_MCAN_DisableProtectedRegisters(); // Disable protected write and take device out of INIT mode
/* Set the interrupts we want to enable for MCAN */
TCAN4550_MCAN_Interrupt_Enable mcan_ie = {0}; // Remember to initialize to 0, or you'll get random garbage!
mcan_ie.DRXE = 1; //Message stored to Dedicated Rx Buffer Interrupt Enable
TCAN4550_MCAN_ConfigureInterruptEnable(&mcan_ie); // Enable the appropriate registers
/* Setup filters, this filter will mark any message with ID 0x055 as a priority message */
TCAN4550_MCAN_SID_Filter SID_ID = {0};
SID_ID.SFT = TCAN4550_SID_SFT_CLASSIC; // SFT: Standard filter type. Configured as a classic filter
SID_ID.SFEC = TCAN4550_SID_SFEC_STORERXBUFORDEBUG; // Store in RX Buffer for debug if the filter matches the incoming message. SFT is ignored if this is selected.
SID_ID.SFID1 = 0x055; // SFID1 is the filter ID to be received
SID_ID.SFID2 = 0x01; //SFID2[10:9] describes where to store message, SFID2[5:0] describes which Rx Buffer to put the message (must be within the Rx Buffer configuration)
TCAN4550_MCAN_WriteSIDFilter(1, &SID_ID); // Write to the MRAM
As per above configurations, my understanding is ,filters are enabled to receive the CAN messages received shall be stored in RX Buffer 1.
2) CAN message reception logic-
while (1)
{
TCAN4550_Device_Interrupts dev_ir = {0}; // Define a new Device IR object for device (non-CAN) interrupt checking
TCAN4550_MCAN_Interrupts mcan_ir = {0}; // Setup a new MCAN IR object for easy interrupt checking
TCAN4550_Device_ReadInterrupts(&dev_ir); // Read the device interrupt register
TCAN4550_MCAN_ReadInterrupts(&mcan_ir); // Read the interrupt register
ReturnData = AHB_READ_32(REG_MCAN_NDAT1);
IndexValue = GetBufferIndex(ReturnData);
if (dev_ir.SPIERR) // If the SPIERR flag is set
TCAN4550_Device_ClearSPIERR(); // Clear the SPIERR flag
if (mcan_ir.DRX) // If a new message in RX buffer 1
{
TCAN4550_MCAN_RX_Header MsgHeader = {0}; // Initialize to 0 or you'll get garbage
uint8_t Mesg_Bytes = 0;
uint8_t dataPayload[64] = {0}; // Used to store the received data
TCAN4550_MCAN_ClearInterrupts(&mcan_ir); // Clear any of the interrupt bits that are set.
Mesg_Bytes = TCAN4550_MCAN_ReadRXBuffer( IndexValue, &MsgHeader, dataPayload); // read message stored in Rx Buffer
AHB_WRITE_32(REG_MCAN_NDAT1 , 0x00000002); //clear NDAT 1
// numBytes will have the number of bytes it transfered in it. Or you can decode the DLC value in MsgHeader.DLC
// The data is now in dataPayload[], and message specific information is in the MsgHeader struct.
if (MsgHeader.ID == 0x55 || MsgHeader.ID == 0x115 || MsgHeader.ID == 0x12345678 ) // Example of how you can do an action based off a received address
{
// Do something
data[0] = dataPayload[0]+1;
data[1] = dataPayload[1]+1;
data[2] = dataPayload[2]+1;
data[3] = dataPayload[3]+1;
data[4] = dataPayload[4]+1;
data[5] = dataPayload[5]+1;
data[6] = dataPayload[6]+1;
data[7] = dataPayload[7]+1;
TCAN4550_MCAN_WriteTXBuffer(1, &header, data);
TCAN4550_MCAN_TransmitBufferContents(1);
}
}
}
3) TCAN4550_MCAN_ReadRXBuffer() used as it is from TI TCAN4550 Demo driver SW.
uint8_t TCAN4550_MCAN_ReadRXBuffer(uint8_t bufIndex, TCAN4550_MCAN_RX_Header *header, uint8_t dataPayload[])
{
uint32_t readData;
uint16_t startAddress;
uint8_t i, getIndex, elementSize;
// Get the get buffer location and size
getIndex = bufIndex;
if (getIndex > 64)
getIndex = 64;
// Get the RX Buffer Start location and size...
#ifdef TCAN4550_MCAN_CACHE_CONFIGURATION
readData = TCAN4550_MCAN_CACHE[TCAN4550_MCAN_CACHE_RXBC];
#else
readData = AHB_READ_32(REG_MCAN_RXBC);
#endif
startAddress = (uint16_t)(readData & 0x0000FFFF) + REG_MRAM;
#ifdef TCAN4550_MCAN_CACHE_CONFIGURATION
readData = TCAN4550_MCAN_CACHE[TCAN4550_MCAN_CACHE_RXESC];
#else
readData = AHB_READ_32(REG_MCAN_RXESC);
#endif
readData = (readData & 0x0700) >> 8;
elementSize = TCAN4550_MCAN_TXRXESC_DataByteValue(readData); // Maximum theoretical data payload supported by this MCAN configuration
// Calculate the actual start address for the latest index
startAddress += (((uint32_t)elementSize + 8) * getIndex);
// Read the data, start with a burst read
AHB_READ_BURST_START(startAddress, 2);
readData = AHB_READ_BURST_READ(); // First header
header->ESI = (readData & 0x80000000) >> 31;
header->XTD = (readData & 0x40000000) >> 30;
header->RTR = (readData & 0x20000000) >> 29;
if (header->XTD)
header->ID = (readData & 0x1FFFFFFF);
else
header->ID = (readData & 0x1FFC0000) >> 18;
readData = AHB_READ_BURST_READ(); // Second header
AHB_READ_BURST_END(); // Terminate the burst read
header->RXTS = (readData & 0x0000FFFF);
header->DLC = (readData & 0x000F0000) >> 16;
header->BRS = (readData & 0x00100000) >> 20;
header->FDF = (readData & 0x00200000) >> 21;
header->FIDX = (readData & 0x7F000000) >> 24;
header->ANMF = (readData & 0x80000000) >> 31;
// Get the actual data
// If the data payload size of the header is smaller than the maximum we can store, then update the new element size to read only what we need to (prevents accidentical overflow reading)
if (TCAN4550_MCAN_DLCtoBytes(header->DLC) < elementSize )
elementSize = TCAN4550_MCAN_DLCtoBytes(header->DLC); // Returns the number of data bytes
// Start a burst read for the number of data bytes we require at the data payload area of the MRAM
// The equation below ensures that we will always read the correct number of words since the divide truncates any remainders, and we need a ceil()-like function
if (elementSize > 0) {
AHB_READ_BURST_START(startAddress + 8, (elementSize + 3) >> 2);
i = 0; // Used to count the number of bytes we have read.
while (i < elementSize) {
if ((i % 4) == 0) {
readData = AHB_READ_BURST_READ();
}
dataPayload[i] = (uint8_t)((readData >> ((i % 4) * 8)) & 0xFF);
i++;
if (i > elementSize)
i = elementSize;
}
AHB_READ_BURST_END(); // Terminate the burst read
}
// Acknowledge the FIFO read
if (getIndex < 32)
{
AHB_WRITE_32(REG_MCAN_NDAT1, 1 << getIndex);
} else {
AHB_WRITE_32(REG_MCAN_NDAT2, 1 << (getIndex-32));
}
return i; // Return the number of bytes retrieved
}