Skip to content

Kwabena/mimxrt can#142

Open
kwagyeman wants to merge 22 commits into
openmv:openmv-1.28.0from
kwagyeman:kwabena/mimxrt_can
Open

Kwabena/mimxrt can#142
kwagyeman wants to merge 22 commits into
openmv:openmv-1.28.0from
kwagyeman:kwabena/mimxrt_can

Conversation

@kwagyeman
Copy link
Copy Markdown
Member

Adds support for machine.CAN with the RT1060. Tested and works on the OpenMV Cam RT1062.

robert-hh and others added 22 commits June 5, 2026 21:20
Ports may need the raw bitrate and not the derived bitrate brp for
set-up of the hardware.

Signed-off-by: robert-hh <robert@hammelrath.com>
Based on original work by Kwabena W. Agyeman.

Signed-off-by: robert-hh <robert@hammelrath.com>
First version, working to some extent:
- create CAN
- init()
- deinit()
- send()
- cancel_send()
- get_counters()
- get_timings()
- state()
- recv()
- restart()
- irq handlers (TX irq is missing)

All port specific functions are implemented, but not all of them are
tested, and some aspects still need consideration.

Open topics:
- Filter masks.
- TX IRQ. Maybe not useful.
- Get the number of FIFO elements instead just a single flag.
- Use the timing settings from init().
- Consider, if the actual value of RFFN is appropriate
  (25 TXMB and 128 Filters). Maybe more TXMB's
- Add setting for the other boards.
- More TESTING, espcially with other boards.

Signed-off-by: robert-hh <robert@hammelrath.com>
Of course only for the boards that support CAN.
Moved CAN1 at Teensy to Pins A8 and A9.
Added a CAN pinout section to the documentation.

Signed-off-by: robert-hh <robert@hammelrath.com>
Supporting filter masks now matches the documentation.

Signed-off-by: robert-hh <robert@hammelrath.com>
Add a conditional compile to either use the timing parameters
as provided by calculate_brp() or use the timing values as determined
by the NXP library. In that case, report back the final settings for
the object print.
Provide C constants for the min/max values of the timing parameters.

Signed-off-by: robert-hh <robert@hammelrath.com>
- Use a single setting to define the number of filters and TX MBs.
  The number of filters is set in machine_can_port_init() to
  CAN_IDFILTERNUM_MAX, and then RFFN and the number of TX MBs
  are derived from that number. At the moment it's 128 Filter
  and 25 TX MBs. Another reasonable number would be 64 filters as there
  are 64 filter masks and 41 TX MBs.
- Remove code duplication, especially the port's print function.
  The common print function is good and provides more information.

Signed-off-by: robert-hh <robert@hammelrath.com>
Not just a single write of the abort command. Step 3 of the instructions
is omitted, because the IFLAG is never set. It returns True if
the message was waiting for transmission or is actually being
transmitted when calling, and False, when no message is waiting or
is transferred.

The code cannot tell the difference between a pending message and a
message being transferred. So it may happen that can.cancel_send()
returns True, but the message is transmitted.

Finally, the CS field of the MB is set to the initial state.

Signed-off-by: robert-hh <robert@hammelrath.com>
Switching between modes requires to call can.deinit() before a new
call to can.init(). Calling can.deinit() will clear the device
including the filters, but must not clear the CAN object.
That is deferred until soft reset.

MP_CAN_MODE_SILENT only receives acknowledged messages.

Signed-off-by: robert-hh <robert@hammelrath.com>
These were define with default values, but port specific values can
be used instead.

Signed-off-by: robert-hh <robert@hammelrath.com>
Signed-off-by: robert-hh <robert@hammelrath.com>
tests/multi-extmod:
- Test 4: Use a hard IRQ avoiding event loss.
- Test 5: Count the result of can.cancel_send() instead of the
  non-supported IRQ_TX_FAILED event.
- Test 8: Add some dummy print statements expected by the test script
  for situations which cannot be handled by MIMXRT.
  Change irq handler to deal either with RX or TX.

tests/tests/extmod_hardware/machine_can_instances.py:
- Set the mode to CAN.MODE_SILENT_LOOPBACK.

Signed-off-by: robert-hh <robert@hammelrath.com>
- The approach does not stop with fail at the first non-empty MB
  with a matching ID, but keeps scanning for a free MB with a higher
  index number and therefore lower priority.
- If CAN_MSG_FLAG_UNORDERED is set, allow to pick the first unused MB
  if the MB with the matching ID is busy.
- Add MACROs to make can_find_txmb() better readable.

Signed-off-by: robert-hh <robert@hammelrath.com>
Changes:
- Add a TX interrupt.
- Do not enable Warning and overflow interrupts for IRQ_RX, avoiding
  additional calls of the IRQ handler.
- Add flags for bus state interrupts.
- The recv() code is slightly shortened with the assumption, the data
  buffer for a received message is always sufficiently large.
  That applies most likely to send() as well, but it's out of scope
  for machine_can.

Comments:
- The handling of interrupts follows the scheme, that the respective
  interrupt is disabled in the handler, if it was triggered. The flags
  telling which interrupt happened stay enabled, such that they can
  be reported by can.irq().flags().
- Reading a message or defining the trigger (re-)enables the RX IRQ.
- The IRQ_TX interrupt happens when any message have been successfully
  sent. At the moment there is not feedback which message of possibly
  many in the TX queue.
- Call can.irq().flags() repeatedly to get the message indexes of all
  transmitted messages. These are coded in the upper 16 bits of
  the value returned by can.irq().flags() (as documented).
- The IRQ_TX interrupt for a MMB is enabled when sending a message or
  when can.irq().flags() is called.

Signed-off-by: robert-hh <robert@hammelrath.com>
Make it consistent to the documentation.
The code now counts and the errors when state transitions happen to
a more severe state and triggers an callback if requested.
A state IRQ is to be signalled for every bus state change. Not all
bus state changes cause a dedicated hardware interrupt. In that case
the state change will only be noticed during processing of another
event, like general bus error, RX, TX, ....
Consider the value of CAN_TX_QUEUE_LEN depending on the value of
FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829.

Signed-off-by: robert-hh <robert@hammelrath.com>
Signed-off-by: robert-hh <robert@hammelrath.com>
- Declare local functions as "static".
- Use named constants for numbers when possible
- Put the IRQ handler into RAM
- Clarify comments

Signed-off-by: robert-hh <robert@hammelrath.com>
Making it a little bit more efficient with MIMXRT.

Signed-off-by: robert-hh <robert@hammelrath.com>
Signed-off-by: robert-hh <robert@hammelrath.com>
That way, a port can do the internal update of the filter set at once.

Signed-off-by: robert-hh <robert@hammelrath.com>
If instance0 starts too quickly before instance1, it could "babble"
enough messages onto the bus without ACK that it goes into Error
Passive. Once in Error Passive, it has to leave an extra 8 bit times
("Suspend Transmission Time") after each message to allow other nodes
to communicate. This prevents the test from working as designed.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants