platformio / platform-ststm32

ST STM32: development platform for PlatformIO
https://registry.platformio.org/platforms/platformio/ststm32
Apache License 2.0
402 stars 312 forks source link

Add support for the STM32U0 #798

Open chintal opened 2 months ago

chintal commented 2 months ago

ST has recently launched a series of low cost ULP MCUs - STM32U0. They've also released Nucleo boards for one of the more capable variants : NUCLEO-U083RC.

I have managed to get my hands on a NUCLEO-U083RC. I intend to use this board baremetal, with ST Cube Framework code manually added where needed.

  1. Is there any way I can add the board definition for this Nucleo for myself? As far as I can tell, I only really need it to set the correct flags for the MCU and configure it to use the Nucleo's on-board STLink debugger - or is there something I'm missing? (I don't intend to use any framework)

  2. What would be needed to add this support to platformio itself? Since I have the board, I'm open to trying to port from one of the other nucleos. The reason I'm concerned is that the version of the ST Cube framework included in platform IO is old enough for Cube MX generated code to error out pretty easily, so it might not include support for the STM32U0 at all.

chintal commented 1 month ago

I've created a nucleo_u083rc.json using nucleo_g071rb.json as a template.

{
  "build": {
    "core": "stm32",
    "cpu": "cortex-m0plus",
    "extra_flags": "-DSTM32U0 -DSTM32U0xx -DSTM32U083xx",
    "f_cpu": "64000000L",
    "framework_extra_flags": {
      "arduino": "-D__CORTEX_SC=0"
    },
    "mcu": "stm32u083rct6",
    "product_line": "STM32U083xx",
    "variant": "STM32U0xx/U083RC"
  },
  "debug": {
    "default_tools": [
      "stlink"
    ],
    "jlink_device": "STM32U083RC",
    "onboard_tools": [
      "stlink"
    ],
    "openocd_target": "stm32u0x",
    "svd_path": "STM32U083.svd"
  },
  "frameworks": [
    "arduino",
    "cmsis",
    "libopencm3",
    "stm32cube",
    "zephyr"
  ],
  "name": "Nucleo U083RC",
  "upload": {
    "maximum_ram_size": 40960,
    "maximum_size": 262144,
    "protocol": "stlink",
    "protocols": [
      "stlink",
      "jlink",
      "cmsis-dap",
      "blackmagic",
      "mbed"
    ]
  },
  "url": "https://www.st.com/en/evaluation-tools/nucleo-u083rc.html",
  "vendor": "ST"
}

I expect none of the frameworks are functional.

Using the current version of ST CubeMX to provide CMSIS, STM32U0xx_HAL_Driver, startup file, and system files seems to build using toolchain-gccarmnoneeabi@>1.120000.0 with no framework, though I don't know yet if it works as expected. Manually writing the generated elf file using STM32CubeProgrammer has not yet resulted in a blinking LED. I expect it's likely there's a mistake in the code somewhere, since I almost blindly retargeted code written for STM32F4. I will try with a minimal blink example using the ST provided HAL over the next few days.

The svd file does not exist and the openocd target (stm32u0x.cfg) does not exist, so flashing and debugging this chip from platformIO is presently not viable.

STM32CubeIDE does include a version of openocd which includes stm32u0x.cfg and can connect to the chip. Unfortunately, that file is entirely different structurally from the files used in vanilla openocd and platformio. I don't know if platformIO will be able to debug using the ST provided stm32u0x.cfg. A naive check by just dumping the cfg file into the platformio openocd folder has not worked, even though the two openocd binaries have the same major version (0.12.0-01004... vs 0.12.0+dev-00597). The ST file looks for and does not find gdb_helper.tcl when used with platformIO's tool-openocd.

There appears to be a patch for adding support in upstream openocd here. I have not yet attempted to build it. I plan to try out the approach discussed here for the moment, and see how that goes.

chintal commented 1 week ago

A quick update:

I have been using PlatformIO with no framework successfully on the STM32U0 as described above. I'll summarize the changes I've made here. Since I haven't tried with any of the frameworks, and I don't actually expect them to work out of the box, I'm not creating a PR. I have also not tested with any debugger other than the Nucleo on-board STLink.

Board file for Nucleo U083RC

The nucleo_u083rc.json file, based on one of the existing Nucleo boards, is created in ~/.platformio/platforms/ststm32/boards with the following content:

{
  "build": {
    "core": "stm32",
    "cpu": "cortex-m0plus",
    "extra_flags": "-DSTM32U0 -DSTM32U0xx -DSTM32U083xx",
    "f_cpu": "64000000L",
    "framework_extra_flags": {
      "arduino": "-D__CORTEX_SC=0"
    },
    "mcu": "stm32u083rct6",
    "product_line": "STM32U083xx",
    "variant": "STM32U0xx/U083RC"
  },
  "debug": {
    "default_tools": [
      "stlink"
    ],
    "jlink_device": "STM32U083RC",
    "onboard_tools": [
      "stlink"
    ],
    "openocd_target": "stm32u0x",
    "openocd_board": "stm32u083_generic",
    "svd_path": "STM32U083.svd"
  },
  "frameworks": [
    "arduino",
    "cmsis",
    "libopencm3",
    "stm32cube",
    "zephyr"
  ],
  "name": "Nucleo U083RC",
  "upload": {
    "maximum_ram_size": 40960,
    "maximum_size": 262144,
    "protocol": "stlink",
    "protocols": [
      "stlink",
      "jlink",
      "cmsis-dap",
      "blackmagic",
      "mbed"
    ]
  },
  "url": "https://www.st.com/en/evaluation-tools/nucleo-u083rc.html",
  "vendor": "ST"
}

OpenOCD

The OpenOCD version provided by PlatformIO does not presently support the STM32U0. Based on some combination of external references and STMCubeMX generated code, I've put together an OpenOCD package for PlatformIO which works, available at https://github.com/ebs-universe/pio-tool-openocd-stm32

I have not published it to the PlatformIO repository since I do not intend to maintain it once the default openOCD version supports this chip.

STM32Cube

Since the default STM32Cube versions provided by PlatformIO do not support the U0, I include the following files generated by CubeMX directly into my source tree.

❯ tree src/cubemx
src/cubemx
├── CMSIS
│   ├── Device
│   │   └── ST
│   │       └── STM32U0xx
│   │           ├── Include
│   │           │   ├── stm32u083xx.h
│   │           │   ├── stm32u0xx.h
│   │           │   └── system_stm32u0xx.h
│   │           ├── LICENSE.txt
│   │           └── Source
│   │               └── Templates
│   ├── Include
│   │   ├── ...
│   └── LICENSE.txt
├── startup_stm32u083rctx.s
├── STM32U083RCTX_FLASH.ld
├── STM32U0xx_HAL_Driver
│   ├── Inc
│   │   ├── Legacy
│   │   ├── ...
│   ├── LICENSE.txt
│   └── Src
│       ├── ...
├── syscalls.c
├── sysmem.c
└── system_stm32u0xx.c

13 directories, 135 files

I have also placed the stm32u0xx_hal_conf.h generated by CubeMX in the platformIO project include folder.

platformio.ini

Successful build, program, and debug using the Nucleo on-board stlink requires the following project configuration:

[env]
platform = ststm32
platform_packages =
  toolchain-gccarmnoneeabi@>1.120000.0
  tool-openocd@https://github.com/ebs-universe/pio-tool-openocd-stm32/archive/refs/heads/main.zip
board = nucleo_u083rc
upload_protocol = stlink
debug_tool = stlink
build_flags = 
    -I include
    -I src/cubemx/CMSIS/Device/ST/STM32U0xx/Include
    -I src/cubemx/CMSIS/Include
    -I src/cubemx/STM32U0xx_HAL_Driver/Inc
    -std=gnu++11
board_build.ldscript = src/cubemx/STM32U083RCTX_FLASH.ld

I forget whether it was the ST Cube HAL or some other library which I am using which required -std=gnu++11. I do not also now remember why exactly I needed to upgrade the toolchain to toolchain-gccarmnoneeabi@>1.120000.0. My code as it stands currently fails to compile if either is removed, but these might be optional in the context of a minimum requirement.