Hi Team,
We are trying to retain a variable across functional reset on S32K3xx, but it is not working.
Implementation:
__attribute__((section(".int_sram_results"))) uint32_t retain_var;
The value is being updated before reset (for testing retain_var= 0x11223344) .
Reset type:
Observed behaviour:
Reference checked:
Request:
Thanks,
Yusup S32K3 S32DS-ARM S32K31XEVB-Q100
Hi @yusupkhan241,
The startup code most likely initializes the entire SRAM to zero (for ECC initialization) after every reset—I haven’t seen your specific startup code.
You could consider skipping the ECC initialization when the reset is functional.
Refer to this answer:
https://community.nxp.com/t5/S32K/SRAM-ECC-Initialization-for-S32K344/m-p/1764143
BR, Daniel
Hi @yusupkhan241,
What do you mean by “it does not work”?
The files you posted do not seem to reflect the latest changes.
Can you step through the startup code and observe the variable in SRAM after a functional reset? This should clearly show where the variable gets overwritten.
To attach the debugger after the functional reset, you can add a simple loop at the beginning of the startup code, for example:
Loop:
mov r0, #1
cmp r0, 0 /* Change r0 to 0 in register view */
bne Loop /* Capture after power-on reset */
Regards,
Daniel
Any support, information, and technology (“Materials”) provided by NXP are provided AS IS, without any warranty express or implied, and NXP disclaims all direct and indirect liability and damages in connection with the Material to the maximum extent permitted by the applicable law.
NXP accepts no liability for any assistance with applications or product design. Materials may only be used in connection with NXP products. Any feedback provided to NXP regarding the Materials may be used by NXP without restriction.
I have simplified the setup to isolate the RAM retention behavior.
I placed the variable in a dedicated SRAM section and used a minimal main function with LED indication and watchdog-triggered reset. The idea is:
Below is the test code being used:
C
__attribute__((section(".int_sram_results"), used))
volatile uint32_t retain_var;
int main(void)
{
Clock_Ip_Init(&Clock_Ip_aClockConfig[0]);
DIO_Init();
WDT_Init();
if (retain_var == 0xAABBCCDD)
{
Siul2_Dio_Ip_SetPins(LED_GREEN_PORT, (1UL << LED_GREEN_PIN));
Siul2_Dio_Ip_ClearPins(LED_RED_PORT, (1UL << LED_RED_PIN));
}
else
{
Siul2_Dio_Ip_SetPins(LED_RED_PORT, (1UL << LED_RED_PIN));
Siul2_Dio_Ip_ClearPins(LED_GREEN_PORT, (1UL << LED_GREEN_PIN));
}
retain_var = 0xAABBCCDD;
while (1)
{
/* watchdog reset */
}
}
Show less
Observation:
I have attached the latest linker and startup files for reference.
Please let me know if you see anything missing on the startup or reset handling side.
Thanks,
Yusup
I replaced the startup instructions below with the changes you shared, but it did not work.
For your reference, I have uploaded the relevant files. The .s and .ld files were uploaded with a .c extension. Please review them and let me know if you need any additional information.
RamInit:
/* Initialize SRAM ECC */
ldr r0, =__RAM_INIT
cmp r0, 0
/* Skip if __RAM_INIT is not set */
beq SRAM_LOOP_END
ldr r0, =MCRGM_DES
ldr r1, [r0]
ldr r2, =MCRGM_DES_F_POR
and r1, r1, r2
cmp r1, 0
beq NO_INIT_STANDBY_REGION
ldr r2, =__INT_SRAM_START
ldr r3, =__INT_SRAM_END
b ZERO_64B_RAM
The above instructions updated with
RamInit: /* Check MC_RGM DES register, if it's non-zero, jump to RAMInit_Start. (RAM init is needed if Destructive reset occurred) */ /* To make it work, customer should clear the MC_RGM DES register in application code. */ ldr r4, =MC_RGM_BASE_ADDR /* 0x4028C000 */ ldr r4, [r4, #0x0] cmp r4, #0x0 bne RamInit_Start /* Check MC_RGM FES register, if the F_EXR bit or ST_DONE bit is set, jump to RAMInit_Start. */ /* RAM init is needed if external reset occurred, or BIST Done functional reset occurred. */ /* To make it work, customer should clear the MC_RGM FES F_EXR register bit in application code. */ ldr r4, =MC_RGM_BASE_ADDR ldr r4, [r4, #0x8] ldr r5, =MC_RGM_FES_MASK_RAM_INIT and r4, r4, r5 cmp r4, #0x0 bne RamInit_Start b SRAM_LOOP_END RamInit_Start: /* Initialize SRAM ECC */ ldr r0, =__RAM_INIT cmp r0, 0 /* Skip if __SRAM_INIT is not set */ beq SRAM_LOOP_END ldr r1, =__INT_SRAM_START ldr r2, =__INT_SRAM_END
Thanks,
Yusup
Can you share the whole test project so that I can easily test it on my side?
Thank you,
Daniel
Below are the observations from our testing:
Debug mode behaviour:
This confirms that RAM retention across functional reset is working when running under debugger.
However, when running standalone (without debugger):
Could you please help identify what might be causing this behaviour? Also, we are planning to use the complete .int_sram_results section to retain multiple parameters across functional reset. Please suggest if any additional changes are required for reliable retention.
Additionally, could you please suggest if there is any API or recommended method to trigger a functional reset (alternative to watchdog)?
For reference, I have included the changes made in the startup and linker files, and the same can be verified in the shared project.
startup file (old code)
RamInit:
/* Initialize SRAM ECC */
ldr r0, =__RAM_INIT
cmp r0, 0
/* Skip if __RAM_INIT is not set */
beq SRAM_LOOP_END
ldr r0, =MCRGM_DES
ldr r1, [r0]
ldr r2, =MCRGM_DES_F_POR
and r1, r1, r2
cmp r1, 0
beq NO_INIT_STANDBY_REGION
ldr r2, =__INT_SRAM_START
ldr r3, =__INT_SRAM_END
b ZERO_64B_RAM
startup file (new code)
.equ MC_RGM_BASE_ADDR, 0x4028C000
.equ MC_RGM_FES_MASK_RAM_INIT, 0xFFFFFFFF
RamInit:
/* Check MC_RGM DES register, if it's non-zero, jump to RAMInit_Start. (RAM init is needed if Destructive reset occurred) */
/* To make it work, customer should clear the MC_RGM DES register in application code. */
ldr r4, =MC_RGM_BASE_ADDR /* 0x4028C000 */
ldr r4, [r4, #0x0]
cmp r4, #0x0
bne RamInit_Start
/* Check MC_RGM FES register, if the F_EXR bit or ST_DONE bit is set, jump to RAMInit_Start. */
/* RAM init is needed if external reset occurred, or BIST Done functional reset occurred. */
/* To make it work, customer should clear the MC_RGM FES F_EXR register bit in application code. */
ldr r4, =MC_RGM_BASE_ADDR
ldr r4, [r4, #0x8]
ldr r5, =MC_RGM_FES_MASK_RAM_INIT
and r4, r4, r5
cmp r4, #0x0
bne RamInit_Start
b SRAM_LOOP_END
RamInit_Start:
/* Initialize SRAM ECC */
ldr r0, =__RAM_INIT
cmp r0, 0
/* Skip if __SRAM_INIT is not set */
beq SRAM_LOOP_END
ldr r1, =__INT_SRAM_START
ldr r2, =__INT_SRAM_END
b ZERO_64B_RAM
linker file changes
old code:
.int_results (NOLOAD):
{
. = ALIGN(4);
KEEP(*(.int_results))
. += 0x100;
} > int_sram_results
new code:
.int_results (NOLOAD):
{
. = ALIGN(4);
KEEP(*(.int_results))
} > int_sram_results
Thanks,
Yusup
Hi @yusupkhan241,
I have debugged it found that the code below was incorrect.
It used R1 and R2 instead of R2 and R3:
We need R2 and R3 because of this:
Where did you get this startup code?
With the debugger connected, the debugger initializes the SRAM ECC.
Without the debugger, there was a Hardfault at 0x20400090.
Regards,
Daniel