User Guide

Overview
As it is said - a picture is worth a thousand words!


Kernel Dispatcher primitives
Logically, there are two main levels of code execution -USER and KERNEL level. We consider the code executed in an interrupt handler a KERENL level code. It is important to note that the code is executed in an arbitrary stack and register context of a user task which implies that used registers should be preserved on the current task stack(Mind the tasks' stack overrun!). A very small number of API functions is available to this level. All the rest is USER level code.
The basic macro, the kernel consists of is _TASK_SWITCH(5).It is actually the dispatcher - the low level scheduler - which decides what is the next task in the system to run and then carries out the task switch to that task. Generally the selection of the task is done on a priority basis. The USER land code is separated into two levels at which the Task's code executes for this kernel implementation:
  • PASSIVE LEVEL(7) - this is the usual level at which a normal user task executes. All CPU resources "belong" to the task during its time quantum. Make sure user level API is called in this level.
  • DEVICE LEVEL(6) - the high level at which the deferred interrupt processing happens. A task could transition from PASSIVE to DEVICE and backwards as many times as it is needed in order to provide best real time processing conditions. It is the interrupt dispatcher which elevates the Tasks's level to DEVICE one as a result of a device interrupt.

Physically the dispatcher consists of the following:
  • a macro which executes an implementation specific algorithm to decide what task will be the next to run when system control exits the kernel. It is activated on each tick of the scheduling timer or when a task relinguishes its time quantum.
  • a collection of data structures which contain all the information that the kernel needs to know about a task (these structures are known as the task control blocks or the task descriptors).
Basically the kernel algorithm is:
  • save the tasks context on its stack.This means that all CPU registers and current stack pointer are preserved.
  • search the tasks marked as high priority tasks in a round robin fashion. Keep servicing high priority tasks until all go back to normal level
  • search the next normal level task to execute if a higher priority task is not found. There is always one task that is elligable to execute - system zero task.
  • restore the state of the selected task by localizing its stack.

Task primitives
The basic unit of execution is a task(4). It is statically created at the CPU initialization(1) and remains in memory until the CPU is powered on. Each task has an initialize(2) portion which is synchronized by a barrier(3) to guarantee that no task enters its body until all has passed the initialization section.
Each task is given a small amount of time to execute its code called quantum. During that time it has all the resources at its disposal so a poorly designed task could crash the system.
  • _REGISTER_TASK - task register macro. All tasks should be predefined! The size and starting position of the task stack is calculated.
  • _YIELD_TASK - relinquish the task quantum by activating the dispatcher.
  • _SLEEP_TASK - sleep the task for a certain period of time.
  • _SUSPEND_TASK - make the task not scheduleable. The dispatcher completely ignores the task.
  • _RESUME_TASK - make the task scheduleable.

Synchronization primitives
The kernel provides a set of primitives which simultaneously allow intertask synchronization,notification and critical section protection.
  • _START_EXECUTIVE_MODE - enter critical section implementation. The disabling of interrupts in the task will protect the shared resource from corruption but it leads to undesirable side effects, namely that interrupts can be disabled for considerable lengths of time depending on the nature of the manipulations on the shared data structure. In a real time system this could lead to performance problems due to the disruption of the precision of the timing. Use for a short amount of time.
  • _END_EXECUTIVE_MODE - leave critical section - enable interrupts
  • _EVENT_SET,_EVENT_CLEAR,_EVENT_WAIT - basic event structure. Used for inter-tasks event notification.
  • _MUTEX_WAIT,_MUTEX_RELEASE - basic mutex structure. Used for resource integrity protection. Only one task can access certain resources.
  • _BARRIER_WAIT - basic barrier.A barrier is a coordination mechanism that forces chosen tasks to wait until each one of them has reached a certain point in its task code. Simple application of the barrier is setting one at the end of each Acorn kernel task initialization segment thus garanteeing no task will proceed until all of the tasks has processed the initialization segment.

Interrupts
An interrupt is a means by which a physical I/O device can let the processor know that it wants attention (see ATMEL CPU for the particular interrupt sources).Each interrupt handler is considered a unit of code that is executed in an atomic fashion. The kernel presumes that the interrupt handler can not be interrupted by another interrupt!All registers accessed from within the handler must be saved on the current task stack. It runs in the context of the interrupted task and therefore becomes effectively a part of this task during its execution as far as the dispatcher is concerned. The task has a limited amount of stack so make sure stack overrun is avoided.
  • _START_EXECUTIVE_MODE - enter critical section implementation. The disabling of interrupts in the task will protect the shared resource from corruption but it leads to undesirable side effects, namely that interrupts can be disabled for considerable lengths of time depending on the nature of the manipulations on the shared data structure. In a real time system this could lead to performance problems due to the disruption of the precision of the timing. Use for a short amount of time.
  • PRE_INTERRUPT,POST_INTERRUPT - wrap each interrupt handler with this code. It preserves the CPU STATUS register.
  • _INTERRUPT_DISPATCH - interrupt dispatch is used to implement the so called differed interrupt processing. It is desirable to spend as little time in interrupt handler as possible so the very interrupt processing is left for a user task that will execute at a high privilege level.
  • _INTERRUPT_WAIT,_INTERRUPT_END - user task marked as interrupt processing task.
  • _DISPATCH_TO_EXTENTION - the interrupt processing code is injected into the interrupted task by the interrupt.

Memory management.
All memory structures are calculated and initialized at CPU reset.
There is one TCB(task control block) per task which consists of 4 bytes
  • 2 bytes - keeps task stack pointer(LSB,MSB).
  • 1 byte - task status byte.Task priority bit,schedulability bit ...
  • 1 byte - sleep time out in units.
CPU RAM is fragmented so that each task has a certain size of ram stack. The stack starts from the ram end towards the static ram structures and variables.
Comments

First solution

By Sergei on Wed Jan 19 08:31:15 UTC 2011

Actually there is a solution if i properly understood what you want.
Right after you send a character invoke SLEEP_TASK.You can tweak the Timer1 interval which is responsible for SLEEP_TASK calculations.Choose an interrupt close to 50ms and call SLEEP_TASK 1.
Now when the sleep interval is over you can check a global variable if the receive interrupt was invoked.
If you can't solve your problem please Contact me(see the contact area for my email).
We may eventually design a wait event with timeout macro!
We my also publish the solution or a snipet of it in the Application area

timer

By Anonymous on Tue Jan 18 22:47:57 UTC 2011

i am doing some serial programming using acorn kernel.
The program is interrupt driven and written in asm.
I would like to have a time out function so if the return data is not received in 50ms
i can try to resend or cause an error, and if the data is received bypass the 50ms timer wait.
since there it no timer
function in acorn i am not sure how to do this can you please help.

Screen Name
Subject
Comment