Skip to content

Commit 5fc800e

Browse files
committed
Add UART support to STM32 platform
Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent ea0b382 commit 5fc800e

14 files changed

Lines changed: 1454 additions & 90 deletions

File tree

.github/workflows/stm32-build.yaml

Lines changed: 15 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,21 @@ jobs:
6464
# FinishTransmission() on the I2C slave when a STOP condition
6565
# occurs, causing the BME280 sensor to get stuck in Reading
6666
# state and ignore subsequent writes.
67-
skip_i2c_test: true
67+
tests: "boot gpio spi crypto uart"
6868
- device: stm32f411ceu6
6969
max_size: 393216
7070
renode_platform: stm32f4.repl
7171
avm_address: "0x08060000"
72-
skip_i2c_test: true
7372
# No RNG peripheral on F411, so the firmware has no crypto NIFs
7473
# (mbedTLS is excluded by STM32_HAS_RNG in CMake).
75-
skip_crypto_test: true
74+
tests: "boot gpio spi uart"
7675
- device: stm32f429zit6
7776
max_size: 524288
7877
- device: stm32h743vit6
7978
max_size: 524288
8079
renode_platform: stm32h743.repl
8180
avm_address: "0x08080000"
81+
tests: "boot gpio i2c spi crypto uart"
8282
- device: stm32h743zit6
8383
max_size: 524288
8484
- device: stm32u585ait6q
@@ -91,6 +91,7 @@ jobs:
9191
max_size: 524288
9292
renode_platform: stm32f746.repl
9393
avm_address: "0x08080000"
94+
tests: "boot gpio i2c spi crypto uart"
9495
- device: stm32g474ret6
9596
max_size: 393216
9697
- device: stm32l476rgt6
@@ -102,10 +103,9 @@ jobs:
102103
# Renode's built-in stm32l552.repl uses STM32F4_I2C (legacy I2C
103104
# register layout) but the L5 HAL uses the newer I2C registers
104105
# (TIMINGR, ISR, etc.), causing a complete register mismatch.
105-
skip_i2c_test: true
106106
# 512 KB flash with avm_address=0x08060000 leaves only 128 KB,
107107
# but the crypto AVM is 207 KB and gets truncated.
108-
skip_crypto_test: true
108+
tests: "boot gpio spi uart"
109109
- device: stm32f207zgt6
110110
max_size: 524288
111111
- device: stm32u375rgt6
@@ -117,7 +117,7 @@ jobs:
117117
# No RNG peripheral on G0B1 (only G041/G061/G081/G0C1 have one),
118118
# so the firmware has no crypto NIFs (mbedTLS is excluded by
119119
# STM32_HAS_RNG in CMake).
120-
skip_crypto_test: true
120+
tests: "boot gpio i2c spi uart"
121121

122122
steps:
123123
- uses: erlef/setup-beam@v1
@@ -195,7 +195,7 @@ jobs:
195195
mkdir build-host
196196
cd build-host
197197
cmake .. -G Ninja
198-
cmake --build . -t stm32_boot_test stm32_gpio_test stm32_i2c_test stm32_spi_test stm32_crypto_test
198+
cmake --build . -t stm32_boot_test stm32_gpio_test stm32_i2c_test stm32_spi_test stm32_crypto_test stm32_uart_test
199199
200200
- name: Install Renode
201201
if: matrix.renode_platform
@@ -207,7 +207,7 @@ jobs:
207207
echo "$PWD/renode-portable" >> $GITHUB_PATH
208208
pip install -r renode-portable/tests/requirements.txt
209209
210-
- name: Run Renode boot test
210+
- name: Run Renode tests
211211
if: matrix.renode_platform
212212
run: |
213213
LOCAL_REPL="src/platforms/stm32/tests/renode/${{ matrix.renode_platform }}"
@@ -216,71 +216,10 @@ jobs:
216216
else
217217
PLATFORM="@platforms/cpus/${{ matrix.renode_platform }}"
218218
fi
219-
renode-test src/platforms/stm32/tests/renode/stm32_boot_test.robot \
220-
--variable ELF:@$PWD/src/platforms/stm32/build/AtomVM-${{ matrix.device }}.elf \
221-
--variable AVM:@$PWD/build-host/src/platforms/stm32/tests/test_erl_sources/stm32_boot_test.avm \
222-
--variable AVM_ADDRESS:${{ matrix.avm_address }} \
223-
--variable PLATFORM:$PLATFORM
224-
225-
- name: Run Renode GPIO test
226-
if: matrix.renode_platform
227-
run: |
228-
LOCAL_REPL="src/platforms/stm32/tests/renode/${{ matrix.renode_platform }}"
229-
if [ -f "$LOCAL_REPL" ]; then
230-
PLATFORM="@$PWD/$LOCAL_REPL"
231-
else
232-
PLATFORM="@platforms/cpus/${{ matrix.renode_platform }}"
233-
fi
234-
renode-test src/platforms/stm32/tests/renode/stm32_gpio_test.robot \
235-
--variable ELF:@$PWD/src/platforms/stm32/build/AtomVM-${{ matrix.device }}.elf \
236-
--variable AVM:@$PWD/build-host/src/platforms/stm32/tests/test_erl_sources/stm32_gpio_test.avm \
237-
--variable AVM_ADDRESS:${{ matrix.avm_address }} \
238-
--variable PLATFORM:$PLATFORM
239-
240-
- name: Run Renode I2C test
241-
if: matrix.renode_platform && !matrix.skip_i2c_test
242-
run: |
243-
LOCAL_REPL="src/platforms/stm32/tests/renode/${{ matrix.renode_platform }}"
244-
if [ -f "$LOCAL_REPL" ]; then
245-
PLATFORM="@$PWD/$LOCAL_REPL"
246-
else
247-
PLATFORM="@platforms/cpus/${{ matrix.renode_platform }}"
248-
fi
249-
renode-test src/platforms/stm32/tests/renode/stm32_i2c_test.robot \
250-
--variable ELF:@$PWD/src/platforms/stm32/build/AtomVM-${{ matrix.device }}.elf \
251-
--variable AVM:@$PWD/build-host/src/platforms/stm32/tests/test_erl_sources/stm32_i2c_test.avm \
252-
--variable AVM_ADDRESS:${{ matrix.avm_address }} \
253-
--variable PLATFORM:$PLATFORM
254-
255-
- name: Run Renode SPI test
256-
if: matrix.renode_platform
257-
run: |
258-
LOCAL_REPL="src/platforms/stm32/tests/renode/${{ matrix.renode_platform }}"
259-
if [ -f "$LOCAL_REPL" ]; then
260-
PLATFORM="@$PWD/$LOCAL_REPL"
261-
else
262-
PLATFORM="@platforms/cpus/${{ matrix.renode_platform }}"
263-
fi
264-
renode-test src/platforms/stm32/tests/renode/stm32_spi_test.robot \
265-
--variable ELF:@$PWD/src/platforms/stm32/build/AtomVM-${{ matrix.device }}.elf \
266-
--variable AVM:@$PWD/build-host/src/platforms/stm32/tests/test_erl_sources/stm32_spi_test.avm \
267-
--variable AVM_ADDRESS:${{ matrix.avm_address }} \
268-
--variable PLATFORM:$PLATFORM
269-
270-
- name: Run Renode crypto test
271-
# Devices without RNG hardware (F411 / G0) don't ship mbedTLS at all;
272-
# L562 has only 512 KB of flash and the 207 KB crypto AVM is truncated
273-
# at AVM_ADDRESS=0x08060000, which kills kernel boot.
274-
if: matrix.renode_platform && !matrix.skip_crypto_test
275-
run: |
276-
LOCAL_REPL="src/platforms/stm32/tests/renode/${{ matrix.renode_platform }}"
277-
if [ -f "$LOCAL_REPL" ]; then
278-
PLATFORM="@$PWD/$LOCAL_REPL"
279-
else
280-
PLATFORM="@platforms/cpus/${{ matrix.renode_platform }}"
281-
fi
282-
renode-test src/platforms/stm32/tests/renode/stm32_crypto_test.robot \
283-
--variable ELF:@$PWD/src/platforms/stm32/build/AtomVM-${{ matrix.device }}.elf \
284-
--variable AVM:@$PWD/build-host/src/platforms/stm32/tests/test_erl_sources/stm32_crypto_test.avm \
285-
--variable AVM_ADDRESS:${{ matrix.avm_address }} \
286-
--variable PLATFORM:$PLATFORM
219+
for TEST in ${{ matrix.tests }}; do
220+
renode-test "src/platforms/stm32/tests/renode/stm32_${TEST}_test.robot" \
221+
--variable ELF:@$PWD/src/platforms/stm32/build/AtomVM-${{ matrix.device }}.elf \
222+
--variable AVM:@$PWD/build-host/src/platforms/stm32/tests/test_erl_sources/stm32_${TEST}_test.avm \
223+
--variable AVM_ADDRESS:${{ matrix.avm_address }} \
224+
--variable PLATFORM:$PLATFORM
225+
done

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- Added support for `nif_start`, `executable_line` and `debug_line` opcodes
1414
- Added named variable debugging support in DWARF when modules are compiled with `beam_debug_info`
1515
- Added more reset reasons and ensured `esp:reset_reason/0` doesn't return `undefined`
16-
- Added I2C and SPI APIs to stm32 platform
16+
- Added I2C, SPI and UART APIs to stm32 platform
1717
- Added `Transfer-Encoding: chunked` response support to `ahttp_client`, including HTTP trailers
1818
- Added `proc_lib:init_fail/2,3`
1919
- Added UART API to rp2 platform

examples/erlang/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,4 @@ pack_runnable(i2c_scanner i2c_scanner eavmlib estdlib DIALYZE_AGAINST avm_esp32
4848
pack_runnable(i2c_lis3dh i2c_lis3dh eavmlib estdlib DIALYZE_AGAINST avm_esp32 avm_rp2 avm_stm32)
4949
pack_runnable(spi_flash spi_flash eavmlib estdlib DIALYZE_AGAINST avm_esp32 avm_rp2 avm_stm32)
5050
pack_runnable(spi_lis3dh spi_lis3dh eavmlib estdlib DIALYZE_AGAINST avm_esp32 avm_rp2 avm_stm32)
51-
pack_runnable(sim800l sim800l eavmlib estdlib DIALYZE_AGAINST avm_esp32 avm_rp2)
51+
pack_runnable(sim800l sim800l eavmlib estdlib DIALYZE_AGAINST avm_esp32 avm_rp2 avm_stm32)

examples/erlang/sim800l.erl

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
%% Default pins are auto-detected from the platform and chip model:
3535
%%
3636
%% Pico (UART1): TX=GP4, RX=GP5
37+
%% STM32 (USART1): TX=PA9, RX=PA10, AF=7
3738
%% ESP32/S2/S3 (UART1): TX=17, RX=16
3839
%% ESP32-C2 (UART1): TX=4, RX=5
3940
%% ESP32-C3/C5 (UART1): TX=4, RX=5
@@ -46,13 +47,8 @@
4647
-define(AT_TIMEOUT, 2000).
4748

4849
start() ->
49-
{TX, RX} = default_pins(),
50-
io:format("Opening UART1 on TX=~B RX=~B~n", [TX, RX]),
51-
UART = uart:open("UART1", [
52-
{tx, TX},
53-
{rx, RX},
54-
{speed, 115200}
55-
]),
50+
Platform = atomvm:platform(),
51+
UART = open_uart(Platform),
5652
%% SIM800L takes 3-5 seconds to boot after power-on
5753
case wait_for_module(UART, 5) of
5854
ok ->
@@ -156,13 +152,33 @@ drain(UART) ->
156152
end.
157153

158154
%%-----------------------------------------------------------------------------
159-
%% Platform-specific default pins
155+
%% Platform-specific UART operations
160156
%%-----------------------------------------------------------------------------
161-
default_pins() ->
162-
default_pins(atomvm:platform()).
163157

164-
%% {TX, RX}
158+
open_uart(stm32) ->
159+
{TX, RX} = default_pins(stm32),
160+
io:format("Opening USART1 on TX=~p RX=~p~n", [TX, RX]),
161+
uart:open([
162+
{peripheral, 1},
163+
{tx, TX},
164+
{rx, RX},
165+
{af, 7},
166+
{speed, 115200}
167+
]);
168+
open_uart(Platform) ->
169+
{TX, RX} = default_pins(Platform),
170+
io:format("Opening UART1 on TX=~p RX=~p~n", [TX, RX]),
171+
uart:open("UART1", [
172+
{tx, TX},
173+
{rx, RX},
174+
{speed, 115200}
175+
]).
176+
177+
%%-----------------------------------------------------------------------------
178+
%% Platform-specific default pins
179+
%%-----------------------------------------------------------------------------
165180
default_pins(pico) -> {4, 5};
181+
default_pins(stm32) -> {{a, 9}, {a, 10}};
166182
default_pins(esp32) -> esp32_default_pins().
167183

168184
esp32_default_pins() ->

examples/erlang/stm32/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,19 @@ add_custom_command(
7070
VERBATIM
7171
)
7272
add_custom_target(stm32_spi_flash ALL DEPENDS stm32_spi_flash.avm)
73+
74+
set(SIM800L_BEAM ${CMAKE_BINARY_DIR}/examples/erlang/sim800l.beam)
75+
add_custom_command(
76+
OUTPUT stm32_sim800l.avm
77+
DEPENDS sim800l_main ${SIM800L_BEAM}
78+
${CMAKE_BINARY_DIR}/libs/estdlib/src/estdlib.avm estdlib
79+
${CMAKE_BINARY_DIR}/libs/avm_stm32/src/avm_stm32.avm avm_stm32
80+
PackBEAM
81+
COMMAND ${CMAKE_BINARY_DIR}/tools/packbeam/packbeam create ${INCLUDE_LINES} stm32_sim800l.avm
82+
${SIM800L_BEAM}
83+
${CMAKE_BINARY_DIR}/libs/estdlib/src/estdlib.avm
84+
${CMAKE_BINARY_DIR}/libs/avm_stm32/src/avm_stm32.avm
85+
COMMENT "Packing runnable stm32_sim800l.avm"
86+
VERBATIM
87+
)
88+
add_custom_target(stm32_sim800l ALL DEPENDS stm32_sim800l.avm)

libs/avm_stm32/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ set(ERLANG_MODULES
2626
gpio
2727
i2c
2828
spi
29+
uart
2930
)
3031

3132
pack_archive(avm_stm32 DEPENDS_ON eavmlib ERLC_FLAGS +warnings_as_errors MODULES ${ERLANG_MODULES})

0 commit comments

Comments
 (0)