Open charlesmodrich-tc opened 3 years ago
Thank you for raising this detailed GitHub issue. I am now notifying our internal issue triagers. Internal Jira reference: https://jira.arm.com/browse/IOTOSM-3922
@charlesmodrich-tc I have similar issues in #222. Did you find a solution? For tcxo control, I am exploring modifying the set_operation_mode call in the driver i.e. set to 0 when RF_OPMODE_SLEEP otherwise 1. But that still leaves a high residual ~300uA.
Unfortunately no, I wasn't able to find a solution. Ultimately I was forced to move away from Mbed OS for this reason since I wasn't able to get the low current performance all of my devices would require.
--
Charles Modrich | Senior Hardware Engineer TeraCode | 405 Cochituate Road | Suite 205 | Framingham MA 01701 M: 847-951-7543 | F: 781-207-0724 http://www.teracode.com | LinkedIn https://www.linkedin.com/in/charlesmodrich/
On Sat, Jun 26, 2021 at 4:58 AM Evan Davey @.***> wrote:
@charlesmodrich-tc https://github.com/charlesmodrich-tc I have similar issues in #222 https://github.com/ARMmbed/mbed-os-example-lorawan/issues/222. Did you find a solution? For tcxo control, I am exploring modifying the set_operation_mode call in the driver i.e. set to 0 when RF_OPMODE_SLEEP otherwise 1. But that still leaves I high residual.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ARMmbed/mbed-os-example-lorawan/issues/227#issuecomment-868978263, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARXQAUS7K7DS4CDEOWWATCDTUWQDTANCNFSM435LKRXQ .
@charlesmodrich-tc - very frustrating.
It really is! I spent a lot of time and hope on this before giving up.
Yes, have been in the same boat! Having to revert back to the manufacturer SDKs is its own path of pain given all the messy #defines to support multiple targets and tight coupling of business logic to SDK logic. It's a shame support resources for MBED seem to have dropped off recently and it is stuck being half a corporate project and half an open source project with neither seeming to have particularly strong momentum.
@charlesmodrich-tc - I have been doing some more debugging, this time on a Murata ISJ dev board (link). This is a STM32L072 + SX126X radio. With the Murata supplied AT firmware, I measure this board at the expected 2uA, so I know this is the baseline. I am using a new example from scratch, but using the master branch of mbed-os (as I needed to make some non power related changes to the SX126X driver).
With the code below, I am able to achieve an average of 50uA. Interestingly, if I power up the board (which puts the radio to sleep), then re-upload the code with the radio.sleep() line commented out, current falls to 11uA, which is very similar to the 14uA you measured. I think this is related to GPIO/peripheral configuration in sleep but I haven't been able to figure out why, or where I am losing 9uA relative to the AT firmware.
mbed_app.json
{
"requires": [
"bare-metal",
"events",
"storage",
"spif-driver",
"lora",
"mbedtls",
"sx1276-lora-driver",
"SX126X-lora-driver"
],
"target_overrides": {
"*": {
"target.macros_add": ["MBED_TICKLESS"],
"target.lpticker_lptim": 0
},
"MURATA_TYPE1SJ_EVB": {
"SX126X-lora-driver.freq-support": "MATCHING_FREQ_915",
"SX126X-lora-driver.device-variant": "SX1262"
}
}
}
main.cpp
#include "mbed.h"
#include "events/EventQueue.h"
#include "radio.h"
#include "SX126X_LoRaRadio.h"
#define MAX_NUMBER_OF_EVENTS 20
static EventQueue ev_queue(MAX_NUMBER_OF_EVENTS *EVENTS_EVENT_SIZE);
SX126X_LoRaRadio radio(LORA_SPI_MOSI,
LORA_SPI_MISO,
LORA_SPI_SCLK,
LORA_SPI_CS,
LORA_RESET,
LORA_DIO1,
LORA_BUSY,
LORA_FREQ_SELECT,
LORA_DEVICE_SELECT,
LORA_CRYSTAL_SELECT,
LORA_ANT_SWITCH);
int main(void)
{
radio.sleep();
ev_queue.dispatch_forever();
}
"target.lpticker_lptim": 0
This is not tested, not validated, so not recommended... Keep the default configuration
@jeromecoutant - this line saves about 30uA . At the moment my objective is to just get current down to 2uA with nothing running, then start adding back functionality to be able to do a full LoRaWAN test so I'll admit I've been trying things such as that line without fulling understanding the impact. The 2uA firmware is written in https://www.st.com/en/embedded-software/i-cube-lrwan.html but I find the structure such a headache to deal with.
That's interesting because I wanted to post a comment this night but went to bed before. In the meantime conversation has new comments. I'm currently switching to mbed for my lorawan E5 and RAK3172 board because it's really nice simple with lot of features and this lorawan example works. But my next step is to go to low power testing and seing this makes me feel inconfortable because the goal of LoRaWAN device is to be low lower. I'm going to 1.5uA with old murata one on custom code without mbed so 11uA or 50uA is not an option on my side. Would be interesting to have @jeromecoutant, or @MarceloSalazar on this point, in the meantime I will give some tries on my boards.
The 2uA firmware is written in https://www.st.com/en/embedded-software/i-cube-lrwan.html but I find the structure such a headache to deal with.
I really don't understand how can this structure give you headache (kidding), but I'm glad I don't feel alone on this ST structure 👍
@hallard - I have some E5's on order along with the https://www.seeedstudio.com/LoRa-E5-mini-STM32WLE5JC-p-4869.html. Is there a target already that works with this chip and can give low power? I don't care what chip I use at this point as long as I can get something functional - don't know if there is anyone using MBED lorawan in the real world.
As to i-cube-lrwan, honestly my adaptions are relatively minor and I could probably mod it to get it working, but :scream: the business logic would be so tightly coupled with that structure I couldn't deliver in good conscience.
@hallard - I have some E5's on order along with the https://www.seeedstudio.com/LoRa-E5-mini-STM32WLE5JC-p-4869.html. Is there a target already that works with this chip and can give low power?
Sure take a look there (not tested on Low Power yet )
for STM32WL i-cude-lrwan has been replaced by STM32Cube MCU Package for STM32WL series(SDK) may be it was too simple. More information here but don't dream, file and folder architecture won't remove you any headache
@hallard thanks for the links. Not Low Power tested is the concern. I've tried the Type ABZ (custom build and DISCO LRWAN1), Type 1SJ and STM32L0/RFM95 (draguino LNS50 node) so far with no luck for easy low power < 10uA (and even struggling for <100uA). I guess the trade-off for using a simplified framework like MBED is you lose that fine-grain control to library implementations. Still, it is such a common problem I'd hope there would be sufficient community support / documentation to get things running at least with a viable battery life for a low power long-term node (i.e. 1 year plus). Especially for dev boards like the DISCO LRWAN1.
Worth looking at this sample code https://os.mbed.com/users/kenjiArai/code/Check_DeepSleep_os6/ For sure need to be adapted for STM32 target (Murata STM32L0 in your case) but could be an excellent starting point because on some boards he got 2uA which is both our target :-)
@hallard I have attempted something like the "LowPowerConfiguration" function before. Firstly, I don't think "AHBENR" exists for a L0 target (so I switched for "IOPENR"). Secondly, I think the presence of the radio messes with this code as I have experienced worse performance after calling such a function following radio.sleep (as in mA). Otherwise, I don't see anything obvious in this code that is doing anything I haven't tried before. I haven't found anything documented as to what happens to peripherals/gpio when deep sleep is called.
BTW, with the exact some code and the LNS50 as a target (so swapping the SX126X driver for SX1276) I see 500uA. But I am not convinced the pin mappings for the SX1276 are correct for the RFM95 module (https://github.com/dragino/Lora/blob/master/LSN50/v2.0/LoRa%20ST%20Sensor%20Node%20v2.0.sch.pdf and https://raw.githubusercontent.com/dragino/Lora/master/LoRaST/v1.0/LoRa%20ST%20v1.0_Sch.pdf).
Ok done some testing on my LoRa-E5 board, after removing all code of the sample (and all GPIO config such as LED and Button) here we go
1.43uA in deep sleep mode, perfect !!
mbed_app.json
{
"requires": ["bare-metal", "events", "lora", "mbedtls"],
"target_overrides": {
"*": {
"target.printf_lib": "std"
}
}
}
code
// Include --------------------------------------------------------------------
#include "mbed.h"
// Constructor ----------------------------------------------------------------
//DigitalIn my_sw(BUTTON1);
//DigitalOut myled(LED1,1);
static BufferedSerial pc(CONSOLE_TX, CONSOLE_RX, 115200);
//------------------------------------------------------------------------------
// Control Program
//------------------------------------------------------------------------------
int main()
{
while (true) {
// myled = 0 ; // ON
// ThisThread::sleep_for(1s);
// myled = 1 ; // Off
// ThisThread::sleep_for(2s);
hal_deepsleep();
}
}
Please not that using ThisThread::sleep_for(2s)
instead sleep at 3mA
@hallard - great, sounds promising. Is this the Seeed Studio dev board or one of your own? I think with bare metal you need to use thread_sleep_for rather than ThisThread::sleep_for for the sleep manager to work (or events.dispatch_forever() like I used). What's happening with the radio? Is it defaulting to off for this board? What are the settings for PeripheralPins.c? What is the system clock configuration?
This code gives me ~1.14mA on the Type 1SJ dev board (which is most likely the radio being on).
@evandavey yes it's my basic own board, pin definitions are here and the radio is included into the STM32WL chip.
hal_deepsleep()
may be not the best because I'm not sure we can wake up with a timer, but I'm wondering how the difference between with thread_sleep_for()
As you can see as soon as I'm using this code consumption in sleep goes from 1.5uA to 2.9mA
int main()
{
while (true) {
thread_sleep_for(5000);
}
}
@hallard - I might be wrong on thread_sleep_for https://forums.mbed.com/t/clarification-on-os-6-empty-vs-os-6-bare-metal-example-programs-1-0-0/8950 and it is equivalent and doesn't call the sleep manager. What do you get using events.dispatch_forever()? Maybe the radio defaults to its sleep state on the STM32WL?
Same thing with
int main()
{
EventQueue queue;
queue.dispatch_forever();
}
mbed_app.json
=> 2.9mA
{
"requires": ["bare-metal", "events", "lora", "mbedtls"],
"target_overrides": {
"*": {
"target.printf_lib": "std"
}
}
}
Same code but not using bare-metal?
Sorry same code, same config so yes bare-metal
Sorry, I meant, what do you get running the same code but not in bare-metal?
Here to follow up my tests
int main()
{
EventQueue queue;
queue.dispatch_forever();
}
mbed_app.json
=> 6.5mA
{
"requires": ["bare-metal", "events", "lora", "mbedtls"],
"target_overrides": {
"*": {
"target.printf_lib": "std",
"target.macros_add": ["MBED_TICKLESS"],
"target.lpticker_lptim": 0
}
}
}
mbed_app.json
=> 2.9mA
{
"requires": ["bare-metal", "events", "lora", "mbedtls"],
"target_overrides": {
"*": {
"target.printf_lib": "std",
"target.macros_add": ["MBED_TICKLESS"]
}
}
}
mbed_app.json
=> 2.9mA
{
"requires": ["bare-metal", "events", "lora", "mbedtls"],
"target_overrides": {
"*": {
"target.printf_lib": "std"
}
}
}
So "target.lpticker_lptim": 0 increases 3.6mA?
For not bare-metal I mean
int main()
{
EventQueue queue;
queue.dispatch_forever();
}
{
"target_overrides": {
"*": {
"target.printf_lib": "std"
}
}
}
and here we go without bare-metal
(sorry took some time to compile), same results, and target.lpticker_lptim": 0
increase 3.6mA
int main()
{
EventQueue queue;
queue.dispatch_forever();
}
mbed_app.json
=> 6.5mA
{
"target_overrides": {
"*": {
"target.printf_lib": "std",
"target.macros_add": ["MBED_TICKLESS"],
"target.lpticker_lptim": 0
}
}
}
mbed_app.json
=> 2.9mA
{
"target_overrides": {
"*": {
"target.printf_lib": "std",
"target.macros_add": ["MBED_TICKLESS"]
}
}
}
mbed_app.json
=> 2.9mA
{
"target_overrides": {
"*": {
"target.printf_lib": "std"
}
}
}
I've done a little more testing myself.
3.4ma
int main()
{
EventQueue queue;
queue.dispatch_forever();
}
2.4ma
#include "SX126X_LoRaRadio.h"
SX126X_LoRaRadio radio(LORA_SPI_MOSI,
LORA_SPI_MISO,
LORA_SPI_SCLK,
LORA_SPI_CS,
LORA_RESET,
LORA_DIO1,
LORA_BUSY,
LORA_FREQ_SELECT,
LORA_DEVICE_SELECT,
LORA_CRYSTAL_SELECT,
LORA_ANT_SWITCH);
int main()
{
EventQueue queue;
queue.dispatch_forever();
}
70uA
#include "SX126X_LoRaRadio.h"
SX126X_LoRaRadio radio(LORA_SPI_MOSI,
LORA_SPI_MISO,
LORA_SPI_SCLK,
LORA_SPI_CS,
LORA_RESET,
LORA_DIO1,
LORA_BUSY,
LORA_FREQ_SELECT,
LORA_DEVICE_SELECT,
LORA_CRYSTAL_SELECT,
LORA_ANT_SWITCH);
int main()
{
EventQueue queue;
radio.sleep();
queue.dispatch_forever();
}
{
"requires": [
"bare-metal",
"events",
"lora",
"mbedtls",
"SX126X-lora-driver"
],
"target_overrides": {
"*": {
"target.macros_add": ["MBED_TICKLESS"],
"target.reset_gpio_on_init": 1
},
"MURATA_TYPE1SJ_EVB": {
"SX126X-lora-driver.freq-support": "MATCHING_FREQ_915",
"SX126X-lora-driver.device-variant": "SX1262"
}
}
}
I am pretty sure that in both bare-metal and RTOS queue->dispatch_forever() should go into deep sleep when idle (and this is what I am experiencing). Can you turn on sleep tracing to see if anything is blocking deep sleep?
May be the Serial port console? do you know how to be sure that any serial is disabled?
You could try: mbed_file_handle(STDIN_FILENO)->enable_input(false) Console and Deep Sleep
With radio driver
#include "mbed.h"
#include "STM32WL_LoRaRadio.h"
STM32WL_LoRaRadio radio;
int main()
{
EventQueue queue;
mbed_file_handle(STDIN_FILENO)->enable_input(false);
radio.sleep();
queue.dispatch_forever();
}
mbed_app.json
=> 6mA average
{
"requires": ["bare-metal", "events", "lora", "mbedtls", "stm32wl-lora-driver"],
"target_overrides": {
"*": {
"target.printf_lib": "std"
}
}
}
And you're using a develop or release build profile (not debug?)
ah ah good catch, it's a debug, compiling above code as release and here we go
Avg 1.7uA and peak are 4mA for approx 2ms
OK, that's great!! And is it the same without the radio.sleep() call?
Perhaps we need to compare the differences between "STM32WL_LoRaRadio.h" and "SX126X_LoRaRadio.h".
Or just use STM32WL chips! :laughing: Still waiting for mine to arrive.
yes same things without radio.sleep()
, I already had 1.5uA with murata ABZ (STM32L0 + SX126x) with another framework so it's do able and may be your issue is related to mbed. Do you have same issue on mbed 5 where ABZ is officially supported?
What framework? I have tried stm32duino / arduino-lmic but similar issues. I am actually using a Type 1SJ for these tests. My LRWAN1 board had to be repurposed in a field test and I haven't re-checked on my custom board. But experiencing similar issues on the Draguino LNS50. Definetely there is some config issues with the framework, but they should be solveable with support....
Please post your results when you have done a end-to-end test with LoRaWAN active.
WIll let you know how the SeeedStudio E5 dev board goes when it arrives (looks like they have landed in Sydney so hopefully early next week).
using this one https://github.com/GrumpyOldPizza/ArduinoCore-stm32l0
By the way do your board manage USB because I remember having issues with that, very tricky, needed to disable some USB stuff and more, needed to reset (start the board) without usb connected, removing USB cable once started prevented to go to low power, got some headache before discovering that. Likely my debug
mode instead of release, thanks for the trick.
Hope you will be able to play with your E5 Dev Boards, absolutely amazing, everything is very well designed, you can disable everything and even a jumper present to be able to measure current consumption, it's the best LoRa Board Dev Kit I've ever seen and price rocks and RS485 as cherry on the cake
I used that GrumpyOldPizza framework very early on but ran into LoRa implementation issues, can't remember exactly what now, and gave up. Could have been related to early days of them supporting AU915. If you have any code you can share that would be greatly appreciated.
I experience a similar issue with the Draguino LNS50 where I have to use a ST-Link and need it unplugged for low power. Have tested the Type 1SJ both with and without the (on-board) debugger connected and it makes no difference (and the ~45uA I am seeking is too low for that anyway).
Here part of my code working for GrumpyOldPizza (with git version since some API have changed since)
#include "STM32L0.h"
#include "LoRaWAN.h"
#include "TimerMillis.h"
// Transmit period in s
#define LORA_TRANSMIT_PERIOD 300
// for USB
#define DEBUG_USB
#define DEBUG_SERIAL
// Disable USB after boot
#define DISABLE_USB_SERIAL
#ifdef DEBUG_SERIAL
#define SERIAL_DEBUG Serial1
#elif defined (DEBUG_USB)
#define SERIAL_DEBUG Serial
#endif
#if defined (DEBUG_USB) || defined (DEBUG_SERIAL)
#define debug(VAL) { SERIAL_DEBUG.print(VAL); }
#define debug2(VAL, MODE) { SERIAL_DEBUG.print(VAL, MODE); }
#define debugln(VAL) { SERIAL_DEBUG.println(VAL); }
#define debug2ln(VAL, MODE) { SERIAL_DEBUG.println(VAL, MODE); }
#define debugflush() { SERIAL_DEBUG.flush(); }
#else
#define debug(VAL) {}
#define debug2(VAL, MODE) {}
#define debugln(VAL) {}
#define debug2ln(VAL, MODE) {}
#define debugflush() {}
#endif
#define WAKE_BTN YOUR_BUTTON_IO_NAME
uint32_t transmitPeriod = LORA_TRANSMIT_PERIOD;
bool VUSB, hasUSB;
volatile bool wake_btn = false;
volatile bool wake_timer = false;
volatile bool wake_join = false;
TimerMillis wakeTimer;
void ledOff()
{
// Letting PWM active prevent stop mode and thus
// stop()/deepsleep() does not go into sleep mode.
pinMode(LED_RED, OUTPUT);
pinMode(LED_GRN, OUTPUT);
pinMode(LED_BLU, OUTPUT);
digitalWrite(LED_RED, LEDOFF);
digitalWrite(LED_GRN, LEDOFF);
digitalWrite(LED_BLU, LEDOFF);
}
void btn_interrupt()
{
wake_btn = true;
STM32L0.wakeup();
}
void timer_interrupt(void)
{
wake_timer = true;
STM32L0.wakeup();
}
void joinCallback(void)
{
debug("joinCallback() ");
wake_join = true;
STM32L0.wakeup();
}
void setup()
{
char buffer[18];
VUSB = USBDevice.attached();
hasUSB = USBDevice.connected();
pinMode(WAKE_BTN, INPUT);
LoRaWAN.begin(EU868);
LoRaWAN.getDevEui(buffer,18);
#ifdef DEBUG_SERIAL
Serial1.begin(115200);
while (!Serial1 && millis()<=2000 ) {
}
Serial1.println("Serial1 OK");
#endif
#ifdef DEBUG_USB
Serial.begin(115200);
while (!Serial && millis()<=5000 ) {
}
Serial.println("OK");
#endif
LoRaWAN.setADR(true);
LoRaWAN.setDutyCycle(false);
LoRaWAN.onJoin(joinCallback);
LoRaWAN.onReceive(receiveCallback);
debugln("LoRa Joining");
LoRaWAN.joinOTAA(appEui, appKey, (const char *) buffer);
#ifdef DEBUG_USB
#ifdef DISABLE_USB_SERIAL
// Switch to real uart
Serial.println("Stopping USB");
Serial.end();
#else
Serial.println("!!!! Leaving USB Serial running !!!!");
#endif
#endif
// In all case even just Serial
#ifdef DISABLE_USB_SERIAL
USBDevice.detach();
#endif
// Initialize our wake timer but do net setup yet
wakeTimer.start( timer_interrupt, 10000);
wakeTimer.stop();
}
void loop()
{
unsigned long next_transmit = transmitPeriod;
if (wake_btn) {
debugln("button");
}
if (wake_join) {
if (!LoRaWAN.joined()) {
debug("NOT ");
}
debugln("JOINED");
wake_join = false;
}
if (wake_timer) {
// Security to be sure to be waked
wake_timer = false;
}
ledOff();
wake_btn = false;
// reset heartbeat every 4 x transmit period
wakeTimer.restart( LORA_TRANSMIT_PERIOD * 4 * 1000 + 5000);
debug("Going to Sleep (");
debug(next_transmit);
debugln("s)...");
debugflush();
attachInterrupt(WAKE_BTN, btn_interrupt, RISING);
STM32L0.deepsleep(next_transmit*1000);
// Just waked up
detachInterrupt(WAKE_BTN);
}
Awesome, thanks! Can't see too much different from MBED in this application code so it must be the initial pin config / deep sleep code that is done differently.
can you share your HW schematics or not because could be some diff on vdd_txo / txco pin used?
Type 1SJ EVM I think technically can't be shared (though they give you access if you buy the board) - I asked if I can share my target files with the mbed-os community but so far no response. My custom board I can't as it is a client design (but I have accounted for TCXO) - it is pretty much the reference design with provision for an external crystal and for TCXO to be GPIO switched. I'd build another one to test with bare minimum components but can't source the Type ABZ modules at the moment. This issue shows up on the DISCO LRWAN1 board too. If I dig in to the SX1276 driver though you supply a TCXO pin I don't think it actually does anything with it so I have manually disabled it. You can measure the impact (about 1mA from memory) but that doesn't help (see https://github.com/ARMmbed/mbed-os-example-lorawan/issues/222).
Here mine
D12 is PB14 in my case
Does the "LoRaWAN.h" in GrumpPizza switch it? If I search _tcxo in mbed SX1276_LoRaRadio.cpp I can see it turned on on line 212 but then not referenced again.
Yep - I can see specific calls in the libraries and looks like the GPIOs are configured better too when it's off for deep sleep:
# https://github.com/GrumpyOldPizza/ArduinoCore-stm32l0/blob/b1cf1cd6eba2f06bbe4edbe76aa43ae5971e8d8c/system/STM32L0xx/Source/LoRa/Boards/cmwx1zzabz-board.c
# Line 134
void SX1276SetBoardTcxo( bool state )
{
if (RADIO_TCXO_VCC != STM32L0_GPIO_PIN_NONE)
{
if( state == true )
{
stm32l0_gpio_pin_configure(RADIO_TCXO_VCC, (STM32L0_GPIO_PARK_NONE | STM32L0_GPIO_PUPD_NONE | STM32L0_GPIO_OSPEED_HIGH | STM32L0_GPIO_OTYPE_PUSHPULL | STM32L0_GPIO_MODE_OUTPUT));
stm32l0_gpio_pin_write(RADIO_TCXO_VCC, 1);
}
else
{
stm32l0_gpio_pin_configure(RADIO_TCXO_VCC, (STM32L0_GPIO_PARK_NONE | STM32L0_GPIO_MODE_ANALOG));
}
}
}
Then called to turn off in the SX1276 sleep function
# https://github.com/GrumpyOldPizza/ArduinoCore-stm32l0/blob/b1cf1cd6eba2f06bbe4edbe76aa43ae5971e8d8c/system/STM32L0xx/Source/LoRa/Radio/sx1276/sx1276.c
# Line 885
if( SX1276.TcxoOn )
{
SX1276SetBoardTcxo( false );
SX1276.TcxoOn = false;
}
And back on again in the standby function
# https://github.com/GrumpyOldPizza/ArduinoCore-stm32l0/blob/b1cf1cd6eba2f06bbe4edbe76aa43ae5971e8d8c/system/STM32L0xx/Source/LoRa/Radio/sx1276/sx1276.c
# Line 912
if( !SX1276.TcxoOn )
{
SX1276SetBoardTcxo( true );
tcxoTimeout = SX1276GetBoardTcxoWakeupTime( );
if( tcxoTimeout )
{
SX1276Delay( tcxoTimeout );
}
SX1276.TcxoOn = true;
}
But this is a (related but) separate issue to deep sleep current when TCXO is hard-coded off (though does imply this library has a more detailed implementation so more likely to minimise current consumption).
I have had a break-through and am now getting down to 7uA!
I created a new SX1276 radio class which extends the original and overrides the sleep() and wakeup() methods.
I have only tested sleep but it looks like this so far:
void sleep() final
{
// call actual sleep method
SX126X_LoRaRadio::sleep();
// Set low power for pins
GPIO_InitTypeDef GPIO_InitStructure = {0};
// Disable ant switch (PA_15)
GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = (GPIO_PIN_15);
__GPIOA_CLK_ENABLE();
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
__GPIOA_CLK_DISABLE();
// Disable SPI pins (SCLK PB_13, MISO PB_14, MOSI PB_15)
GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = (GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
__GPIOB_CLK_ENABLE();
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
__GPIOB_CLK_DISABLE();
}
I have tried with CS (PB_12) with various pull up settings but this always results in ~1mA so assume this is turning the radio back on. Don't know if this accounts for the missing 5uA.
Don't know if there is a better MBED way of doing this in PeripheralPins.c. Also not sure if there are any global sleep / wakeup hooks that could be used instead as part of the sleep manager.
Will also need to work-out how to reverse in the wakeup() override.
HW deinit seems like it might be a (very long term) outstanding mbed issue https://github.com/ARMmbed/mbed-os/issues/3106 @jeromecoutant - any way to deinit / init SPI just for an STM32L0 target?
Description of defect
Inability to enter sleep mode (or at least reach expected sleep mode average current) after calling
static LoRaWANInterface lorawan(radio);
when working with NRF52840-DK + SX1262MB2xAS mbed shieldeven when building with Develop profile. Results in average "sleep" current of ~6.5mA. Uncommenting all code before main() (except for above line) and removing all code except sleep_for within main() yields expected sleep current (~14uA).
Target(s) affected by this defect ?
NRF52840-DK
Toolchain(s) (name and version) displaying this defect ?
Mbed Studio 1.4.0
What version of Mbed-os are you using (tag or sha) ?
6.3.0
What version(s) of tools are you using. List all that apply (E.g. mbed-cli)
Mbed CLI 2
How is this defect reproduced ?
Set up 2 NRF52840 DK's: one with PowerProfilerKit, another with SX1262MB2xAS mbed shield. Connect both to PC via microUSB (not nRF USB). Have PPK DK power LoRa shield DK via External supply, switch power on LoRaDK ON, nRF ONLY switch, VEXT->nRF switch to ON. Load up nRF Connect utility for the power profiler kit application, and enable DUT power and monitoring.
Use the default example for this sketch, but remove most of the code such that all that remains looks as below:
change the following in mbed_app.json:
"target_overrides": { "*": { "platform.stdio-convert-newlines": true, "platform.stdio-baud-rate": 115200, "platform.default-serial-baud-rate": 115200, "lora.over-the-air-activation": true, "lora.duty-cycle-on": false, "lora.phy": "US915", "lora.device-eui": "{ 0x00, 0x80, 0xA0, 0xD0, 0x09, 0xEA, 0x82, 0x37 }", "lora.application-eui": "{ 0x70, 0xB3, 0xD5, 0x7E, 0xD0, 0x03, 0xE4, 0x02 }", "lora.application-key": "{ 0xEE, 0xB6, 0x72, 0x7D, 0xEB, 0x52, 0x08, 0x1C, 0x2E, 0x32, 0xC4, 0x3B, 0xB8, 0x96, 0x86, 0x6D }", "target.components_add": ["SX126X"], "lora.app-port": 2, "lora.fsb-mask": "{0xFF00, 0x0000, 0x0000, 0x0000, 0x0002}" },
"macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_lora_config.h\"", "MBED_TICKLESS=1"]
Now, compile, upload and compare the average currents when
static LoRaWANInterface lorawan(radio);
is commented, and uncommented. For me, results for commented are ~14uA average sleep current over 52ms period, while uncommented shows an average sleep current of approximately 6.5mA over 52ms period.