Академический Документы
Профессиональный Документы
Культура Документы
RTOS
Reference Book
Build Toolchain B u ild B in a r y t o o ls
B u ild G C C f o r t h e 1 s t t im e
( w it h o u t G lib c )
B u ild G lib c
( N e e d k e r n e l h e a d f il e )
B u ild G C C f o r t h e 2 n d
t im e
( W it h G lib c )
B u ild u G lib c f o r e m b e d d e d
d e v e lo p m e n t
B u ild G D B
Binutils
cd binutils-2.13.90.0.16
./configure --target=powerpc-linux --prefix=/opt/linuxppc
make
make install
cd gcc-2.95.3
./configure --target=powerpc-linux –prefix=/opt/linuxppc \
--enable-shared --enable-languages=c --with-newlib
make
make install
Extract Kernel
tar xvfz …
GLIBC
Un-compress GLIBC & glibc-linuxthreads
ln –s include/asm-ppc /opt/powerpc-linux/include/asm
ln –s include/linux /opt/powerpc-linux/include/linux
CC = powerpc-linux-gcc
AR=powerpc-linux-ar
RANLIB=powerpc-linux-ranlib
./configure --host=powerpc-linux –enable-add-ons \
--with-headers=/opt/powerpc-linux/include\
--prefix=/opt/linuxppc
make
make install_root=/opt/powerpc-linux install
GCC (2 Compile) nd
make distclean
./configure --prefix=/opt/linuxppc –target=powerpc-linux \
--enable-shared –enable-threads
make && make install
Why RTOS?
Learn RTOS:
– Fill the gap between Computer Science
Experts and Application Engineers
– Understanding Computer more theoretically
Using RTOS:
– Simplify the Application Programming
Higher the System Performance and
Reliability
Feature of Morden RTOS
CPU 的管理 ( 硬件初始化、 MMU 、定
时器、中断 )
提供任务内存管理
设备管理文件和网络的支持
提供 C/C++ JAVA 图形模块等编程接口
Real Time Kernel
Advantage/Disadvantage of
Using RTOS
Advantage
– Split application to multi tasks, simplify the
design, easy to be understand, expend and
maintenance
– Time latency is guaranteed
– Higher system reliability
Disadvantage
– More RAM/ROM usage
– 2~5% CPU overhead
– Adding additional cost, if commercial TROS is
used
About 80 RTOS vendors, cost from $70 to $30,000 some
are royalty free, some need $5 to $250 /MCU, MCU
dependent
What is uCOS II?
Micro-Controller Operating Systems,
Version 2
A very small real-time kernel.
Memory footprint is about 20KB for a
fully functional kernel.
Source code is about 5,500 lines,
mostly in ANSI C.
It’s source is open but not free for
commercial usages.
Feature of uC/OSII
Preemptible priority-driven real-time
scheduling.
64 priority levels (max 64 tasks), 8 reserved
for uC/OS-II
Each task is an infinite loop.
Deterministic execution times for most
uC/OS-II functions and services.
Nested interrupts could go up to 256 levels.
Real Time Kernel on uCOS
µC/OS is Widely Used in Many
Fields
cameras
medical instruments
Engine control
musical instruments
network adapter
highway telephone call
box
ATM machine
industrial robots
……
Ports On Different CPUs
Manufacture MCU
AMD 80x86
Analog Device SHARC (AD21065L)
ARM ARM7
Atmel AVR, AT103
Fujitsu SPARC
Hitachi 64180, H8-300H, H8S,SH2,SH3
Infineon Tri.Core, 80C166/167
Intel Strong ARM110,80C251,XC52, 80x86,
196K
Motorola M68HC08, M68HC11, M68HC12, M68HC16,
M68000, CPU32, DSP568xx, Cold.Fire,
M.Core, PowerPC8xx,MPC555
Philips XA
ST 80C166/167
TI TMS320-C40, TMS320-C6201
Automation V8
Zilog Z-80, Z-180
Roadmap of Learning
Read the book and the µC/OS-II source code
– Understanding RTOS concepts
Compiler the µC/OS-II with examples and run
on a PC
– Add some codes to the examples
Porting the µC/OS-II to a MCU, which you are
familiar with
– Write the CPU.c and the CPU.a files
Do a project with a MCU board
– Learn how to divide an application to several tasks
– Communication and synchronization within tasks
uCOS II Architecture
Applications (Tasks)
CPU Independent Code Application
uCOS-II.h (Global Var) Configuration
uCOS_II.c Groups:
OS_Core.c OS_Task.c Code
OS_Time.c OS_Sem.c OS_CFG.h
OS_Mbox.c OS_Q.c Includes.h
OS_Mem.c
Preemptive Kernel
– In it, when an event makes a higher priority
task ready to run, the current task is
immediately suspended and the higher
priority task is given control of the CPU
Reentrancy
– A reentrant function is a function which can
be used by more than one task without fear
of data corruption.
uC/OS II Overview
External
IRQ
Task Scheduler
} } }
Multi-
Tasking
Overview
Sample Code (0)
Task0 Task1
MBox0 MBox1
Sample Code (1)
Global Variables
main()
{
init OS;
init Global Variables;
init Task0 and Task1
}
Task0() Task1()
{ {
… …
} }
#include "includes.h"
// Create Mailbox
MBox0 = OSMboxCreate((void*)0);
MBox1 = OSMboxCreate((void*)0);
// Waiting for mail from mailbox 0 (reply from task1) // Waiting for mail from mailbox 1 (mail
msg = OSMboxPend(MBox0, 100, &err); from task 0)
msg = OSMboxPend(MBox1, 100, &err);
// Get data attached in the mail
n = *((int*)msg);
} // Get data attached in the mail
} m = *((int*)msg);
Calculate n Calculate m
Send mail to 1 Wait mail from 0
Waiting reply from 1 Retrieve data from mail
Retrieve data from mail Reply 0
OSInit (1)
internal structures of uC/OS-2.
Task ready list.
Priority table.
Task control blocks (TCB).
Free pool. int main (void)
{
Create housekeeping tasks. … OSInit();
…
The idle task. OSTaskCreate(…);
…
The statistics task. OSTaskCreate(…);
…
OSStart();
return 0; // Never return
}
OSInit OSRdyGrp Ready List
(2)
1 0 0 0 0 0 0 0 OSTCBPrioTbl[]
OSRdyTbl[] 0 [0]
0 [1]
0 [2]
0 0 0 0 0 0 0 0 0 [3]
0 [4]
0 0 0 0 0 0 0 0 0 [5]
0 [6]
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0
1 1 0 0 0 0 0 0 0
0
[OS_LOWEST_PRIO - 1]
[OS_LOWEST_PRIO]
OSTaskStat() OSTaskIdle()
OS_TCB OS_TCB
OSTCBStk Ptr OSTCBStk Ptr
OSTCBExtP tr = NULL OSTCBExtPtr = NULL
OSTCBStk Botto m OSTCBStk Botto m
OSTCBStk Size = stack size OSTCBStk Size = stack size
OSTCBId = OS_LOWEST_PRIO OSTCBId = OS_LOWEST_PRIO
OSTCBList OSTCBNext
OSTCBPrev
OSTCBNext
OSTCBPrev
OSTCBEventPtr = NULL OSTCBEventP tr = NULL
OSPrioCur = 0 OSTCBMsg = NULL OSTCBMsg = NULL
OSPrioHighRdy = 0 0 OSTCBDly = 0
OSTCBStat = OS_STAT_RDY
OSTCBDly = 0
OSTCBStat = OS_STAT_RDY
0
OSTCBCur = NULL OSTCBPrio = OS_LOWEST_PRIO-1
OSTCBX = 6
OSTCBPrio = OS_LOWEST_PRIO
OSTCBX = 7
OSTCBHighRdy = NULL OSTCBY = 7 OSTCBY = 7
OSTime = 0L OSTCBBitX = 0x40
OSTCBBitY = 0x80
OSTCBBitX = 0x80
OSTCBBitY = 0x80
OSIntNesting = 0 OSTCBDelReq = FALSE OSTCBDelReq = FALSE
OSLockNesting = 0
OSCtxSwCtr = 0
OSTaskCtr = 2
OSRunning = FALSE
OSCPUUsage = 0
OSIdleCtrMax = 0L
OSIdleCtrRun = 0L
OSIdleCtr = 0L Task Stack
OSStatRdy = FALSE Task Stack
OS_MAX_TASKS
OS_TCB OS_TCB OS_TCB OS_TCB
OSTCBStkPtr OSTCBStkPtr OSTCBStkPtr OSTCBStkPtr
OSTCBExtPtr OSTCBExtPtr OSTCBExtPtr OSTCBExtPtr
OSTCBStkBottom OSTCBStkBottom OSTCBStkBottom OSTCBStkBottom
OSTCBStkSize OSTCBStkSize OSTCBStkSize OSTCBStkSize
OSTCBId OSTCBId OSTCBId OSTCBId
OSTCBFreeList OSTCBNext
OSTCBPrev
OSTCBNext
OSTCBPrev
OSTCBNext
OSTCBPrev
OSTCBNext
OSTCBPrev
0
OSTCBEventPtr OSTCBEventPtr OSTCBEventPtr OSTCBEventPtr
OSTCBMsg OSTCBMsg OSTCBMsg OSTCBMsg
OSTCBDly OSTCBDly OSTCBDly OSTCBDly
OSTCBStat OSTCBStat OSTCBStat OSTCBStat
OSInit
OSTCBPrio OSTCBPrio OSTCBPrio OSTCBPrio
OSTCBX OSTCBX OSTCBX OSTCBX
OSTCBY OSTCBY OSTCBY OSTCBY
OSTCBBitX OSTCBBitX OSTCBBitX OSTCBBitX
OSTCBBitY OSTCBBitY OSTCBBitY OSTCBBitY
OSTCBDelReq OSTCBDelReq OSTCBDelReq OSTCBDelReq
OSEventFreeList OSEventPtr
OSEventTbl[]
OSEventPtr
OSEventTbl[]
OSEventPtr
OSEventTbl[]
OSEventPtr
OSEventTbl[]
0
OSEventCnt OSEventCnt OSEventCnt OSEventCnt
OSEventType OSEventType OSEventType OSEventType
OSEventGrp OSEventGrp OSEventGrp OSEventGrp
OS_MAX_QS
OS_Q OS_Q OS_Q OS_Q
OSQFreeList OSQPtr
OSQStart
OSQPtr
OSQStart
OSQPtr
OSQStart
OSQPtr
OSQStart
0
OSQEnd OSQEnd OSQEnd OSQEnd
OSQIn OSQIn OSQIn OSQIn
OSQOut OSQOut OSQOut OSQOut
OSQSize OSQSize OSQSize OSQSize
OSQEntries OSQEntries OSQEntries OSQEntries
OS_MAX_MEM_PART
OS_MEM OS_MEM OS_MEM OS_MEM
X
[0] 7 6 5 4 3 2 1 0
[1] 15 14 13 12 11 10 9 8
[2] 23 22 21 20 19 18 17 16
[3] 31 30 29 28 27 26 25 24
Y
[4] 39 38 37 36 35 34 33 32
[5] 47 46 45 44 43 42 41 40
[6] 55 54 53 52 51 50 49 48
[7] 63 62 61 60 59 58 57 56
Task Priority #
Task's Priority
Lowest Priority Task
(Idle Task)
0 0 Y Y Y X X X
Priority of
created task Stack For Task
OSMBoxPost() OSMBoxPend()
OSQPost() OSQPend()
OSQPostFront()
OSTaskDel() OSSemPost() OSSemPend()
OSTaskResume() OSTaskSuspend()
OSTimeDlyResume() OSTimeDly()
OSTimeTick() OSTimeDlyHMSM()
OSTaskCreate()
OSTaskCreateExt() OSStart()
OSIntExit() Interrupt
OS_TASK_SW()
DORMANT READY RUNNING ISR
OSIntExit()
OSTaskDel()
Task is Preempted
OSTaskDel()
OSTCBTbl[OS_MAX_TASKS+OS_N_SYS_TASKS-1]
OS_ENTER_CRITICAL();
if ((OSLockNesting | OSIntNesting) == 0) {/* Task scheduling must be enabled and not ISR level */
y = OSUnMapTbl[OSRdyGrp]; /* Get pointer to highest priority task ready to run */
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
if (OSPrioHighRdy != OSPrioCur) { /* No context switch if current task is highest ready */
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++; /* Increment context switch counter */
OS_TASK_SW(); /* Perform a context switch */
}
}
OS_EXIT_CRITICAL();
}
Memory Management in uCOS
malloc() and free() is dangerous in Embedded
real-time system
– Unable to obtain a single contiguous memory area
due to fragmentation
Execution time of malloc() and free() are also
nondeterministic
– Algorithms used to locate a contiguous block of free
memory
– Time for de-fragmentation
Fixed-sized memory blocks from a partition
made of a contiguous memory area.
– All memory blocks are the same size and the
partition contains an integral number of blocks
– Allocation and deallocation of these memory blocks
is done in constant time and is deterministic
Memory Management in uCOS
(contd.)
Partition #1 Partition #2 Partition #3 Partition #4
OSMemFreeList= addr
OSMemBlkSize = blksize
OSMemNBlks = nblks
OSMemNFree = nblks
Contiguous memory
OSMemCreate() arguments
OS_MEM *CommTxBuf;
INT8U CommTxPart[100][32];
void main(void)
{
INT8U err;
...
OSInit();
...
CommTxBuf = OSMemCreate(CommTxPart, 100, 32,
&err);
...
OSStart();
}
Memory Management Functions
OSMemCreate (void *addr, INT32U nblks,
INT32U blksize, INT8U *err)
– Format a memory partition
OSMemGet (OS_MEM *pmem, INT8U *err)
– Get a memory block from one of the created
memory partitions
OSMemPut (OS_MEM *pmem, void *pblk)
– Returning a Memory Block to the appropriate
partition
OSMemQuery()
– Obtaining status of a Memory partition
Memory Management Example
OSTime
OSTimeGet()
(3)
ErrMsgQ
(4) (7)
OSMemGet() OSMemPut()
(2) (8)
ErrMsgPart 0
Time Management
10m s
T ic k In t e rru p t
(2 ) (1 ) (5 )
O S T ic k IS R ( )
(3 )
A ll H P T
(6 )
L o w - P r io r it y T a s k
T a s k c a lls (4 )
5m s
O S T im e D ly ( 1 ) h e re !
Time Management Function
OSTimeDly()
–Delay for a user-specified number of clock ticks
OSTimeDlyHMSM()
hours(H), minutes(M), seconds(S),
milliseconds(m), Maximum Delay 256hours (11days)
OSTimeDlyHMSM( 0, 0, 1, 500);
OSTimeDlyResume()
–Resuming a Delayed Task
OSTimeGet() & OSTimeSet()
–32-bit counter
Time Management Function
(contd.)
1 Task A Task A call
OSTimeDly(100)
2
3
Task A Task A sleep now
Task B
Find the highest
priority ready task
B, and activate it
This ISR is called
every time tick to
advance the clock
OSTickISR
Hooks
A hook function will be called by uC/OS-
when the corresponding event occurs.
– Event handlers could be in user programs.
– For example, OSTaskSwHook () is called every
time when context switch occurs.
The hooks are specified in the compiling time
in uC/OS-II:
– uC/OS-II is an embedded OS.
• OS_CFG.H (OS_CPU_HOOKS_EN = 0)
– Many OS’s can register and un-register hooks.
Hook Functions Empty function, can be
overridden by user
void OSInitHookBegin (void)
void OSInitHookEnd (void)
void OSTaskCreateHook (OS_TCB *ptcb)
void OSTaskDelHook (OS_TCB *ptcb)
void OSTaskIdleHook (void)
void OSTaskStatHook (void)
void OSTaskSwHook (void)
void OSTCBInitHook (OS_TCB *ptcb)
void OSTimeTickHook (void)
Mail Box
A mailbox is for data exchanging between
tasks.
– A mailbox consists of a data pointer and a wait-list.
OSMboxPend():
– The message in the mailbox is retrieved.
– If the mailbox is empty, the task is immediately
blocked and moved to the wait-list.
– A time-out value can be specified.
OSMboxPost():
– A message is posted in the mailbox.
– If there is already a message in the mailbox, then
an error is returned (not overwritten).
– If tasks are waiting for a message from the mailbox,
then the task with the highest priority is removed
from the wait-list and scheduled to run.
Mail Box Operation
OS_EVENT* MBox0;
OS_EVENT* MBox1;
…
MBox0 = OSMboxCreate((void*)0);
MBox1 = OSMboxCreate((void*)0);
…
err = OSMboxPost(MBox1, (void*)&n);
…
msg = OSMboxPend(MBox0, 100, &err);
OSMboxCreate
Step 1
– Get a OS_EVENT node from OSEventFreeList
Step 2
– Assign type OS_EVENT_TYPE_MBOX to the OS_EVENT
node
Step 3
– Attach the message (given from caller) to the OS_EVENT
node
Step 4
– Return the point of the OS_EVENT node to the caller
Note
– Mail box is an event in the view of uCOS
– Mail box is not attach to specific task when created
– The mail box has a table to record the tasks that are waiting
on the mail box.
OSMboxPost
Step 1
– If there has some Task waiting on the mail box,
wake up it and give the message to it directly
Step 2 (Step 1 is not run)
– If the mail box is full return error
OS_MBOX_FULL
Step 3 (Step 2 is not run)
– Attach mail message to the mail box (mail box is
a special event)
OSMboxPend
Step 1
– If mail box is empty,
empty pending the task by calling
OSEventTaskWait() (This function will register the
task on the event table of the mail box, so that when
mail box receive a message, it can check its table to
wake up those tasks)
Step 2 (Step 1 is not run)
– This step is run either because mail box get new
email or timeout event occur
– The mail will be sent to task directly
– Note:
• The message can be found by task’s message pointer. If
there are already tasking waiting for mail in the mailbox, the
arriving mail is given to task directly instead of storing to
mailbox and then inform the task
• The message can be found in mail box’s pointer if the mail
is sent when no tasking is pending for mail of the mail box.
Message Qeue
A message queue consists of an array of elements and a
wait-list.
Different from a mailbox, a message queue can hold
many data elements (in a FIFO basis).
As same as mailboxes, there can be multiple tasks
pend/post to a message queue.
OSQPost(): a message is appended to the queue. The
highest-priority pending task (in the wait-list) receives the
message and is scheduled to run, if any.
OSQPend(): a message is removed from the array of
elements. If no message can be retrieved, the task is
moved to the wait-list and becomes blocked.
Intertask Comm. & Synch.
S ig n a l W a it IS R S ig n a l Task
W a it
IS R EC B Task
T im e EC B
ou t
Task S ig n a l W a it
Task
T im e
W a it / ou t
Task S ig n a l
S ig n a l
W a it
Task EC B Task EC B
T im e
ou t W a it /
Task T im e
S ig n a l
ou t
typedef struct {
void *OSEventPtr;
INT8U OSEventTbl[OS_EVENT_TBL_SIZE];
INT16U OSEventCnt;
INT8U OSEventType;
INT8U OSEventGrp;
} OS_EVENT;
•OSEventPtr Event Control
ECB is assigned to a mailbox or a queue
Blocks
•OSEventTbl[] & .OSEventGrp
Contains a list of tasks waiting on the event
•OSEventCnt
Hold the semaphore count
•OSEventType
The type associated with the ECB
OS_EVENT_SEM, OS_EVENT_TYPE_MBOX, OS_EVENT_TYPE_Q
Event Control Blocks
Highest Priority Task Waiting
.OSEventGrp
.OSEventTbl[OS_LOWEST_PRIO/8+1]
7 6 5 4 3 2 1 0 x
[0 ] 7 6 5 4 3 2 1 0
[1 ] 15 14 13 12 11 10 9 8
[2 ] 23 22 21 20 19 18 17 16
[3 ] 31 30 29 28 27 26 25 24
y
[4 ] 39 38 37 36 35 34 33 32
[5 ] 47 46 45 44 43 42 41 40
[6 ] 55 54 53 52 51 50 49 48
[7 ] 63 62 61 60 59 58 57 56
Task’s Priority Priority of task waiting
0 0 Y Y Y X X X for the event to occur
OSEventTaskRdy()
: Removes the highest priority task(HPT) from the wait list of the ECB and make
this task ready to run
called by OSSemPost(), OSMboxPosr(), OSQPost(), OSQPostFront()
OSEventTaskWait()
: called by OSSemPend(), OSMboxPend(), OSQPend() when a task must wait on
an ECB
Removes the current task from the ready list and places it in the wait list of the
ECB
Semaphores
16-bit unsigned integer used to hod the semaphore count (0 to 65535)
a list of tasks waiting for the semaphore count to be greater than 0
uC/OS-II provides five services to semaphores
- OSSemCreate() O S S e m C re a te ( )
- OSSemPend()
O S S e m P o s t( )
- OSSemPost() O S S em P en d ()
Task O S S e m A c c e p t( )
- OSSemAccept() N O S S e m Q u e ry ( )
- OSSemQuery()
O R Task
IS R
N
O S S e m P o s t( )
O S S e m A c c e p t( )
OSSemCreate() OSSemPend()
: Creates and initializes a semaphore : When a task wants exclusive access to
a resource, needs to synchronize its
OS_EVENT *DispSem;
activities with an ISR or a task, or is
void main(void) waiting until an event occurs
{
...
void DispTask(void *pdata)
OSInit();
... {
DispSem = OSSemCreate(1);
INT8U err;
...
pdata = pdata;
OSStart();
for (;;) {
} ...
OSSemPend(DispSem, 0, &err);
...
}
}
OSSemPost() OSSemQuery()
: A semaphore is signaled by calling : Obtain information about a semaphore
OSSemPost().
…. ...
Message Mailboxes
A message mailbox is a uC/OS-II object that allows a task or an ISR to send a
pointer sized variable to another task
uC/OS-II provides five services to mailboxes
O S M b o x C re a te ( )
- OSMboxCreate()
- OSMboxPend() O S M b o x P o s t( )
O S M b o xP en d ()
- OSMboxPost() Task O S M b o x A c c e p t( )
O S M b o x Q u e ry ( )
- OSMboxAccept()
- OSMboxQuery() Task
IS R M a ilb o x
M essage
O S M b o x P o s t( )
O S M b o x A c c e p t()
OSMboxCreate() OSMboxPend()
: Creates and initializes a mailbox : When a task task expects to receive a
message.
OS_EVENT *CommMbox;
void main(void) void CommTask(void *pdata)
{ {
... INT8U err;
OSInit(); void *msg;
...
CommMbox = OSMboxCreate((void *)0); pdata = pdata;
... for (;;) {
OSStart(); ...
if (err==OS_NO_ERR) {
/* Code for received message */
} else {
/* Code for message not received within
time out */
OSMboxPost() OSMboxQuery()
: Send a message to a task through : Obtain information about a message
a mailbox mailbox
OS_EVENT *CommMBox
void Task (void *pdata)
INT8U CommRxBuf[100];
{
OS_MBOXDATA mbox_data:
void CommTaskRx(void *pdata) INT8U err;
{ pdata=pdata;
for (;;) {
INT8U err;
... ...
err = OSMboxQuery(CommMbox,
pdata = pdata;
&mbox_data);
for (;;) {
if (err==OS_NO_ERR) {
...
/* Mailbox contains a message if
err = OSMboxPost(CommMbox, (void *)
mbox_data.OSMsg is not NULL */ }
&CommRxbuf[0]);
...
...
Message Queues
A message queue is a uC/OS-II object that allows a task or an ISR to send pointer
sized variables to another task.
uC/OS-II provides seven services to Queues
O S Q C re a te ( )
- OSQCreate()
- OSQPend() O S Q P o s t( )
O S Q P o s tF ro n t( )
- OSQPost() Task O S Q F lu s h ( ) O S Q P en d ()
N O S Q A c c e p t( )
- OSQPostFront() O S Q Q u e ry ( )
- OSQAccept() Task
- OSQFlush() IS R Q ueue
- OSQQuery() M essage
O S Q P o s t( )
O S Q P o s tF ro n t( )
O S Q F lu s h ( )
O S Q A c c e p t( )
OSQCreate() OSQPend()
: Creates a message queue : When a task task expects to receive a
message from a queue
OS_EVENT *CommQ;
void *CommMsg[10]; void CommTask(void *pdata)
{
All of them
TaskA(){…}
TaskB(){…}
are
TaskC(){…} compiled
TaskD(){…} into a large
binary file
Interrupts under uC/OS-II
uC/OS-II requires that an Interrupt Service Routine(ISR) be
written in assembly language.
Pseudocode for an ISR
YourISR:
Save all CPU registers;
Call OSIntEnter() or, increment OSIntNesting
directly;
Execute user code to service ISR;
Call OSIntExit();
Restore all CPU registers;
Execute a return from interrupt instruction;