tests/periph_rtc: fix system locks in ISR#13035
Conversation
|
This also makes the code a better example as not so much stuff is happening in the interrupt. Just call |
Hm, even though Therefore, I would prefer to keep this mechanism. The global variable can be avoided in same way as with mutex. I pushed a small fixup. |
@benpicco Is it okay for you to keep the mutex? |
|
Sorry I forgot about this PR. |
c503534 to
bc6457e
Compare
No problem, I'm usually pinging after some time? |
|
Squashed. |
|
Hm, with this patch the test stops working on |
|
Really? Strange. |
smlng
left a comment
There was a problem hiding this comment.
try to add a msg queue to the main, maybe that helps to make it work on the failing platforms
tests/periph_rtc/main.c
Outdated
| @@ -54,15 +56,10 @@ static void inc_secs(struct tm *time, unsigned val) | |||
| static void cb(void *arg) | |||
| { | |||
| (void)arg; | |||
There was a problem hiding this comment.
not needed, arg is used in msg_try_send
tests/periph_rtc/main.c
Outdated
| inc_secs(&time, PERIOD); | ||
| rtc_set_alarm(&time, cb, NULL); | ||
| } | ||
| memset(&msg, 1, sizeof(msg_t)); |
There was a problem hiding this comment.
why? I don't think that's necessary.
|
OK, this is such a silly bug: The RTC callback argument was just never set on lpc2387… Still, I think the mutex solution is much simpler: diff --git a/tests/periph_rtc/main.c b/tests/periph_rtc/main.c
index 4cb3e6e86..7ec6120f2 100644
--- a/tests/periph_rtc/main.c
+++ b/tests/periph_rtc/main.c
@@ -53,16 +53,7 @@ static void inc_secs(struct tm *time, unsigned val)
static void cb(void *arg)
{
- (void)arg;
-
- puts("Alarm!");
-
- if (++cnt < REPEAT) {
- struct tm time;
- rtc_get_alarm(&time);
- inc_secs(&time, PERIOD);
- rtc_set_alarm(&time, cb, NULL);
- }
+ mutex_unlock(arg);
}
int main(void)
@@ -76,6 +67,8 @@ int main(void)
.tm_sec = 57
};
+ mutex_t rtc_mutex = MUTEX_INIT_LOCKED;
+
puts("\nRIOT RTC low-level driver test");
printf("This test will display 'Alarm!' every %u seconds for %u times\n",
PERIOD, REPEAT);
@@ -91,12 +84,25 @@ int main(void)
/* set initial alarm */
inc_secs(&time, PERIOD);
print_time(" Setting alarm to ", &time);
- rtc_set_alarm(&time, cb, NULL);
+ rtc_set_alarm(&time, cb, &rtc_mutex);
/* verify alarm */
rtc_get_alarm(&time);
print_time(" Alarm is set to ", &time);
puts("");
+ while (1) {
+
+ mutex_lock(&rtc_mutex);
+ puts("Alarm!");
+
+ if (++cnt < REPEAT) {
+ struct tm time;
+ rtc_get_alarm(&time);
+ inc_secs(&time, PERIOD);
+ rtc_set_alarm(&time, cb, &rtc_mutex);
+ }
+ }
+
return 0;
}It also saves 688 bytes of ROM on |
|
I'm still a little reluctant to use the mutex API in an ISR even if an unlock is not blocking. How about using a thread flag as a synchronization mechanism. |
But why? This is a common pattern. |
Hm, even in RIOT? In FreeRTOS there are special functions If we start using |
Yes even in RIOT. (picked those at random)
Not necessarily if they think about it for a bit.
Yea that's probably a good idea. |
Ok, that's good to know.
I already ran into problems with a driver (I don't remember which one) that tried to read the sensor data via I2C from an ISR. The problem was that I2C uses of course a mutex to coordinate the acccess. I can provide a PR with a warning in mutex documentation. |
Yea but that issue there is that it's not obvious that I2C and SPI operations involve acquiring a mutex.
That'd be great! |
benpicco
left a comment
There was a problem hiding this comment.
Much simpler now :)
Please squash.
tests/periph_rtc/main.c
Outdated
| inc_secs(&time, PERIOD); | ||
| rtc_set_alarm(&time, cb, NULL); | ||
| } | ||
| mutex_unlock((mutex_t *)arg); |
There was a problem hiding this comment.
You don't need to cast the void*
There was a problem hiding this comment.
Changed. I squashed it directly, I hope that's ok for this small change.
d839083 to
c01768b
Compare
`tests/periph` calls the functions `rtc_get_alarm` and `rtc_set_alarm` from an ISR. Depending on the implementation of `periph_rtc`, however, these functions use `newlib` functions such as `localtime` and `mktime`, which in turn call the `newlib` lock function `__tz_lock`. This can lead to a system lock if the `newlib` with real lock functionality is used instead of the `newlib_nano`.
c01768b to
46dbd86
Compare
That was suggested in any discussion about mutex and ISRs in the past (I couldn't find it again).
|
|
Ok, all lights are green. |
Contribution description
This PR fixes a system lock that occurs when the
newlibwith real locking functionality is used instead of thenewlib_nano.tests/periphcalls the functionsrtc_get_alarmandrtc_set_alarmfrom an ISR. Depending on the implementation ofperiph_rtc, these functions may usenewlibfunctions such aslocaltimeandmktime, which in turn call thenewliblock function__tz_lock. This can lead to a system lock if thenewlibwith real lock functionality is used instead of thenewlib_nano.This PR moves the call of the
rtc_get_alarmandrtc_set_alarmfunctions from interrupt context to the thread context of the main thread. The ISR just sends a message to the main thread to inform the about the interrupt. The interrupt is then handled in thread context.The problem was figured out while testing PR #12955.
Testing procedure
The PR has to be tested together with PR #12955.
In PR #12955,
tests/periph_rtcblocks without this PR, but works with this PR.Issues/PRs references
Fixes partially issue #12732
Prerequisite for PR #12955