So I just wrote
memset(NULL, 0xcc, 2048);
on purpose, expecting it to actually do something. Does that make me a horrible person?
(backstory: debugging ITCM initialization code, STM32H7 ITCM is mapped starting at physical memory address 0x00000000)
This is IMO a terrible idea, because it means that buggy code that tries to write to a null pointer is going to scribble over executable SRAM rather than crashing hitting an unmapped address.
Anyway, the 0xcc's are intact and my firmware is still crashing so the bug is elsewhere, not memory corruption.
Root cause appears related to init of . data and/or calling global constructors. Having anything in .tcmtext seems to bork it.
This will be fun to debug.
Ok not quite. It looks like the actual problem is .rodata getting placed by the linker in ITCM.
Which makes no sense and it's not being initialized as a result.
So the first time I call a virtual function it crashes because it's trying to dereference a vtable that's not there.
So now the question is, how did the changes I made to my linker script to support code-in-itcm make it mis place .rodata...
Looks like I was emitting .rodata but not .rodata.* so some of the segments weren't ending up in the right spot.
Next problem, everything works until the first time I *call* a function in ITCM at which point it segfaults.
And that's fixed. My linker script had some padding added inside, rather than outside, the symbols I was using to determine bounds of TCM so start code was copying padding over to where the functions were supposed to be.
I now have the IPv4 checksum function happily executing out of ITCM and will play around later to try and get a bunch of the hot code moved in there.