Pycom MicroPython und Espressif SDK

Einleitung

Da es mittlerweile verschiedene MicroPython Derivate gibt, wollen wir hier einen näheren Blick darauf werfen, was mit der Pycom Firmware mitgeliefert wird bzw. auf welchem Softwarestand das Pycom Ökosystem ist – sowohl hinsichtlich MicroPython als auch hinsichtlich des Espressif ESP-IDF SDKs bzw. dessen Fork GitHub - pycom/pycom-esp-idf: A fork of the Espressif IDF.

Gerade die Änderungen im Vergleich zu den Ursprungskomponenten interessieren uns, um uns einen besseren Überblick zu verschaffen, wie die Dinge zusammenhängen.

MicroPython

Die erste Ausgabe der REPL-Shell zeigt folgendes.

Pycom MicroPython 1.20.0.rc11 [v1.9.4-0a38f88] on 2019-05-14; FiPy with ESP32

Auf den Pycom Geräten hat man also ein MicroPython v1.9.4-0a38f88 zur Verfügung.

Demgegenüber wurde am 29. Mai 2019 das Vanilla MicroPython v1.11 veröffentlicht, siehe MicroPython v1.11 release notes.

ESP-IDF

Weil die Frage aufkam, wie die Schwerkraftverhältnisse im Pycom Universum sind – hier ein paar isolierte commits, die das ESP-IDF entsprechend für den Einsatz auf Pycom Geräten anpassen.

2018

2019

Diese Änderungen gehen gegen das ESP-IDF v3.2.

Interrupt handling capabilities

Introduction

Pycom’s MicroPython port introduces a significant improvement to the interrupt handling mechanism.
In Pycom’s ESP32 MicroPython port there are no restrictions on what can be done within an interrupt handler. For example, other ports do not allow allocating memory inside the handler or the use of sockets.

Description

These limitations have been relaxed by handling the interrupt events differently. When an interrupt happens, a message is posted into a queue, notifying a separate thread that the appropriate callback handler should be called. [1] Such handler would receive an argument. By default it is the object associated with the event.

The user can do whatever is required inside of the callback, such as creating new variables, or even sending network packets. Bear in mind that interrupts are processed sequentially and thus it is ideal to keep the handlers as short as possible in order to attend all of them in the minimum time.

Currently, there are 2 classes that support interrupts; the Alarm and Pin classes. Both classes provide the .callback() method that enables the interrupt and registers the given handler. For more details about interrupt usage along with examples, please visit their respective sections.

:warning: Currently, the interrupt system can queue up to 16 interrupts.

https://docs.pycom.io/firmwareapi/notes/

Review

It looks like the designers at Pycom have studied their textbooks well and took the chance to implement the concept of Tasklets and Bottom-Half Processing [1:1] on top of the ESP-IDF.

The implementation in components/driver/dma.c most probably brings in this extension to the vanilla Espressif SDK, see also https://github.com/pycom/pycom-esp-idf/commit/127a49975bd11413a6be94813b394a8232b2265c.

We can’t tell whether there’s an overhead when not requiring to perform a longish task at all and if there’s a downside to this approach when it comes to eventual timing issues [2].


  1. Hard and soft interrupt handlers

    The process described above defers the execution of the interrupt handler to a decoupled subsystem running asynchronously along the main execution flow effectively enabling the system to perform longish tasks within a more highlevel event handler eventually being triggered by a lowlevel hardware interrupt. Interrupt handlers their selves need to finish up quickly and must not keep interrupts blocked for too long in order not to strangle the operating system they are entangled with. [3]

    The Microsoft NT Kernel, the Linux Kernel and many other operating systems [4] resolve this problem by splitting the interrupt handler into two halves. The so-called top half is the routine that actually responds to the interrupt—the one you register as a regular interrupt handler. The bottom half is a routine that is scheduled by the top half to be executed later, at a safer time.

    Tasklets and Bottom-Half Processing - Linux Device Drivers, Second Edition [Book]

    Bottom halves

    The job of bottom halves is to perform any interrupt-related work not performed by the interrupt handler. You want the interrupt handler to perform as little work as possible and in turn be as fast as possible. By offloading as much work as possible to the bottom half, the interrupt handler can return control of the system to whatever it interrupted as quickly as possible.

    https://notes.shichao.io/lkd/ch8/

    The Linux softirq framework

    I’ll Do It Later: Softirqs, Tasklets, Bottom Halves, Task Queues,Work Queues and Timers; Matthew Wilcox, Hewlett-Packard Company

    Deferred Procedure Calls

    A Deferred Procedure Call (DPC) is a Microsoft Windows operating system mechanism which allows high-priority tasks (e.g. an interrupt handler) to defer required but lower-priority tasks for later execution. This permits device drivers and other low-level event consumers to perform the high-priority part of their processing quickly, and schedule non-critical additional processing for execution at a lower priority.

    Deferred Procedure Call - Wikipedia ↩︎ ↩︎

  2. Timing things on MicroPython for ESP32 ↩︎

  3. Writing interrupt handlers — MicroPython latest documentation ↩︎

  4. Divided handlers in modern operating systems ↩︎