Adventures with .mpy modules

A project log for ESP32 micropython led matrix driver

Efficient driver for cheap LED matrix panels using the I2S peripheral of the ESP32 to display images with zero CPU load.

DanielDaniel 01/03/2021 at 14:400 Comments

What are .mpy modules?

Besides statically linked modules, Micropython also offers a way to dynamically load binary code. These are .mpy files, which can be copied to a device and imported just like an ordinary python module. This has a huge usability benefit over the "normal" binary modules, since users can simply install those on prebuilt Micropython installations. "Installing" a statically linked module requires to (re-)build Micropython yourself.

So I thought having this driver as a dynamically loadable module would be neat.

Limitations of dynamically loaded modules

A dynamically loaded module has no direct access to the function provided by the platform / operating system so only a very limited table of functions is available which are defined in py/nativeglue.h. Normally, this would mean implementing a hardware driver with this system is a bad idea because all the HAL functions are unavailable. But since my driver comes with its own variant of the I2S driver anyway and otherwise does very little hardware specific, I wanted to give it a try and started planning.

Non-IDF version of the I2S driver

For this to work, we need to make a version of the parallel I2S driver, that does not rely on the ESP32 IDF. Looking at the driver, there are four categories interaction with the IDF:

DPORT mutual access mitigation

The DPORT registers hold bits, to enable / disable and reset peripherals of the CPU. Since these registers are shared between both cores, an access mitigation is required in order to implement bit set / clear operations safely. Sadly, that is something I cannot do from within the dynamically loaded module as the required functions are not accessible. On a single core CPU, I could get away with disabling interrupts while accessing the registers. But since this is a dual-core, things are way more difficult.

This leaves me with only two options:

For now I decided to not implement my driver as a .mpy module. But I'm still searching for solutions.