cancel
Showing results for 
Search instead for 
Did you mean: 

STM32LE5 blocks main thread during lorawan uplink

ASL07
Visitor

I have an application consisting on two different tasks:

1. Control a DMX bus which requires the MCU to transmit a command to the UART every 22ms

2. Send an uplink message via Lora periodically (every 10 seconds for example)

I am using the RAK3172 SoC which is based on the STM32WLE5CC (single core Cortex-M4)

I am hypothesizing that the LORA stack blocks the single core context for up to 100ms during the lora transmission. During this time, the main thread does not execute. Is this correct? And if so, is is possible to minimize the time the main thread is blocked?
I am using Arduino just for the PoC. I am also open to experiment with FreeRTOS multi threading, but I suspect that this is a design limitation and cannot be worked around due to having a single core. I see there is a similar post  created by @jflaxman which exposes a similar problem. The user reported they worked around it by adding a separate MCU for the background task and using the STM strictly for LORA comms.

In order to prove my hypothesis I have built a simple Arduino sketch. The program simply calls a loop() function continuously and profiles the amount taken on each iteration. If the interval between the calls to loop() exceeds the 22ms required a message is printed to the serial port.

The loop function is as follows:

void sendPacket() {
  uint32_t now = millis();
  if (api.lorawan.send(sizeof(buffer), (uint8_t*)&buffer, 2)) {
    uint32_t elapsed = millis() - now;
    Serial.print("send() took ");
    Serial.print(elapsed);
    Serial.println(" ms");
  } else {
    Serial.println("Sending failed");
  }
}

void loop() {
  static uint64_t last_rs = 0;
  static uint64_t last_lora = 0;
  static uint64_t elapsed_rs;
  static uint64_t elapsed_lora;
  static uint32_t lastMillis = millis();  // Measure the milliseconds to check how often loop() is executed

  uint32_t now = millis();
  uint32_t difference = now - lastMillis;
  if (difference > DMX_INTERVAL_MILLIS && now >= lastMillis) {
    Serial.print("Interval between loop() calls is too high (should be <22): ");
    Serial.print(difference);
    Serial.print(" Now: ");
    Serial.print(now);
    Serial.print(" Last: ");
    Serial.print(lastMillis);
    Serial.println();
  }

  if ((elapsed_lora = millis() - last_lora) > OTAA_INTERVAL) {  // UPLINK LORAWAN TEST POR INTERVALOS
    RAK_LORA_chan_rssi chan_arssi;
    sendPacket();
    last_lora = millis();
  }

  lastMillis = millis();
}

Below is an example of the serial port output:

send() took 1 ms
+EVT:TX_DONE
Interval between loop() calls is too high (should be <22): 110 Now: 22774 Last: 22664
send() took 1 ms
+EVT:TX_DONE
Interval between loop() calls is too high (should be <22): 103 Now: 33762 Last: 33659
send() took 1 ms
+EVT:TX_DONE
Interval between loop() calls is too high (should be <22): 110 Now: 42686 Last: 42576
send() took 1 ms
+EVT:TX_DONE


Some observations after looking at the output:
- The send() function is non blocking, as it returns within <1ms
- The loop() function takes less than 22ms to execute, unless a lora uplink message is being transmitted
- When a lora message is being transmitted, there is an observed latency of up to 100ms in the loop function()
- This latency indicates some blocking of the main thread somewhere internally within the LORA stack


Thanks for taking the time to assist me with this in advance. I am open to test this further and provide additional information if required.


0 REPLIES 0