Any ideas? Yes. Don't POLL the MBs. They may not like it. As well, if you're not using multiple MBs for different filtered IDs (which you aren't) and you don't need to implement some sort of FIFO because your code can't guarantee timing (which your one can), then don't program more than one MB to receive. Just simply program one MB and then poll it ONCE every 250us. That is a lot simpler and might be more reliable. But it may not.
How are you "polling the MBs"? What registers are you reading? You shouldn't read the MBs at all once you've made one "ready to receive" or "ready to transmit", but should leave it alone. There are other status registers that give a summary of what has completed.
A lot of these peripherals are very complicated internally, and are often a little CPU internally, running a fixed program that "emulates" the peripheral. One of the things they have to do is to service read and write requests to the shared registers. There can be TWO different classes of problems with this, both of which I've seen. But let me say I haven't seen in in the FlexCAN peripheral because I'd never deliberately write code to cause these problems.
Firstly, with some peripherals, when you read a register to poll the chip it delays the internal operation of that chip. If you poll it too quickly you might overload it so it doesn't work properly. This was first famously seen in an old Western Digital FD1771 Floppy Disk Controller (yes, I've written code for that and its later friends). The best solution to these problems is to NEVER poll these chips. Or any controllers in case that causes a problem. You wait for the Interrupt. When that happens you have a guarantee that the MB isn't busy and you can poll/read/write it. If you don't want to write your code that way, then set up the interrupts and poll the interrupt status bit in the interrupt controller instead. Or you may be able to poll the FlexCAN Status register. Just don't poll the MBs.
The later FlexCAN chips have other problems. The most advanced one has 64 MBs and can handle multiple MBs receiving the same message. But not all of them. There's a very complicated table in the manuals for them that gives the maximum number of MBs the chip can handle at particular baud-rates and clock rates without getting overloaded, because it has to internally POLL all of them in sequence, and TWICE when a message arrives.
Secondly, with a LOT of peripherals, they don't handle simultaneous access to the register from the "internal machine" and the external CPU. If the internal machine is about to update a bit in a status register, then it has to write to a shared memory location (which is the register) to change that bit. If the CPU reads or writes the same register in the same cycle - well there SHOULD be hardware in place to make sure those operations still happen properly. But in a lot of cases that hardware is missing and they don't. For instance, in the MCF5329 LCD controller [1] it is impossible to read the status register without losing status bits. It has this problem. If you are reading the register to see if a bit is set while it is trying to write that bit (or some other bit) then that write silently fails and your code fails. That makes it really hard to use properly, and it needs horrible undocumented workarounds. The Freescale MSCAN chip has a free-running timestamp register in it that can be used to timestamp the CAN messages. Unfortunately it has two problems. Firstly there's no way to READ the timestamp, so it can't be compared to anything. Secondly, the code that increments the timestamp register gets blocked when the timestamp is read (by the MSCAN hardware) to write to an MB, so the timestamp "slips" bu a count on every receive and transmit message. So it can't keep proper time either! [2]
As I said, I don't know if the FlexCAN chip has problems like these, but unless you like spending weeks writing tests to find these sort of problems, it is a lot more productive to write you code so it can't cause these problems.
Suggestions:
1 - Program one receive MB only.
2A - Don't poll the MBs. Poll the IFLAG register. If that works, you're done [3].
2B - If that still has problems, enable the MB interrupt in IMASK, but disable it in IMRL1 and poll IPLR1.
3 - If that doesn't fix it you may have a bug in your code.
4 - If you don't have a bug in your code you may have found a new one with the FlexCAN controller.
Note 1: MCF5239 LCDC Problems
MCF5329 LCDC: Reading ISR register loses events
Note 2: MSCAN Timestamp Problems
https://community.nxp.com/message/91157
Note 3: If you're polling IFLAG or IPLR1, then when the status bit sets you have to ack it by writing 1 to that same bit in the IFLAG register so it is now clear for next time.
Tom