Skip to content

Commit

Permalink
Merge pull request #937 from UncleGrumpy/stm32_dev_config
Browse files Browse the repository at this point in the history
Correctly configure STM32 devices from cmake options
  • Loading branch information
fadushin authored Nov 13, 2023
2 parents 6a5e2df + aa749ec commit 11f0da3
Show file tree
Hide file tree
Showing 16 changed files with 734 additions and 28 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/stm32-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ jobs:
/home/runner/libopencm3
key: ${{ runner.os }}-build-deps

- uses: erlef/setup-beam@v1
with:
otp-version: "26"

- name: Install arm-embedded toolchain
if: ${{ steps.builddeps-cache.outputs.cache-hit != 'true' }}
working-directory: /home/runner
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed a bug that would leave the STM32 trapped in a loop on hard faults, rather than aborting
- Fixed a bug that would make the VM to loop and failing to process selected fds on Linux
- Fixed classes of exceptions in estdlib.
- Fixed STM32 code that was hard coded to the default target device, now configured based on the `cmake -DDEVICE=` parameter

### Changed

Expand All @@ -30,6 +31,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added support for `net:getaddrinfo/1,2`
- Added minimal support for the OTP `ssl` interface.
- Added support for `crypto:one_time/4,5` on Unix and Pico as well as for `crypto:hash/2` on Pico
- Added ability to configure STM32 Nucleo boards onboard UART->USB-COM using the `-DBOARD=nucleo` cmake option
- Added STM32 cmake option `-DAVM_CFG_CONSOLE=` to select a different uart peripheral for the system console

## [0.6.0-alpha.1] - 2023-10-09

Expand Down
1 change: 1 addition & 0 deletions doc/release-notes.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ AtomVM has been tested on the following development boards:
|------------------------------|----------------|
| [Nucleo-F429ZI](https://www.st.com/en/evaluation-tools/nucleo-f429zi.html) | ✅ |
| [STM32F4Discovery](https://www.st.com/en/evaluation-tools/stm32f4discovery.html) | ✅ |
| [BlackPill V2.0](https://stm32-base.org/boards/STM32F411CEU6-WeAct-Black-Pill-V2.0) | ✅ |

Due to the proliferation of boards for the [STMicroelectronics](https://www.st.com) [STM32](https://www.st.com/en/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus.html) platform, AtomVM does not currently support pre-build binaries for STM32. In order to deploy AtomVM to the STM32 platform, you will need to build AtomVM for STM32 from source. See the [Build Instructions](build-instructions.md) for information about how to build AtomVM from source code.

Expand Down
6 changes: 6 additions & 0 deletions doc/src/atomvm-tooling.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ You may now flash your application to your STM32 device:
...
===> st-flash --reset write /path/to/atomvm_examples/erlang/hello_world/_build/default/lib/hello_world.avm 0x8080000

For devices with only 512KB of flash the application address is different and must be specified:

shell$ rebar3 atomvm stm32_flash -o 0x8060000
...
===> st-flash --reset write /path/to/atomvm_examples/erlang/hello_world/_build/default/lib/hello_world.avm 0x8060000

See the [`atomvm_rebar3_plugin`](https://atomvm.github.io/atomvm_rebar3_plugin) page for more detailed instructions about how to use the `stm32_flash` target.

You can now use a serial console program such as [minicom](https://en.wikipedia.org/wiki/Minicom) or [screen](https://en.wikipedia.org/wiki/GNU_Screen) to view console output from a device.
Expand Down
32 changes: 25 additions & 7 deletions doc/src/build-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -505,11 +505,11 @@ The following software is required to build AtomVM for the STM32 platform:
* `cmake`
* `make`
* `git`
* `python`
* Erlang/OTP `escript`

> Note. AtomVM tests this build on the latest Ubuntu github runner.


### Setup libopencm3

Before building for the first time you need to have a compiled clone of the libopencm3 libraries, from inside the AtomVM/src/platforms/stm32 directory:
Expand All @@ -530,12 +530,30 @@ Before building for the first time you need to have a compiled clone of the libo
### Changing device

The default build is based on the STM32F4Discovery board chip (`stm32f407vgt6`). If you want to target a different
chip, pass the `-DDEVICE` flag when invoking cmake. For example, to use the STM32F429Discovery, pass
`-DDEVICE=stm32f429zit6`
chip, pass the `-DDEVICE` flag when invoking cmake. For example, to use the BlackPill V2.0, pass `-DDEVICE=STM32F411CEU6`. At this time any `STM32F4` or `STM32F7` device with 512KB or more of on package flash should work with AtomVM. If an unsupported device is passed with the `DEVICE` parameter the configuration will fail. For devices with either 512KB or 768KB of flash the available application flash space will be limited to 128KB. Devices with only 512KB of flash may also suffer from slightly reduced performance because the compiler must optimize for size rather than performance.

>Important Note: for devices with only 512KB of flash the application address is different and must be adjusted when flashing your application with st-flash, or using the recommended `atomvm_rebar3_plugin`. The application address for these devices is `0x8060000`.
### Configuring the Console

The default build for any `DEVICE` will use `USART2` and output will be on `PA2`. This default will work well for most `Discovery` and generic boards that do not have an on-board TTL to USB-COM support (including the `STM32F411CEU6` A.K.A. `BlackPill V2.0`). For `Nucleo` boards that do have on board UART to USB-COM support you may pass the `cmake` parameter `-DBOARD=nucleo` to have the correct USART and TX pins configured automatically. The `Nucleo-144` series use `USART3` and `PD8`, while the supported `Nucleo-64` boards use `USART2`, but passing the `BOARD` parameter along with `DEVICE` will configure the correct `USART` for your model. If any other boards are discovered to have on board USB UART support pull requests, or opening issues with the details, are more than welcome.

Example to configure a `NUCLEO-F429ZI`:

$ cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/arm-toolchain.cmake -DDEVICE=stm32f429zit6 -DBOARD=nucleo

If you are building for a different target board the `CLOCK_FREQUENCY` definition in main.c will need to be changed to match the clock frequency (in hertz) of your cpu.
The AtomVM system console `USART` may also be configured to a specific uart peripheral. Pass one of the parameters from the chart below with the `cmake` option `-DAVM_CFG_CONSOLE=CONSOLE_#`, using the desired console parameter in place of `CONSOLE_#`. Not all UARTs are available on every supported board, but most will have several options that are not already used by other on board peripherals. Consult your data sheets for your device to select an appropriate console.

The rcc_clock_setup_XXX_XXX will also need to be changed to match your particular chip-set. Consult [ST's documentation](https://www.st.com/en/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus.html) for appropriate settings.
| Parameter | USART | TX Pin | AtomVM Default | Nucleo-144 | Nucleo-64 |
|-----------|-------|--------|----------------|------------|-----------|
| `CONSOLE_1` | `USART1` | `PA9` | | | |
| `CONSOLE_2` | `USART2` | `PA2` || ||
| `CONSOLE_3` | `USART3` | `PD8` | || |
| `CONSOLE_4` | `UART4` | `PC10` | | | |
| `CONSOLE_5` | `UART5` | `PC12` | | | |
| `CONSOLE_6` | `USART6` | `PC6` | | | |
| `CONSOLE_7` | `UART7` | `PF7` | | | |
| `CONSOLE_8` | `UART8` | `PJ8` | | | |

### Configure logging with `cmake`
The default maximum log level is `LOG_INFO`. To change the maximum level displayed pass `-DAVM_LOG_LEVEL_MAX="{level}"` to `cmake`, with one of `LOG_ERROR`, `LOG_WARN`, `LOG_INFO`, or `LOG_DEBUG` (listed from least to most verbose). Log messages can be completely disabled by using `-DAVM_LOG_DISABLE=on`.
Expand All @@ -558,7 +576,7 @@ By default, stdout and stderr are printed on USART2. On the STM32F4Discovery boa
using a TTL-USB with the TX pin connected to board's pin PA2 (USART2 RX). Baudrate is 115200 and serial transmission
is 8N1 with no flow control.

> If building for a different target USART and gpio pins may need to be adjusted in `main.c`.
> If building for a different target USART may be configure as explained above in [Configuring the Console](#configuring-the-console).
### Configuring for "deployment"
After your application has been tested (_and debugged_) and is ready to put into active use you may want to tune the build of AtomVM. For instance disabling logging with `-DAVM_LOG_DISABLE=on` as a `cmake` configuration option may result in slightly better performance. This will have no affect on the console output of your application, just disable low level log messages from the AtomVM system. You may also want to enabling automatic reboot in the case that your application ever exits with a return other than `ok`. This can be enabled with the `cmake` option `-DAVM_CONFIG_REBOOT_ON_NOT_OK=on`.
Expand Down
8 changes: 5 additions & 3 deletions doc/src/getting-started-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ For information about how to flash your application to your ESP32, see the [Atom

## Getting Started on the STM32 platform

AtomVM can run on a wide variety of STM32 chip-sets available from [STMicroelectronics](https://www.st.com). The support is not nearly as mature as for the ESP32 platform, but work is ongoing, and pull requests are always welcome. At this time AtomVM will work on any board with a minimum of around 128k ram and 512k (1M recommended) flash. Simple applications and tests have been successfully run on a stm32f411ceu6 (A.K.A. Black Pill V2). These minimum requirements may need to be raised as platform support matures.
AtomVM can run on a wide variety of STM32 chip-sets available from [STMicroelectronics](https://www.st.com). The support is not nearly as mature as for the ESP32 platform, but work is ongoing, and pull requests are always welcome. At this time AtomVM will work on any board with a minimum of around 128KB ram and 512KB (1M recommended) flash. Simple applications and tests have been successfully run on a stm32f411ceu6 (A.K.A. Black Pill V2). These minimum requirements may need to be raised as platform support matures.

### Requirements

Expand Down Expand Up @@ -196,15 +196,17 @@ To flash your image, use the following command:

Congratulations! You have now flashed the AtomVM VM image onto your STM32 device!

> Note. AtomVM expects to find the AVM at the address 0x808000. On a STM32 Discovery board this means that the 1MB of flash will be split in 512KB available for the program and 512KB available for the packed AVM. If for any reason you want to modify this, you can change `AVM_ADDRESS` and `AVM_FLASH_MAX_SIZE` defines in `main.c`.
> Note. AtomVM expects to find the AVM at the address 0x8080000. On a STM32 Discovery board this means that the 1MB of flash will be split in 512KB available for the program and 512KB available for the packed AVM. For devices with only 512KB of flash the application address is 0x8060000, leaving 128KB of application flash available.
#### Printing

By default, stdout and stderr are printed on USART2. On the STM32F4Discovery board, you can see them using a TTL-USB with the TX pin connected to board's pin PA2 (USART2 RX). Baudrate is 115200 and serial transmission is 8N1 with no flow control.

For Nucleo boards the on board USB-COM to USART may be used by configuring your build with a BOARD parameter, see the [STM32 Build Instructions](./build-instructions.md#building-for-stm32) for [Configuring the Console](./build-instructions.md#configuring-the-console).

### Deploying an AtomVM application

An AtomVM application is a collection of BEAM files, which have been compiled using the Erlang or Elixir compiler. These BEAM files are assembled into an AtomVM "packbeam" (`.avm`) file, which in turn is flashed to the `main` data partition on the STM32 flash module, starting at address `0x210000`.
An AtomVM application is a collection of BEAM files, which have been compiled using the Erlang or Elixir compiler. These BEAM files are assembled into an AtomVM "packbeam" (`.avm`) file, which in turn is flashed to the `main` data partition on the STM32 flash module, starting at address `0x8080000`, for boards with 512KB of flash the address is `0x8060000`.

When the AtomVM virtual machine starts, it will search for the first module that contains an exported `start/0` function in this partition, and it will begin execution of the BEAM bytecode at that function.

Expand Down
4 changes: 4 additions & 0 deletions src/platforms/stm32/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ if (NOT CMAKE_TOOLCHAIN_FILE)
message(FATAL_ERROR "Cross compiling only. Please use -DCMAKE_TOOLCHAIN_FILE=cmake/arm-toolchain.cmake or use\
your own toolchain file")
endif ()
mark_as_advanced(CMAKE_TOOLCHAIN_FILE)

if ((NOT ${CMAKE_C_COMPILER_ID} STREQUAL "GNU") OR
(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") OR
Expand All @@ -93,6 +94,9 @@ if (NOT DEVICE)
set(DEVICE stm32f407vgt6)
endif ()

# Include auto-device configuration
include(cmake/atomvm_dev_config.cmake)

# Include libopencm3
include(cmake/libopencm3.cmake)

Expand Down
2 changes: 2 additions & 0 deletions src/platforms/stm32/cmake/arm-toolchain.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ find_program(ARM_CXX arm-none-eabi-g++)
find_program(ARM_OBJCOPY arm-none-eabi-objcopy)
find_program(ARM_SIZE arm-none-eabi-size)

mark_as_advanced(ARM_CC ARM_CXX ARM_OBJCOPY ARM_SIZE)

SET(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(CMAKE_C_COMPILER ${ARM_CC})
set(CMAKE_CXX_COMPILER ${ARM_CXX})
73 changes: 73 additions & 0 deletions src/platforms/stm32/cmake/atomvm_dev_config.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#
# This file is part of AtomVM.
#
# Copyright 2023 Winford <winford@object.stream>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
#

# Generate config information for device.
if (NOT DEVICE)
message(FATAL_ERROR "No DEVICE specified for device config generator")
endif ()

find_program(ESCRIPT escript)
if (NOT ESCRIPT)
message(FATAL_ERROR "Erlang/OTP 'escript' not found in PATH. Check your Erlang/OTP installation.")
endif ()
mark_as_advanced(ESCRIPT)

set(DEVCONFIG_SCRIPT "${CMAKE_SOURCE_DIR}/tools/atomvm_stm32_config_query.erl")
execute_process(
COMMAND "${ESCRIPT}" "${DEVCONFIG_SCRIPT}" "${DEVICE}" "clock"
OUTPUT_VARIABLE DEVCONFIG_CLOCK_HZ
)
add_compile_definitions(${DEVCONFIG_CLOCK_HZ})
execute_process(
COMMAND "${ESCRIPT}" "${DEVCONFIG_SCRIPT}" "${DEVICE}" "rom"
OUTPUT_VARIABLE DEVCONFIG_FLASH_SIZE
)
add_compile_definitions(${DEVCONFIG_FLASH_SIZE})
## also needs to be set for correct optomization flags to be used.
set(CMAKE_FLASH_SIZE "${DEVCONFIG_FLASH_SIZE}")

if (AVM_CFG_CONSOLE)
set(AVM_CFG_CONSOLE ${AVM_CFG_CONSOLE} CACHE STRING "AtomVM system console uart")
set_property(CACHE AVM_CFG_CONSOLE PROPERTY STRINGS CONSOLE_1 CONSOLE_2 CONSOLE_3 CONSOLE_4 CONSOLE_5 CONSOLE_6 CONSOLE_7 CONSOLE_8)
add_compile_definitions(${AVM_CFG_CONSOLE})
elseif (BOARD)
execute_process(
COMMAND "${ESCRIPT}" "${DEVCONFIG_SCRIPT}" "${DEVICE}" "${BOARD}_com"
OUTPUT_VARIABLE DEVCONFIG_CONSOLE
)
add_compile_definitions(${DEVCONFIG_CONSOLE})
set(AVM_CFG_CONSOLE ${DEVCONFIG_CONSOLE} CACHE STRING "AtomVM system console uart")
set(BOARD ${BOARD} CACHE STRING "Board variant configuration")
set_property(CACHE AVM_CFG_CONSOLE PROPERTY STRINGS CONSOLE_1 CONSOLE_2 CONSOLE_3 CONSOLE_4 CONSOLE_5 CONSOLE_6 CONSOLE_7 CONSOLE_8)
else()
add_compile_definitions(CONSOLE_2)
set(AVM_CFG_CONSOLE CONSOLE_2 CACHE STRING "AtomVM system console uart")
set_property(CACHE AVM_CFG_CONSOLE PROPERTY STRINGS CONSOLE_1 CONSOLE_2 CONSOLE_3 CONSOLE_4 CONSOLE_5 CONSOLE_6 CONSOLE_7 CONSOLE_8)
endif()

message("----------------------------------------")
message(STATUS "Device : ${DEVICE}")
if (BOARD)
message(STATUS "Board : ${BOARD}")
endif()
message("--------Device Configuration Info-------")
message(STATUS "Clock Hz : ${DEVCONFIG_CLOCK_HZ}")
message(STATUS "Flash Size : ${DEVCONFIG_FLASH_SIZE}")
message(STATUS "Console : ${AVM_CFG_CONSOLE}")
4 changes: 4 additions & 0 deletions src/platforms/stm32/cmake/compile-flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ set(CXX_WARN_FLAGS "${COMMON_WARN_FLAGS} -Wctor-dtor-privacy -Wnoexcept -Wold-st
-Wsign-promo -Wstrict-null-sentinel -Wuseless-cast -Wzero-as-null-pointer-constant")

# Use C and C++ compiler optimizatons for size and speed.
if (${CMAKE_FLASH_SIZE} STREQUAL "ROM_512K")
set(OPTIMIZE_FLAG "-Os")
else()
set(OPTIMIZE_FLAG "-O2")
endif()

# Pass them back to the CMake variable
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_WARN_FLAGS} ${OPTIMIZE_FLAG}")
Expand Down
4 changes: 2 additions & 2 deletions src/platforms/stm32/cmake/libopencm3.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ find_program(PYTHON python)
if (NOT PYTHON)
message(FATAL_ERROR "python is required to generate the linker script, please install it.")
endif ()
mark_as_advanced(PYTHON)

set(GENLINK_SCRIPT "${LIBOPENCM3_DIR}/scripts/genlink.py")
set(DEVICES_DATA "${LIBOPENCM3_DIR}/ld/devices.data")
Expand Down Expand Up @@ -80,8 +81,7 @@ execute_process(
COMMAND "${PYTHON}" "${GENLINK_SCRIPT}" "${DEVICES_DATA}" "${DEVICE}" "DEFS"
OUTPUT_VARIABLE GENLINK_DEFS
)
message("----------------------------------------")
message(STATUS "Device : ${DEVICE}")

message("-----------Device Linker Info-----------")
message(STATUS "Family : ${GENLINK_FAMILY}")
message(STATUS "Sub-family : ${GENLINK_SUBFAMILY}")
Expand Down
1 change: 1 addition & 0 deletions src/platforms/stm32/src/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ cmake_minimum_required (VERSION 3.13)
project (libAtomVMPlatformSTM32)

set(HEADER_FILES
avm_devcfg.h
avm_log.h
gpio_driver.h
stm_sys.h
Expand Down
Loading

0 comments on commit 11f0da3

Please sign in to comment.