Skip to content

Conversation

@projectgus
Copy link
Contributor

@projectgus projectgus commented Dec 15, 2025

Summary

This work follows on from #13149 and closes #12337. The goal is to have a machine.CAN API that can be used on multiple ports, and an implementation that works on stm32 port. The existing pyb.CAN API is being kept alongside this.

The machine.CAN API has changed substantially from the draft submitted in #13149. See comment with more explanation about what happened.

Status

I'm afraid this PR is still not complete, although TX and RX functionality work and the supplied new tests all pass. Remaining items:

  • Decision about scoped Enums (see comment).
  • Implement CAN.recv() error flags and add test coverage.
  • Implement controller errors: CAN.get_state(), CAN.State enum, CAN.IRQ_STATE interrupt trigger.
  • Implement CAN.get_counters()
  • Implement CAN.get_timings()
  • Implement CAN.reset() and CAN.restart(), and/or simplify the API to remove one of these.
  • Implement CAN.mode() and add test coverage.
  • Verify pyb.CAN still works, using multi_pyb_can tests.

Future PRs

  • Create can & aiocan modules in micropython-lib. The goal of machine.CAN is to only implement the bare bones needed to make a higher level "Pythonic" CAN library on top.
  • Implement CAN-FD support (the current PR works on STM32 CAN-FD controller peripherals, but only in Classic CAN mode).

Testing

  • The added tests pass when run between a NUCLEO_H723ZG board (fdcan peripheral) and a PYBDV11 (bxCAN peripheral).
  • Still need to test using an STM32G4 (simplified version of the H7 fdcan peripheral, has subtly different HAL API).
  • As noted above, haven't tested for regressions on pyb.CAN yet.

Trade-offs and Alternatives

  • The biggest trade-off here was deciding to abandon the more ambitious API design from docs: Add machine.CAN low-level API docs. #13149 as it was too hard to implement properly. 😆. This pushes some more of the complexity into the eventual micropython-lib libraries, but it should be easier to implement all of it in Python now the Python-C interface is simpler.

@projectgus projectgus added port-stm32 extmod Relates to extmod/ directory in source labels Dec 15, 2025
.. note:: Not all modes are supported by all CAN controller hardware.
Passing an unsupported mode value will raise ``ValueError``.

.. class:: CAN.Mode
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were so many flags associated with CAN that I thought it might useful to scope some of them to enum classes, i.e. CAN.Mode.NORMAL rather than CAN.MODE_NORMAL. This does take up a little more code size, and it's not the common pattern for machine drivers, so maybe it should be swapped back to the "normal" API pattern.

// include is a no-op (as the file is included directly into
// extmod/machine_can.c). However, including it anyway means that Language
// Servers and IDEs can correctly analyse the machine_can.c file while the
// developer is writing it.
Copy link
Contributor Author

@projectgus projectgus Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other extmod/machine_*.c files don't have a _port.h shared header like this, but I found it very useful when writing the stm32 implementation using clangd for IDE-style checks.

I also think it's generally a useful pattern as it encourages explicitly writing out the interface between the extmod source file and the port-specific source file, even though they get compiled together. So I'd like to implement it for the other extmod machine drivers, eventually.

@codecov
Copy link

codecov bot commented Dec 15, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.38%. Comparing base (099cc9f) to head (fc11501).

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #18572   +/-   ##
=======================================
  Coverage   98.38%   98.38%           
=======================================
  Files         171      171           
  Lines       22300    22300           
=======================================
  Hits        21939    21939           
  Misses        361      361           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link

github-actions bot commented Dec 15, 2025

Code size report:

Reference:  all: Bump version to 1.28.0-preview. [099cc9f]
Comparison: WIP: stm32: Add machine.CAN implementation. [merge of 3b52285]
  mpy-cross:    +0 +0.000% 
   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:    +0 +0.000% standard
      stm32: +3804 +0.961% PYBV10[incl +4(bss)]
     mimxrt:    +0 +0.000% TEENSY40
        rp2:    +0 +0.000% RPI_PICO_W
       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS
  qemu rv32:    +0 +0.000% VIRT_RV32

API is different to the original machine.CAN proposal, as numerous
shortcomings were found during initial implementation.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
Partially working, some API still unimplemented.

Adds new multi_can tests which pass when testing between NUCLEO_H723ZG and
PYBDV11.

This work was mostly funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
@sveinungkb
Copy link

Thanks for keeping at this! I've been using the previous branch for a while.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extmod Relates to extmod/ directory in source port-stm32

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New machine.CAN driver

2 participants