Hill climbing the new BSP learning curve

Hi Everyone, I’m in the process of developing an understanding of the structure and building of BSPs. My eventual goal is to build one for the NRF8340 but for now I’m just trying to get my feet wet.

Since there already exists an Cortex-M33 BSP for the STM32U5 I thought I would start there (I also have the STM32U5-Discovery board so I can test on it). So this is what I’ve done, and questions about how things should actually work.

The only ‘board’ associated with the stm32u5 is the stm32u5-grisp-nano so I looked and found it in the specs\bsps\arm\stm32u5 directory. I copied it to a new file called stm32u5-discovery.yml and then did a manual build with waf first by creating a config.ini that said that was the BSP I wanted. I also added STM32U5_CONSOLE_ENABLE_USART1 = True as the discovery board puts
, then ./waf configure --prefix=$HOME/bin/rtems/7 which worked and finally ./waf install which built a bunch of files and installed them in $HOME/bin/rtems/7/arm-rtems7/stm32u5-discovery/lib. Seems like progress.

Then, following the documentation I created a new top level directory for my hello world application, and asked waf to configure it for using the arm/stm32u5-discovery
It also seems to have worked, and I generated hello.exe so now to attach my black magic probe (OpenOCD doesn’t know about the STM32U5-Discovery yet) and see if I can load it and debug it.

And its close, but not quite there yet. gdb(1) reports the following:

(gdb) attach 1
Attaching to program: /freenas/home/cmcmanis/arm-experiments/projects/rtems-projects/hello/build/arm-rtems7-stm32u5-discovery/hello.exe, Remote target
0x080002ea in stm32u5_memory_flash_begin ()
(gdb) load
Loading section .start, size 0xd90 lma 0x8000000
Loading section .text, size 0x14954 lma 0x8000dc0
Loading section .init, size 0xc lma 0x8015714
Loading section .fini, size 0xc lma 0x8015720
Loading section .rodata, size 0x224c lma 0x8015730
Loading section .ARM.exidx, size 0x8 lma 0x801797c
Loading section .eh_frame, size 0x4 lma 0x8017984
Loading section .tdata, size 0xc lma 0x8017988
Loading section .init_array, size 0x4 lma 0x8017994
Loading section .fini_array, size 0x4 lma 0x8017998
Loading section .rtemsroset, size 0x74 lma 0x801799c
Loading section .fast_data, size 0x8 lma 0x8017a10
Loading section .data, size 0x888 lma 0x8017a18
Start address 0x080007c0, load size 98924
Transfer rate: 67 KB/sec, 883 bytes/write.
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /freenas/home/cmcmanis/arm-experiments/projects/rtems-projects/hello/build/arm-rtems7-stm32u5-discovery/hello.exe 

Program received signal SIGTRAP, Trace/breakpoint trap.
bsp_start_vector_table_end () at ../../../bsps/arm/shared/start/start.S:597
597             ldr     sp, =_ISR_Stack_area_end
(gdb) 

So missing _ISR_Stack_area_end which suggests to me that perhaps the linker script or Start.S needs some attention.

And the plot thickens. The symbol _ISR_Stack_area_end is defined in the shared startup file ../arm/share/start/start.S but that file only defines it if armv7m is defined, which it isn’t perhaps because the Cortex-M33 is an Arm v8M device. So I’m wondering how the stm32u5 BSP could ever work if it doesn’t include v8m support?

@AndreiC any advice here? I’m out of place I know nothing about STM haha.

I’ll do a stream of conciousness thing and we’ll see if anything pops out.
STM32U5 Discovery board uses a… U585AI processor (unless you’ve got one of the boards with the round displays, in which case chime in).

The U585AI is a top of the line 585 with 2MB of Flash and 786KB of RAM with ALL of the pins (169), so a good choice for hacking around on. You’re not likely to run out of Flash/RAM/pins/peripherals before running out of project.

First, check your linker file. You should have 2MB based at 0x0800 0000 (RX).
RAM is in 4 blocks.
SRAM1 - 192K @0x2000 0000
SRAM2 - 64K @
SRAM3 - 512K @
SRAM4 - 16k @
plus battery backed RAM
BKPSRAM - 2K @

Hold on a FLASH, I’ll just fire up CubeMX, generate a project for U585 and have it generate a linker file for me.

MEMORY
{
  RAM	(xrw)	: ORIGIN = 0x20000000,	LENGTH = 768K
  SRAM4	(xrw)	: ORIGIN = 0x28000000,	LENGTH = 16K
  FLASH	(rx)	: ORIGIN = 0x08000000,	LENGTH = 2048K
}

So SRAM1-3 are all contiguous, and SRAM4 is special and is used for DMA when the processor is stopped.

You’re program blanks while loading the stack pointer with the initial stack pointer.

ST uses:

_estack = ORIGIN(RAM) + LENGTH(RAM);	/* end of "RAM" Ram type memory */
_sstack = _estack - _Min_Stack_Size;

The end of the stack is calculated with ORIGIN(RAM) would be 0x2000 0000, and LENGTH(RAM) would be 0x000C 0000. So the end of the stack would be 0x200C 0000, which should be the end of RAM.
The start of the stack is the end of stack minus 0x400 bytes (as configured in CubeMX).
They just allocate a stack space of 0x400 bytes but never check for overflows.

So, what do I think? The U585 has a memory protection unit that will KLANK the processor if you stray outside of the known memory regions. So I’d look at _ISR_Stack_area_end (or equivalently, the value stored at location 0x0800 0004) and make sure that it is not zero and it IS something like 0x200C 0000.

I am not going to add anything part specific to the great post from @Andrei.

Going back to your first post, I wanted to save you a little bit of effort. You can enable the RTEMS sample tests in the ini file. This is a small number of tests which are sufficient to get a BSP to the basic functioning. There is hello for basic startup and printing and ticker which has four tasks with three doing varying delays. It is good for getting a working clock tick and rough idea that it is correct. By that I mean the test tasks blocked for 5, 10 and 15 seconds. If they run much faster or much slower, you usually have a divider or rate programmed wrong.

Anyway using the samples will save you from doing the install and having your own externally built test to do a clean and build on.

Hi Joel, I tried enabling the sample tests in the ini file and waf said

Unknown configuration option             : RTEMS_SAMPLES

I was using the line from the example in the documentation RTEMS_SAMPLES = True for the configuration file.

This is all correct, I went back and tried to figure out if it built correctly. So doing an objdump -t on hello.exe says:

20003660 g       .rtemsstack    00000000 _ISR_Stack_area_end

That’s a somewhat “reasonable” hex value (at least it is in RAM) (I agree it should be at the end of RAM but at least that shouldn’t do a bus fault). And in the gdb session after loading the file it says:

(gdb) print/x (uint32_t)_ISR_Stack_area_end
$3 = 0x9896800

Which is not a reasonable value, but the registers are:

(gdb) info registers 
r0             0x0                 0
r1             0x0                 0
r2             0x0                 0
r3             0x0                 0
r4             0x0                 0
r5             0x0                 0
r6             0x0                 0
r7             0x0                 0
r8             0xffffffff          -1
r9             0xffffffff          -1
r10            0xffffffff          -1
r11            0xffffffff          -1
r12            0xffffffff          -1
sp             0x20003660          0x20003660 <SystemCoreClock>
lr             0xffffffff          0xffffffff
pc             0x80007c0           0x80007c0 <bsp_start_vector_table_end>
xpsr           0xf9000000          -117440512
fpscr          0x80                128
msp            0x20003660          0x20003660 <SystemCoreClock>
psp            0x0                 0x0
primask        0x0                 0 '\000'
basepri        0x0                 0 '\000'
faultmask      0x0                 0 '\000'
control        0x0                 0 '\000'
(gdb)

Which shows the MSP has the “correct” value (which it should because the start of the exception table has that value:

(gdb) print/x *(uint32_t *)(0x08000000)
$4 = 0x20003660
(gdb)

So something very weird is going on. Dumping symbols shows only the one definition so I don’t think there is a masked symbol in start.S. So I’m wondering if arm-rtems7-gdb is doing some sort of symbol munging on load? I don’t know.

And for what its worth, its not easy reconstructing what the actual linker file is from what RTEMS provides. I may be able to do that manually by following all the includes, but as I mention above it seems to have some things in the right places (if not optimally for the amount and types of memory that are available)

If the build generates it, it should be under the build directory.

It apparently doesn’t generate it. It appears that it always tells the linker to use the script linkcmds (although even that isn’t in the cache of stuff defined for builds). I say ‘appears’ because if you look at <bsp name>/lib/linkcmds it includes other files from the lib directory and apparently builds a linker script from all of those. In the case of the stm32u5 BSPs that gives you a pretty weird but functionally complete (albeit without the ability to specify which variant of the stm32u5 you are using (needed to tailor the script to the precise memory limits). If I can get things working I send a PR to fix that.

Also linkcmds.base in this BSP had this not-so-helpful bit:

   /* FIXME */                                                                                    
    RamBase = ORIGIN (REGION_WORK);                                                                
    RamSize = LENGTH (REGION_WORK);                                                                
    RamEnd = RamBase + RamSize;                                                                    
    WorkAreaBase = bsp_section_work_begin;                                                         
    HeapSize = 0;

That’s gonna be an issue too. But it does helpfully say “Fix me” :smiley:

The post on linkcmds in Documentation was super helpful.

1 Like

Remember I’m new at RTEMs and BSPs but not at doing embedded development (especially on the STM32 series). So with that in mind…

Since I could load the code with gdb and poke around I realized things were not adding up. I verified that the code loaded into memory matched the various segments in the ELF file so I knew gdb, blackmagic (the same code that runs in the probe but running as an application server), and the discovery board were all in agreement. And just to be sure I put together a quick test with libopencm3 and my console test program I’ve used on various boards and that worked flawlessly so it was something else. Reloaded my hello world and started using the gdb step command…

Okay so I could step though, and watch the system boot up through the startup code. The BSP was initializing the Octospi which wasn’t really necessary for me but didn’t hurt either (the Grisp Nano which was the BSP that is in there uses the Octospi for RAM). So this thing runs until it gets to _Context_Switch in ../../../cpukit/score/src/threaddispatch.c (line 309). That’s RTEMs code not BSP code.

Okay, bringing this to a close and using

./waf bspdefaults

And capturing the output into a file so I could just look at my BSP, several things became clear, the first being that the option for getting the samples built was
BUILD_SAMPLES = True
And enabling USART1 wasn’t enough I also had to make it the ‘printk’ device. Final config.ini looks like this:

[DEFAULT]
RTEMS_POSIX_API = True
RTEMS_SMP = False

[arm/stm32u5-discovery]
BUILD_SAMPLES = True
STM32U5_PRINTK_INSTANCE = stm32u5_usart1_instance
STM32U5_CONSOLE_ENABLE_USART1 = True

Then doing a ./waf configure --prefix=<my rtems prefix> followed by a ./waf build and ./waf install and voila, I could use gdb to load build/arm/stm32u5-discovery/testsuites/samples/hello.exe and when I ran it got:

RTEMS version: 7.0.0.a241e49bda7e41342af7da22229647e2d606360c
RTEMS tools: 15.2.0 20250808 (RTEMS 7, Build 2026.03.04, RSB 96b1831ff22a49672cebdf16abc731219232ff09, Newlib a7c61498)
executing thread ID: 0x0a010001
executing thread nam

*** BEGIN OF TEST HELLO WORLD ***
*** TEST VERSION: 7.0.0.a241e49bda7e41342af7da22229647e2d606360c
*** TEST STATE: EXPECTED_PASS
*** TEST BUILD: RTEMS_POSIX_API
*** TEST TOOLS: 15.2.0 20250808 (RTEMS 7, Build 2026.03.04, RSB 96b1831ff22a49672cebdf16abc731219232ff09, Newlib a7c61498)
Hello World

*** END OF TEST HELLO WORLD ***


[ RTEMS shutdown ]

So yay! Now I’ve got a BSP that works (caveat the linker script needs improving) and sample programs that can run on the STM32U5-Discovery board.

1 Like