Skip to content

esp32: add pool-based TWAI node module - #603

Open
MilladAnsari wants to merge 3 commits into
lvgl-micropython:mainfrom
MilladAnsari:feat/esp32-twai-node
Open

esp32: add pool-based TWAI node module#603
MilladAnsari wants to merge 3 commits into
lvgl-micropython:mainfrom
MilladAnsari:feat/esp32-twai-node

Conversation

@MilladAnsari

@MilladAnsari MilladAnsari commented Aug 31, 2026

Copy link
Copy Markdown

Summary

This PR adds ESP32 TWAI/CAN support as a standalone twai MicroPython user module, using the ESP-IDF v5.5.1 node-based TWAI API.

It follows the architecture proposed by @kdschlosser in the PR #600 discussion: keep CAN transport work off the MicroPython/LVGL core, use interrupt-driven reception where the driver supports it, and reuse preallocated frame objects rather than allocating on the hot path.

Implementation

  • Adds twai.Node and fixed-size twai.Frame types under ext_mod/twai.
  • Uses twai_node_register_event_callbacks() from esp_driver_twai.
    • RX is handled by the driver's on_rx_done ISR callback; there is no RX polling task.
    • on_error and on_state_change track error and bus-off events.
    • ISR callbacks do not allocate, log, acquire the GIL, or invoke Python.
  • Pins the FreeRTOS TX task to core 0. MicroPython/LVGL remains on core 1.
  • Uses separate user-provided RX and TX Frame pools.
    • Frame has fixed 8-byte storage and exports the buffer protocol.
    • frame[:] and memoryview(frame) are supported.
    • RX frames are returned to the pool with release().
  • Node.send() is non-blocking and returns OSError(EAGAIN) when the software TX queue is full.
  • Internal atomic counters track error_count, bus_off_count, and dropped_rx_count; non-zero values are logged during Node.deinit().
  • Adds a migrated LVGL six-lamp example using the new pool-based API:
    ext_mod/twai/examples/lamp_control.py.
  • Registers the module only for ESP builds and links esp_driver_twai.

Build and partition support

  • Adds PART_SRC support to builder/esp32.py, allowing an explicitly supplied partition CSV to be copied verbatim and preventing automatic partition resizing.
  • Adds the 16MiB partition layout at boards/partitions-16MiB.csv.
  • The factory app partition is 0x350000, leaving sufficient headroom for the ESP32-S3 image.

Validation

Built successfully with:

python3 make.py esp32 \
  BOARD=ESP32_GENERIC_S3 \
  BOARD_VARIANT=SPIRAM_OCT \
  --flash-size=16 \
  DISPLAY=rgb_display \
  INDEV=gt911 \
  --enable-uart-repl=y \
  --optimize-size \
  BOARD_DIR=boards/ESP32_GENERIC_S3 \
  PART_SRC=boards/partitions-16MiB.csv

##Deferred work
This PR intentionally does not add:

  • Python callback dispatch / GIL acquisition from the second core.
  • Hardware acceptance filtering.
  • Python-facing counter APIs.
    These can be added in follow-up work without changing the allocation-free ISR and pool design introduced here.

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.

1 participant