Книга: Real-Time Concepts for Embedded Systems
15.7.2 Asynchronous Data Reception from Multiple Data Communication Channels
15.7.2 Asynchronous Data Reception from Multiple Data Communication Channels
Commonly, a daemon task receives data from multiple input sources, which implies that data arrives on multiple message queues. A task cannot block and wait for data on multiple message queues. Therefore, in such cases, multiple sources may use a single semaphore to signal the arrival of data. A task cannot block and wait on multiple semaphores either.
The task blocks and waits on the semaphore. Each ISR inserts data in the corresponding message queue followed by a give operation on the semaphore.
As shown in Figure 15.18, a single interrupt lock is sufficient to protect against multiple interrupt sources, as long as the masked interrupt level covers these sources. Both the interrupt service routines use a single semaphore as the signal channel.
Figure 15.18: Task waiting on multiple input sources.
Listing 15.3 shows the code that the task runs when multiple input message queues are present. Note that the semaphore used in this case is a binary semaphore.
Listing 15.3: Pseudo code for task waiting on multiple input sources.
while (Get(Binary_Semaphore))
disable(interrupts)
for (each msgQueue)
get msgQueueLength
for (msgQueueLength)
remove a message
enable(interrupts)
process the message
disable(interrupts)
endfor
endfor
enable(interrupts)
end while
Some RTOS kernels do not have the event-register object. Implementing the event register using the common basic primitives found in the majority of the RTOS kernels can be quite useful when porting applications from one RTOS to another.
The event-register object can be implemented using a shared variable, an interrupt lock, and a semaphore. The shared variable stores and retrieves the events. The interrupt lock guards the shared variable because ISRs can generate events through the event register. The semaphore blocks the task wanting to receive desired events.
Event_Receive(wanted_events) {
task_cb.wanted_events = wanted_events
While (TRUE)
Get(task_cb.event_semaphore)
disable(interrupts)
events = wanted_events XOR task_cb.recvd_events
task_cb.wanted_events = task_cb.wanted_event AND (NOT events)
enable(interrupts)
If (events is not empty)
return (events)
endIf
EndWhile
}
The variable task_cb refers to the task control block, in which the kernel keeps its private, task-specific information. Note that the unwanted events are not cleared because the task can call event_receive some time later.
Event_Send(events) {
disable(interrupts)
task_cb.recvd_events = task_cb.recvd_events OR events
enable(interrupts)
Give(task_cb.event_semaphore)
}
- 15.7.1 Data Transfer with Flow Control
- 15.7.2 Asynchronous Data Reception from Multiple Data Communication Channels
- 15.7.3 Multiple Input Communication Channels
- 15.7.4 Using Condition Variables to Synchronize between Readers and Writers
- 15.7.5 Sending High Priority Data between Tasks
- 15.7.6 Implementing Reader-Writer Locks Using Condition Variables
- Информация заголовочной страницы (Database header)
- Database dialect
- Инструкция INSERT INTO ... FROM ... UNION ...
- DATABASE CACHE SIZE
- Data sending and control session
- SCTP DATA chunk
- Integrated Secure Communications System
- Creating CDs from the Command Line
- Data Binding Using the GridView Control
- Interbase DataPump
- GetDataBack
- Работа с DataRow