STM32F072 discovery board with libopencm3

Hi,

I am a beginner who would like to program the STM32F072 Discovery Board.

My platform.ini is:

[env:disco_f072rb]
platform = ststm32
board = disco_f072rb
framework = libopencm3

When I platformio run I get:

Processing disco_f072rb (platform: ststm32; board: disco_f072rb; framework: libopencm3)
-----------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/ststm32/disco_f072rb.html
PLATFORM: ST STM32 6.1.0 > ST Discovery F072RB
HARDWARE: STM32F072RBT6 48MHz, 16KB RAM, 128KB Flash
DEBUG: Current (stlink) On-board (stlink) External (blackmagic, jlink)
PACKAGES:
 - framework-libopencm3 1.1.0
 - toolchain-gccarmnoneeabi 1.70201.0 (7.2.1)
Error: This board doesn't support libopencm3 framework!

I don’t understand why my board is not supported by the libopencm3 framework. There are several issues in the libopencm3 repository that indicate that libopencm3 should on STM32F072 discovery board.

Is it possible to make platformio run build successfully an executable or is there indeed an incompatibility of the STM32F072 with libopencm3?

Update:

I added libopencm3 to the frameworks array in platforms/ststm32/boards/disco_f072rb.json. If I now run platformio run I get:

KeyError: "Invalid board option 'build.core'":
  File "/Users/bodokaiser/.pyenv/versions/3.8.1/Python.framework/Versions/3.8/lib/python3.8/site-packages/platformio/builder/main.py", line 156:
    env.SConscript("$BUILD_SCRIPT")
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Script/SConscript.py", line 597:
    return _SConscript(self.fs, *files, **subst_kw)
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Script/SConscript.py", line 286:
    exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals)
  File "/Users/bodokaiser/.platformio/platforms/ststm32/builder/main.py", line 98:
    target_elf = env.BuildProgram()
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Environment.py", line 219:
    return self.method(*nargs, **kwargs)
  File "/Users/bodokaiser/.pyenv/versions/3.8.1/Python.framework/Versions/3.8/lib/python3.8/site-packages/platformio/builder/tools/platformio.py", line 61:
    env.ProcessProgramDeps()
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Environment.py", line 219:
    return self.method(*nargs, **kwargs)
  File "/Users/bodokaiser/.pyenv/versions/3.8.1/Python.framework/Versions/3.8/lib/python3.8/site-packages/platformio/builder/tools/platformio.py", line 118:
    env.BuildFrameworks(env.get("PIOFRAMEWORK"))
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Environment.py", line 219:
    return self.method(*nargs, **kwargs)
  File "/Users/bodokaiser/.pyenv/versions/3.8.1/Python.framework/Versions/3.8/lib/python3.8/site-packages/platformio/builder/tools/platformio.py", line 330:
    SConscript(env.GetFrameworkScript(f), exports="env")
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Script/SConscript.py", line 660:
    return method(*args, **kw)
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Script/SConscript.py", line 597:
    return _SConscript(self.fs, *files, **subst_kw)
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Script/SConscript.py", line 286:
    exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals)
  File "/Users/bodokaiser/.platformio/platforms/ststm32/builder/frameworks/libopencm3/libopencm3.py", line 147:
    if board.get("build.core") == "tivac":
  File "/Users/bodokaiser/.pyenv/versions/3.8.1/Python.framework/Versions/3.8/lib/python3.8/site-packages/platformio/managers/platform.py", line 795:
    raise KeyError("Invalid board option '%s'" % path)

I’ve run into the same problem with a Nucleo-F042K6 board and got it working with several changes.

1. Modified board definition

Copy the file ~/.platformio/platforms/ststm32/boards/nucleo_f072rb.json to ~/.platformio/boards/nucleo_f072rb_libopencm.json. If the boards directory doesn’t exist, create it.

Then change the file like so (relevant changes are extra_flags, new libopencm3 block, additional frameworks entry):

{
  "build": {
    "cpu": "cortex-m0",
    "extra_flags": "-DSTM32F042x6 -DSTM32F072RB -DSTM32F0",
    "f_cpu": "48000000L",
    "mcu": "stm32f072rbt6",
    "libopencm3": {
      "ldscript": "stm32f07xzb.ld"
    },
  },
  "connectivity": [
    "can"
  ],
  "debug": {
    "default_tools": [
      "stlink"
    ],
    "jlink_device": "STM32F072RB",
    "onboard_tools": [
      "stlink"
    ],
    "openocd_board": "st_nucleo_f0",
    "svd_path": "STM32F072x.svd"
  },
  "frameworks": [
    "mbed",
    "stm32cube",
    "libopencm3"
  ],
  "name": "ST Nucleo F072RB",
  "upload": {
    "maximum_ram_size": 16384,
    "maximum_size": 131072,
    "protocol": "stlink",
    "protocols": [
      "jlink",
      "stlink",
      "blackmagic",
      "mbed"
    ]
  },
  "url": "https://developer.mbed.org/platforms/ST-Nucleo-F072RB/",
  "vendor": "ST"
}

2. Modify libopencm3.py

Apply the below changes to libopencm3.py in ~\.platformio\platforms\ststm32\builder\frameworks\libopencm3 :

At line 124, insert:

    incre = re.compile(r"^INCLUDE\s+\"?([^\.]+\.ld)\"?", re.M)

At about line 133, replace:

                return fp.read()

with:

                return incre.sub(r'_INCLUDE_ \1', fp.read())

3. platformio.ini entries

In platformio.ini, put these entries to make sure you get the latest version of libopencm3 and STM32 platform. (I’m not sure the second is needed.)

platform = https://github.com/platformio/platform-ststm32.git
platform_packages = framework-libopencm3 @ https://github.com/libopencm3/libopencm3#master
framework = libopencm3

I like the libopencm3 framework. But it’s not the most popular one. So it hasn’t the highest priority with PlatformIO.

Great thanks for your detailed answer!

Why did you use nucleo_f072rb.json over disco_f072rb.json?

I changed the function merge_ld_scripts in ~\.platformio\platforms\ststm32\builder\frameworks\libopencm3\libopencm3.py to:

def merge_ld_scripts(main_ld_file):

    def _include_callback(match):
        incre = re.compile(r"^INCLUDE\s+\"?([^\.]+\.ld)\"?", re.M)
        included_ld_file = match.group(1)
        # search included ld file in lib directories
        for root, _, files in walk(join(FRAMEWORK_DIR, "lib")):
            if included_ld_file not in files:
                continue
            with open(join(root, included_ld_file)) as fp:
                #return fp.read()
                return incre.sub(r'_INCLUDE_ \1', fp.read())
        return match.group(0)

    content = ""
    with open(main_ld_file) as f:
        content = f.read()

    incre = re.compile(r"^INCLUDE\s+\"?([^\.]+\.ld)\"?", re.M)
    with open(main_ld_file, "w") as f:
        f.write(incre.sub(_include_callback, content))

Furthermore, I updated the platformio.ini to:

[env:disco_f072rb]
board = nucleo_f072rb_libopencm
platform = https://github.com/platformio/platform-ststm32.git
platform_packages = framework-libopencm3 @ https://github.com/libopencm3/libopencm3#master
framework = libopencm3
debug_tool = stlink
upload_protocol = stlink

platformio run fails with:

KeyError: "Invalid board option 'build.core'":
  File "/Users/bodokaiser/.pyenv/versions/3.8.1/Python.framework/Versions/3.8/lib/python3.8/site-packages/platformio/builder/main.py", line 156:
    env.SConscript("$BUILD_SCRIPT")
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Script/SConscript.py", line 597:
    return _SConscript(self.fs, *files, **subst_kw)
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Script/SConscript.py", line 286:
    exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals)
  File "/Users/bodokaiser/.platformio/platforms/ststm32@src-15e0e87f41a00aa2f9602f71367ac29c/builder/main.py", line 98:
    target_elf = env.BuildProgram()
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Environment.py", line 219:
    return self.method(*nargs, **kwargs)
  File "/Users/bodokaiser/.pyenv/versions/3.8.1/Python.framework/Versions/3.8/lib/python3.8/site-packages/platformio/builder/tools/platformio.py", line 61:
    env.ProcessProgramDeps()
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Environment.py", line 219:
    return self.method(*nargs, **kwargs)
  File "/Users/bodokaiser/.pyenv/versions/3.8.1/Python.framework/Versions/3.8/lib/python3.8/site-packages/platformio/builder/tools/platformio.py", line 118:
    env.BuildFrameworks(env.get("PIOFRAMEWORK"))
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Environment.py", line 219:
    return self.method(*nargs, **kwargs)
  File "/Users/bodokaiser/.pyenv/versions/3.8.1/Python.framework/Versions/3.8/lib/python3.8/site-packages/platformio/builder/tools/platformio.py", line 330:
    SConscript(env.GetFrameworkScript(f), exports="env")
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Script/SConscript.py", line 660:
    return method(*args, **kw)
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Script/SConscript.py", line 597:
    return _SConscript(self.fs, *files, **subst_kw)
  File "/Users/bodokaiser/.platformio/packages/tool-scons/script/../engine/SCons/Script/SConscript.py", line 286:
    exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals)
  File "/Users/bodokaiser/.platformio/platforms/ststm32@src-15e0e87f41a00aa2f9602f71367ac29c/builder/frameworks/libopencm3/libopencm3.py", line 147:
    if board.get("build.core") == "tivac":
  File "/Users/bodokaiser/.pyenv/versions/3.8.1/Python.framework/Versions/3.8/lib/python3.8/site-packages/platformio/managers/platform.py", line 795:
    raise KeyError("Invalid board option '%s'" % path)

Can it be that we are missing a core property in the build block of ~/.platformio/boards/nucleo_f072rb_libopencm.json?

nucleo_f072rb.json vs disco_f072rb.json is a mistake on my side. Better use disco_f072rb.json.

And as for the error:

In the board definition within the build block, add:

"core": "stm32"
2 Likes

Now it works! Thank you very much :slight_smile:

I summarized the changes in this gist for others.