nRF5 SDK is not maintained anymore
More Info: Consider nRF Connect SDK for new designs
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

RAM retention failure

Hello

I am trying to figure out the ram retention on my nRF52-DK using SES and SDK v17.1.0. I've run through the example ram_retention, and studied a topic in Nordic's documentation, as well as a couple of threads here in DevZone, like this one, and this one. I adapted my code to implement RAM retention using the given examples, but it didn't work for me. 

I did all the mentioned steps:

  • declared the variable I want to retain in the .non_init section ( static uint32_t ble_activate __attribute__((section(".non_init"))); )
  • turned the RAM powered on during the SystemOFF sleepmode:
    // Configure the RAM retention parameters
    uint8_t i;
    for(i = 0; i < 8; i++) // Retain RAM 0 - RAM 7
    {
        sd_power_ram_power_set(i, (POWER_RAM_POWER_S0POWER_On << POWER_RAM_POWER_S0POWER_Pos) |
                                  (POWER_RAM_POWER_S1POWER_On << POWER_RAM_POWER_S1POWER_Pos) |
                                  (POWER_RAM_POWER_S0RETENTION_On << POWER_RAM_POWER_S0RETENTION_Pos) |
                                  (POWER_RAM_POWER_S1RETENTION_On << POWER_RAM_POWER_S1RETENTION_Pos));
    }
    // Delay for one second 
    nrf_delay_ms(1000);
  • And checking up the NRF_POWER->GPREGRET  for a pre-set value upon every wakeup.

However, I see that value is not preserved since I am outputting it using printf and it returns back as a nonsense number. Please, find my main.c attached. The crucial steps are implemented in void mers_ram_retention(void). The code is loosely based on ble_app_uart example, that is, in configures BLE stack as per original method and then starts advertising, and finally, goes to SystemOFF. 

Could you please tell me what went wrong?

Best, 

W

Parents
  • Hello,

    The RAM configuration looks to be correct. However, when the noinit section gets corrupted it usually is because there is a bootloader overwriting the section on startup. Could that be the case here? If not, I will try to set up a test tomorrow and see if I can replicate the issue on my side.

    Best regards,

    Vidar

  • Hello Vidor, thanks for the reply. I'm not using the bootloader, as far as I know. I have started from ble_app_uart and built upon it, never including any bootloader. 

    Hey, if it helps, I have uploaded you a complete project -  I've stripped down all functionality except ble-uart and ram retention to demonstrate the issue. It should run on PCA10040:

    Best, P

  • Hello,

    Thanks for uploading the project. That made it easy to test here. The problem was that you used the sd_power_ram_power_set() function before the Softdevice was enabled so the function was just returning NRF_ERROR_SOFTDEVICE_NOT_ENABLED without actually configuring the power register.

    Peripheral view of the POWER module when running your original code:

    Notice that the retention bits are set to '0'.

    You can access the POWER registers directly as long as the softdevice is disabled. E.g.

          NRF_POWER->RAM[i].POWERSET = ((POWER_RAM_POWER_S0POWER_On << POWER_RAM_POWER_S0POWER_Pos) |
                                       (POWER_RAM_POWER_S1POWER_On << POWER_RAM_POWER_S1POWER_Pos) |
                                       (POWER_RAM_POWER_S0RETENTION_On << POWER_RAM_POWER_S0RETENTION_Pos) |
                                       (POWER_RAM_POWER_S1RETENTION_On << POWER_RAM_POWER_S1RETENTION_Pos));

    Best regards,

    Vidar

  • Hey Vidar, this has worked out! Thanks man, you're awesome!

    I've taken your approach with NRF_POWER->RAM[i].POWERSET functions, since I turn SoftDevice on, only after the RAM retention is set, and only if the variable retained in RAM checks out. Is that a right way to do things here? Check the variable in RAM, and turn the BLE depending on it?

    Second, I feel it's kinda waste of power to turn on all of the RAM regions, since my 4-byte variable resides only in one of them. Can you tell me how to find out where my variable actually is, and how to pick a proper RAM region accordingly?

    Best, 

    P

  • Excellent Slight smile

    Is that a right way to do things here? Check the variable in RAM, and turn the BLE depending on it?

    Yes, this will work.

    Can you tell me how to find out where my variable actually is, and how to pick a proper RAM region accordingly?

    You can see where the .non_init section is located in RAM from the memory usage view in SES here (or from the *.map output):

    And when you know the address, you can look up the which RAM slave and section it belongs to by referring to figure 1 in the Memory chapter of the PS. Each 4K section consumes about 30 nA when retention is enabled.

    Important: the .non_init section does not start at a fixed address. So it may change between builds. E.g. when you turn off or enable compiler optimization.

  • You can see where the .non_init section is located in RAM from the memory usage view in SES here (or from the *.map output):

    Can you believe, I did exaxtly that last night? I found out that my variable lives at 0x20003F00, i.e in the section RAM 1. When I turned off all sections except that one, it worked just fine! How cool is that?

    Important: the .non_init section does not start at a fixed address. So it may change between builds. E.g. when you turn off or enable compiler optimization.

    This is what I also noticed. Is there a way to fix a variable at the given section and make sure it stays there every time?

  • Yes, you can specify a fixed start address for the non_init section in your flash_placemecement.xml file.

    e.g.

    Note that this fixed address must be somewhere between .tbss and   .heap (or .stack if you don't use heap).

Reply Children
Related