Real-Time Library: RTX AG & AH 1 What is an RTOS? An RTOS is a special version of an operating system that provides a more deterministic behaviour for the tasks under its control. At its core is a Real-Time Executive(RTX). The RTX provides the primitives to Create, Manage and Schedule tasks Manage and use time in controlling tasks allow inter-task communication through: semaphores mutexes events mailboxes 4-2 What is a Task? For our purposes we can consider a task to be a basic unit of programming that the operating system controls. Our tasks will be written in 'C' and be of the form of an endless while(1) loop. We will use a simple RTX to create and manage our tasks. Our application programs will consist of a number of tasks which are controlled by the RTX and that communicate with each other using some of the RTX features. Covered later! void task1(void) { while(1) { // do task 1 } void task2(void) { while(1) { // do task 2 } void task3(void) { while(1) { // do task 3 } } } } 4-3 The Scheduler At the Kernel of the RTX is the scheduler Responsible for allocating CPU time to the tasks. A hardware timer provides a basic "tick" to measure time. "tick" time is configurable and affects responsiveness of the system. Default RTX tick time is 10ms. This scheduler is essentially a timer interrupt that allots a certain amount of execution time to each task. So task1 may run for 100ms then be de-scheduled to allow task2 to run for a similar period; task 2 will give way to task3, and finally control passes back to task1. By allocating these slices of runtime to each task in a roundrobin fashion, we get the appearance of all three tasks running in parallel to each other. 4-4 The Scheduler In order to make the task-switching process happen, we have the code overhead of the RTOS and we have to dedicate a CPU hardware timer to provide the RTOS time reference. For ARM7 and ARM9 this must be a timer provided by the microcontroller peripherals. In a Cortex-M microcontroller, RTX will use the SysTick timer within the Cortex-M processor. 4-5 The Scheduler Each time we switch running tasks the RTOS saves the state of all the task variables to a task stack and stores the runtime information about a task in a Task Control Block. The “context switch time”, that is, the time to save the current task state and load up and start the next task, is a crucial value and will depend on both the RTOS kernel and the design of the underlying hardware. 4-6 Task states A task can be in one of four basic states, RUNNING, READY, WAITING, or INACTIVE. In a given system only one task can be running, that is, the CPU is executing its instructions while all the other tasks are suspended in one of the other states If, during our RTOS program, there is no task running and no task ready to run (e.g. they are all waiting on delay functions), then RTX uses the spare runtime to call an “Idle Demon 4-7 Simple Round Robin Scheduler All tasks have the same priority and tasks run in turn on the CPU for a given number of "time quanta" or "ticks". CPU Task at front of queue selected to run Ready Queue of tasks. 8 The running task Round Robin time out. Task put on end of ready queue. Example with three tasks T1, T2 and T3 Each task runs for the Round Robin time. Running task T1 T2 T3 T1 T2 T3 T1 Time 9 etc. Round Robin with task waiting queues Task at front of queue selected to run Typically a running task often has to wait for some resource therefore is removed from the CPU and is placed in a queue. CPU The running task Round Robin time out Queue of ready to run tasks NB. There is a system task called os_idle_demon that runs when there are no tasks in the ready queue. 10 Tasks waiting for mutex, semaphore or mailbox Tasks waiting for event(s) Tasks becomes ready and rejoin queue of ready tasks Delayed and periodic tasks Example with three tasks T1, T2 and T3 T1 execution time is 50ms then delays for 180ms second,T2 and T3 never delay and the round robin time is 50ms. Assume ready queue is T1,T2,T3. T1 T2 T3 T2 T3 T2 T1 T3 T2 Time ms 0 50 100 150 200 250 300 350 T1 delays for 180ms T1 delays itself for 180ms 11 T1 now joins ready queue, at time 230ms. T1run after T2. Remember it joins the end of the queue. Round Robin with Priority scheduling Highest priority task is selected when CPU free. Queue of ready Tasks queue sorted into priority order 12 CPU Running task doesn't need to run for a certain time so relinquishes the CPU. The running task Round Robin time up Tasks waiting for mutex, semaphore or mailbox Tasks waiting for event(s) Tasks becomes ready and rejoin queue of ready tasks Delayed and periodic tasks Round Robin with Priority Scheduling E.g.Three tasks T1, T2 with priority 4 in the ready queue and T3 with priority 6 is in a waiting queue.T3 is an event driven task that executes in 30ms. T1 T2 T1 T3 T2 T1 T2 T1 Time ms 0 50 100 Time 125ms: T3 becomes ready and joins ready queue. 13 150 200 Time 150ms: T3 now runs because highest priority ready task. 250 300 350 Time 180ms: T3 runs for 30ms then relinquishes CPU and joins a waiting queue again. Scheduler runs next task from the ready queue. Round Robin Priority scheduling with pre-emption. Pre-empt running task if a higher priority task is ready. Highest priority task is selected when CPU free. Queue of ready Tasks queue sorted into priority order CPU Running task doesn't need to run for a certain time so relinquishes the CPU. The running task Round Robin time up Tasks waiting for mutex, semaphore or mailbox Tasks waiting for event(s) Tasks becomes ready and rejoin queue of ready tasks 14 Delayed and periodic tasks Round Robin Priority scheduling with pre-emption. E.g.Tasks T1, T2 with priority 4 both in the ready queue and T3 with priority 6 is in a waiting queue. 6 Priority 5 4 T3 T1 T2 T1 T1 T2 T1 T2 T1 Time ms 0 50 100 150 Time 125ms: T3 becomes ready and immediately pre-empts the currently running task. because it is higher priority. 15 200 250 300 350 Time 155ms: T3 runs for 30ms then relinquishes the CPU and joins a waiting queue again. Pre-empted T1 is restarted and runs for the rest of its round robin time - assuming it is still the highest priority. The ARM RL-RTX We will be using a Real Time eXecutive with the ARM based board Keil MCB 2300 To use the RTX the file RTL.h must be included in the 'C' source file and the operating system project option set to use the RTX Kernel. There are 35 RTX related functions providing facilities for: 16 task creation and management time management events mutexes semaphores mailboxes #include <RTL.h> The RTX Scheduler - Timer Tick Interrupt 17 The RTX kernel for ARM7™ uses one of the standard ARM timers to generate a periodic interrupt. This interrupt is called the RTX kernel timer tick. For some of the RTX library functions, you must specify timeouts and delay intervals as a number of RTX kernel timer ticks. The parameters for the RTX kernel timer are selected in the RTC_Config.c configuration file. For example, the RTX_Config.c file for NXP LPC23XX use Timer 0, 1,2 or 3 for the RTX kernel timer. RTX_Config.c The timer clock value specifies the input clock frequency and depends on CPU clock and APB clock. For a device with CPU clock 48 MHz and VPB divider 4 the peripheral clock is 12MHz and therefore the value is set to 12000000. The time tick value specifies the interval of the periodic RTX interrupt. The value 10000 us configures timer tick period of 0.01 seconds. 18 Starting the OS and Task Creation Start the OS and creating the first task with a default priority of 1. void os_sys_init(task_name); os_sys_init (begin); // start os then start task begin Create tasks OS_TID os_task_create(task_name, priority); t1_ID = os_tsk_create (task1, 4); t2_ID = os_tsk_create (task2, 6); t1_ID and t2_ID must have been declare globals in the program : 19 OS_TID t1_ID, t2_TID; Task Creation Start the OS and create the initial task. void os_sys_init(task_name); /* priority defaults to 1 os_sys_init (begin); // start os then start task begin To create further tasks the initial task uses: OS_TID os_task_create(task_name, priority); Example OS_TID t1_ID; // define a task ID variable // now create the task t1_ID = os_task_create (task1, 4); priority is from 1 to 255. 1 being the lowest priority. Beware: If task1 is now the highest priority it will pre-empt the current task!! 20 Tasks are basically 'C' functions with the special attribute __task added before the function definition. Other Task Management Functions os_tsk_delete - Terminates a selected task – os_tsk_delete_self -Terminates the running task os_tsk_self - Returns the task ID of the running task os_tsk_pass - Passes control to the next task ready to run os_tsk_prio - Changes the priority of a given task os_tsk_prio_self - Changes the priority of the running task 21 Typical task A task is nothing more than a 'C' function. The task will usually be in the form of an endless while loop that never terminates. Many tasks are periodic E.g. __task void mytask(void) { /* create variables for this task */ while(1) { /* do stuff */ os_dly_wait(100); /* periodic - so have a rest */ } } 22 Time Management functions void os_dly_wait(n_ticks) Pauses the –calling task for a specified interval. void os_itv_set(n_ticks) Enables the calling task for periodic wake up. void os_itv_wait(n_ticks) Pauses the calling task until the periodic wake up interval expires. Examples FIO2SET = LED_A; os_dly_wait(10); FIO2CLR = LED_A; 23 void task1 (void) __task { os_itv_set(20); while(1) { FIO2PIN ^= LED_A; // toggle led os_itv_wait(); } } Event Flag Management functions Used to provide very simple inter-task signalling. os_evt_clr Clears one or more event flags of a task. os_evt_get Retrieves the event flags that caused os_evt_wait_or to complete. os_evt_set Sets one or more event flags of a task. os_evt_wait_and Waits for one or more event flags to be set. os_evt_wait_or Waits for any one event flag to be set. isr_evt_set Sets one or more event flags of a task. 24 Better inter-task communication methods are available - coming soon! RTX Based Program Operation 'C' main function should Start OS and first task. First task will: initialise system ready for other tasks initialise I/O create and initialise global systems feature such as : mutexes semaphores filesystems etc Start the other tasks Terminate self 25 Now other tasks run & operate concurrently. A first example - RTX01.c Before any of the RTX functions can be used the RTX must be started. os_sys_init (taskname); This function initialises and starts the RTX and then starts the taskname task. The initial task is given the default priority of 1 NOTES: The os_sys_init function must be called from the main C function. The os_sys_init function NEVER returns! 26 Starting the OS and the application tasks. #include <RTL.h> /* ... */ OS_TID t1_ID, t2_ID, t3_ID; /* create task IDs */ int main (void) { uint32_t volatile start; /* Wait for debugger connection */ for (start = 0; start < 1000000; start++) { ; } os_sys_init (begin);/* Initialize OS and start the initial task */ } __task void begin (void) { os_tsk_prio_self(10); /* increase priority of this task */ /* initialise system peripherals etc. here */ t1_ID = os_tsk_create (task1, 4); /* start task1 */ t2_ID = os_tsk_create (task2, 2); /* start task2 */ t3_ID = os_tsk_create (task3, 1); /* start task3 */ os_tsk_delete_self (); } 27