I’ve got a problem with ADL semaphores. A little background: I connect a small RS232-capable sensor to UART1 of my Fastrack Supreme 20.
This sensor is polled automatically by the modem to generate alarm notifications when necessary. Additionally, the sensor can be queried interactively by using self-written AT commands via the USB serial interface of the modem. Communication with the sensor always involves sending a query and receiving a response. So far, so good.
The task setup in my OpenAT application is as follows:
- Task #0: AT command processing, etc
- Task #1: processing of asynchronous UART1 I/O
- Task #2: periodic query of the sensor
I use a semaphore (that simulates a mutex) to block sensor requests while a different request is currently being processed. This should work well because (a) requests originate from different tasks, so there should be no deadlock, and (b) requests from one task can’t be issued recursively, this is assured.
Processing a single sensor request involves the following steps:
- the calling task consumes the semaphore
- the calling tasks writes bytes to the UART (asynchronously)
- Task #1 receives indication that write is completed (via message queue)
- Task #1 programs a timeout for the response
- Task #1 receives indication about response received (or timeout) via message queue
- Task #1 does post-processing and produces the semaphore
This scheme works extremely well as long as there are no concurrent requests involved. The problem I see is that this scheme somehow deadlocks in the following situation:
- Task #2 consumes the semaphore
- Task #2 writes data to the UART
- Task #1 is notified that write is completed
- Task #0 tries to consume the semaphore and is suspended
- the on_receive_complete UART callback is invoked and sends a message to Task #1
- Task #1 never wakes up and cannot procuce the semaphore
I would expect Task #0 to be suspended by adl_semConsume[Delay] so that there’s no reason why Task #1 should be unable to run. However, (verified by traces), this is exactly what I DO see. Am I doing something wrong?
I would love to stick with the semaphore (instead of, say, having a third process that just serializes sensor requests), because the semaphore gives an effective rate-limiting at the request-producer side, which may be important if the sensor is not responding and we have to wait for the timeouts to occur and requests arrive faster than we can process them.