Portenta H7: BSP and CubeIDE project

If you ask like me:
"is there a (C-code) BSP? How to setup a CubeIDE project for it? How to have a full Open Source project (to see and manage every single line of code) ..."
and you do not find, you do not get any answer (like me, or as "Arduino does not provide"),
here is my project to share.

It is (links to download below):

  • a full Open Source project (every single line of code as source code, including PMIC configuration, INT vector setup, startup code,. SDRAM config, SDCard config, ETH Network config ...)

  • It is a native C-code project (not any C++ code, not using any "foreign" LIB)

  • it is for STM CubeIDE, with CMSIS RTOS V2, FatFs, LwIP, STM USB Device middleware

The entire source code provides these features:

  • configure the PMIC on board and set it to 3.3V (instead of 3.0V)

  • an UART via USB-C (use TeraTerm)

  • it has a command interpreter on UART (or via network), use "help" first to see which commands are there

  • it initializes, uses and supports: ETH network (not WiFi) - with a web page (HTTPD server running), SDRAM (right now just for testing if bit error free usage), SDCard - for displaying root directory, printing files, creating/writing/deleting a text file, execute a text file as commands (for command interpreter = like a "shell program" executed)

  • Web Server (HTTPD, for web browser), Python command interface via network (send commands from Python scripts), TFTP in order to transfer files to/from SDCard via network TFTP protocol ...

  • SPI, I2C - as user or to recover another Portenta H7 board (when bricked), GPIOs (In/Out,. not Interrupts)

Not used (yet) are: Crypto chip, WiFi/BT chip (no intention to use), QSPI flash memory (potentially I add and need in future)

ATTENTION:
This project (see linker script, BIN file) uses entire Flash space: it overwrites the Portenta H7 bootloader. You need an external debugger connected or use the BOOT1 option (DIP switch and use the STM bootloader instead of Arduino bootloader).
The Arduino bootloader will be overwritten (and is gone, but no worries: the board works fine w/o any Arduino stuff, you can still update and flash newer versions, even w/o a debugger - STM bootloader via BOOT1 is "your friend").

Project Links:
CubeIDE project as ZIP
CubeIDE project exported as archive

The related Python script to access board via (ETH) network:
Python script to access board, send commands via network

The BIN file:
ATTENTION: it has to be flashed from start of MCU flash (0x08000000): use debugger or BOOT1 option.
BIN file: flash it at 0x08000000

Commands
With UART terminal connected (TeraTerm, baudrate 1843200, or any should be fine) - via USB-C cable, enter command "help" to see list of all supported commands.

SDCard needs a command "sdinit 1" first, before you can access, you can do anything with SDCard (other commands). Also TFTP to transfer files to/from SDCard via network TFTP needs this command "sdinit 1" first.

Please, have fun and enjoy my "full Open Source Project" (even using some pieces from other projects, but every single line of code involved is visible to you - exactly what I have asked for or expected when using this board).

3 Likes

Hey tjaekel,
First of all thank you for your great support about using portenta with stm32CubeIDE.
As soon as I will read your project files and try to understand what you did. I really curious about PMIC configuration did you solve the problem which is ' Portenta does not run again when plugged off ? '. I mean this orange led problem :slight_smile:

Best regards, stay safe.

There are several threads on forum dealing with PMIC, the orange LED, e.g.

Yes, I understand what is going on and how to recover.
Orange LED on means: PMIC chip on board is not configured (e.g. no FW running, bootloader gone /overwritten etc.).
In order to recover: you need a second board with I2C and write via I2C registers in PMIC chip on broken board.

I have PMIC config in my project. I do it as the very first step (in main()), as early I can do. I think,
the PMIC powers on for a short period of time, but needs "immediately" a configuration.
Otherwise no power on board: measure the 3V3 pins. They should be 3.0V but when orange LED is on (PMIC goes into idle mode) - voltage is just 0.xxV.

I have in my project also a setting for 3.3V (not just 3.0V). And: a UART command to use I2C to a broken board and to "recover" (program) external PMIC chip on other board.

Thank you for your reply tjaekel,
I tried your PortentaH7_CubeIDE project on my portenta.After I upload your project on Portenta it look likes run normaly. I try to say if I plug off the Portenta and plug on again with usb-c cable it runs normally all time and I can debug Portenta again. ( what I want ) But on my projects portenta always breaks when i plug off. I have to erase all memory and flash arduino bootloader again for use portenta again. So I want to know what sould i do for basic configuration for portenta. Is this about PMIC configuration or something else ? In short I want only portenta runs normally when i plug off and on again :confused:

Great.
I have just some guesses about your issue:

  • your project might be linked to place code starting at flash start, 0x08000000. This overwrites the Arduino bootloader: you had to flash the bootloader again all the time.

  • your IDE uses a linker script where the code is placed on RAM: I see in my CubeIDE project two files created: "STM32H747XIHX_FLASH.ld" and "STM32H747XIHX_RAM.ld". So, make your sure your IDE uses for the linker the right script: if the code is linked to run on RAM: after every power cycle the code is gone and has to be reloaded again.

I suggest to check which linker script is used, how it looks like in terms where to place the code, or check the generated *.MAP file to get a clue where the code is located.
I assume: something wrong with the code location (on RAM or overwriting bootloader).

BTW:
I have changed my linker script to keep using the Arduino Bootloader: it loads the code at 0x08040000 and the DTCM RAM has space reserved for the INT Vector table (with bootloader the vector table is relocated to 0x20000000).

I have uploaded my project BIN file to work/use the Arduino Bootloader here:
My project BIN files to flash and run with Arduino Bootloader

Part of my linker script looks like this (see comments to toggle between with vs. without Arduino Bootloader):

/* Memories definition */
MEMORY
{
  FLASH   (rx)   : ORIGIN = 0x08040000, LENGTH = 2048K - 0x40000    /* with Arduino Bootloader: Actual start is 0x08000000 and actual length is 2048K */
  DTCMRAM (rwx)  : ORIGIN = 0x20000000 + (((166 * 4) + 7) & 0xFFFFFFF8), LENGTH = 128K - (((166 * 4) + 7) & 0xFFFFFFF8)
  /* FLASH   (rx)   : ORIGIN = 0x08000000, LENGTH = 2048K */
  /* DTCMRAM (rw)   : ORIGIN = 0x20000000, LENGTH = 128K */
  RAM_D1 (rw)    : ORIGIN = 0x24000000, LENGTH = 512K	/* MPU config */
  RAM_D2 (rw)    : ORIGIN = 0x30000000, LENGTH = 288K	/* MPU config */
  RAM_D3 (rw)    : ORIGIN = 0x38000000, LENGTH = 64K
  BACKUPRAM (rw) : ORIGIN = 0x38800000, LENGTH = 4K
  ITCMRAM (xrw)  : ORIGIN = 0x00000000, LENGTH = 64K
  SDRAM (rw)     : ORIGIN = 0xC0000000, LENGTH = 8M
}
1 Like

I am done here.
My project with Pico-C works.
More details here:
Portenta H7 CubeIDE project with Pico-C

Good bye.

Hi
The link provided in the url is not available anymore.
Is it possible to receive a copy of it?
Thanks in advance
King regards

Yeaah, my web site is down (because my provider is too restrictive with traffic).
Please find here:
tjaekel Portenta H7 GitHub

I ordered an STM32H747I-DISCO to try with Cube and ThreadX.

I got confirmation that Arduino have no plans to implement MIPI/DSI interface, and I think if you want the application to look really professional, that is required.

Might reserve the Arduino side for reading the sensors, and the Cube side for the Ethernet, GUI side.

Might be good for a future version 2 of the project.

BTW: I use NUCLEO-H745ZI-Q (also the Dual Core version as Portenta H7) and NUCLEO-H743ZI2 boards (with STM32CubeIDE). If you need help ...
Also a STM32H735 Discovery Kit (single core CM7, with 550 MHz (fastest MCU speed), but not touched yet.

Was supposed to come today, but board stuck in Winnipeg :frowning:

I am curious to try ThreadX.

The board has am arduino interface on the bottom, so I can use something like a Sparkfun Artemis board - 96 MHz - to run the Arduino stuff, like the sensor reads, and the board would run the Web Server, data storage, MQTT and modbus - I saw no modbus libraries anywhere, but they say their NetXDuo is BSD compatible, and it seems libmodbus is using a BSD library, so maybe would not be hard to compile it.

The graphics look very nice.

I will save this board as a version 2.0 of the project.

The Nucleo boards have a very appealing price.
(On the side - my crashing issues seem to be getting resolved - 3 boards running - combined total of 26 days - with no crashes - only problem is that I made very few changes in the code to account for it).

Does using this linker script mean that only the M7 core can be used since all the flash memory is being used for the M7 core?

When you build a project where both cores are running (CM7 and CM4) - they are quite separated: each project is like a standalone project (for one core), with its own linker script.

So, you have to make sure that one linker script, e.g. the one for CM7 does not use all flash memory. Some space (a region) is excluded. The other linker script (for CM4) does the "opposite": it uses the excluded CM7 space as CM4 for code (and RAM) and excludes to use the CM7 memories.

So, two linker scripts, well designed, to give each core their dedicated memories. Example is: you split the 2MB flash (code) memory into two half, so that CM7 uses one half, the CM4 the other half.

You have to consider also the bootloader, e.g. where to place the vector table. CM7 and CM4 have their own vector table and the entry point is fix defined (by the bootloader and the CMx vector table base address).

If you never enable the CM4 - ATT: there is a fuse bit in MCU which can be set if CM4 should boot as well or not (not just released by CM7) - you can assign all memory to the single core (CM7) just running this as a single-core system.

If both cores are running - they have their own memory regions, defined via the linker scripts (two!) whereby the assignment of the memories is like "exclusive" (available for one or the other, via the linker scripts, but shared memories are also possible).

Just look at the linker scripts and you will see how the code region is defined ("mutual exclusive").

I did the same thing for the Arduino Nicla Vision, if I erase the bootloader and program the board from 0x8000000, it works perfectly, FreeRtos, I2C, SPI, etc. But if I keep the bootloader and change the linker script, it does nothing once I upload it.
Any ideas what might be the problem?

What do you mean?
Yes, for me as well: with Arduino Bootloader and flashing your FW (starting at 0x08040000) - hangs in Arduino Bootloader (I had to press Run twice, debugger disconnects, board needs a power cycle).

Here, how I use it:

  • generate project for debugging, starting at 0x08000000 (from start, without Arduino bootloader):
    now all works fine, I can flash with (external) STLINK-V3 debugger, debug, step through code etc.
  • when all is fine:
    • flash back the Arduino Bootloader (0x08000000..0x08040000)
    • and modify project Linker Script to start at 0x08040000
      Now, I can still flash the new FW with STLINK-V3 (starting at 0x08040000) but the debugging does
      not work anymore!:
  • after flashing FW, the MCU boots but enters the Arduino Bootloader
  • there is an INT fired and the debugger stops there - press Run again
  • when I press again Run - the FW seems to run but the debugger disconnects (no way to have breakpoints or to step through the code)
    Also: often, the reboot after FW flash with STLINK-V3 is stuck in Arduino Bootloader: I have to power cycle the board. Also: often you have to wait at least 10 seconds before you can plug in the USB again (the Arduino Bootloader uses the RTC registers which are not reset and a power cycle has to be long enough so that the status info disappears there).

When Arduino Bootloader is flashed again: you can also flash the new FW with Arduino dft-util.exe tool (instead of using STLINK-V3 connected).

The Arduino Bootloader (when flashed) interferes with STLINK-V3 as debugger. So, I debug my project without using Arduino Bootloader (all native from 0x08000000), later I modify Linker Script again and flash Bootloader back and the FW.

Just to bear in mind:
have a copy of the Arduino Bootloader (in MCU board); read it and save it from a virgin Portenta H7 board (the code on 0x08000000..0x08040000). So, you have the Arduino Bootloader saved and you can re-flash with STLINK-V3 it again.

Just be careful: it happens sometimes that my entire Portenta H7 seems to be bricked: the orange LED (from PMIC chip) comes on. In this case - it might be tricky to recover (the PMIC chip has to be configured via I2C from another board).
So, a good advice is also: when entire system works, with Arduino bootloader and your FW - save the entire flash memory into a file: 0x08000000, length 0x02000000 (the entire 2MB). Potentially, on a bricked board - you flash all back and it recovers.
You might need a real power cycle, long enough (approx. 10 sec) and the board should be back (but after flashing with STLINK-V3 and doing a reboot - the FW might not be entered, still hanging in Arduino Bootloader).

1 Like

Nothing, I load the bootloader onto the board, change the linker script for the cm7 core to start at 0x8040000, create the bin and load it with dfu-util, nothing happens, I tried the long power cycle and still nothing.

Im working with the Arduino Nicla Vision, I have the bootloader, and I know how to recover the board in case of a error. Is just that when I try loading the code via dfu-util, it just doesnt do anything, I can still press the reset button twice and enter the board on dfu, is just that the code doesnt do anything after loading it.

Several reasons:
a) are you sure there is the Arduino Bootloader?
(or have you overwritten once with a FW starting at 0x08000000)
When you press Reset 2x quickly - you should see a green fading blinking LED. If not, do a very
quick power cycle on USB-C.
If you do not get a green fading LED - you do not have the Arduino Bootloader (in MCU, not running)
b) if your FW has a bug and crashes right on startup of your own FW - nothing happens

Actually: if the Arduino Bootloader is there - you should be able to flash MCU with new BIN file using the dft-util.exe (and CMD line). If this fails - no Bootloader in MCU.
If this works, but your FW does not do anything - a bug in your FW (your FW crashes).

Your FW is wrong (and crashes).
Make sure, when you build your FW project, YOUR FW starts at 0x08040000.
My linker script I use:

MEMORY
{
  /* with Arduino Bootloader */
  FLASH   (rx)   : ORIGIN = 0x08040000, LENGTH = 2048K - 0x40000    /* with Arduino Bootloader: actual start is 0x08000000 and actual length is 2048K */
  DTCMRAM (rw)   : ORIGIN = 0x20000000 + (((166 * 4) + 7) & 0xFFFFFFF8), LENGTH = 128K - (((166 * 4) + 7) & 0xFFFFFFF8) /* with Bootloader */
  /* without Arduino Bootloader - native, for debug */
  /* FLASH   (rx)   : ORIGIN = 0x08000000, LENGTH = 2048K	/* without Bootloader */
  /* DTCMRAM (rw)   : ORIGIN = 0x20000000, LENGTH = 128K	/* without Bootloader */
1 Like

Maybe your FW uses the DTCRAM also needed a bit for Bootloader?
Maybe your Linker Script generates code "somewhere" which would overwrite code/data needed to be untouched when Bootloader is in MCU?

1 Like

Create a very simple project, e.g. "blinky" with Arduino IDE. Load this one. If it works, but your FW does not - find the "bug" in your FW.

If all this does not help: if you have a full STM32 HAL project for this Portenta H7 (with the PMIC configuration!!!!) - build for start address 0x08000000 and use external STLINK-V3 (to flash and debug). Find the bug in your FW with STLINK-V3 debugger...
Change back to flash Arduino Bootloader and your FW at 0x08040000.

Watch, if you get an orange LED (on PMIC chip): if you see it - your board is bricked.