Crash after powerdown if ram is not powered

sdk: 2.5.1

cpu: nrf5340

I have a bootloader which have a big ram block for upgrade purpose (around 250kb) in bss section (I will move it in noinit, but it is not the point here).

I  have an app, that poweroff unused ram with VMC register.

Sometimes, the app will enter in poweroff (using REGULATORS register), and will be awakened by vbus or nfc.

When the cpu is awakened, the bss section and idle stacks are in a part of the ram that is powered off, and this is a unrecoverable crash.

I found a solution with powering ram at early startup, but I would like to check with you if it is correct.

The solution may also be about powering up ram before entering poweroff, but I would like may bootloader to be robust.

I wrapped the method z_arm_reset (with linker argument --wrap), and wrote this method:

extern void __real_z_arm_reset();

__attribute__((naked))
void __wrap_z_arm_reset(void)
{
  NRF_VMC->RAM[0].POWERSET = 0xFFFF;
  NRF_VMC->RAM[1].POWERSET = 0xFFFF;
  NRF_VMC->RAM[2].POWERSET = 0xFFFF;
  NRF_VMC->RAM[3].POWERSET = 0xFFFF;
  NRF_VMC->RAM[4].POWERSET = 0xFFFF;
  NRF_VMC->RAM[5].POWERSET = 0xFFFF;
  NRF_VMC->RAM[6].POWERSET = 0xFFFF;
  NRF_VMC->RAM[7].POWERSET = 0xFFFF;
   __asm__ volatile ("b __real_z_arm_reset");
}

I checked the generated code, and no stack seem to be used:

00002a28 <__wrap_z_arm_reset>:
    2a28:       f64f 72ff       movw    r2, #65535      ; 0xffff
    2a2c:       4b09            ldr     r3, [pc, #36]   ; (2a54 <__wrap_z_arm_reset+0x2c>)
    2a2e:       f8c3 2604       str.w   r2, [r3, #1540] ; 0x604
    2a32:       f8c3 2614       str.w   r2, [r3, #1556] ; 0x614
    2a36:       f8c3 2624       str.w   r2, [r3, #1572] ; 0x624
    2a3a:       f8c3 2634       str.w   r2, [r3, #1588] ; 0x634
    2a3e:       f8c3 2644       str.w   r2, [r3, #1604] ; 0x644
    2a42:       f8c3 2654       str.w   r2, [r3, #1620] ; 0x654
    2a46:       f8c3 2664       str.w   r2, [r3, #1636] ; 0x664
    2a4a:       f8c3 2674       str.w   r2, [r3, #1652] ; 0x674
    2a4e:       f00a b9e7       b.w     ce20 <z_arm_reset>
    2a52:       bf00            nop
    2a54:       50081000        .word   0x50081000

Waiting for your answer.

Regards,

  • I can’t make myself understood.

    As the ram is powered down, the bootloader crash very very early. Far before init of the kernel. Inside the reset part, just when the MPS is needed.

  • Okay, this is the complete sequence leading to successful start to crash on reset in your case:

    1. After device reset (reset pin or power reset), all RAM is configured through VMC to be enabled when the system is ON, and powered down when the system is OFF.

    2. Your bootloader starts successfully, as all RAM is powered.

    3. You jump to the application, all works as expected.

    4. At this point, before entering power off, you configure all RAM to be powered down in system ON state.

    5. You immediately enter poweroff, if you tried to read from RAM here, the application would likely crash, and never enter OFF state.

    6. The system is now in the OFF state, and the VMC is configured to always power down all RAM, regardless of power state.

    7. You trigger wakeup

    8. System powers up, you bootloader starts

    9. VMC has not been configured to automatically power on any RAM, including the RAM used by your bootloader for normal operation

    10. Bootloader reaches an instruction which requires reading from RAM

    11. System crashes


    To add your solution to the sequence, this happens after step 9.

    9. ...

    10. Manually configure VMC to power all RAM

    11. Bootloader reaches an instruction which requires reading from RAM

    12. Bootloader runs as expected


    So, to answer your original question:

    I found a solution with powering ram at early startup, but I would like to check with you if it is correct.

    Wrapping early C code to manually power on RAM used by the bootloader for normal operation is not robust, nor necessary. The VMC is designed to automatically power the RAM needed for system ON, and retain any RAM required by the application as well.

    The solution is to configure the VMC to power RAM used by your bootloader and application automatically, and create a separate section in RAM which your bootloader/application manually powers on/off at runtime.

  • 4. At this point, before entering power off, you configure all unused RAM to be powered down in system ON state.

    5. You immediately enter poweroff, if you tried to read from RAM here, the application would likely crash, and never enter OFF state.

    6. The system is now in the OFF state, and the VMC is configured to always power down all RAM unused by app

    I do not want to have separate section in ram for bootloader and app, as there are some app that will consume all the ram. It is not possible for the bootloader to reserve a part of ram.

    What I want here is to ensure that bootloader will not crash, even if app is doing bad thinks, like power down the ram needed by the bootloader. It must not be a need for the bootloader that the app developper is clever.

  • If you wish to protect your bootloader/trusted application from a user application, you will want to look into the SPU (System Protection Unit) https://infocenter.nordicsemi.com/topic/ps_nrf5340/spu.html?cp=4_0_0_6_31_3#peripheral_access_control and TF-M (Trusted firmware) https://trustedfirmware-m.readthedocs.io/en/latest/introduction/index.html 

    The SPU allows you to configure access to peripherals from the secure/non-secure domains, you can use this to disallow the application from accessing VMC all together, preventing invalid configuration of most peripherals, VMC included :)

  • I will stop there, because I cannot make myself understood. The code I mentioned in my first post works: the bootloader starts normally even if the ram has been turned off by the application (nothing to do with spu protection: I do not want to prevent the extinction of ram, since it is an important element for low-power). I just wanted to have it checked by the Nordic experts, and also shared.

Related