I am working on firmware for receiving CAN data from some sensors.
Using code examples, I have been able to initialize CAN modules and receive data.
I have also been able to make use of DMA and interrupts
to handle received data, instead of doing it "manually".
Now the problem is,
the IDs of the CAN messages received from these sensors are cycled from 1010 to 1203,
so I have to add each of these numbers, 194 of them,
to ID filter table elements, which start at the offset 0xE0 of the used CAN module.
(By the way, just the standard ID length - 11 bits - is used.)
Since there's only 127 elements,
I can't use the option of having just one ID in each of them,
and I have to set the option of two IDs in each element.
This means I have to set the IDAM field in the CAN_MCR register to 0x1.
Also, I need 104 filter elements active,
so that, with 2 IDs in each element, I have enough space for the 194 IDs that I need
(sadly, 96 elements don't quite cut it).
For this, I have to set the RFFN field in the CAN_CTRL2 register to 0xC.
Unfortunately, I don't receive all CAN messages this way.
I only receive the ones whose ID is written in the upper half-word of a filter element,
which would be bits 2-12 for standard ID length,
and I don't receive the ones with IDs in the lower half-word.
Since the same bits (2-12) are used in the option of one ID per filer element,
it would seem that the option to use two IDs per element doesn't work,
and the module behaves as if I'd only written one CAN ID per element...
Here's the source code of my function which initializes a CAN module:
// Initializes CAN module 1.
// Set clock source to oscillator clock (40MHz).
// The module must be disabled before setting the clock source.
CAN_1.MCR.B.MDIS = 1;
CAN_1.CTRL1.B.CLKSRC = 0;
CAN_1.MCR.B.MDIS = 0;
// Wait for freeze acknowledge.
// Set up CAN features for this bus.
// CAN bus: 40 MHz clksrc, 500 kbps with 16 tq
// PRESDIV + 1 = Fclksrc/Ftq = 40MHz/8MHz = 5 so PRESDIV = 4
// RJW = Resync Jump Width - 1 = 4 - 1 = 3
// PSEG1 = Phase_Seg1 - 1 = 4 - 1 = 3
// PSEG2 = PSEG1 = 3
// SMP = 1: use 3 bits per CAN sample
// PROPSEG = Prop_Seg - 1 = 7 - 1 = 6
CAN_1.CTRL1.R = 0x04DB0086;
// Deactivate all 96 message buffers.
for (i = 0; i < 96; i++)
CAN_1.MB[i].CS.B.CODE = 0;
// global acceptance mask (accept all CAN IDs)
CAN_1.RXMGMASK.R = 0x0;
// Initialize pins for this CAN module.
SIUL2.MSCR.B.SSS = 1; // PC10 source signal is CAN1_TX.
SIUL2.MSCR.B.OBE = 1; // Output Buffer Enable.
SIUL2.MSCR.B.SRC = 3; // Maximum slew rate.
SIUL2.MSCR.B.IBE = 1; // Enable pad for input.
SIUL2.IMCR.B.SSS = 3; // CAN1_RX connected to pad PC11.
// If DMA is used for receiving, it is necessary to enable RX FIFO.
// RX FIFO structure is placed at address CAN_BASE_ADDRESS + 0x80.
// First "ID filter table element 0" is placed at CAN_BASE_ADDRESS + 0xE0.
CAN_1.CTRL2.B.RFFN = 0xC; // Message buffers 0-31 are occupied by RX FIFO and ID filter table.
// There are 104 ID filter table elements.
CAN_1.MCR.B.IDAM = 0x1; // Two full standard IDs per ID Filter Table element.
// Initialize ID filter table elements 0-31 to receive messages with standard IDs 1010-1218 (RTR and IDE = 0).
filter = 1010;
for (i = 0xE0; i < 0x280; i += 4)
*(uint32_t *)((uint32_t)(&CAN_1) + i) =
(((uint32_t)filter & 0x7ff) << 19)
| ((((uint32_t)filter & 0x7ff) + 1) << 3);
filter += 2;
// Enable DMA, enable RX FIFO, negate FlexCAN halt state for 64 MBs.
CAN_1.MCR.R = 0x2000803F;
// Wait for the driver to become ready.
while (CAN_1.MCR.B.FRZACK & CAN_1.MCR.B.NOTRDY);
With this initialization, I am only receiving CAN messages with an even ID.
Obviously, if I were to change the order of the IDs in one filter element
I would only be receiving messages with odd IDs.
I can't use one ID per filter element, since there are not enough elements for all the IDs that I need.
So I either have to use 2 IDs per element,
or resort to not using DMA at all, and simply accept all CAN IDs.
Does anybody know where the problem might be?
I have tested CAN DMA reception with fewer IDs
and using only one ID per filter element,
and it worked fine.
So I don't think there's an obvious error in my initialization.
Thanks in advance!