# Timer blocking application loop

**URL:** <https://community.particle.io/t/timer-blocking-application-loop/58813>\
**Category:** Firmware\
**Tags:** boron\
**Created:** [December 16, 2020, 10:58pm UTC](https://community.particle.io/t/timer-blocking-application-loop/58813 "2020-12-16T22:58:33Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![daradib](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/daradib/32/17688_2.png) [@daradib](https://community.particle.io/u/daradib)\
**Post date:** [December 16, 2020, 10:58pm UTC](https://community.particle.io/t/timer-blocking-application-loop/58813/1 "2020-12-16T22:58:33Z")

</div>

On a Boron running DeviceOS 1.5.2, timers do not block the application loop, only other timers as expected. When upgraded to DeviceOS 2.0.0, timers using I2C seem to block the application loop, perhaps because of clock stretching.

For example, the timer below wraps a call to [SparkFun\_SHTC3\_Arduino\_Library](https://github.com/sparkfun/SparkFun_SHTC3_Arduino_Library) which commands a measurement over I2C that takes about 10 to 12 ms. I see log warning “delay 13 ms” every 5 seconds, corresponding to the timer, on 2.0.0 but not on 1.5.2.

```auto
SYSTEM_MODE(MANUAL);
SYSTEM_THREAD(ENABLED);

#include "SparkFun_SHTC3.h"

SHTC3 shtc3;
Timer sensorTimer(5000, readSensor);
SerialLogHandler logHandler;
unsigned long now = millis();

void setup() {
  Cellular.off();
  Wire.begin();
  if (shtc3.begin() == SHTC3_Status_Nominal) {
    sensorTimer.start();
  } else {
    Log.error("failed to initialize");
  }
}

void loop() {
  if (millis() - now > 1) {
    Log.warn("delay %lu ms", millis() - now);
  }
  now = millis();
}

void readSensor() {
  WITH_LOCK(Wire) {
    if (shtc3.update() != SHTC3_Status_Nominal) {
      Log.error("measurement failed");
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![armor](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/armor/32/18398_2.png) [@armor](https://community.particle.io/u/armor)\
**Post date:** [December 18, 2020, 4:32pm UTC](https://community.particle.io/t/timer-blocking-application-loop/58813/2 "2020-12-18T16:32:09Z")

</div>

@daradib I wouldn’t structure the readSensor() as a timer handler - timer handlers should be very short and quick - 12mS isn’t! Rather I would use a millis() based timer in the loop thus;

`unsigned long readsensorupdate = 0UL; //global declaration`

in setup()  
`readsensorupdate = millis();`

in loop()

```auto
if (millis() - readsensorupdate >= 5000UL)
{
  readsensorupdate = millis();
  readSensor();
}

```

As others have pointed out - with OS 2.0.0 it is much tighter managing shared resources. Have you tried running the same without `WITH_LOCK(Wire)`?

---

<div class="post-metadata">

**Author:** ![peekay123](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/peekay123/32/810_2.png) [@peekay123](https://community.particle.io/u/peekay123)\
**Post date:** [December 18, 2020, 7:14pm UTC](https://community.particle.io/t/timer-blocking-application-loop/58813/3 "2020-12-18T19:14:41Z")

</div>

To add to @armor’s comments, Software Timers run in a single thread and are daisy-chained so if one timer blocks, the others won’t run. Also, the timer thread doesn’t have a large stack so you have to be careful with the calls you make.

---

<div class="post-metadata">

**Author:** ![daradib](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/daradib/32/17688_2.png) [@daradib](https://community.particle.io/u/daradib)\
**Post date:** [December 19, 2020, 4:43am UTC](https://community.particle.io/t/timer-blocking-application-loop/58813/4 "2020-12-19T04:43:52Z")

</div>

@armor I’m trying to avoid blocking the application loop for more than ~5 ms while commanding an I2C measurement. A millis() based timer is indeed preferable because I wouldn’t have to consider thread safety and the constraints @peekay123 mentioned, but it blocks the thread by design.

I tried removing `WITH_LOCK`, but the timer still blocks the application loop. These lines in the sensor library seem to block regardless of a lock:

```auto
_wire->beginTransmission(SHTC3_ADDR_7BIT);
_wire->write((((uint16_t)cmd) >> 8));
_wire->write((((uint16_t)cmd) & 0x00FF));
res = _wire->endTransmission();

```

A timer running `delayMicroseconds` also blocks, but `delay` does not.

I replaced the timer with a thread and now neither the I2C calls nor `delayMicroseconds` seem to block:

```auto
SYSTEM_MODE(MANUAL);
SYSTEM_THREAD(ENABLED);

#include "SparkFun_SHTC3.h"

SHTC3 shtc3;
Thread *thread = NULL;
system_tick_t lastThreadTime = 0;
SerialLogHandler logHandler;
unsigned long now = 0;

void setup() {
  Cellular.off();
  Wire.begin();
  if (shtc3.begin() == SHTC3_Status_Nominal) {
    thread = new Thread("sensorThread", readSensor, OS_THREAD_PRIORITY_DEFAULT,
                        1024);
  } else {
    Log.error("Failed to initialize");
  }
  now = millis();
}

void loop() {
  if (millis() - now > 1) {
    Log.warn("Delay %lu ms", millis() - now);
  }
  now = millis();
}

void readSensor() {
  while (true) {
    WITH_LOCK(Wire) {
      if (shtc3.update() == SHTC3_Status_Nominal) {
        Log.info("Measurement OK");
      } else {
        Log.error("Measurement failed");
      }
    }
    os_thread_delay_until(&lastThreadTime, 5000);
  }
}

```

It seems if the thread priority is higher than the application thread (OS\_THREAD\_PRIORITY\_DEFAULT), the thread takes precedence and effectively blocks. So I’d speculate that the software timer thread runs at a higher priority in 2.0.0.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/particle/original/3X/6/4/64635adccc35238caa19e9b553ec3e98b163d026.png) [@system](https://community.particle.io/u/system)\
**Post date:** [June 19, 2021, 4:43pm UTC](https://community.particle.io/t/timer-blocking-application-loop/58813/5 "2021-06-19T16:43:54Z")

</div>

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.
