660 likes | 1.14k Views
INTRODUCTION. RTOS ???Real Time Operating SystemWhere used?Satellite systemsMeasuring equipmentGSM (antennas and devices)Cars (e.g. ABS)CamerasMedical instrumentsMotor controlNetwork adaptersRobotsFax machines, copiersPrinters, terminals, scanners, modemsSwitches and routersFlight sys
E N D
1. Real Time Operating Systems
Johan DamsEmail: jd@puv.fi
2. INTRODUCTION RTOS ???
Real Time Operating System
Where used?
Satellite systems
Measuring equipment
GSM (antennas and devices)
Cars (e.g. ABS)
Cameras
Medical instruments
Motor control
Network adapters
Robots
Fax machines, copiers
Printers, terminals, scanners, modems
Switches and routers
Flight systems, weapon systems
Micro-wave systems, dishwashers, thermostats
...
3. MicroC/OS-II (Jean J Labrosse) Free for educational use
Easy as entry level
Can handle 64 tasks (-8 for system)
64 priority levels
Price: $60 book+disk
Implementations exist for:
Win95/98
68HC11
80x86
M16C (!)
4. Foreground/Background systems Foreground
= "Interrupt level"
based on Interrupt Service Routines (ISR)
Background
= "Task level"
Most used
5. Real-Time Systems ConceptDefinitions "Critical Section of Code": has to be treated uninterrupted
Resource (printer, keyboard, but also variable, structure...)
Shared Resource: can be used by more then one task. Mutual Exclusion !!!
Multitasking: process in which CPU-time is divided under multiple tasks
Task or thread :
Thinks it has got the CPU for itself.
Has a priority
Five conditions in which a task can be:
DORMANT
exists in memory
not yet offered to the multitasking kernel
READY
can be executed
has lower priority then running tasks
RUNNING
if the task has control of the CPU
6. Definitions
WAITING
waits for an event (e.g. I/O)
waits for resource to be available
wait till certain time elapses
ISR (Interrupt Service Routine)
if there is an interrupt
Context switch
Context ? See fig.
Task Control Block gets
exchanged by OS with Registers
More CPU registers => more
overhead
7. Definitions Kernel
Piece of a multitasking system that controls tasks
Primary task = context switching
Extra ROM and RAM needed -> problem for single-chip processors
RAM gets eaten
Extra CPU-time needed (2 tot 5%)
Scheduler (or: dispatcher)
controls which task will run
Mostly priority based
Priority-based kernel = gives highest priority task that is ready to run control of the CPU
8. Preemptive and non-preemptive kernels non-preemptive kernel
also: "cooperative multitasking"
A task has to give up the CPU itself
releasing the CPU has to be done fast
small interrupt latency
every task can run completely
before the CPU is released
less danger for corruption
(non-reentrant functions)
bad response on high-priority
tasks
crash of a task, or endless
loop --> ??
9. Preemptive and non-preemptive kernels Preemptive kernel
Used when response time important
eg. microC/OS-II
Highest priority task ALWAYS gets control
Highest priority tasks gets
immediate control
response time very short
Non-reentrant functions
cannot be used!
After execution of task
continue with highest priority
task (not interrupted task)
10. Reentrant functions Can be used by multiple tasks at the same time
Examples:
int Temp;
void swap(int *x, int *y)
{
Temp = *x;
*x = *y;
*y = Temp;
}
void strcpy(char *dest, char *src)
{
while(*dest++ = *src++) {
*dest = NULL;
}
}
11. Round-Robin scheduling When: if 2 or more tasks have the same priority
Every task gets fixed amount of time: a quantum
= time slicing
Alternative: Task priority. Highest priority gets CPU
12. Static and Dynamic priorities Static: priority does not change
Dynamic : priority changes during execution
Dynamic is needed to prevent priority inversions
13. Priority inversions One of the problems when using real time kernels
Situation: 3 tasks with different priority (H-M-L)
Task 1 (High priority) needs a semaphore (resource), occupied by task 3
problem: task 1 (H)
has to wait too long
to start running
14. Priority inversions Solution: give task 3 a very high priority For as long as it occupies the resource
Needed: a kernel
that can change the
priority itself
15. Assigning priorities to tasks SOFT real-time system: tasks dont have to be completed within a certain time
HARD real-time system: tasks have to be completed correctly within time
Method: RMS (Rate Monotonic Scheduling)
Most executed tasks -> highest priority
Demands:
tasks occur regularly
tasks dont exchange anything
preemptive scheduling needed
real-time deadlines are met when
Ei maximum time needed for task i
Ti time between i and i+1
n = number of tasks
16. Assigning task priorities
Conclusion
NUMBER OF TASKS
1 1.000
2 0.828
3 0.779
4 0.756
5 0.743
... ...
0.693
Thus: never use more then 60% to 70% CPU time
17. Mutual Exclusion Demand: exclusive use of a resource
How?
Disable interrupts
Used on critical sections of code
For very short time only
Test-and-set operations
For important sections
Needs more time
Principle:
disable interrupt
test test-and-set variable
Set test-and-set variable to 1
enable interrupt
Access resource
disable interrupt
Set test-and-set variable to 0
enable interrupt
18. Mutual Exclusion
Disable scheduling
Normal: after interrupt, processing goes to highest priority task
Now: after interrupt, processing goes back to interrupted task
Use of semaphores
Better method than disabling scheduling
Invented mid 1960
Principle
Access control on shared resource
Event gets clearly flagged
Two tasks can synchronise
= key you need in order to continue processing
If semaphore in use, keep WAITING until it gets available
Give me the key. If it is in use, Ill keep waiting."
19. Mutual Exclusion Binary semaphore: two conditions, used or not
Counting semaphore:from 0 tot 2^8, 2^16 of 2^32
=> semaphore counts downwards (!)
20. Three semaphore operations INITIALIZE (or CREATE)
initial waiting list is empty
WAIT (or PEND)
a task requests a resource
If semaphore = 0,
next task goes in WAIT
next task is put on waitinglist
If semaphore > 0,
tasks begins execution
semaphore gets decremented
SIGNAL (or POST)
a task releases the semaphore
no task waiting: semaphore incremented
task waiting: key is given to new task
new task is
first task that asked for semaphore (FIFO)
highest priority task
21. Three semaphore operations Example
22. Encapsulated semaphores Principle:
task does not have to control semaphore
Resource controls the semaphore
Typical: driver of the resource solves semaphores
Release of a semaphore is done through a timeout
eg. Network card, serial port, ...
Advantages:
tasks just use the driver
programmer does not have to deal with the semaphores
23. Deadlocks (Deadly embrace) What ?
Two tasks waiting for each others semaphore
Solutions
acquire all resources before proceeding
always acquire resources in the same order and
always release in reverse order
use of time-outs on semaphores
24. Synchronisation What ?
Synchronisation between tasks
Synchronisation between tasks and ISR
How ?
Use of semaphores
"unilateral rendezvous"
semaphore signals an event (flag, NOT a key)
25. Synchronisation
counting semaphores for accumulation of events not processed yet
More than one task can be waiting for event:
highest task first
first task first (FIFO)
"bilateral rendezvous"
synchronising two tasks (not task + ISR) with two semaphores
26. Event Flags When ?
A task has to synchronise with multiple events
Disjunctive synchronisation
logical OR
synchronisation if one of the events occurred
Conjunctive synchronisation
logical AND
synchronisation if all
events occurred
27. Inter task communication What ?
ISR or task sends information to other task
How ?
Global variables
sending messages
Global variables
Make sure you have exclusive access
by disabling and enabling interrupts
by use of semaphores
Alterations are passed on by
use of semaphores
polling of the results
Better methods: "message mailbox" and "message queues"
28. Message mailboxes Principle:
interchanging messages through the kernel
typical pointer size variable
Kernel provides a mailbox service
Task or ISR drops a message (pointer) in the mailbox
pointer can point to any data
transmitter and receiver know what data the pointer holds
Waiting list
every mailbox can have a waiting list
used if more tasks are waiting the arrival of a message in one mailbox
Task asking message from empty mailbox
goes in SUSPEND (WAIT)
goes active as soon a message is present
highest priority first
first task first serve (FIFO)
in general: timeout is specified
after timeout: error code
29. Message mailboxes
I-beam = message box
hourglass "10" = number of clock ticks before time-out
Typical operations on a mailbox
init of mailbox, can have a message initially
deposit message in mailbox (POST)
get message from mailbox, wait if no available (PEND)
get message from mailbox, don't wait if no available (ACCEPT)
30. Message Queues Principle
used to send one or more messages to a task
typical an array of mailboxes
a task or ISR can deliver a message (pointer) in hte message queue
one or more tasks can receive messages from the queue through the kernel
sender and receiver know what kind of data is behind the pointer
typical FIFO, also LIFO and highest priority possible
Also here:
task can go in WAIT if queue is empty
task can specify time out
square = queue - "10" = max number of messages in queue - "0" = time-out
31. Interrupts What?
hardware mechanism for asynchronous event
If interrupt is recognised
CPU saves (part of) local variables (CPU-Registers)
CPU jumps to special part of memory (ISR)
At the end of the interrupt, the program continues with:
the background (foreground/background system)
the interrupted task (non-preemptive kernel)
the highest priority task ready to run (preemptive kernel)
Allow to run process events when they happen
no POLLING needed
Disabling interrupts
possible, but highly not recommended
in real-time systems, as short as possible
interrupts are NOT Queued
interrupts can be missed
32. Interrupt Latency Important RTOS specification:
Amount of time interrupts are disabled
Disabling is needed for critical sections
During disabling: interrupt latency
Interrupt latency?
Interrupt latency = maximum amount of time interrupts are disabled + Time to start executing the first instruction of the ISR
Interrupt response time
= time between the reception of an interrupt and the start of user code that handles the interrupt.
For foreground/background systems AND non-preemptive kernels
= interrupt latency + time needed to save CPU context
For preemptive kernels
= interrupt latency + time needed to save CPU context
+ execution time of the kernel ISR entry function
33. Interrupt Latency Interrupt Recovery
For foreground/background systems AND non-preemptive kernels
= time to put CPU context back + time for RTI instruction
For preemptive kernels
= Time to determine if a higher priority task is ready
+ time to put CPU context back
+ time for RTI instruction
Non-maskable interrupts
Cannot be disabled
Mostly in hardware
Only for important tasks
Eg. To save data during power-down.
34. Clock tick = special interrupt
Periodical
= RTOS heartbeat
Typical 1 tot 200 ms
Higher clock tick leads to more overhead
Delaying a task: n clock ticks
35. Memory usage of a RTOS Foreground-background systems
Only dependant on application size
RTOS
Extra room needed for kernel
for mControllers: 1 tot 100 KBytes for the RTOS
MicroC-OS/II : 3KB
Extra RAM needed for ISR and context switching of tasks
36. ad- and disadvantages of RTOS Advantages:
Real time applicaties are easier to expand
Timecritical applications are dealt with more efficiently
Important services
semaforen
mailboxes
queues
fixed time delays
time-out handling
Disadvantages:
More CPU-time (2 to 5%), RAM and ROM needed
Extra cost for the RTOS
37. MicroC/OS II
38. Kernel structure: critical sections Critical sections
During critical moments : disable interrupts
Usercode can also indicate critical sections
OS_ENTER_CRITICAL()
OS_EXIT_CRITICAL()
These macros are in OS_CPU.H
Tasks
Result = void
Structure
void JustAnotherTask(void *pdata)
{
User Code;
System Call;
User Code;
}
39. Kernel structure: Tasks Example of an infinite task
void JustAnotherTask(void *pdata)
{
for (;;)
{
User Code;
OSMboxPend(); of
OSQPend(); of
OSSemPend(); of
OSTaskDel(OS_PRIO_SELF); of
OSTaskSuspend(OS_PRIO_SELF); of
OSTimeDly(); of
OSTimeDlyHMSM();
User Code;
}
}
40. Kernel structure: Tasks Example of a temporary task
void MyTask(void *pdata)
{
User Code;
OsTaskDel(OS_PRIO_SELF);
}
Function of void *pdata
void can be any kind of data
pdata is given to the task during startup
eg. Number of a serial port
? 1 task can handle all serial ports
41. Kernel structure: priorities Priorities
Max 64 priority levels
8 levels reserved for OS
56 for user
from 0 tot OS_LOWEST_PRIO-2
Low number = high priority
Highest priority is dealt with first
Creation of tasks
Task must be offered to Kernel
Memory address and parameters are given
OSTaskCreate() or OSTaskCreateExt()
42. Kernel structure: states of a task States of a task
DORMANT
Not yet offered to kernel
READY
Task offered with OSTaskCreate() or OSTaskCreateExt()
Back to dormant by OSTaskDel()
RUNNING
After multitasking has been started (see also further)
Highest priority first
WAITING
A task can delay itself with OSTimeDly()or OSTimeDlyHMSM()
A task can also be waiting for an event, like
OSSemPend(); OSMboxPend(), OSQPend()
ISR state
When interrupt has occurred
43. Kernel structure: states of the kernel States of the kernel
Multitasking is started with OSStart()
A WAITING task gets back activated with OSTimeTick()
If all tasks are waiting for an event: idle task OSTaskIdle()
44. Kernel structure: Task Control Blocks Task Control Blocks (OS_TCBs)
A task that has been created, gets an OS_TCB
typedef struct os_tcb {
OS_STK *OSTCBStkPtr;
void *OSTCBExtPtr;
OS_STK *osTCBStkBottom;
INT32U OSTCBStkSize;
INT16U OSTCBOpt;
INT16U OSTCBId;
struct os_tcb *OSTCBNext;
struct os_tcb *OSTCBPrev;
OS_EVENT *oSTCBEventPtr;
void *OSTCBMsg;
INT16U OSTCBDly;
INT8U OSTCBStat;
INT8U OSTCBPrio;
INT8U OSTCBX;
INT8U OSTCBY;
INT8U OSTCBBitX;
INT8U OSTCBBitY;
BOOLEAN OSTCBDelReq;
} OS_TCB;
45. Kernel structure: Task Control Blocks Explanations
OSTCBStkPtr
Every task has its own stack
OSTCBExtPtr
Pointer to own part of TCB
OSTCBStkBottom
Points to the end of the TCB
OSTCBDly
Number of clock ticks the task needs to be delayed
OSTCBStat
Contains current task status
0 = READY, see uCOS_II.H file
OSTCBPrio
Contains task priority, low number = high priority
OSTCBDelReq
Request to be deleted
46. Kernel structure: Task Control Blocks Some constants
OS_MAX_TASKS
Max number of tasks available
Can be reduced ? less memory needed
Reduce to the actual number used
List of OS_TCBs is made in advance
Notice list structure
OS_LOWEST_PRIO
Lowest applicable priority
Note! Number of priorities can be higher than number of tasks
47. Kernel structure: Locking Scheduler
Will let highest priority task run
Lower priority task gets interrupted
Locking the scheduler
Using OSSchedLock() allows scheduler to be stopped
Low priority tasks keeps in control
Stays like that until OSSchedUnlock() gets called
When?
Normally: never
Exceptions, eg. If a task has to post a lot of messages
multiple mailboxes, queues, semaphores
messages have to be dealt with simultaneous ? synchronisation
48. Kernel structure: Statistics What?
Keeps the amount (% ) of CPU in use
Resolution = 1%
How?
Call in the beginning OSStatInit()
Set a variablein configuration file: OS_TASK_STAT_EN
Every second, the task OSTaskStat() will be started.
Result is kept in variable OSCPUUsage
with: OSIdleCtr : gets +1 if OSTaskIdle() gets called
OSIdleCtrMax : calculated once during Init
49. Kernel structure: starting program How?
A program in C starts with
void main(void)
{
/* own code */
}
In this routine the following has to happen:
Initialisation of the RTOS : OSInit()
Creation of a task by OSTaskCreate() or OSTaskCreateExt()
Starting of the RTOS : OSStart()
Example:
void main(void) {
OSInit()
OSTaskCreate(TaskStart,(void *) 0,(void *) &TaskStartStk[TASK_STK_SIZE-1],0);
OSStart();
}
50. Kernel structure: starting program Structure of TaskStart()
Is the actual program
General structure:
void TaskStart(void *pdata) {
? Install and Init OS Ticker
OSStatInit(); // initialises statistics Task
? Install tasks that comprise your program
for (;;) {
your own code
OSTimeDlyHMSM(0,0,1,0);
}
51. Kernel structure: OS Ticker Remember
OS Ticker is the 1..200ms heartbeat
BAD way of starting
void main (void) {
OSInit()
InitTick();
OSStart()
}
Reason:
Tick interrupt can start before your first task
Enabling of TICKER is done before OSStart()
Program can crash
52. Kernel structure: OS Ticker GOOD way of starting
void TaskStart (void *pdata) {
OS_ENTER_CRITICAL()
InitTick();
OS_EXIT_CRITICAL()
Start other tasks
FOR (;;) {
other stuff
}
}
53. Task Management General form of your program
TASK = 1) Infinite loop, or
2) Task that deletes itself
C program
Return value = void
void My_Task(void *pdata) void My_Task(void *pdata)
{ {
for (;;) { /* own code here */
/* own code here */ OSTaskDel(OS_PRIO_SELF);
one of following calls: }
OSMBoxPend();
OSQPend();
OSSemPend();
OSTaskDel(OS_PRIO_SELF);
OSTaskSuspend(OS_PRIO_SELF);
OSTimeDly();
OSTimDlyHMSM();
}
}
54. Creation of a Task Task is offeres to the kernel
OSTaskCreate()
OSTaskCreateExt(): has extra options
Stack checking: if stack should get too big
User-defined data area
User-defined checks on data
At least one task needed before OSStart()can run
Every task has its own STACK space
Can be expanded dynamically with malloc()
/* other code */
pstk = (OS_STK *) malloc(stack_size);
if (pstk != (OS_STK *)0) ; see if enough memory
{
/* create task */
}
/* Other code */
Problem: fragmentation of memory
55. Deleting a Task Done by OSTaskDel()
Code still exists
Goes back to DORMANT state
= hard delete
Request to delete: OSTaskDelReq()
= soft delete
Task gets chance to clear semaphores and memory
Task has to check for OSTaskDelReq !
/* other code */
if (OSTaskDelReq(OS_PRIO_SELF) == OS_TASK_DEL_REQ) }
/* Release all resources */
/* De-allocate memory */
OSTaskDel(OS_PRIO_SELF);
}
else {
/* Other code */
}
56. Other operations on tasks Changing the priority
OSTaskChangePrio()
Suspend
Starts after OSTaskSuspend()
Can only be undone by OSTaskResume()
57. Time Management Delaying a task using OSTimeDly()
OSTimeDly(ticks)
creates context switch
Delay of 1 to 65535 system Ticks
Delaying a task using OSTimeDlyHMSM()
OSTimeDlyHMSM(hours,minutes,seconds,milli)
HMSM = Hours Minutes Seconds Milliseconds
Can go till 256 hours (around 11 days)
Resuming a delayed task with OSTimeDlyResume()
Requesting time with OSTimeGet()
Result in Ticks
Size = INT32U
58. Communication and synchronisation Use of ECBs (Event Control Blocks)
2 forms of communication
a) Task or ISR gives flag to a Task
b) A Task Waits for an event
only Tasks can wait
!! An ISR cannot wait
Time-out possible
A ECB can be
a semaphore
Task keeps wachten, or
Task can be flagged
a message mailbox
a message queue
59. Use of semaphores Link between a Task, ISR en semaphore:
Creation of the semaphore with OSSemCreate()
A flag passed to a semaphore: OSSemPost()
Waiting for a semaphore: OSSemPend()
Accepting a semaphore without waiting: OSSemAccept()
Requesting status of a semaphore: OSSemQuery()
60. Use of Message Mailboxes Link between een Task, ISR en Message Mailbox:
Creation of a mailbox with OSMboxCreate()
Posting a message in a mailbox: OSMboxPost()
Waiting for a message in a mailbox: OSMboxPend()
Getting a mailbox without waiting: OSMboxAccept()
Request status of a mailbox: OSMboxQuery()
61. Use of Message Queues Queue is comprised of Queue Control Blocks
62. Use of Message Queues A Message Queue is a circular buffer
63. Use of Message Queues Link between Task, ISR en Message Queue:
Creation of the Message Queue using OSQCreate()
Posting a message in the queue (FIFO): OSQPost()
Posting a message in the queue (LIFO): OSQPostFront()
Waiting for a message in the queue: OSQPend()
Requesting a queue without waiting: OSQAccept()
Requesting status of a queue: OSQQuery()
64. Memory Management How does C work ?
malloc() Function for requesting memory
free() Function for releasing memory
Problems
In RTOS danger for fragmentation
Quick shortage of continues memory blocks
RTOS solution
Use of memory blocks with fixed size
All blocks same size
Size of blocks is configurable
65. Memory Management Creation of memorypartition by use of OSMemCreate()
Has to be done in advance
eg. creation of 100 blocks of 32 bytes each
OS_MEM *CommTxBuf; // create pointer to buffer
INT8U CommTxPart[100][32]; // allocate memory
void main(void)
{
/* Other code */
CommTxBuf = OSMemCreate(CommTxPart,100,32,&err);
/* Check for errors using err */
/* Other code */
OSStart();
}
66. Memory Management Requesting a memory block OSMemGet()
releasing a memory block OSMemPut()
Bigger blocks get linked