PlatformIO Community

Nucleo_f446ze does not support Arduino framework. Looking for advice

Here is the boards page on the f446ze. The arduino framework isn’t mentioned there, and indeed I’m unable to create a project using it.

Why is this? The f446ze Nucleo board is advertised as Arduino compatible. A similar MCU, the f446re, which differs only by the pin count, is supported by PlatformIO with arduino.

BTT uses the f446ze in their Octopus 3D printer controller, which runs Marlin, a PlatformIO project. It appears they are using a custom board definition.

I have Octopus board and I want to write Arduino code for it. I am tempted to use the Marlin platformio project as a skeleton and add my own code. Is this the best way to proceed?

Hm but the F446ZE variant supported by the Arduino STM32 core:

One can use the custom Arduino varaint that Marlin uses, but it’s cleaner to use the official STM32Duino core. All it needs is a bit of a different board definition. Let me write one.

It is advertised (by ST) as being Arduino *connectivity" compatible! (NUCLEO-F446ZE - STM32 Nucleo-144 development board with STM32F446ZE MCU, supports Arduino, ST Zio and morpho connectivity - STMicroelectronics) not that it is Arduino software compatible.

The RE is, as you note, a Nucleo-64 while the ZE is a Nucleo-144 and I’m wondering if there is a reason why it isn’t supported with the Arduino framework. I’m not as familiar with ST stuff as I am with Atmel, although I do have a Nucleo-64 in my board collection which is definitely Arduino compatible, software and connectivity.

I’ve checked oout the list of supported Nucleo-144 boards in the Arduino IDE (STM32duino) and yours is not listed on the supported boards list at

I’m not sure where you go from here I’m afraid, unless you want to add your own variant? Details at if so.

Sorry. :frowning:


Thanks to both of you for your replies. It looks to me that STM32duino does support the F446ZE, but they haven’t updated the readme file to reflect it. This then led to platformIO not building in support for it.

@maxgerhardt, thank you for the offer to write a board definition. It is greatly appreciated!

Hi @maxgerhardt,

Interesting. It appears that, once again, I stand corrected!

@zouden My apologies. :frowning_face:


@NormanDunbar no need to apologise at all- you found the stm32duino docs which (incorrectly) shows the board isn’t supported. I think that explains why PlatformIO didn’t support it.

I’ll raise a github issue to let them know.

1 Like

Can you try this example:

It’s basically a genericSTM32F446ZE definition derived from the other generic board definitions plus the info from the Nucleo F446ZE info, plus referencing the STM32F4xx/F446Z(C-E)(H-J-T) variant from the STM32Duino core. Also needed a linker script (generated by STM32CubeMX) since otherwise there’s an error that there’s no ldscript.ld in the variant folder.

The pins for UART and LED should be correct, looked up from mbed-os and STM32CubeMX.

Let me know if that example is flashable & blinks the LED & outputs something to the serial monitor.

Thanks so much for this. I’m not actually using a Nucleo board, but rather a 3d printer mainboard called Octopus. I’ve changed the LED pin to PA13. The code compiles, but I can’t upload it because it doesn’t have an STlink. I think I need to use DFU mode or copy the file to the sdcard, neither of which I’m able to investigate right now. I’ll return to this on Monday. Thanks again and have a great weekend.

Oh I see, I overread this.

After reading through the schematics I’ve expanded the example because that board definitley needs a different clock initialization function (12MHz crystal instead of 8MHz clock-in signal). There’s now an octopus environment in the platformio.ini for the board (selectable via the project environment switcher as always).

I’ve also added the build flags and code to use the USB serial by default (SerialUSB), redirected the UART output (Serial) to the pin header for the Raspberry Pi (has TX2 and RX2 on it), and changed the blink LED to PA13. Though you have to be careful with the PA13 pin when using an SWD programmer like an STLink to program the board, PA13 is also the SWDIO programming signal… if the firmware reconfigures that pin to be a GPIO output, you will probably need to connect the NRST line from the MCU to the programmer to and make it use a hardware reset (possibly needing a change in the OpenOCD board configuration), otherwise programming is possible.

And in fact the board features a standard USB-A USB-C connector (“USB2”) which is connected to the MCU. So, if you reset the MCU into bootloader mode (set the BOOT0 jumper and press reset once, USB-DFU open on USB pins PA11 and PA12 which goes to the USB-C connector), the MCU is flashable via its built-in USB DFU bootloader. PlatformIO also supports programming via that (upload_protocol = dfu in the platformio.ini, uses dfu-util). So, you should be able to upload a firmware via that, get the board to blink and get serial output via the USB Serial opened by the board, even without a SWD programmer.

Though if you want to live-debug the board, a SWD programmer is preferrable. Mind the PA13 caveat though.

Edit: Corrected USB pins – there are two USB connectors on the board, both go the MCU, but only the USB-C connector is used by the USB-DFU bootloader.

Edit 2: If USB DFU upload is not working, it may be due to wrong USB VID/PID information in the board manifest .The bootloader mode document only talks about the PID being 0x0421 for STM32F446xx devices, but not about the VID. Looking it up in a database reveals VID = 0x0483, but for DFU devices STM32CubeProgrammer autofills 0xDF11. The tuple may still be switched (PID / VID switched around), or the values might be wrong. Use the STM32CubeProgrammer and see if it can connect to the chip via DFU, and what VID/PID it shows.

Hi Max, thank you for all this effort. Your links to various documents are greatly appreciated.

I was able to get the board into DFU mode by applying the boot0 jumper and pressing reset. I had to install STM32cubeProgrammer to get the driver. The hardware is vid=0483&pid=df11, so I changed your json file to

  "hwids": [

(removing the other hwids entry, because it didn’t work otherwise). I was able to upload to the board successfully. I then removed the boot0 jumper and reset the board. Unfortunately the LED isn’t blinking, and no USB device is found (so there’s no Serial output).

I’m unsure how to proceed. I can get back to DFU mode and flash the code again, but it doesn’t seem like the board is executing the code. Commenting out the PA13 LED stuff (leaving only the SerialUSB printing) doesn’t make a difference, so I don’t think PA13 is causing a conflict.

Here is the verbose compile output, if it helps.

> Executing task: C:\Users\zouden\.platformio\penv\Scripts\platformio.exe run --verbose --environment octopus <

Processing octopus (platform: ststm32; board: genericSTM32F446ZE; framework: arduino; board_build.ldscript: STM32F446ZETx_FLASH.ld; build_flags: -DSERIAL_UART_INSTANCE=2, -DPIN_SERIAL_RX=PD6, -DPIN_SERIAL_TX=PD5, -DHSE_VALUE=12000000L, -DPIO_FRAMEWORK_ARDUINO_ENABLE_CDC, -DOCTOPUS_BOARD; monitor_dtr: 1; upload_protocol: dfu)
PLATFORM: ST STM32 (14.2.0) > STM32F446ZE (128k RAM. 512k Flash)
HARDWARE: STM32F446ZET6 180MHz, 128KB RAM, 512KB Flash
DEBUG: Current (stlink) On-board (stlink) External (blackmagic, cmsis-dap, jlink)
 - framework-arduinoststm32 4.20000.210603 (2.0.0)
 - framework-cmsis 2.50700.210515 (5.7.0)
 - tool-dfuutil 1.9.200310
 - toolchain-gccarmnoneeabi 1.90201.191206 (9.2.1)
LDF: Library Dependency Finder ->
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 11 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
MethodWrapper(["checkprogsize"], [".pio\build\octopus\firmware.elf"])
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [          ]   2.9% (used 3852 bytes from 131072 bytes) 
Flash: [          ]   4.4% (used 22964 bytes from 524288 bytes)
.pio\build\octopus\firmware.elf  :

section              size        addr

.isr_vector           452   134217728

.text               20564   134218180

.rodata              1896   134238744

.ARM                    8   134240640

.init_array            20   134240648

.fini_array             8   134240668

.data                 504   536870912

.bss                 3348   536871416

._user_heap_stack    1540   536874764

.ARM.attributes        48           0

.comment              102           0

.debug_frame         1360           0

Total               29850
========================================================================== [SUCCESS] Took 24.78 seconds ==========================================================================

Environment    Status    Duration
-------------  --------  ------------
octopus        SUCCESS   00:00:24.778

I see. Let’s eliminate some variables and make it minimalistic.

I’ve update the repo to incorporate the fix in the board definition. Additionally I overlooked some stuff in the linker script that the STM32Duino linker scripts do, and I’ve fixed those.

I’ve stripped down the code to do only LED flashing and replaced the clock init function with one that just starts up from the internal HSI oscillator, to eliminate problems when try to use the external crystal on the board. USB will not work with this, but it should be well enough to get the PA13 LED blinking.

Please re-download the linked example and switch to the octopus_minimal environment, then flash that via DFU.

If that still does not work, there might a be a problem with the DFU upload. Try building the project normally with PlatformIO, then feed the .pio\build\octopus_minimal\firmware.bin file into STM32CubeProgrammer and tell it to flash it to the standard 0x8000000 address in flash via DFU.

And if that still does not work, the only thing that can help is attaching a SWD debugger to see where exactly the microcontroller is struck. Debugging should work out-of-the-box with that board definition.

Oh and actually I’ve spotted an error in the previous “Boot Octopus board from 12MHz HSE” code that will have definitely stopped it dead in its track – the HSE was in bypass mode, not in crystal oscillator mode. It won’t have attempted to get the crystal swinging. That is now fixed.

If the octopus_minimal environment turns out to be working, try the octopus environment with the current code. If that still works, try adding back the SerialUSB.begin(115200); etc stuff.

Wow, it works! Both octopus_minimal and the main one works. I even have serialUSB working too.

Thanks so much for this! I definitely wouldn’t have been able to achieve this myself.

BTW I created a github issue a few days ago about the support for this MCU. Your input there would be valued as it sounds like they need the linker script that you created.

1 Like