Hi,
I need to save a 16 bit counter into a retained register.
I cannot use the 2 GPRETREG since they are already used and I cannot write internal flash.
I cannot use RAM retained.
Is there any other register suitable for this purpose?
Hi,
I need to save a 16 bit counter into a retained register.
I cannot use the 2 GPRETREG since they are already used and I cannot write internal flash.
I cannot use RAM retained.
Is there any other register suitable for this purpose?
Hi,
The GPREGRET registers are the only supported way to retain data that is not in flash during a reset. Other than that, the only approach that works reliably is to store the data in flash. However, you can also store data data in non-initialized RAM together with a checksum and read that data after reset. If the checksum is valid, it can be used. In most cases this will be fine, as the RAM content is never cleared by a reset, it is just not guaranteed to be intact. Note however that if you have a bootloader that runs first, you must make sure that this does not use the same memory region as that would overwrite it during boot. See this thread for details about that.
Hi, Einar! Are there any examples of how to write & read to & from the GPREGRET2 register the best way in nrfConnect SDK 3.0?
This works for me:
As an aside, note there are other registers which are retained and could be used for data when the associated peripheral is not used on a particular design (taking care to avoid side-effects of course). Some mapping is required as the bits within the registers are not contiguous. Retained registers on the nRF52832:
Hi,
I am sorry for the late reply.
Normally both GPREGRET registers are available and usable. I tested with a modified beacon sample from SDK 3.2 with updated main function like this and see that both are incremented as expected after reset, without any errors. If this still do not work on your end, we need to look more closely at what you do in your design.
#include <hal/nrf_power.h>
int main(void)
{
int err;
printk("Starting Beacon Demo\n");
uint32_t gpregret0_val = nrf_power_gpregret_get(NRF_POWER, 0);
uint32_t gpregret1_val = nrf_power_gpregret_get(NRF_POWER, 1);
/* Initialize the Bluetooth Subsystem */
err = bt_enable(bt_ready);
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
}
printk("GPREGRET0: 0x%08X\n", gpregret0_val);
printk("GPREGRET1: 0x%08X\n", gpregret1_val);
gpregret0_val++;
gpregret1_val++;
nrf_power_gpregret_set(NRF_POWER, 0, gpregret0_val);
nrf_power_gpregret_set(NRF_POWER, 1, gpregret1_val);
return 0;
}
Hi, Einar,
Thanks for your answer. I think the only difference of your code and mine is that you access the registers in your main function on the APPLICATION stage, but in my case I've accessed them in a function which is run on a PRE_KERNEL_1 stage.
Hi,
I see. That should not matter though, and I also have no problems when I test like this:
/* main.c - Application main entry point */
/*
* Copyright (c) 2015-2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.h>
#include <stddef.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <hal/nrf_power.h>
int main(void)
{
int err;
printk("Starting Beacon Demo\n");
/* Initialize the Bluetooth Subsystem */
err = bt_enable(NULL);
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
}
printk("GPREGRET0: 0x%08X\n", nrf_power_gpregret_get(NRF_POWER, 0));
printk("GPREGRET1: 0x%08X\n", nrf_power_gpregret_get(NRF_POWER, 1));
return 0;
}
static int retention_registers_increment(void)
{
uint32_t gpregret0_val = nrf_power_gpregret_get(NRF_POWER, 0);
uint32_t gpregret1_val = nrf_power_gpregret_get(NRF_POWER, 1);
gpregret0_val++;
gpregret1_val++;
nrf_power_gpregret_set(NRF_POWER, 0, gpregret0_val);
nrf_power_gpregret_set(NRF_POWER, 1, gpregret1_val);
return 0;
}
SYS_INIT(retention_registers_increment, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Thanks a lot, Einar! It works for me this way.
Thanks a lot, Einar! It works for me this way.