What LMIC state must be preserved during sleep mode?


MCUs like ESP8266 and ESP32 do not preserve RAM in sleep mode.
Waking up from sleep on these MCUs is similar to a reboot.

In order to make a node initially connect to the TTN network using OTAA and then each time when it wakes up from sleep reconnect to the network using ABP with keys received during the OTAA join (to minimize re-connection time, minimize power usage and to prevent issues with the maximum number of OTAA joins for a node),

What LMIC state (which parameters/variables) must be preserved during sleep (saved before entering sleep and restored when awaking from sleep) to make this work flawlessly?

Is an overview of all required LMIC state variables available somewhere?
Are there any specific actions (e.g. proces/functions calls) required to bring LMIC back to its pre-sleep state?

It would be nice if LMIC would have methods for getting and setting its state as a contiguous block of bytes so that it can be quickly and easily saved to and restored from non-volatile memory (of arbitrary type).

1 Like

I do not have any overview handy, but I agree that this would be a usecase worth supporting. I suspect that currently, you would have to preserve pretty much the complete LMIC struct. To minimize that to just the session variables, I suspect that some additional API should be added to re-initialize LMIC from an existing session, rather than a new session.

Do you see possibility to implement that? :blush:

See OTAA best practice: how to not join every time? and its replies.

What I do on another platform (Arduino MKRWAN) is:

  • ABP join (using the session keys from the initial OTAA join). This initialize the data structure properly.
  • Set the other saved values (uplink/downlink counters, …)

It is pretty straightforward and can be encapsulated…

@bluejedi i may be wrong but i think the modified LMIC library from @grazy will help you: https://github.com/ngraziano/lmicesp32

He stores and restores the LMIC state in RTC RAM

1 Like

Thanks. This may serve as an example.
My goal is to be able to use non-volatile memory of arbitrary type, not just RTC memory (which has a limited lifetime for the number of writes per cell) and not only for ESP32.

Getting and setting state is something that should be implemented in the LMIC library itself. Any state implementation details and its intricasies should be encapsulated from clients that are using the library.

The responsibility of the application would be to save and restore the state to/from volatile memory. The type of volatile memory used is a client dependent implementation detail and not the responsibility of the LMIC library.

The ESP32 specific LMIC fork mentioned uses ESP32 RTC memory but that is limited to both ESP32 and its RTC memory. From design perspective the saving and restoring of state to/from (whatever form of) non-volatile memory should not be done in the LMIC library.

FRAM will be your friend here :wink:

FRAM is one of the non-volatile memory types I want to be able to use it with. :wink:

@bluejedi I agree that the save should be made in lmic library, and should adapt to different kind of storage. Maybe it can be made by a function which call a callback in user program to save on or more block of byte.

To be generic I think that all the value modified by OTAA join response and by mac command should be save.
It includes, session keys but also RX2 configuration, channels configuration, current datarate, … (like describe in the link put by @arjanvanb)

But for the state to be correct the time must also be correct (for globalDutyavail and Band.avail for global and band duty rate) or maybe you can ignore theses values if you sleep long enough (maybe more than 3 hours, I did not do the exact calculation).

While a callback is a nice option I think it is not required here and possibly makes things more complex / dependent / slower.

Time is a good point. Many/most nodes will not have a realtime clock nor can they access a (NTP) time server, so I’m curious how the time issue might be solved or (reliably) worked around in this case.

Maybe @htdvisser has some ideas for this.

As an aside, I once noticed the following:

In case of an ESP32, the RTC keeps running in deep sleep, so I guess time is not an issue here, or did i misunderstood the issue?

I think you are correct. Preserving ‘time’ is probably not an issue there, only when the ESP32 is powered off.

…or does it :wink:

Yes, you opened a can of worms, don’t be alarmed :slight_smile:

Or you can sleep more than 7FFFFFFF ostick => 9h32min and even with rtc clock in hal_ticks you will have some problem (US_PER_OSTICK_EXPONENT = 4).

Again, that is only valid for AVR micro’s, not for the ESPx.

Right, this is a generic LMIC thread, not an ESP one…

Low-power and sleep are so essential that it should just work and be simple. :wink:

1 Like

Yes, and it seems that this combination is the best kept secret :wink:

1 Like