cancel
Showing results for 
Search instead for 
Did you mean: 

Calling a virtual function seems to stop the execution of the MCU (Nucleo F446RE)

ECLEW.1
Associate III

I'm trying to port over a JUCE framework project (a wavetable VCO), and I'd like to test it on a Nucleo-F446RE that I got about a year ago.

My entire build system is a clone of this lady Emilie Gillet's code base that she used to build eurorack modules.  It's not quite HAL, and I guess not quite Bare Metal, but somewhere in between?

My repository is here.

https://github.com/eclewlow/eurorack/tree/master/waves2

I'm just porting over a little bit of code at a time.  One thing I ran into was virtual functions being called just causing the flow of execution to stop.  I don't think it's a hard fault, but the execution of the MCU definitely stops.

For example, in bootloader.cc

https://github.com/eclewlow/eurorack/blob/master/waves2/bootloader/bootloader.cc

void Init() { System sys; sys.Init(false); sys.StartTimers(); GPIO_ResetBits(GPIOA, GPIO_Pin_5); BufferAllocator allocator(shared_buffer, 16384); childA.Paint(); Engine* e = &childA; volatile size_t counter = 1000000; while (counter--); e->Paint(); // the execution reaches here and then stops, and the LED does not blink GPIO_SetBits(GPIOA, GPIO_Pin_5); } int main(void) { Init(); // after Init calls, infinitely blink once per second // If I call the virtual function e->Paint() in Init(), then // this following code will never execute. while (1) { if((system_clock.milliseconds() / 1000) % 2 < 1) { GPIO_SetBits(GPIOA, GPIO_Pin_5); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_5); } } }
View more

I'm a newb to compilers and linkers, so if there is an error there, I would have no idea.

I've been messing around with compiler and linker flags, and the linker script.

One thing I noticed was at first the vtable entries in the .map file were missing?  And it wasn't until I edited the linker script file did the vtables show up.  However, it didn't fix the issue.

https://github.com/eclewlow/stmlib/commit/c1e4fb1913e813cdc76abfb34ccc4ab5793ce8a3

https://github.com/eclewlow/stmlib/blob/master/linker_scripts/stm32f4xx_flash.ld

The .map file seems to show a vtable entry for each virtual function, and they are assigned to different spaces in memory.  Are the memory addresses somehow incorrect maybe?

*(.rodata) *(.rodata*) .rodata._ZTVN6waves26EngineE 0x0000000008000600 0x10 build/waves2_bootloader/bootloader.o 0x0000000008000600 vtable for waves2::Engine .rodata._ZTVN6waves26ChildAE 0x0000000008000610 0x10 build/waves2_bootloader/child_a.o 0x0000000008000610 vtable for waves2::ChildA .rodata._ZTVN6waves26ChildBE 0x0000000008000620 0x10 build/waves2_bootloader/child_b.o 0x0000000008000620 vtable for waves2::ChildB

I'm building the code on a MacOS Sonoma 14.5, with the arm-4.8.3 release, as recommended by Emilie.  Although, what's really recommended is building in a virtual machine, which I'm not doing.

2 REPLIES 2
TDK
Guru

When you debug the code and step through execution on that line, what happens?

If you feel a post has answered your question, please click "Accept as Solution".
ECLEW.1
Associate III

Thank you for your response.

So I don't know how to debug without CubeIDE, so I created a new CubeIDE project targeting my current Nucleo board.

There was no need to debug there.  The code runs fine.  The virtual function is called followed by blinking the LED.

I tried to dig around a little bit: checking out the makefile and linker scripts that are auto-generated by CubeIDE.  They are different than the build system I was using.

I'll just use CubeIDE.