Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2012 / uCOS / uCOSII_ebook.pdf
Скачиваний:
82
Добавлен:
10.02.2015
Размер:
1.08 Mб
Скачать

2.24 Message Mailboxes

Messages can be sent to a task through kernel services. A Message Mailbox, also called a message exchange, is typically a pointer size variable. Through a service provided by the kernel, a task or an ISR can deposit a message (the pointer) into this mailbox. Similarly, one or more tasks can receive messages through a service provided by the kernel. Both the sending task and receiving task will agree as to what the pointer is actually pointing to.

A waiting list is associated with each mailbox in case more than one task desires to receive messages through the mailbox. A task desiring to receive a message from an empty mailbox will be suspended and placed on the waiting list until a message is received. Typically, the kernel will allow the task waiting for a message to specify a timeout. If a message is not received before the timeout expires, the requesting task is made ready-to-run and an error code (indicating that a timeout has occurred) is returned to it. When a message is deposited into the mailbox, either the highest priority task waiting for the message is given the message (called priority-based) or the first task to request a message is given the message (called First-In-First-Out, or FIFO). Figure 2-16 shows a task depositing a message into a mailbox. Note that the mailbox is represented graphically by an I-beam and the timeout is represented by an hourglass. The number next to the hourglass represents the number of c lock ticks (described later) that the task will wait for a message to arrive.

TASK

Mailbox

POST PEND

10

TASK

Figure 2-16, Message mailbox.

Kernel services are typically provided to:

a)Initialize the contents of a mailbox. The mailbox may or may not initially contain a message.

b)Deposit a message into the mailbox (POST).

c)Wait for a message to be deposited into the mailbox (PEND).

d)Get a message from a mailbox, if one is present, but not suspend the caller if the mailbox is empty (ACCEPT). If the mailbox contains a message, the message is extracted from the mailbox. A return code is used to notify the caller about the outcome of the call.

Message mailboxes can also be used to simulate binary semaphores. A message in the mailbox indicates that the resource is available while an empty mailbox indicates that the resource is already in use by another task.

2.25 Message Queues

A message queue is used to send one or more messages to a task. A message queue is basically an array of mailboxes. Through a service provided by the kernel, a task or an ISR can deposit a message (the pointer) into a message queue. Similarly, one or more tasks can receive messages through a service provided by the kernel. Both the sending task and receiving task will agree as to what the pointer is actually pointing to. Generally, the first message inserted in the queue will be the first message extracted from the queue (FIFO). In addition to extract messages in a FIFO fashion, µC/OS-II allows a task to get messages Last-In-First-Out (LIFO).

As with the mailbox, a waiting list is associated with each message queue in case more than one task is to receive messages through the queue. A task desiring to receive a message from an empty queue will be suspended and placed on the waiting list until a message is received. Typically, the kernel will allow the task waiting for a message to specify a timeout. If a message is not received before the timeout expires, the requesting task is made ready-to-run and an error code (indicating a timeout occurred) is returned to it. When a message is deposited into the queue, either the highest priority task or the first task to wait for the message will be given the message. Figure 2-17 shows an ISR (Interrupt Service Routine) depositing a message into a queue. Note that the queue is represented graphically by a double I -beam. The 10 indicates the number of messages that can be accumulated in the queue. A 0 next to the hourglass indicates that the task will wait forever for a message to arrive.

Kernel services are typically provided to:

a)Initialize the queue. The queue is always assumed to be empty after initialization.

b)Deposit a message into the queue (POST).

c)Wait for a message to be deposited into the queue (PEND).

d)Get a message from a queue, if one is present, but not suspend the caller if the queue is empty (ACCEPT). If the queue contained a message, the message is extracted from the queue. A return code is used to notify the caller about the outcome of the call.

Interrupt

ISR

Queue

POST 10 PEND

0

TASK

Figure 2-17, Message queue.

2.26 Interrupts

An interrupt is a hardware mechanism used to inform the CPU that an asynchronous event has occurred. When an interrupt is recognized, the CPU saves part (or all) of its context (i.e. registers) and jumps to a special subroutine called an Interrupt Service Routine , or ISR. The ISR processes the event and upon completion of the ISR, the program returns to:

a)The background for a foreground/background system.

b)The interrupted task for a non-preemptive kernel.

c)The highest priority task ready-to-run for a preemptive kernel.

Interrupts allow a microprocessor to process events when they occur. This prevents the microprocessor from continuously polling an event to see if this event has occurred. Microprocessors allow interrupts to be ignored and recognized through the use of two special instructions: disable interrupts and enable interrupts, respectively. In a real-time environment, interrupts should be disabled as little as possible. Disabling interrupts affects interrupt latency (see section 2.27, Interrupt Latency) and also, disabling interrupts may cause interrupts to be missed. Processors

generally allow interrupts to be nested. This means that while servicing an interrupt, the processor will recognize and service other (more important) interrupts as shown in Figure 2-18.

TIME

TASK

ISR #1

ISR #2

ISR #3

Interrupt #1

Interrupt #2

Interrupt #3

Figure 2-18, Interrupt nesting.

2.27 Interrupt Latency

Probably the most important specification of a real-time kernel is the amount of time interrupts are disabled. All real-time systems disable interrupts to manipulate critical sections of code and re -enable interrupts when the critical section has executed. The longer interrupts are disabled, the higher the interruptlatency . Interrupt latency is given by:

Maximum amount of time interrupts are disabled +

Time to start executing the first instruction in the ISR

Equation 2.2, Interrupt latency.

2.28 Interrupt Response

Interrupt response is defined as the time between the reception of the interrupt and the start of the user code which will handle the interrupt. The interrupt response time accounts for all the overhead involved in handling an interrupt. Typically, the processor's context (CPU registers) is saved on the stack before the user code is executed.

For a foreground/background system, the user ISR code is executed immediately after saving the processor's context. The response time is given by:

Interrupt latency +

Time to save the CPU's context

Equation 2.3, Interrupt response, foreground/background system.

For a non-preemptive kernel, the user ISR code is executed immediately after the processor's context is saved. The response time to an interrupt for a non-preemptive kernel is given by:

Interrupt latency +

Time to save the CPU's context

Equation 2.4, Interrupt response, Non-preemptive kernel.

For a preemptive kernel, a special function provided by the kernel needs to be called. This function notifies the kernel

that an ISR is in progress and allows the kernel to keep track of interrupt nesting. For µC/OS-II, this function is called OSIntEnter(). The response time to an interrupt for a preemptive kernel is given by:

Interrupt latency +

Time to save the CPU's context +

Execution time of the kernel ISR entry function

Equation 2.5, Interrupt response, Preemptive kernel.

A system's worst case interrupt response time is its only response. Your system may respond to interrupts in 50 µS 99 percent of the time, but if it responds to interrupts in 250 µS the other 1 percent, you must assume a 250 µS interrupt response time.

2.29 Interrupt Recovery

Interrupt recovery is defined as the time required for the processor to return to the interrupted code.

Interrupt recovery in a foreground/background system simply involves restoring the processor's context and returning to the interrupted task. Interrupt recovery is given by:

Time to restore the CPU's context +

Time to execute the return from interrupt instruction

Equation 2.6, Interrupt recovery, Foreground/background system.

As with a foreground/background system, interrupt recovery with a non-preemptive kernel simply involves restoring the processor's context and returning to the interrupted task. Interrupt recovery is thus:

Time to restore the CPU's context +

Time to execute the return from interrupt instruction

Equation 2.7, Interrupt recovery, Non-preemptive kernel.

For a preemptive kernel, interrupt recovery is more complex. Typically, a function provided by the kernel is called at the end of the ISR. For µC/OS-II, this function is called OSIntExit() and allows the kernel to determine if all

interrupts have nested. If all interrupts have nested (i.e. a return from interrupt will return to task level code), the kernel

Соседние файлы в папке uCOS