Nucleo_f446ze does not support Arduino framework. Looking for advice

Hi @maxgerhardt,

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

@zouden My apologies. :frowning_face:

Cheers,
Norm.

@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": [
  [
    "0x0483",
    "0xDF11"
  ]
 ]

(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)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------CONFIGURATION: https://docs.platformio.org/page/boards/ststm32/genericSTM32F446ZE.html
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)
PACKAGES:
 - 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 -> http://bit.ly/configure-pio-ldf
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
Edit:
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

@maxgerhardt
Max,
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.

Uploading and monitoring can be two seperate project tasks. If you look at PlatformIO IDE for VSCode — PlatformIO latest documentation you can first click “Upload”, then see if that worked, then reseat the jumpers and reset if you have to, then press “Monitor”.

However, after the DFU upload, actually shouldn’t need to reset the board’s BOOT0 jumper, the bootloader should automatically reboot the device to run the firmware.

That does not happen, I get nothing on my LCD until I Undo Boot0, and press the reset button.
Edit: After pressing the reset button and undoing Boot0 all is well and my code runs as i want it to.

Yes, the monitor does work. I put a delay in my code to give me enough time to reset the board and connect before it starts.

Hm that’s weird :confused:

You should be able to replace the static delay with a

while(!Serial) {}
delay(100); //just a bit of safety delay

expression. (overloaded boolean operator on the Serial object returns whether someone actually established a USB connection).

When STM32Duino successfully runs on the board with the USB-serial, can you try uploading without re-setting into bootloader mode through BOOT0? I think STM32Duino implements a reset-to-bootloader-via-1200bps-Serial-open method.

Otherwise it sounds like you got it running succesfully on the board.

Update, you got me thinking:
I was using an actual jumper on boot0 / a little breadboard switch i made.
I just switched that out for a pushbutton, pressed it, and the reset button.
Then let go (and uploaded) and it booted right into the code. I was taking jumping out boot zero too literally. It just has to be jumped when the reset button is pressed.

Yes it is running. Thank you so much for this thread i honestly you enabled this whole project to get off the ground.

Here is a flow chart of my new process:
Boot0 pressed (held) → reset button pressed → boot0 released-> upload (works) → board goes right into code.
Results: Monitor works, other than the send on enter.
If i try to upload again without, Pressing Boot0 and repeating the cycle it fails to upload. That is expected correct?

I cant thank you enough for this, this board is honestly the only thing that can run our project cost effectively. You will most certainly be mentioned in the special thanks. I really appreciate the help.

1 Like