4.8 KiB
Adding *io
support to other ports
digitalio
provides a well-defined, cross-port hardware abstraction layer built to support different devices and their drivers. It's backed by the Common HAL, a C api suitable for supporting different hardware in a similar manner. By sharing this C api, developers can support new hardware easily and cross-port functionality to the new hardware.
These instructions also apply to analogio
, busio
, pulseio
and touchio
. Most drivers depend on analogio
, digitalio
and busio
so start with those.
File layout
Common HAL related files are found in these locations:
shared-bindings
Shared home for the Python <-> C bindings which includes inline RST documentation for the created interfaces. The common hal functions are defined in the .h files of the corresponding C files.shared-module
Shared home for C code built on the Common HAL and used by all ports. This code only usescommon_hal
methods defined inshared-bindings
.<port>/common-hal
Port-specific implementation of the Common HAL.
Each folder has the substructure of / and they should match 1:1. __init__.c
is used for module globals that are not classes (similar to __init__.py
).
Adding support
Modifying the build
The first step is to hook the shared-bindings
into your build for the modules you wish to support. Here's an example of this step for the atmel-samd/Makefile
:
SRC_BINDINGS = \
board/__init__.c \
microcontroller/__init__.c \
microcontroller/Pin.c \
analogio/__init__.c \
analogio/AnalogIn.c \
analogio/AnalogOut.c \
digitalio/__init__.c \
digitalio/DigitalInOut.c \
pulseio/__init__.c \
pulseio/PulseIn.c \
pulseio/PulseOut.c \
pulseio/PWMOut.c \
busio/__init__.c \
busio/I2C.c \
busio/SPI.c \
busio/UART.c \
neopixel_write/__init__.c \
time/__init__.c \
usb_hid/__init__.c \
usb_hid/Device.c
SRC_BINDINGS_EXPANDED = $(addprefix shared-bindings/, $(SRC_BINDINGS)) \
$(addprefix common-hal/, $(SRC_BINDINGS))
# Add the resulting objects to the full list
OBJ += $(addprefix $(BUILD)/, $(SRC_BINDINGS_EXPANDED:.c=.o))
# Add the sources for QSTR generation
SRC_QSTR += $(SRC_C) $(SRC_BINDINGS_EXPANDED) $(STM_SRC_C)
The Makefile
defines the modules to build and adds the sources to include the shared-bindings
version and the common-hal
version within the port specific directory. You may comment out certain subfolders to reduce the number of modules to add but don't comment out individual classes. It won't compile then.
Hooking the modules in
Built in modules are typically defined in mpconfigport.h
. To add support you should have something like:
extern const struct _mp_obj_module_t microcontroller_module;
extern const struct _mp_obj_module_t analogio_module;
extern const struct _mp_obj_module_t digitalio_module;
extern const struct _mp_obj_module_t pulseio_module;
extern const struct _mp_obj_module_t busio_module;
extern const struct _mp_obj_module_t board_module;
extern const struct _mp_obj_module_t time_module;
extern const struct _mp_obj_module_t neopixel_write_module;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)µcontroller_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_analogio), (mp_obj_t)&analogio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_digitalio), (mp_obj_t)&digitalio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_busio), (mp_obj_t)&busio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write),(mp_obj_t)&neopixel_write_module } \
Implementing the Common HAL
At this point in the port, nothing will compile yet, because there's still work to be done to fix missing sources, compile issues, and link issues. I suggest start with a common-hal directory from another port that implements it such as atmel-samd
or esp8266
, deleting the function contents and stubbing out any return statements. Once that is done, you should be able to compile cleanly and import the modules, but nothing will work (though you are getting closer).
The last step is actually implementing each function in a port specific way. I can't help you with this. :-) If you have any questions how a Common HAL function should work then see the corresponding .h file in shared-bindings
.
Testing
Woohoo! You are almost done. After you implement everything, lots of drivers and sample code should just work. There are a number of drivers and examples written for Adafruit's Feather ecosystem. Here are places to start: