Skip to content

Commit e02dee3

Browse files
committed
MCU8MASS-1754 Move over to use _delay_ms in the library to prevent hang ups with the millis timer during low power
1 parent a9b6dc8 commit e02dee3

File tree

9 files changed

+196
-86
lines changed

9 files changed

+196
-86
lines changed

src/http_client.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <stdio.h>
99
#include <stdlib.h>
1010
#include <string.h>
11+
#include <util/delay.h>
1112

1213
// We only use profile 0 to keep things simple we also stick with spId 3
1314
// which we dedicate to HTTPS
@@ -123,7 +124,7 @@ static HttpResponse sendData(const char* endpoint,
123124

124125
// Wait some before delivering the payload. The modem might hang if we
125126
// deliver it too quickly
126-
delay(100);
127+
_delay_ms(100);
127128

128129
// Now we deliver the payload
129130
SequansController.writeBytes(data, data_length);

src/led_ctrl.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "led_ctrl.h"
22
#include "log.h"
33

4+
#include <util/delay.h>
5+
46
#ifdef __AVR_AVR128DB48__ // MINI
57

68
#define LED_CELL_PIN PIN_PA0
@@ -95,21 +97,21 @@ void LedCtrlClass::toggle(Led led, bool is_from_system_event) {
9597
void LedCtrlClass::startupCycle() {
9698
for (int i = int(Led::CELL); i <= int(Led::USER); i++) {
9799
this->on(Led(i));
98-
delay(50);
100+
_delay_ms(50);
99101
}
100102

101103
for (int i = int(Led::CELL); i <= int(Led::USER); i++) {
102104
this->off(Led(i));
103-
delay(50);
105+
_delay_ms(50);
104106
}
105107

106108
for (int i = int(Led::USER); i >= int(Led::CELL); i--) {
107109
this->on(Led(i));
108-
delay(50);
110+
_delay_ms(50);
109111
}
110112

111113
for (int i = int(Led::USER); i >= int(Led::CELL); i--) {
112114
this->off(Led(i));
113-
delay(50);
115+
_delay_ms(50);
114116
}
115117
}

src/low_power.cpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
#include "log.h"
55
#include "lte.h"
66
#include "sequans_controller.h"
7+
#include "timeout_timer.h"
78

89
#include <Arduino.h>
910
#include <Wire.h>
1011
#include <avr/io.h>
1112
#include <avr/sleep.h>
13+
#include <util/delay.h>
1214

1315
#define AT_COMMAND_DISABLE_EDRX "AT+SQNEDRX=0"
1416
#define AT_COMMAND_ENABLE_PSM "AT+CPSMS=1,,,\"%s\",\"%s\""
@@ -214,7 +216,7 @@ attemptToEnterPowerSaveModeForModem(const unsigned long waiting_time_ms) {
214216
SequansController.setPowerSaveMode(0, NULL);
215217

216218
do {
217-
delay(50);
219+
_delay_ms(50);
218220
SequansController.clearReceiveBuffer();
219221
} while (SequansController.isRxReady());
220222

@@ -223,11 +225,11 @@ attemptToEnterPowerSaveModeForModem(const unsigned long waiting_time_ms) {
223225
ring_line_activity = false;
224226

225227
// Now we wait until the ring line to stabilize
228+
const TimeoutTimer timeout_timer(waiting_time_ms);
226229
unsigned long last_time_active = millis();
227-
const unsigned long start_time = millis();
228230

229231
do {
230-
delay(PSM_WAITING_TIME_DELTA_MS);
232+
_delay_ms(PSM_WAITING_TIME_DELTA_MS);
231233

232234
// Reset timer if there has been activity or the RING line is high
233235
if (ring_line_activity || RING_PORT.IN & RING_PIN_bm) {
@@ -239,7 +241,7 @@ attemptToEnterPowerSaveModeForModem(const unsigned long waiting_time_ms) {
239241
modem_is_in_power_save = true;
240242
return true;
241243
}
242-
} while (millis() - start_time < waiting_time_ms);
244+
} while (!timeout_timer.hasTimedOut());
243245

244246
return false;
245247
}
@@ -314,6 +316,7 @@ static void enablePIT(void) {
314316
temp = CLKCTRL.XOSC32KCTRLA;
315317
temp &= ~CLKCTRL_ENABLE_bm;
316318
_PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, temp);
319+
317320
while (CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm) {
318321
__asm__ __volatile__("nop\n\t");
319322
}
@@ -330,16 +333,21 @@ static void enablePIT(void) {
330333
temp |= CLKCTRL_ENABLE_bm;
331334
_PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, temp);
332335

336+
RTC.CLKSEL |= RTC_CLKSEL_XOSC32K_gc;
337+
333338
// Wait for registers to synchronize
334339
while (RTC.PITSTATUS) { __asm__ __volatile__("nop\n\t"); }
335340

336-
RTC.CLKSEL |= RTC_CLKSEL_XOSC32K_gc;
337341
RTC.PITINTCTRL |= RTC_PI_bm;
338342
RTC.PITCTRLA |= RTC_PERIOD_CYC32768_gc | RTC_PITEN_bm;
339343

344+
// Wait for registers to synchronize
345+
while (RTC.PITSTATUS) { __asm__ __volatile__("nop\n\t"); }
346+
340347
// The first PIT intterupt will not necessarily be at the period specified,
341348
// so we just wait until it has triggered and track the reminaing time from
342349
// there
350+
343351
while (!pit_triggered) { __asm__ __volatile__("nop\n\t"); }
344352
pit_triggered = false;
345353
}
@@ -629,7 +637,7 @@ static void enableLDO(void) {
629637
digitalWrite(LOWQ_PIN, HIGH);
630638

631639
// Wait a little to let LDO mode settle
632-
delay(100);
640+
_delay_ms(100);
633641
}
634642

635643
/**
@@ -640,7 +648,7 @@ static void disableLDO(void) {
640648
digitalWrite(LOWQ_PIN, LOW);
641649

642650
// Wait a little to let PWM mode settle
643-
delay(100);
651+
_delay_ms(100);
644652
}
645653

646654
/**
@@ -785,8 +793,7 @@ void LowPowerClass::powerSave(void) {
785793

786794
enableLDO();
787795

788-
// It's important that we stop the millis after enabling the LDO, as it
789-
// uses delay() to wait for the LDO mode to settle
796+
// Stop millis interrupt
790797
stop_millis();
791798

792799
sleep_cpu();
@@ -816,8 +823,7 @@ void LowPowerClass::powerDown(const uint32_t power_down_time_seconds) {
816823
enablePIT();
817824
enableLDO();
818825

819-
// It's important that we stop the millis after enabling the LDO, as it uses
820-
// delay() to wait for the LDO mode to settle
826+
// Stop millis interrupt to prevent the timer waking up the core
821827
stop_millis();
822828

823829
uint32_t remaining_time_seconds = power_down_time_seconds;

src/lte.cpp

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
#include "log.h"
55
#include "mqtt_client.h"
66
#include "sequans_controller.h"
7+
#include "timeout_timer.h"
78

89
#include <Arduino.h>
10+
#include <util/delay.h>
911

1012
#define AT_CONNECT "AT+CFUN=1"
1113
#define AT_DISCONNECT "AT+CFUN=0"
@@ -100,7 +102,7 @@ static void timezoneCallback(__attribute__((unused)) char* buffer) {
100102

101103
bool LteClass::begin(const uint32_t timeout_ms, const bool print_messages) {
102104

103-
const uint32_t start = millis();
105+
const TimeoutTimer timeout_timer(timeout_ms);
104106

105107
// If low power is utilized, sequans controller will already been
106108
// initialized, so don't reset it by calling begin again
@@ -111,7 +113,7 @@ bool LteClass::begin(const uint32_t timeout_ms, const bool print_messages) {
111113
// Disconnect before configuration if already connected
112114
SequansController.writeCommand(AT_DISCONNECT);
113115

114-
delay(100);
116+
_delay_ms(100);
115117
SequansController.clearReceiveBuffer();
116118

117119
SequansController.registerCallback(TIMEZONE_CALLBACK, timezoneCallback);
@@ -162,17 +164,16 @@ bool LteClass::begin(const uint32_t timeout_ms, const bool print_messages) {
162164
Log.infof("Connecting to operator");
163165
}
164166

165-
while (!isConnected() && millis() - start < timeout_ms) {
167+
while (!isConnected() && !timeout_timer.hasTimedOut()) {
166168
LedCtrl.toggle(Led::CELL, true);
167-
delay(500);
169+
_delay_ms(500);
168170

169171
if (print_messages) {
170172
Log.rawf(".");
171173
}
172174
}
173175

174-
if (millis() - start >= timeout_ms) {
175-
176+
if (!isConnected()) {
176177
Log.rawf(" Was not able to connect to the network within the timeout "
177178
"of %d ms. Consider increasing the timeout or checking your "
178179
"cellular coverage.\r\n",
@@ -223,26 +224,32 @@ bool LteClass::begin(const uint32_t timeout_ms, const bool print_messages) {
223224

224225
// Not valid time, have to do sync. First we wait some to see if we get
225226
// the timezone URC
226-
const unsigned long start = millis();
227-
while (millis() - start < TIMEZONE_WAIT_MS && !got_timezone) {}
227+
const TimeoutTimer timezone_timer(TIMEZONE_WAIT_MS);
228+
229+
while (!timezone_timer.hasTimedOut() && !got_timezone) {}
228230

229231
if (!got_timezone) {
230-
// Do manual sync with NTP server
231232

233+
// Do manual sync with NTP server
232234
if (print_messages) {
233235
Log.info("Did not get time from operator, doing NTP sync. "
234236
"This can take some time...");
235237
}
236238

237239
// Will break from this when we get the NTP sync
238-
while (true) {
240+
241+
const TimeoutTimer ntp_sync_timer(timeout_ms);
242+
bool got_ntp_sync = false;
243+
244+
while (!ntp_sync_timer.hasTimedOut() && !got_ntp_sync) {
239245

240246
// We might be disconnected from the network whilst doing the
241247
// NTP sync, so return if that is the case
242248
if (!isConnected()) {
243-
Lte.end();
244249
Log.warn(
245250
"Got disconnected from network whilst doing NTP sync");
251+
SequansController.unregisterCallback(TIMEZONE_CALLBACK);
252+
Lte.end();
246253
return false;
247254
}
248255

@@ -262,9 +269,19 @@ bool LteClass::begin(const uint32_t timeout_ms, const bool print_messages) {
262269

263270
if (buffer[NTP_STATUS_INDEX] == NTP_OK) {
264271
Log.info("Got NTP sync!");
272+
got_ntp_sync = true;
265273
break;
266274
}
267275
}
276+
277+
if (!got_ntp_sync) {
278+
Log.warnf("Did not get NTP sync within timeout of %lu ms. "
279+
"Consider increasing timeout for Lte.begin()\r\n",
280+
timeout_ms);
281+
SequansController.unregisterCallback(TIMEZONE_CALLBACK);
282+
Lte.end();
283+
return false;
284+
}
268285
}
269286
}
270287

@@ -285,8 +302,9 @@ void LteClass::end(void) {
285302

286303
// Wait for the CEREG URC after disconnect so that the modem doesn't
287304
// have any pending URCs and won't prevent going to sleep
288-
uint32_t start = millis();
289-
while (isConnected() && millis() - start < 2000) {}
305+
const TimeoutTimer timeout_timer(2000);
306+
while (isConnected() && !timeout_timer.hasTimedOut()) {}
307+
290308
SequansController.unregisterCallback(CEREG_CALLBACK);
291309

292310
SequansController.clearReceiveBuffer();

src/mqtt_client.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ static void internalConnectedCallback(char* urc_data) {
180180
SequansController.writeBytes((uint8_t*)MQTT_DISCONNECT,
181181
strlen(MQTT_DISCONNECT),
182182
true);
183-
delay(10);
184183
SequansController.clearReceiveBuffer();
185184

186185
if (disconnected_callback != NULL) {
@@ -195,7 +194,6 @@ static void internalDisconnectCallback(char* urc_data) {
195194
SequansController.writeBytes((uint8_t*)MQTT_DISCONNECT,
196195
strlen(MQTT_DISCONNECT),
197196
true);
198-
delay(10);
199197
SequansController.clearReceiveBuffer();
200198

201199
if (disconnected_callback != NULL) {
@@ -402,8 +400,6 @@ bool MqttClientClass::begin(const char* client_id,
402400
SequansController.writeBytes((uint8_t*)MQTT_DISCONNECT,
403401
strlen(MQTT_DISCONNECT),
404402
true);
405-
406-
delay(100);
407403
SequansController.clearReceiveBuffer();
408404

409405
// -- Configuration --
@@ -531,15 +527,20 @@ bool MqttClientClass::end(void) {
531527
SequansController.unregisterCallback(MQTT_ON_CONNECT_URC);
532528
SequansController.unregisterCallback(MQTT_ON_DISCONNECT_URC);
533529

534-
SequansController.writeBytes((uint8_t*)MQTT_DISCONNECT,
535-
strlen(MQTT_DISCONNECT),
536-
true);
537-
delay(10);
538-
SequansController.clearReceiveBuffer();
530+
if (isConnected()) {
539531

540-
internalDisconnectCallback(NULL);
532+
SequansController.writeBytes((uint8_t*)MQTT_DISCONNECT,
533+
strlen(MQTT_DISCONNECT),
534+
true);
541535

542-
connected_to_broker = false;
536+
SequansController.clearReceiveBuffer();
537+
538+
connected_to_broker = false;
539+
}
540+
541+
if (disconnected_callback != NULL) {
542+
disconnected_callback();
543+
}
543544

544545
return true;
545546
}

0 commit comments

Comments
 (0)