RIOT icon indicating copy to clipboard operation
RIOT copied to clipboard

cpu/cortexm_common: add persistent RAM invalidation

Open derMihai opened this issue 4 months ago • 2 comments

Contribution description

Added cpu_invalidate_persistent_ram(), which forces a clear of any persistent RAM on next reboot. This is useful e.g. after performing a firmware update.

Testing procedure

It's relatively difficult to provide tests for persistent state. However, I wrote a small application and tested it with different configurations on same54-xpro, which does provide backup RAM, and samd20-xpro, which doesn't.

main.c:

#include "cpu.h"
#include "periph/pm.h"
#include "test_utils/expect.h"

#include <stdio.h>

#ifdef CPU_HAS_BACKUP_RAM
#include "periph/gpio.h"

BACKUP_RAM_NOINIT uint32_t volatile noinit_backup_var;
BACKUP_RAM_DATA uint32_t volatile backup_var = 1;
#endif

__attribute__((__section__(".noinit"))) uint32_t volatile noinit_var;

MAYBE_UNUSED
static void _wakeup_isr(void *arg)
{
    (void)arg;
    puts("wakeup from backup\n");
}

int main(void)
{
    printf("noinit_var=%"PRIu32"\n", noinit_var);
#ifdef CPU_HAS_BACKUP_RAM
    printf("noinit_backup_var=%"PRIu32"\n", noinit_backup_var);
    printf("backup_var=%"PRIu32"\n", backup_var);
#endif

#ifdef CPU_HAS_BACKUP_RAM
    noinit_backup_var = 1;
    backup_var = 2;
#endif
    noinit_var = 1;

    /* comment this to allow RAM contents to persist */
    cpu_invalidate_persistent_ram();

#ifdef CPU_HAS_BACKUP_RAM
    /* also inits tamper pin interrupt (module periph_gpio_tamper_wake) */
    int res = gpio_init_int(GPIO_PIN(PC, 1),
                            GPIO_IN_PU,
                            GPIO_FALLING,
                            _wakeup_isr,
                            NULL);

    expect(res == 0);
    /* comment this to reboot instead  */
    pm_set(0);
#endif

    pm_reboot();
    return 0;
}

Makefile:

# BOARD ?= samd20-xpro
BOARD ?= same54-xpro

include ../Makefile.cpu_common

FEATURES_REQUIRED += cpu_core_cortexm

ifeq (same54-xpro, $(BOARD))
	USEMODULE += periph_gpio_tamper_wake
	USEMODULE += periph_gpio
	USEMODULE += periph_gpio_irq
endif

include $(RIOTBASE)/Makefile.include

derMihai avatar Aug 22 '25 16:08 derMihai

Murdock results

:heavy_check_mark: PASSED

cace91636028f4d644bf34e01f29aa3a0572e53f cpu/cortexm_common: added invalidate variable for persistent RAM

Success Failures Total Runtime
10535 0 10536 19m:32s

Artifacts

riot-ci avatar Aug 22 '25 18:08 riot-ci

I'm not sure if this is the right thing to do since you'll need a way to verify your .noiinit section contains valid data anyway.

e.g. a magic value at the start or end of your .noinit section that gets set once you use it - this could then be cleared when you do a firmware update that changes the data structure of the section.

benpicco avatar Aug 25 '25 10:08 benpicco