POWERSAVE_NO_TIMEOUT not defined

RAK4631 RUI3 (both Arduino and VScode development environments)


The RUI3 API calls

api.system.sleep.cpu()
api.system.sleep.lora()
api.system.sleep.all()

supposedly default to (ms_time = POWERSAVE_NO_TIMEOUT). If you leave the parameter out as shown above, the “cpu” and “all” versions compile, but the “lora” version doesn’t have a matching “no parameter” case and the compile fails. In the file “sleep.cpp” it looks like the no parameter interface was not included as it is for the “cpu” and “all” versions.

The existing code in sleep.cpp is this:

#ifdef SUPPORT_LORA
void sleep::lora(uint32_t ms_time) {
  if (ms_time == 0) {
    return;
  }

  udrv_radio_sleep_ms(ms_time);
}

void sleep::lora(int ms_time) {
  if (ms_time == 0) {
    return;
  }

  udrv_radio_sleep_ms((uint32_t)ms_time);
}
#endif

with the two interfaces there to support signed or unsigned integer ms_time.

Using POWERSAVE_NO_TIMEOUT explicitly doesn’t help, because it isn’t defined. I think it’s meant to be zero because that would be correctly handled in udrv_sleep_ms (in udrv_powersave.c), but with a zero value passed to the routines in sleep.cpp shown above, the logic would simply return without doing anything at all.

We need to add the parameterless case, like the “cpu” and “all” versions support already.

void sleep::lora() {
  udrv_radio_sleep_ms(0);
}

However, there doesn’t seem to me any reason why we shouldn’t be allowed to do this:

api.system.sleep.lora(POWERSAVE_NO_TIMEOUT)

but if POWERSAVE_NO_TIMEOUT is defined as zero, the do nothing early exits don’t make any sense.

I wonder if it should be like this:

#define POWERSAVE_NO_TIMEOUT 0

#ifdef SUPPORT_LORA
void sleep::lora() {
  udrv_radio_sleep_ms(POWERSAVE_NO_TIMEOUT);
}

void sleep::lora(uint32_t ms_time) {
  udrv_radio_sleep_ms(ms_time);
}

void sleep::lora(int ms_time) {
  udrv_radio_sleep_ms((uint32_t)ms_time);
}
#endif

BTW the same question over removing the early returns applies to the “cpu” and “all” versions of the call.

There might be a reason for it, I have to ask our R&D guys.

I am only using api.system.sleep.all(); in the main loop and have the rest of my application running based on events (LoRa packets, external interrupts, timers).

With api.system.lpm.set(1); and (only RAK3172 and only in latest RUI3 version V4.2.1) api.system.lpmlvl.set(2); the automatic sleep function is enabled and the system sleeps automatically in stop mode 2 whenever it has nothing to do.

Thanks @beegee

For a lot of the time my application will be underwater. The nRF52840 will be kept busy doing DSP but all the radio(s) will be essentially useless. When underwater I want to power down the GNSS, BLE and LoRa, and a careful reader of this forum might see a certain trend running through my recent post topics.

For the GNSS, I can drop the 3V3_S, but first the 32kHz oscillator needs to be running and stable and the ephemeris updated, so that when I resurface the GNSS can get a hot start.

For the BLE my working assumption has been that ble.stop() will shutdown the whole thing (but I’ve run into BLE comms issues along the way)

IIRC the LoRa stack mostly powers down all by itself; sleep.lora() was to make sure. I can get around the POWERSAVE_NO_TIMEOUT problem by specifying an enormous timeout value. I was mostly pointing out the mismatch between the API doco and the code. But also, re-enabling LoRa while it is asleep is another likely place for lurking bugs.