Custom Board definition for STM32G031G8

Hi all,

I hope to tap the knowledge of the community, since I am hitting a brick wall. I want to set up a custom board for a generic STM32G031G8U6. So far, I setup the board file (generic_stm32g031g8u6.json) according to what I could find on the internet:

{
  "build": {
    "core": "stm32",
    "cpu": "cortex-m0plus",
    "extra_flags": "-DSTM32G0 -DSTM32G0xx -DSTM32G031xx",
    "f_cpu": "64000000L",
    "framework_extra_flags": {
      "arduino": "-D__CORTEX_SC=0"
    },
    "mcu": "stm32g031g8",
    "product_line": "STM32G031xx",
    "variant": "STM32G0xx/G031K(4-6-8)(T-U)_G041K(6-8)(T-U)"
  },
  "debug": {
    "default_tools": [
      "stlink"
    ],
    "jlink_device": "STM32G031G8",
    "onboard_tools": [
      "stlink"
    ],
    "openocd_target": "stm32g0x",
    "svd_path": "STM32G031.svd"
  },
  "frameworks": [
    "arduino",
    "cmsis",
    "stm32cube"
  ],
  "name": "ST NUCLEO-G031G8",
  "upload": {
    "maximum_ram_size": 8192,
    "maximum_size": 65536,
    "protocol": "stlink",
    "protocols": [
      "blackmagic",
      "cmsis-dap",
      "dfu",
      "jlink",
      "serial",
      "stlink",
      "mbed"
    ]
  },
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32g031g8.html",
  "vendor": "FB"
}

This is basically a copy of the nucleo_g031k8.json.
My platformio.ini for a project with this board looks as expected:

[env]
boards_dir = ./boards

[env:custom_stm32g031g8u6]
platform = ststm32
board = generic_stm32g031g8u6
; board_build.ldscript = ./boards/ldscript.ld
framework = arduino
upload_protocol = stlink
upload_port = stlink

When I try to build a blank project, it compiles all the necessary files, as far as I can see, but then the linker throws a lot of errors:

/Users/fb/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/12.3.1/../../../../arm-none-eabi/bin/ld: warning: .pio/build/custom_stm32g031g8u6/firmware.elf has a LOAD segment with RWX permissions
/Users/fb/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/12.3.1/../../../../arm-none-eabi/bin/ld: .pio/build/custom_stm32g031g8u6/SrcWrapper/src/stm32/hw_config.c.o: in function `hw_config_init':
hw_config.c:(.text.hw_config_init+0xe): undefined reference to `SystemClock_Config'
/Users/fb/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/12.3.1/../../../../arm-none-eabi/bin/ld: .pio/build/custom_stm32g031g8u6/libFrameworkArduino.a(HardwareSerial.cpp.o): in function `HardwareSerial::setRx(unsigned long)':
HardwareSerial.cpp:(.text._ZN14HardwareSerial5setRxEm+0x4c): undefined reference to `digitalPin'
/Users/fb/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/12.3.1/../../../../arm-none-eabi/bin/ld: HardwareSerial.cpp:(.text._ZN14HardwareSerial5setRxEm+0x50): undefined reference to `analogInputPin'
/Users/fb/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/12.3.1/../../../../arm-none-eabi/bin/ld: .pio/build/custom_stm32g031g8u6/libFrameworkArduino.a(HardwareSerial.cpp.o): in function `HardwareSerial::setTx(unsigned long)':
HardwareSerial.cpp:(.text._ZN14HardwareSerial5setTxEm+0x4c): undefined reference to `digitalPin'
/Users/fb/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/12.3.1/../../../../arm-none-eabi/bin/ld: HardwareSerial.cpp:(.text._ZN14HardwareSerial5setTxEm+0x50): undefined reference to `analogInputPin'
/Users/fb/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/12.3.1/../../../../arm-none-eabi/bin/ld: .pio/build/custom_stm32g031g8u6/libFrameworkArduino.a(HardwareSerial.cpp.o): in function `HardwareSerial::HardwareSerial(void*, HalfDuplexMode_t)':
HardwareSerial.cpp:(.text._ZN14HardwareSerialC2EPv16HalfDuplexMode_t+0x90): undefined reference to `analogInputPin'
/Users/fb/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/12.3.1/../../../../arm-none-eabi/bin/ld: HardwareSerial.cpp:(.text._ZN14HardwareSerialC2EPv16HalfDuplexMode_t+0x98): undefined reference to `digitalPin'
collect2: error: ld returned 1 exit status
*** [.pio/build/custom_stm32g031g8u6/firmware.elf] Error 1

I tried adding a linker script from CubeIDE, therefore the commented boards_build.ldscript definition in the platformio.ini, but with this, the result is the same.
I think I am missing something obvious here, but I can’t see it. Any help would be greatly appreciated.
Cheers

There are multiple faults at play here.

First, you say that you have a STM32G031G8U6 but then you put this as your chosen variant

This is wrong. This folder is for all STM32G031K[4/6/8] and G041K[6/8]. Your G031G8 is not at all in there. You have to look at what STM32Duino/variants/STM32G0xx is offering and chose the correct folder.

The right folder for you is STM32G0xx/G031G(4-6-8)U_G041G(6-8)U.

Second of all, the filename itself

Is problematic. There is some “magic” in the STM32Duino builder script that takes the board name and converts it to the -DARDUINO_<board name> macro. You’re not following the naming convention genericSTM32...json so it’s gonna generate a macro that the Arduino core will not recognize. Specifically, in the correct variant folder we’re looking at files like

whose implemention is guarded by requiring that one of these macros must be activated. Obviously, for your stm32g031g8 that should be ARDUINO_GENERIC_G031G8UX.

So you either

  • fixup your filename to be genericSTM32G031G8U6.json plus use a “mcu” field of stm32g031g8u6
  • or add -DARDUINO_GENERIC_G031G8UX to your "extra_flags".

Thank you for the quick replay. Works perfectly now.
How did I not see the G / K there? As I said, something obvious I was missing.

I know this thread is kind of old, but this has solved an almost identical issue for me as well (I have the first lines of a new topic I almost opened in another tab).

I don’t really have anything to add to the problem itself (it is solved after all). But is there any documentation about those naming conventions? This thread is the only place where I came across it in the last few hours of doing my head in. I didn’t want to just add the -D to the extra-flags, because I didn’t know if I’d fix the cause or only a symptom of the problem.

I copied the definitions and variant folders of a nucleo_l011k4 and nucleo_l031k6 (because they were closest to the L011D4 or L031F6 I intend to use; I need special clock and UART settings - the code of which I create with CubeMX). Out of sheer luck I named the files genericSTM32....json. Luck because I did not know about the build script “magic”. Everything worked for the L011D4 (meaning the right defines were set, ARDUINO_GENERIC_L011D4PX for that case). But it didn’t for the L031F6. As the only place where these defines appeared was in a single (except for the variant files itself obviously) framework-arduinoststm32 file (boards_db.cmake to be exact), I went down a deep rabbit hole on how that definition is plucked out of there into the build environment.
Well, it isn’t at all anyways apparently. I just made almost the same single letter mistake. I changed the "mcu" from stm32l031k6t6 to stm32l031f6t6 in the copied json file. But it should have been stm32l031f6p6. Yeah, spot that difference.

Btw. is this automatism only working in the combination VS Code + platformIO + STM32 + Arduino?