This is an example application based on Mbed-OS LoRaWAN protocol APIs. The Mbed-OS LoRaWAN stack implementation is compliant with LoRaWAN v1.0.2 specification.

Dependents:   Projet_de_bachelor_code Projet_de_bachelor_code

Issue: Out of memory failures

I have been trying to port this example to an ST Nucleo L073RZ with a SX1276MB1LAS LoRa WAN radio. It has 20KB of SRAM, 10KB of which are being taken by uninitialized data.

After setting the main stack size to 1024 and disabling memory debug I can get the example to a point where it will join but will then later fail on the next uplink with an error code of -1014 which indicates that the crypto library failed. The failure is a result of the crypto library unable to allocate memory.

I have tried the default, develop, and release profile; all with the same result.

Any thoughts on what else I can disable to free up more SRAM would be helpful.

Thank you, Parker MacKenzie

- Compiler GCC - mbed compile -m nucleo_l073rz -t GCC_ARM

- Changes to mbed_app.json (beyond setting the device eui, app key, and app eui): "lora.phy": 8,

"main_stack_size": { "value": 1024 },

"lora-spi-mosi": { "value": "D11" }, "lora-spi-miso": { "value": "D12" }, "lora-spi-sclk": { "value": "D13" }, "lora-cs": { "value": "D10" }, "lora-reset": { "value": "A0" }, "lora-dio0": { "value": "D2" }, "lora-dio1": { "value": "D3" }, "lora-dio2": { "value": "D4" }, "lora-dio3": { "value": "D5" }, "lora-dio4": { "value": "D8" }, "lora-dio5": { "value": "D9" }, "lora-rf-switch-ctl1": { "value": "NC" }, "lora-rf-switch-ctl2": { "value": "NC" }, "lora-txctl": { "value": "NC" }, "lora-rxctl": { "value": "NC" }, "lora-ant-switch": { "value": "NC" }, "lora-pwr-amp-ctl": { "value": "NC" }, "lora-tcxo": { "value": "NC" }

4 comments:

20 Jun 2018

Digging a bit deeper with a little more debugging.

Summary

Long story short, after the uninitialized variables are allocated in the RAM there is not a lot of space for the heap. Finding a way to significantly cut these back should help. The example definitely runs out of memory, likely there is some heap left when it fails but it is likely too fragmented to carve off a 280 Byte chunk. Any thoughts or suggestions would be welcome.

Here are the details

As mentioned in the last post the device is running out of memory. With the main stack size set to 1024 the device will run out of dynamic memory (heap) attempting to send a packet in the aes_ctx_alloc() called by the mbedtls_cipher_setup attempting to allocate 1 block of 280 Bytes through calloc.

First here is the static analysis of the image which shows that 13K of the 20K of SRAM is being used for data and bss (should leave 7K +- for heap)...

Elf2Bin: mbed-os-example-lorawan
+----------------------------+--------+-------+-------+
| Module                     |  .text | .data |  .bss |
+----------------------------+--------+-------+-------+
| [fill]                     |    161 |     4 |    17 |
| [lib]/c.a                  |  26773 |  2472 |    89 |
| [lib]/gcc.a                |  12352 |     0 |     0 |
| [lib]/m.a                  |   1060 |     0 |     0 |
| [lib]/misc                 |    220 |    12 |    28 |
| main.o                     |   1837 |     4 |  5312 |
| mbed-lora-radio-drv/SX1272 |    521 |     0 |     0 |
| mbed-lora-radio-drv/SX1276 |   9561 |     0 |     0 |
| mbed-os/drivers            |   1999 |     4 |   144 |
| mbed-os/events             |   1536 |     0 |     0 |
| mbed-os/features           |  40386 |     8 |    88 |
| mbed-os/hal                |   1915 |     4 |    68 |
| mbed-os/platform           |   3519 |   264 |   349 |
| mbed-os/rtos               |  14691 |   168 |  3001 |
| mbed-os/targets            |  13354 |     4 |  1188 |
| Subtotals                  | 129885 |  2944 | 10284 |
+----------------------------+--------+-------+-------+
Total Static RAM memory (data + bss): 13228 bytes
Total Flash memory (text + data): 132829 bytes

Of the remaining 7K Bytes of static ram almost 6K of it is being allocated to heap:

(gdb) x /12xw 0x200023a0
0x200023a0 <mbed_heap_size>:	0x00001794	0x2000346c	0x00000400	0x20004c00
0x200023b0 <os_isr_queue>:	0x20002068	0x20002068	0x20002068	0x20002068
0x200023c0 <os_isr_queue+16>:	0x20002068	0x20002068	0x20002068	0x00000000
20 Jun 2018

...continued A little more analysis shows 2.5KBytes of the heap are in use as determined using the MBED_HEAP_STATS_ENABLED function. Note that when turning on the debug of the heap (MBED_HEAP_STATS_ENABLED) will cause the program to fail to allocate memory for encryption at the join instead of what is seen here at the ::send() function.

Also to note the stacks are within their limits and the heap is not too incredibly large.

 Adaptive data  rate (ADR) - Enabled 
[ 143] cur:2568 max:2568
[ 146] cur:2568 max:2568

 Connection error, code = -1014 

Heap debugged disabled and stack debug enabled:

 Dummy Sensor Value = 2.1 
Thread: 0x20002D3C, Stack size: 1024, Max stack: 880
Thread: 0x200024BC, Stack size: 512, Max stack: 104
Thread: 0x20002474, Stack size: 768, Max stack: 120
Thread: 0x20002068, Stack size: 1024, Max stack: 376

 send() - Error code -1014 
20 Jun 2018

...continued The following shows the straw (280 Bytes) which is breaking the camels (heap) back.

#0  0x0800a69e in aes_ctx_alloc () at ./mbed-os/features/mbedtls/src/cipher_wrap.c:169
#1  0x0800a5f2 in mbedtls_cipher_setup () at ./mbed-os/features/mbedtls/src/cipher.c:159
#2  0x08007c16 in LoRaMacCrypto::compute_mic () at ./mbed-os/features/lorawan/lorastack/mac/LoRaMacCrypto.cpp:71
#3  0x08005e4a in LoRaMac::prepare_frame () at ./mbed-os/features/lorawan/lorastack/mac/LoRaMac.cpp:1591
#4  0x080072e4 in LoRaMac::send () at ./mbed-os/features/lorawan/lorastack/mac/LoRaMac.cpp:999
#5  0x080073b0 in LoRaMac::send_ongoing_tx () at ./mbed-os/features/lorawan/lorastack/mac/LoRaMac.cpp:1308
#6  0x080043ca in LoRaWANStack::process_scheduling_state () at ./mbed-os/features/lorawan/LoRaWANStack.cpp:1083
#7  0x08004858 in LoRaWANStack::state_controller () at ./mbed-os/features/lorawan/LoRaWANStack.cpp:998
#8  0x08004930 in LoRaWANStack::handle_tx () at ./mbed-os/features/lorawan/LoRaWANStack.cpp:330
#9  0x08003ba4 in LoRaWANInterface::send () at ./mbed-os/features/lorawan/LoRaWANInterface.cpp:122
#10 0x080003f6 in send_message () at ./main.cpp:198
#11 0x080004b2 in lora_event_handler () at ./main.cpp:266
#12 0x08000188 in mbed::Callback<void (lora_events)>::function_call<void (*)(lora_events)>(void const*, lora_events) () at ./mbed-os/platform/Callback.h:1178
#13 0x08003d94 in mbed::Callback<void (lora_events)>::call(lora_events) const () at ./mbed-os/platform/Callback.h:1103
#14 mbed::Callback<void (lora_events)>::operator()(lora_events) const () at ./mbed-os/platform/Callback.h:1109
#15 events::EventQueue::context10<mbed::Callback<void (lora_events)>, lora_events>::operator()() () at ./mbed-os/events/EventQueue.h:2344
#16 events::EventQueue::function_call<events::EventQueue::context10<mbed::Callback<void (lora_events)>, lora_events> >(void*) () at ./mbed-os/events/EventQueue.h:2315
#17 0x08003748 in equeue_dispatch () at ./mbed-os/events/equeue/equeue.c:410
#18 0x08003298 in events::EventQueue::dispatch () at ./mbed-os/events/EventQueue.cpp:35
#19 0x0800036c in events::EventQueue::dispatch_forever () at ./mbed-os/events/EventQueue.h:92
#20 main () at ./main.cpp:170
20 Jun 2018

...continued...

The following disassembly shows the first attempt of the LoRaMAC::send() to allocated an AES context of 280 (r1) Bytes failing (returning 0) (r0).

(gdb) disassemble
Dump of assembler code for function aes_ctx_alloc:
   0x0800a692 <+0>:	movs	r1, #140	; 0x8c
   0x0800a694 <+2>:	push	{r4, lr}
   0x0800a696 <+4>:	lsls	r1, r1, #1
   0x0800a698 <+6>:	movs	r0, #1
=> 0x0800a69a <+8>:	bl	0x8012388 <calloc>
   0x0800a69e <+12>:	subs	r4, r0, #0
   0x0800a6a0 <+14>:	beq.n	0x800a6a6 <aes_ctx_alloc+20>
   0x0800a6a2 <+16>:	bl	0x8009838 <mbedtls_aes_init>
   0x0800a6a6 <+20>:	movs	r0, r4
   0x0800a6a8 <+22>:	pop	{r4, pc}
End of assembler dump.
(gdb) info registers
r0             0x1	1
r1             0x118	280
r2             0x3	3
r3             0x800a693	134260371
r4             0x20001314	536875796
r5             0x801e0f8	134340856
r6             0x20001314	536875796
r7             0x22	34
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0x0	0
r12            0x0	0
sp             0x20002f68	0x20002f68 <_main_stack+480>
lr             0x800a5f3	134260211
pc             0x800a69a	0x800a69a <aes_ctx_alloc+8>
xPSR           0x1000000	16777216
(gdb) ni
0x0800a69e	169	    mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) );
(gdb) disassemble
Dump of assembler code for function aes_ctx_alloc:
   0x0800a692 <+0>:	movs	r1, #140	; 0x8c
   0x0800a694 <+2>:	push	{r4, lr}
   0x0800a696 <+4>:	lsls	r1, r1, #1
   0x0800a698 <+6>:	movs	r0, #1
   0x0800a69a <+8>:	bl	0x8012388 <calloc>
=> 0x0800a69e <+12>:	subs	r4, r0, #0
End of assembler dump.
(gdb) info registers
r0             0x0	0
r1             0x0	0
r2             0x0	0
r3             0x0	0
r4             0x20001314	536875796