2024-12-26 12:30 PM - edited 2024-12-26 01:01 PM
I'm using an STM32H747XI Discovery board for testing. I seem to have the opposite problem of everyone else, my DTCM value is NOT clearing upon losing power.
I have the following in my LD script:
MEMORY
{
...
/* Put NOINIT at the top of the DTCM block. */
NOINIT (rwx) : ORIGIN = 0x20000000 + 128K - 0x100, LENGTH = 0x100
...
}
...
SECTIONS
{
...
.noinit (NOLOAD) :
{
/* KEEP(*(*.noinit*)) */
*(.noinit*)
} > NOINIT
...
}
and in the code I have:
#define ENABLE_BLUSB_MAGIC 0xDEADBEEF
__attribute__((section(".noinit"))) volatile int g_iEnableBLUSB;
int main(void)
{
if (g_iEnableBLUSB != ENABLE_BLUSB_MAGIC)
{
...
g_iEnableBLUSB = ENABLE_BLUSB_MAGIC;
}
...
}
The first time I debug using STM32CubeIDE, g_iEnableBLUSB will not be the magic number, this is the correct behavior. I then disconnect and debug again, g_iEnableBLUSB will be the magic number; this is also the correct behavior. Now if I power off the board, wait some amount of time (waited over 10 minutes just to see), plug the USB back in to power up the board, it immediately behaves as if g_iEnableBLUSB matches the magic number (this is the incorrect behavior).
What am I missing here? Shouldn't that DTCM block (and the same for the SRAM blocks) go to random values upon chip power up?
Thanks - C-Coder
Solved! Go to Solution.
2025-01-01 02:27 PM
My guess: using __attribute__ in order to specify the location of the storage for a data variable seems to be slight different (at least I use it in a slightly different way):
Maybe: try to place the __attribute__ afterwards (not in front):
instead of:
__attribute__((section(".noinit"))) volatile int g_iEnableBLUSB;
try this:
volatile int g_iEnableBLUSB __attribute__((section(".noinit")));
But it does not explain really why g_iEnableBLUSB can be already initialized on a new power cycle.
Sorry, no idea.
2025-01-01 02:27 PM
My guess: using __attribute__ in order to specify the location of the storage for a data variable seems to be slight different (at least I use it in a slightly different way):
Maybe: try to place the __attribute__ afterwards (not in front):
instead of:
__attribute__((section(".noinit"))) volatile int g_iEnableBLUSB;
try this:
volatile int g_iEnableBLUSB __attribute__((section(".noinit")));
But it does not explain really why g_iEnableBLUSB can be already initialized on a new power cycle.
Sorry, no idea.
2025-01-01 02:50 PM
Another (not important) remark:
Chip designers use often the value "DEADBEEF" in RTL (chip) design to return a 32bit value if something goes wrong (e.g. bus error or memory location cannot be read - they let return "DEADBEEF" as a value).
Try a different Magic Key (not "DEADBEEF"), just to make sure.
Check with debugger if there is really this key "DEADBEEF" in the memory (dump the content of DTCM memory).
Is there a startup code running which initializes all the DTCM (with "DEADBEEF")? Where could the "DEADBEEF" come from on startup?
Do you use stack also on DTCM and the stack is "colored"?
I agree: very strange, but there should be an explanation for this behavior.
2025-01-01 09:39 PM
You’re right that uninitialized variables will have “random” values at power-on. But that’s only because the charge being stored in the flip-flops has leaked away in the absence of power.
If the supply is only lost for a “short” time then there will be enough remaining charge to overcome electrical noise and slight mismatches between transistors and the memory will remember what was there before. Particularly if that section of RAM has error-correction hardware. Maybe not every bit, and maybe not every time.
But who’s to say what a “short” time is? The circuit designers don’t add anything to ensure individual memory cells are lost / scrambled on power-loss.
Some memory cells in the RTC are specifically arranged to be cleared on “tamper” events.
However ST do generally include a value you can read to identify the reason-for reset, which might be watchdog, external-reset-pin or power-on. See the Reference Manual for your stm32, the section on Reset and Clock Control, for more details. Once you’ve read the reason and dealt with it, do clear the value so it’s not wrongly remembered and noticed at next reset.
2025-01-03 01:07 PM
I ended up making both changes (changed the DEADBEEF value and the location of the attribute). It is now working expected. Hopefully also unrelated is the fact that I switched from a Segger j-Link debugger to my dev board's built in ST Link debugger.
Thanks for the suggestions.
C-Coder
2025-01-03 01:30 PM
Great, well done.
I do not think it is the debugger used: it should be related to how the code is generated.
And DEADBEEF could be something what the chip RTL (internal logic) might return in case of an error
(chip designers use often this value to indicate something went wrong and could not be read).
Good to know it works now as it should be.