[riot-devel] Current best practice for sleeping in a device driver?

Nikander Pekka pekka.nikander at aalto.fi
Thu Sep 13 10:33:49 CEST 2018


Hi Joakim, all,

It turns out that locking the mutex twice sometimes blocks the thread.  Or at least it does that in my implementation, when running with multiple other threads.

My updated nRF52 ADC driver can be found here:

   https://github.com/AaltoNEPPI/RIOT/blob/feature-nrf52-adc-interrupts/cpu/nrf52/periph/adc.c#L171

The commit that changes from polling to interrupts is here:

  https://github.com/AaltoNEPPI/RIOT/commit/4eaf9ff275b903bf2eab97874cc6171e2cbbc974

I'm currently working on this on our own custom board (made by Aalto students) with custom peripherals, so there isn't any easy way I could provide a test program.  But I'll make one unless I manage to fix this.

When running just one thread, the ADC driver works just fine.  However, when I combine it with my main program, with multiple threads, the "CT" thread that calls the ADC driver blocks at some point.  All other threads continue running and the system is stable.

ps shows as follows:
```
	pid | name                 | state    Q | pri | stack  ( used) | base addr  | current     
	  - | isr_stack            | -        - |   - |   8192 (  712) | 0x200022b8 | 0x20004268
	  1 | idle                 | pending  Q |  15 |   1024 (  192) | 0x20004abc | 0x20004dfc 
	  2 | main                 | bl rx    _ |   7 |   1536 (  612) | 0x200044bc | 0x2000499c 
	  3 | BLE                  | bl rx    _ |   2 |   2048 ( 2044) | 0x20006080 | 0x20006794 
	  4 | led_thread           | bl rx    _ |   6 |   2048 ( 2044) | 0x200068fc | 0x2000700c 
	  5 | MPU                  | bl rx    _ |   5 |   2048 ( 2044) | 0x20004f4c | 0x20005644 
	  6 | CT                   | bl mutex _ |   8 |   2048 ( 2044) | 0x20007114 | 0x200077cc 
	  7 | shell                | running  Q |   8 |   2048 ( 2044) | 0x200057fc | 0x20005e14 
	    | SUM                  |            |     |  20992 (11736)
```

There are no other mutexes in the CT thread; hence, I'm 99.9% sure that it blocks at the ADC driver mutex.

I'll proceed next to implement what I suggested earlier:

> Hence, I would suggest that we add a couple of new functions, for example:
> 
>    void thread_sleep_keep_mutex(mutex_t *m);
>    void thread_wakeup_mutex(mutex_t *);
> 
> The first one would basically just lock the mutex second time, but it could be called with interrupts already disabled.  It would enable interrupts while the thread is sleeping, and disable them again before returning, if they were disabled when called.  As an additional safeguard, it would check that the calling thread already possesses the mutex.
> 
> The second one would wakeup one thread sleeping on the mutex.  In practice, it would be just syntactic sugar over mutex_unlock().

I'll report what happens.

--Pekka



More information about the devel mailing list