Extract from eavmlib platform-specific modules#2111
Extract from eavmlib platform-specific modules#2111pguyot wants to merge 1 commit intoatomvm:mainfrom
Conversation
There was a problem hiding this comment.
Honestly I'm not sure about this specific change:
On one side, having just one module for gpio allows us to have just a central documentation page for GPIOs, and avoiding copy and pasting around the common parts.
On the other side, in the recent past we leaked too much platform specific parts into this module, so the developer experience is not great at all.
I think that having an unified approach is totally doable for some parts, and I believe that gpios are one of the parts that can be quite standard.
Indeed some sort of cleanup / reorganization and more general functions is required.
There was a problem hiding this comment.
What kind of blockers prevents us from having a generic I2C module?
There was a problem hiding this comment.
We can have a generic i2c interface but we cannot have a generic i2c module. We'll have conflicting erlang code / nif code if we try to map everything, and we would end up writing too much C.
In PR #2112 I suggest a very simple i2c driver for the Pico where the functions are directly mapped from the SDK to Erlang. C function i2c_foo() is i2c:foo/n.
Compatibility layer with the ESP32 API is done in Erlang. It's not perfect as the Pico API is blocking (which is bad for the scheduler), but it works as expected for anyone knowing the Pico SDK API. We could only expose the non-blocking API or cheat for blocking APIs (keep the semantics of the Pico SDK API and handle it differently). Yet I find it much more satisfying to port the I2C function, and much faster. I feel like I could port and test i2c/uart/spi on both rp2 and stm32 in few days, the longest being to test them without frying any board.
If we maintain a compatible high level abstraction API, the drivers could work on any platform. We could implement a behavior to enforce it, e.g. gpio_hal or i2c_hal (or maybe gpio_port_hal / gpio_nif_hal).
There was a problem hiding this comment.
I pushed a simple gpio_nif_hal behavior that makes stm32 implementation fail because it lacks a callback.
There was a problem hiding this comment.
What kind of blockers prevents us from having a generic SPI module?
There was a problem hiding this comment.
What kind of blockers prevents us from having a generic UART module?
|
Rather than building all of these platform specific libraries as part of the generic_unix build, I think we should consider having the platform specific modules in the platform’s subdirectory and building the complete atomvmlib.avm in the platform build directory, pulling in the common modules from the current libs directory. This would speed up a lot of the builds, since creating uf2s would only happen when building for RP2 platform, and unsupported modules (i2c, SPI, esp, pico, stm32…) wouldn’t be compiled for generic_unix builds. |
I concur. This means requiring erlang as part of the platform builds, but it's only a problem with CI builds, users probably already have erlang installed. However this could be part of another PR. |
I definitely would love this for a number of reason, but would make other scenarios harder. For example, when using esp-idf from an official esp-idf docker container. We cannot assume those are equipped with Erlang. |
|
Excellent point! I did not consider docker containers… was just thinking that OTP would be installed on the system, but that is not true for IDF or other containers. |
e0d4270 to
67d116d
Compare
|
The behavior approach is a good solution, but I think that a lot of duplication is still there, such as doc duplication. So I had an idea for a different approach that might work. Let's think about gpio.erl: -spec digital_write(Pin :: pin(), Level :: level()) -> ok | {error, Reason :: atom()} | error.
digital_write(Pin, Level) ->
gpio_backend(Pin, Level).A platform such as ESP32 might override it, since we can override any function using NIFs. So we care of having as a public documented API, with typespecs and everything else just the |
|
Unfortunately, I don't think it would work. For a given abstraction (gpio, spi, i2c, uart, pwm, watchdog, rtc, etc...), what we really want is: 1/ a common interface so that drivers are portable across 3 (esp32/stm32/rp2) or 4 platforms (unix,...). 2/ low level transparent nifs that just implement the platform sdk functions with transparent names. gpio is a poor example because it's quite simple, old and has (ugly to my eyes) function names that only exist with arduino and ability to take low/high atoms that just don't make sense when you read a platform's sdk. But I ported spi, i2c, uart and even started watchdog, and i2c is a much better example, especially considering esp API changed. We will need specific Erlang wrappers or implementation and I can't see how we can write this in a maintainable way for 4 platforms in a single module. |
Speaking of names not making sense… gpio:digital_read should return 0 or 1… gpio:read should return low/high atoms. These same names can work for both nif and port implementations, the port one requiring an extra port() parameter. |
67d116d to
4d18f4d
Compare
bettio
left a comment
There was a problem hiding this comment.
This requires rebase, tests are failing.
3721a2d to
0f82b87
Compare
Create new avm_emscripten, avm_esp32, avm_network, avm_rp2 and avm_stm32
libraries and build atomvmlib-<platform>-<jit aarch>.avm files for each
platform and jit combination.
Create new `{gpio,i2c,spi,uart}_hal` behavior module that serve as abstractions
for all platforms.
Signed-off-by: Paul Guyot <pguyot@kallisys.net>
0f82b87 to
e6e1c62
Compare
Following discussion #1669 and to allow me to work on porting i2c and spi to rp2 without being forced to emulate esp32 API in C, this PR aims to split eavmlib into eavmlib (shared modules) and avm_ or avm_network.
These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later