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: Arduino_Core_STM32/variants/STM32F4xx/F446Z(C-E)(H-J-T) at 2.0.0 · stm32duino/Arduino_Core_STM32 · GitHub.

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 GitHub - stm32duino/Arduino_Core_STM32: STM32 core support for Arduino.

I’m not sure where you go from here I’m afraid, unless you want to add your own variant? Details at Add a new variant (board) · stm32duino/wiki Wiki · GitHub 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: GitHub - maxgerhardt/nucleo-f446ze-with-arduino

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

First off excellent job this was instrumental in helping me get my custom code running on the board. However, I can’t get any communication off the board when boot 0 isn’t jumped out. Is there something I’m missing? Is there a way to get a serial output out of the USBC header? Please forgive me if I’m missing something simple I’m very new to arm boards GitHub - c3charvat/STM32F446ZETb_PlatformIO_Install at master
I did update the platform.ini with the USB-c pins feel like I’m still missing something.

Are you using the Octopus or some other board? The serial works fine on USB C with my octopus board.

You write

But nowhere in your repo is that file.

Edit: I can’t compile your project because

Error: Unknown board ID 'genericSTM32F446ZE'

your project doesn’t have a boards folder with the genericSTM32F446ZE.json definition (my original one is here). You should avoid modifying your local <home>/.platformio/platforms/ststm32/boards folder these purposes, the definition can be put in the project.

Also your project contains 9 .ino files. Try to only do the most minimal main.cpp code to check whether basic things like USB serial work, don’t put 9 million functions an 3 libraries in the first test firmware.

Especially regarding USB: As said above I’m pretty sure you need to setup the clocks (USB peripheral clock) from an external crystal (HSE), not HSI, and a clock initialization function in the firmware. I see you have the latter, but then you also need to make sure you’re building for the octopus enviornment and not the octopus_minimal environment which uses the HSI.

1 Like

Ive moved the boards folder and your .jason into the repo. I’ve only been using PlatformIO for 2 weeks now, the documentation wasn’t super clear that i could define boards within the project.

I got an extension, that watches the serial port instead. The issue is the PlatformIO monitor tires to connect before I can even get the board out of boot0, thus there was no COM port to connect to. On top of that send_on_enter flag seems to be broken for me which makes the monitor useless as the entire project is based on strings.

You are correct, I am using HSI, and a clock config and compiling in the octopus environment. I’m a little confused on “setup the clocks (USB peripheral clock) from an external crystal (HSE)” If there is a resource i could read up on or example to look at I will under stand more of what’s going on. Please do forgive me this is my first time taking on anything nearly this advanced.

A little background on what I’m doing: I’m writing a motion control firmware for my senior design project (As a mechanical engineer), I choose Arduino because it is easy, and the team that works after me has to be able to read and modify the code. This is also my first time implementing my knowlage of C outside the classroom, I’m learning everything on the fly. I just ordered a Black Magic probe the other day.

I am using the octopus board. The issue im having is the monitor tries to connect before i can even get the board out of boot0 from flashing the firmware.