Fix for FlexCAN library provided with Teensyduino

I have been developing NMEA2000 library since 2015. It has used FlexCAN library with teensy. The original FlexCAN library did not use interrupting for receiving and transmitting. The new version of FlexCAN did not work with our system due to compatibilitys change on initialization. Some days ago I started to solve problems with new version to get interrupt handled frame handling to work. So I finally found several bugs on Current FlexCAN release:
- There was parameter used before initialization. So my code sometimes started to communicate and sometimes not.
- There was no interrupt locking during reading and writing buffers outside of interrupt. So in possible case one could just read buffer and change buffer read index, while you got interrupt for new frame, which also modifies indexes. In principle different indexes will be used, but it is not good to rely that all logic will work.
- writing frames tested is mail box free a bit wrong.
- writing to specific mailbox caused that mailbox lock time to time.
- frames were sometimes send in wrong order. In NMEA 2000 it is important that fast packet frames will be sent on right order.

I made new fork under my repositories (https://github.com/ttlappalainen/FlexCAN_Library), where
- I fixed errors I found.
- I also made cosmetic changes to code to improve readibility.
- Added mailbox specific transmit buffers, which user have to enable
- Changed buffers sizing so that it does not require code change. So buffers are created dynamically on open.

Code after my changes should be still compatible with current version of FlexCAN library except now it works reliably with NMEA 2000 protocol.

So I would prefer to at least think about updating FlexCAN library! I also prefer that someone with CAN project would try my fork for testing.
 
I have cloned it and I will begin testing it. I have used Colin's FlexCAN with great success, so I look forward to testing with this version.

Just swapping libraries from a known-good implementation of the COlinK library, here's the result:

Code:
FlexCAN.h: In member function void FlexCAN::irqLock()
 
FlexCAN.h: 126:49: error: 'IRQ_CAN_MESSAGE' was not declared in this scope
   void irqLock() { IrqEnabled=NVIC_IS_ENABLED(IRQ_CAN_MESSAGE); NVIC_DISABLE_IRQ(IRQ_CAN_MESSAGE); }
kinetis.h:5630: note  in definition of macro NVIC_IS_ENABLED
   #define NVIC_IS_ENABLED(n) (*((volatile uint32_t *)0xE000E100 + ((n) >> 5)) & (1 << ((n) & 31)))
FlexCAN.h: In member function void FlexCAN::irqRelease()
 
Last edited:
I have cloned it and I will begin testing it. I have used Colin's FlexCAN with great success, so I look forward to testing with this version.

Just swapping libraries from a known-good implementation of the COlinK library, here's the result:

Code:
FlexCAN.h: In member function void FlexCAN::irqLock()
 
FlexCAN.h: 126:49: error: 'IRQ_CAN_MESSAGE' was not declared in this scope
   void irqLock() { IrqEnabled=NVIC_IS_ENABLED(IRQ_CAN_MESSAGE); NVIC_DISABLE_IRQ(IRQ_CAN_MESSAGE); }
kinetis.h:5630: note  in definition of macro NVIC_IS_ENABLED
   #define NVIC_IS_ENABLED(n) (*((volatile uint32_t *)0xE000E100 + ((n) >> 5)) & (1 << ((n) & 31)))
FlexCAN.h: In member function void FlexCAN::irqRelease()

I am getting this issue in Collin's FlexCAN library as well(https://github.com/collin80/FlexCAN_Library), but Pawsky's works fine (https://github.com/pawelsky/FlexCAN_Library).
 
My original question is still open. Could FlexCan library provided with Teensyduino be my developed version. Now when people installs Teensyduino, it installs as default the version, which does not work right with NMEA2000. So to get things working, they have to manually remove FlexCan under "C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\FlexCAN"
 
I played with collin80's CAN library last week on a Teensy 3.2 and it basically didn't work properly. I ended up having to revert to the old Teachop library to get it to behave.

1. Didn't handle both STD and EXT messages on the same bus
2. The interrupt/object driven code didn't work at all.

IMO the FlexCAN library has gotten too bloated and needs to be refactored into a proper peripheral API and a more generic Arduino-compatible CAN library. Pass the peripheral object a pointer to a ring buffer, and run everything out of that instead of having it all internal. The FlexCAN library should only extend to the functionality described in the Kinetis reference manual.
 
Did you try it as just plain or with CanListener? The plain (read method) buffering uses also interrupts and fills up buffers. Also plain transmitting (write method) uses interrupt for transmitting. That part works perfectly at least with EXT messages. I use that with my https://github.com/ttlappalainen/NMEA2000 library and there is also (at least) one NMEA 2000 certified device build with my library and modified FlexCAN.

Old Teachop library has same problem as all default CAN libraries for NMEA 2000 use - they do no keep frames in order for fast packet messages. If the controller has several mailboxes and write method jus uses next free mailbox, the NMEA 2000 fast packet frames may be sent non sequential order. In this case receivers will not handle the messages. This problem does not exist on J1939, since long messages will be sent by using TP protocol.

If library would be refactored, due to above reason it can not have just single ring buffer. Since Kinetis CAN controller also has several mailboxes and they have different priority, it can be really used also with NMEA 2000 message prioritizing. In my library I use higher priority ringbuffer for higher priority messages.
 
Back
Top