Skip to content

Commit 83fc580

Browse files
authored
Merge pull request #11773 from fkjagodzinski/fix-watchdog_reset_test
Fix watchdog reset test
2 parents 9ca69cf + 55e1a76 commit 83fc580

File tree

3 files changed

+98
-71
lines changed

3 files changed

+98
-71
lines changed

TESTS/mbed_drivers/watchdog_reset/main.cpp

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@
7272
*/
7373
#define SERIAL_FLUSH_TIME_MS 20
7474

75+
#define TIMEOUT_US (1000 * (TIMEOUT_MS))
76+
#define KICK_ADVANCE_US (1000 * (KICK_ADVANCE_MS))
77+
#define SERIAL_FLUSH_TIME_US (1000 * (SERIAL_FLUSH_TIME_MS))
78+
7579
using utest::v1::Case;
7680
using utest::v1::Specification;
7781
using utest::v1::Harness;
@@ -84,13 +88,21 @@ struct testcase_data {
8488
uint32_t received_data;
8589
};
8690

87-
void release_sem(Semaphore *sem)
91+
testcase_data current_case;
92+
93+
Thread wdg_kicking_thread(osPriorityNormal, 768);
94+
Semaphore kick_wdg_during_test_teardown(0, 1);
95+
96+
void wdg_kicking_thread_fun()
8897
{
89-
sem->release();
98+
kick_wdg_during_test_teardown.acquire();
99+
Watchdog &watchdog = Watchdog::get_instance();
100+
while (true) {
101+
watchdog.kick();
102+
wait_us(20000);
103+
}
90104
}
91105

92-
testcase_data current_case;
93-
94106
bool send_reset_notification(testcase_data *tcdata, uint32_t delay_ms)
95107
{
96108
char msg_value[12];
@@ -124,11 +136,11 @@ void test_simple_reset()
124136
TEST_ASSERT_TRUE(watchdog.start(TIMEOUT_MS));
125137
TEST_ASSERT_TRUE(watchdog.is_running());
126138
// Watchdog should fire before twice the timeout value.
127-
wait_ms(2 * TIMEOUT_MS); // Device reset expected.
139+
wait_us(2 * TIMEOUT_US); // Device reset expected.
128140

129-
// Watchdog reset should have occurred during wait_ms() above;
141+
// Watchdog reset should have occurred during a wait above.
130142

131-
watchdog.kick(); // Just to buy some time for testsuite failure handling.
143+
kick_wdg_during_test_teardown.release(); // For testsuite failure handling.
132144
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
133145
}
134146

@@ -143,8 +155,6 @@ void test_sleep_reset()
143155
}
144156

145157
// Phase 1. -- run the test code.
146-
Semaphore sem(0, 1);
147-
Timeout timeout;
148158
if (send_reset_notification(&current_case, 2 * TIMEOUT_MS) == false) {
149159
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
150160
return;
@@ -154,22 +164,21 @@ void test_sleep_reset()
154164
TEST_ASSERT_TRUE(watchdog.start(TIMEOUT_MS));
155165
TEST_ASSERT_TRUE(watchdog.is_running());
156166
sleep_manager_lock_deep_sleep();
157-
// Watchdog should fire before twice the timeout value.
158-
timeout.attach_us(mbed::callback(release_sem, &sem), 1000ULL * (2 * TIMEOUT_MS));
159167
if (sleep_manager_can_deep_sleep()) {
160168
TEST_ASSERT_MESSAGE(0, "Deepsleep should be disallowed.");
161169
return;
162170
}
163-
sem.wait(); // Device reset expected.
171+
// Watchdog should fire before twice the timeout value.
172+
ThisThread::sleep_for(2 * TIMEOUT_MS); // Device reset expected.
164173
sleep_manager_unlock_deep_sleep();
165174

166-
// Watchdog reset should have occurred during sem.wait() (sleep) above;
175+
// Watchdog reset should have occurred during the sleep above.
167176

168-
watchdog.kick(); // Just to buy some time for testsuite failure handling.
177+
kick_wdg_during_test_teardown.release(); // For testsuite failure handling.
169178
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
170179
}
171180

172-
#if DEVICE_LOWPOWERTIMER
181+
#if DEVICE_LPTICKER
173182
void test_deepsleep_reset()
174183
{
175184
// Phase 2. -- verify the test results.
@@ -180,27 +189,28 @@ void test_deepsleep_reset()
180189
}
181190

182191
// Phase 1. -- run the test code.
183-
Semaphore sem(0, 1);
184-
LowPowerTimeout lp_timeout;
185-
if (send_reset_notification(&current_case, 2 * TIMEOUT_MS) == false) {
192+
if (send_reset_notification(&current_case, 2 * TIMEOUT_MS + SERIAL_FLUSH_TIME_MS) == false) {
186193
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
187194
return;
188195
}
196+
wait_us(SERIAL_FLUSH_TIME_US); // Wait for the serial buffers to flush.
189197
Watchdog &watchdog = Watchdog::get_instance();
190198
TEST_ASSERT_FALSE(watchdog.is_running());
191199
TEST_ASSERT_TRUE(watchdog.start(TIMEOUT_MS));
192200
TEST_ASSERT_TRUE(watchdog.is_running());
193-
// Watchdog should fire before twice the timeout value.
194-
lp_timeout.attach_us(mbed::callback(release_sem, &sem), 1000ULL * (2 * TIMEOUT_MS));
195-
wait_ms(SERIAL_FLUSH_TIME_MS); // Wait for the serial buffers to flush.
196201
if (!sleep_manager_can_deep_sleep()) {
197202
TEST_ASSERT_MESSAGE(0, "Deepsleep should be allowed.");
198203
}
199-
sem.wait(); // Device reset expected.
200204

201-
// Watchdog reset should have occurred during sem.wait() (deepsleep) above;
205+
// The Watchdog reset is allowed to be delayed up to twice the timeout
206+
// value when the deepsleep mode is active.
207+
// To make the test less sensitive to clock/wait accuracy, add 20% extra
208+
// (making tha whole deepsleep wait equal to 2.2 * timeout).
209+
ThisThread::sleep_for(220 * TIMEOUT_MS / 100); // Device reset expected.
210+
211+
// Watchdog reset should have occurred during the deepsleep above.
202212

203-
watchdog.kick(); // Just to buy some time for testsuite failure handling.
213+
kick_wdg_during_test_teardown.release(); // For testsuite failure handling.
204214
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
205215
}
206216
#endif
@@ -226,13 +236,13 @@ void test_restart_reset()
226236
TEST_ASSERT_FALSE(watchdog.is_running());
227237
TEST_ASSERT_TRUE(watchdog.start(TIMEOUT_MS));
228238
TEST_ASSERT_TRUE(watchdog.is_running());
229-
wait_ms(TIMEOUT_MS / 2UL);
239+
wait_us(TIMEOUT_US / 2);
230240
TEST_ASSERT_TRUE(watchdog.stop());
231241
TEST_ASSERT_FALSE(watchdog.is_running());
232242
// Check that stopping the Watchdog prevents a device reset.
233243
// The watchdog should trigger at, or after the timeout value.
234244
// The watchdog should trigger before twice the timeout value.
235-
wait_ms(TIMEOUT_MS / 2UL + TIMEOUT_MS);
245+
wait_us(TIMEOUT_US / 2 + TIMEOUT_US);
236246

237247
if (send_reset_notification(&current_case, 2 * TIMEOUT_MS) == false) {
238248
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
@@ -241,11 +251,11 @@ void test_restart_reset()
241251
TEST_ASSERT_TRUE(watchdog.start(TIMEOUT_MS));
242252
TEST_ASSERT_TRUE(watchdog.is_running());
243253
// Watchdog should fire before twice the timeout value.
244-
wait_ms(2 * TIMEOUT_MS); // Device reset expected.
254+
wait_us(2 * TIMEOUT_US); // Device reset expected.
245255

246-
// Watchdog reset should have occurred during that wait() above;
256+
// Watchdog reset should have occurred during a wait above.
247257

248-
watchdog.kick(); // Just to buy some time for testsuite failure handling.
258+
kick_wdg_during_test_teardown.release(); // For testsuite failure handling.
249259
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
250260
}
251261

@@ -266,19 +276,19 @@ void test_kick_reset()
266276
for (int i = 3; i; i--) {
267277
// The reset is prevented as long as the watchdog is kicked
268278
// anytime before the timeout.
269-
wait_ms(TIMEOUT_MS - KICK_ADVANCE_MS);
279+
wait_us(TIMEOUT_US - KICK_ADVANCE_US);
270280
watchdog.kick();
271281
}
272282
if (send_reset_notification(&current_case, 2 * TIMEOUT_MS) == false) {
273283
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
274284
return;
275285
}
276286
// Watchdog should fire before twice the timeout value.
277-
wait_ms(2 * TIMEOUT_MS); // Device reset expected.
287+
wait_us(2 * TIMEOUT_US); // Device reset expected.
278288

279-
// Watchdog reset should have occurred during that wait() above;
289+
// Watchdog reset should have occurred during a wait above.
280290

281-
watchdog.kick(); // Just to buy some time for testsuite failure handling.
291+
kick_wdg_during_test_teardown.release(); // For testsuite failure handling.
282292
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
283293
}
284294

@@ -313,6 +323,10 @@ int testsuite_setup(const size_t number_of_cases)
313323
return utest::v1::STATUS_ABORT;
314324
}
315325

326+
// The thread is started here, but feeding the watchdog will start
327+
// when the semaphore is released during a test case teardown.
328+
wdg_kicking_thread.start(mbed::callback(wdg_kicking_thread_fun));
329+
316330
utest_printf("This test suite is composed of %i test cases. Starting at index %i.\n", number_of_cases,
317331
current_case.start_index);
318332
return current_case.start_index;
@@ -322,7 +336,7 @@ Case cases[] = {
322336
Case("Watchdog reset", case_setup, test_simple_reset),
323337
#if DEVICE_SLEEP
324338
Case("Watchdog reset in sleep mode", case_setup, test_sleep_reset),
325-
#if DEVICE_LOWPOWERTIMER
339+
#if DEVICE_LPTICKER
326340
Case("Watchdog reset in deepsleep mode", case_setup, test_deepsleep_reset),
327341
#endif
328342
#endif

TESTS/mbed_hal/watchdog_reset/main.cpp

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,11 @@
6666
* flushing the Tx FIFO would take: 16 * 8 * 1000 / 9600 = 13.3 ms.
6767
* To be on the safe side, set the wait time to 20 ms.
6868
*/
69-
#define SERIAL_FLUSH_TIME_MS 20
69+
#define SERIAL_FLUSH_TIME_MS 20
70+
71+
#define TIMEOUT_US (1000 * (TIMEOUT_MS))
72+
#define KICK_ADVANCE_US (1000 * (KICK_ADVANCE_MS))
73+
#define SERIAL_FLUSH_TIME_US (1000 * (SERIAL_FLUSH_TIME_MS))
7074

7175
using utest::v1::Case;
7276
using utest::v1::Specification;
@@ -78,13 +82,20 @@ struct testcase_data {
7882
uint32_t received_data;
7983
};
8084

81-
void release_sem(Semaphore *sem)
85+
testcase_data current_case;
86+
87+
Thread wdg_kicking_thread(osPriorityNormal, 768);
88+
Semaphore kick_wdg_during_test_teardown(0, 1);
89+
90+
void wdg_kicking_thread_fun()
8291
{
83-
sem->release();
92+
kick_wdg_during_test_teardown.acquire();
93+
while (true) {
94+
hal_watchdog_kick();
95+
wait_us(20000);
96+
}
8497
}
8598

86-
testcase_data current_case;
87-
8899
bool send_reset_notification(testcase_data *tcdata, uint32_t delay_ms)
89100
{
90101
char msg_value[12];
@@ -116,11 +127,11 @@ void test_simple_reset()
116127
}
117128
TEST_ASSERT_EQUAL(WATCHDOG_STATUS_OK, hal_watchdog_init(&config));
118129
// Watchdog should fire before twice the timeout value.
119-
wait_ms(2 * TIMEOUT_MS); // Device reset expected.
130+
wait_us(2 * TIMEOUT_US); // Device reset expected.
120131

121-
// Watchdog reset should have occurred during wait_ms() above;
132+
// Watchdog reset should have occurred during a wait above.
122133

123-
hal_watchdog_kick(); // Just to buy some time for testsuite failure handling.
134+
kick_wdg_during_test_teardown.release(); // For testsuite failure handling.
124135
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
125136
}
126137

@@ -136,30 +147,27 @@ void test_sleep_reset()
136147

137148
// Phase 1. -- run the test code.
138149
watchdog_config_t config = { TIMEOUT_MS };
139-
Semaphore sem(0, 1);
140-
Timeout timeout;
141150
if (send_reset_notification(&current_case, 2 * TIMEOUT_MS) == false) {
142151
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
143152
return;
144153
}
145154
TEST_ASSERT_EQUAL(WATCHDOG_STATUS_OK, hal_watchdog_init(&config));
146155
sleep_manager_lock_deep_sleep();
147-
// Watchdog should fire before twice the timeout value.
148-
timeout.attach_us(mbed::callback(release_sem, &sem), 1000ULL * (2 * TIMEOUT_MS));
149156
if (sleep_manager_can_deep_sleep()) {
150157
TEST_ASSERT_MESSAGE(0, "Deepsleep should be disallowed.");
151158
return;
152159
}
153-
sem.wait(); // Device reset expected.
160+
// Watchdog should fire before twice the timeout value.
161+
ThisThread::sleep_for(2 * TIMEOUT_MS); // Device reset expected.
154162
sleep_manager_unlock_deep_sleep();
155163

156-
// Watchdog reset should have occurred during sem.wait() (sleep) above;
164+
// Watchdog reset should have occurred during the sleep above.
157165

158-
hal_watchdog_kick(); // Just to buy some time for testsuite failure handling.
166+
kick_wdg_during_test_teardown.release(); // For testsuite failure handling.
159167
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
160168
}
161169

162-
#if DEVICE_LOWPOWERTIMER
170+
#if DEVICE_LPTICKER
163171
void test_deepsleep_reset()
164172
{
165173
// Phase 2. -- verify the test results.
@@ -171,24 +179,25 @@ void test_deepsleep_reset()
171179

172180
// Phase 1. -- run the test code.
173181
watchdog_config_t config = { TIMEOUT_MS };
174-
Semaphore sem(0, 1);
175-
LowPowerTimeout lp_timeout;
176-
if (send_reset_notification(&current_case, 2 * TIMEOUT_MS) == false) {
182+
if (send_reset_notification(&current_case, 2 * TIMEOUT_MS + SERIAL_FLUSH_TIME_MS) == false) {
177183
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
178184
return;
179185
}
186+
wait_us(SERIAL_FLUSH_TIME_US); // Wait for the serial buffers to flush.
180187
TEST_ASSERT_EQUAL(WATCHDOG_STATUS_OK, hal_watchdog_init(&config));
181-
// Watchdog should fire before twice the timeout value.
182-
lp_timeout.attach_us(mbed::callback(release_sem, &sem), 1000ULL * (2 * TIMEOUT_MS));
183-
wait_ms(SERIAL_FLUSH_TIME_MS); // Wait for the serial buffers to flush.
184188
if (!sleep_manager_can_deep_sleep()) {
185189
TEST_ASSERT_MESSAGE(0, "Deepsleep should be allowed.");
186190
}
187-
sem.wait(); // Device reset expected.
188191

189-
// Watchdog reset should have occurred during sem.wait() (deepsleep) above;
192+
// The Watchdog reset is allowed to be delayed up to twice the timeout
193+
// value when the deepsleep mode is active.
194+
// To make the test less sensitive to clock/wait accuracy, add 20% extra
195+
// (making tha whole deepsleep wait equal to 2.2 * timeout).
196+
ThisThread::sleep_for(220 * TIMEOUT_MS / 100); // Device reset expected.
197+
198+
// Watchdog reset should have occurred during the deepsleep above.
190199

191-
hal_watchdog_kick(); // Just to buy some time for testsuite failure handling.
200+
kick_wdg_during_test_teardown.release(); // For testsuite failure handling.
192201
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
193202
}
194203
#endif
@@ -212,24 +221,24 @@ void test_restart_reset()
212221
// Phase 1. -- run the test code.
213222
watchdog_config_t config = { TIMEOUT_MS };
214223
TEST_ASSERT_EQUAL(WATCHDOG_STATUS_OK, hal_watchdog_init(&config));
215-
wait_ms(TIMEOUT_MS / 2UL);
224+
wait_us(TIMEOUT_US / 2);
216225
TEST_ASSERT_EQUAL(WATCHDOG_STATUS_OK, hal_watchdog_stop());
217226
// Check that stopping the Watchdog prevents a device reset.
218227
// The watchdog should trigger at, or after the timeout value.
219228
// The watchdog should trigger before twice the timeout value.
220-
wait_ms(TIMEOUT_MS / 2UL + TIMEOUT_MS);
229+
wait_us(TIMEOUT_US / 2 + TIMEOUT_US);
221230

222231
if (send_reset_notification(&current_case, 2 * TIMEOUT_MS) == false) {
223232
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
224233
return;
225234
}
226235
TEST_ASSERT_EQUAL(WATCHDOG_STATUS_OK, hal_watchdog_init(&config));
227236
// Watchdog should fire before twice the timeout value.
228-
wait_ms(2 * TIMEOUT_MS); // Device reset expected.
237+
wait_us(2 * TIMEOUT_US); // Device reset expected.
229238

230-
// Watchdog reset should have occurred during that wait() above;
239+
// Watchdog reset should have occurred during a wait above.
231240

232-
hal_watchdog_kick(); // Just to buy some time for testsuite failure handling.
241+
kick_wdg_during_test_teardown.release(); // For testsuite failure handling.
233242
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
234243
}
235244

@@ -248,19 +257,19 @@ void test_kick_reset()
248257
for (int i = 3; i; i--) {
249258
// The reset is prevented as long as the watchdog is kicked
250259
// anytime before the timeout.
251-
wait_ms(TIMEOUT_MS - KICK_ADVANCE_MS);
260+
wait_us(TIMEOUT_US - KICK_ADVANCE_US);
252261
hal_watchdog_kick();
253262
}
254263
if (send_reset_notification(&current_case, 2 * TIMEOUT_MS) == false) {
255264
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
256265
return;
257266
}
258267
// Watchdog should fire before twice the timeout value.
259-
wait_ms(2 * TIMEOUT_MS); // Device reset expected.
268+
wait_us(2 * TIMEOUT_US); // Device reset expected.
260269

261-
// Watchdog reset should have occurred during that wait() above;
270+
// Watchdog reset should have occurred during a wait above.
262271

263-
hal_watchdog_kick(); // Just to buy some time for testsuite failure handling.
272+
kick_wdg_during_test_teardown.release(); // For testsuite failure handling.
264273
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
265274
}
266275

@@ -295,6 +304,10 @@ int testsuite_setup(const size_t number_of_cases)
295304
return utest::v1::STATUS_ABORT;
296305
}
297306

307+
// The thread is started here, but feeding the watchdog will start
308+
// when the semaphore is released during a test case teardown.
309+
wdg_kicking_thread.start(mbed::callback(wdg_kicking_thread_fun));
310+
298311
utest_printf("This test suite is composed of %i test cases. Starting at index %i.\n", number_of_cases,
299312
current_case.start_index);
300313
return current_case.start_index;
@@ -304,7 +317,7 @@ Case cases[] = {
304317
Case("Watchdog reset", case_setup, test_simple_reset),
305318
#if DEVICE_SLEEP
306319
Case("Watchdog reset in sleep mode", case_setup, test_sleep_reset),
307-
#if DEVICE_LOWPOWERTIMER
320+
#if DEVICE_LPTICKER
308321
Case("Watchdog reset in deepsleep mode", case_setup, test_deepsleep_reset),
309322
#endif
310323
#endif

0 commit comments

Comments
 (0)