Reset Retained Variables w/o power cycle

Is there a way to wipe Retained variables to the uninitialized state without performing a hard power cycle and removing/disconnecting the RTC battery?

On OTA firmware updates sometimes the retained variables need to change that causes the order to change from the previous, this can cause retained variables to be wrong for the declared variable.

Example

retained bool firstRetained = 1; 
retained bool secondRetained = 0; 

Now there is a firmware update and the size or location changes to below:

//retained bool firstRetained = 1;  //removed
retained bool secondRetained = 0; 

now secondRetained can equal 1 instead of 0.

I’d like a way to reinitialized them without a hard power cycle and our boards have a permanent rechargeable backup battery connected too.

No, but the workaround that I like is to put the retained data in a struct. At the beginning of the struct, put some magic bytes. I usually use a uint32_t (4 bytes).

If something else moves the struct in retained memory, the magic bytes will not be set and you can reinitialize. Same for cold boot.

If you change the struct (add or remove elements), you change the magic bytes to force reinitialization.

1 Like

thats cool, do you have an examlpe by chance? im not familiar with magic bytes

“Magic byte” or “magic number” is just a term for some constant number you choose and check whether the data you read matches your expected/chosen value.

1 Like

How do you force reinitialization? By just setting them again like below?

startup
retained bool firstRetained = 1; 
retained bool secondRetained = 0; 

if (magicbytes Change) {
firstRetained = 1; 
secondRetained = 0; 
}

The idea is that you put all of your retained variables in a struct, like this:

There’s only one member, deviceName, but you’d add all of your retained values after that if you had more.

The magic value itself is 0xa2c7206a, which I generated randomly.

A setup or some similar time, you check if the magic is valid, and if not, reinitialize all of your values.

		if (retainedData.magic != RETAINED_DATA_MAGIC || retainedData.deviceName[0] == 0) {
			memset(&retainedData, 0, sizeof(retainedData));
			retainedData.magic = RETAINED_DATA_MAGIC;

			Particle.subscribe("spark/", deviceNameHandler);
			Particle.publish("spark/device/name");
			state = NAME_WAIT_STATE;
			stateTime = millis();
		}
3 Likes