Specifying a board with a native build

Greetings, I’m working on a hybrid host/target development mode: build a native app, which talks to an embedded board to access on-board hardware, memory, etc. The embedded board is running custom “bridger” firmware to respond to host requests. So far, it works for I2C and SPI, but I’d like to extend it to GPIO and full memory access. The goal is to allow developing embedded applications (at least partly) via host builds, using the same API and code as on the target µC. This is much quicker than uploading and much easier to debug. It allows accessing real hardware, in a tethered “Firmata-like” mode.

It’s all based on a library which auto-generates board-specific headers (from the corresponding SVD file) to greatly simplify low-level hardware peripheral access. This uses a Python script tied into PIO’s build mechanism.

With the platform set to “native”, I cannot specify a “board = …” in the project ini file (Unknown board ID 'nucleo_g431kb'), because there is (obviously) no platform/native/boards/ directory. The error I get due to this line: https://git.sr.ht/~jcw/jeeh/tree/main/item/make/pio-extra.py#L19

I’m looking for a way to resolve this, i.e.

  1. build for native
  2. specify a “remote target” board in the ini file, preferably with board = ...
  3. find the SVD file for it in the extra script, i.e. via Python and Scons

Step 3 is where I’m stumbling: how to use PIO’s build tooling to locate that SVD file, even though I’m not setting the platform to ststm32.

For more details, see https://git.sr.ht/~jcw/jeeh/tree/main/item/boards/bridged/

If this can be solved, a header with remote µC details could be auto-generated, and host-side builds could then also use it to access board-specific details.

-jcw

To follow up, I’ve hacked around this to get it working anyway:

[platformio]
src_dir = .

[g431k]
# can't use "board" as this fails in native builds
board_name = nucleo_g431kb
board_leds = B8
board_uart = N:USART2 P:A2:U7,A3 F:170 D:1 L:CH T:1 R:2 C:27,26 O:1
board_i2c = N:I2C1 P:B7:OH4,A15 F:170 D:1 L:CH T:3 R:4 C:17,16 O:1
board_spi = N:SPI1 P:B5:5,B4,B3 F:170 D:1 L:CH T:5 R:6 C:11,10 O:1
board_pins = vcc:B6 bmp:A11 lcd:A12 sram:B0 sd:A7

[env]
platform = native
extends = g431k
# need to specify the actual SVD filename instead, since "board" is not set
# TODO can probably de derived from board_name, using same logic as in PIO
board_svd = STM32G431xx.svd
build_flags = -std=c++17 -DPIOENV='"${PIOENV}"' -DPIO_${PIOPLATFORM}
    -Wall -Wextra -Wpedantic -Werror -Wno-format
build_src_filter = +<${PIOENV}.cpp>
lib_deps = symlink://../..

# this builds the embedded firmware:

[env:bridger]
platform = ststm32
framework = cmsis
# this is a hack, to still set the board name for non-native builds
board = ${env.board_name}
build_flags = ${env.build_flags} -DXTAL=0

# these are all native builds, talking to the bridger:

[env:blink]
[env:scan]
[env:fram]
[env:sram]
[env:imu]
[env:oled]

It’s not great, using board_name iso board to get around the native build error, and then setting board anyway for the embedded “bridger” build. And I have to specify the SVD filename, which is normally found by PIO itself.

The board_* settings are how my code manages all hardware differences. By placing this in [env] iso [env:bridger], these are now also made available to native builds.

There’s way too much complexity and magic involved IMO, but hey … it works.

And to follow up once more, the following workaround solves it all:

[platformio]
boards_dir = ~/.platformio/platforms/ststm32/boards/

This way, boards = ... works even in native builds, and SVDs will be found.