Home
        A Portable Real-Time Kernel in C, 5/92
         Contents
1.  design would require additional support  circuitry  A minimal 80188 system can be built with four chips  80188  RAM  EPROM  and 8255 PPI      UCOS FEATURES    Although it was developed on an IBM PC compatible  uCOS is targeted for embedded  systems that use microcontrollers  The kernel is written almost entirely in C  with  microprocessor specific code written in assembly language  A small amount of assembly  language was necessary but was kept to a minimum     The uCOS source code is separated into five files  Three of these files contain target   specific code  In our 80186 example  UCOS186 C contains the task creation function   UCOS 186 H is a header file  and UCOS186A ASM contains the system startup and  context switching code   The files mentioned here are in the UCOS ZIP archive file on the  Embedded SystemsProgramming BBS at  415  905 2389 or in library 12 of CLMFORUM  on CompuServe   These files are where the target specifics are located     The uCOS source code that is not target specific is in the two remaining files  UCOS H  and UCOS C  The header file contains the system constants  data types  and function  prototypes  and UCOS C file contains the system variables and functions     Because of its organization  uCOS can be ported to just about any microprocessor  The  only requirements are that the microprocessor provides a stack pointer and the CPU  registers can be pushed onto and popped from the stack  Also  your C compiler must be  ANSI compatible and provide
2.  don t have to repeat the exercise  In this article  I m going to explain the  design of uCOS  a portable  preemptive multitasking kernel for microcontrollers  I ve  written this kernel almost entirely in C  and its performance is comparable to many  commercial kernels  Using my source code  you ll be able to avoid some of the costs of  creating your own kernel and spend more time on your application     The creation and documentation for even a modest kernel can become an overwhelming  task  To keep things simple  this month  I ll be discussing the kernel internals and its  multitasking model at a relatively high level  Next month  I ll continue with a look at the  various kernel services     THE NATURE OF THE PROJECT    UCOS stands for  microcontroller operating system   The initial goals for uCOS were to  create a small yet powerful kernel for Motorola s 68HC11 microcontroller  Specifically  I  wanted a ROMable real time kernel with preemptive multitasking  As the design evolved   however  I removed some of the target specific limitations of uCOS to make it portable to  other microprocessors  Using this approach  I was able to develop and test uCOS on a PC  using Borland International s Turbo C      For this reason  the implementation of uCOS  shown in this article is for an Intel 80186 88 microprocessor  using the small memory  model      The Intel 80186 was chosen as a target over the 8086 because the latter is a poor choice  for embedded control applications  An 8086 88
3.  field for each OS_TCB if it is nonzero  When  OSTBDly is decremented to zero  the task is made ready to run  The execution time of  OSTimeTick   is directly proportional to the number of tasks created in an application   approximately 15 000 bus cycles worst case with 63 tasks   Before returning to the  interrupted task  or the highest priority task that is ready to run  an INT OF2H is  performed to chain into the IBM PC s BIOS tick ISR  used only for the example   When  the BIOS returns from this interrupt  OSTickISR properly terminates the ISR as required  by uCOS     SYSTEM SERVICES    The uCOS kernel offers a number of services to the programmer  In next month s  continuation  we ll look at most of the uCOS services  It should be mentioned for the    impatient  however  that one of the most basic kernel services is to allow a task to delay  execution for a number of system ticks  The function that performs this operation is called  OSTimeDly    which is found in UCOS C     The kernel is initialized by calling OsInit    also in UCOS C  which is also where the idle  task is created  You must specify a pointer to the idle stack and the maximum number of  tasks in your application  After calling OSInit    you may create your application tasks   Multitasking starts when you call OSStart    OsInitQ  must be called before OSStart   and  you must create at least one of your tasks prior to calling OSStart    OSStart   will  execute the highest priority task that you created     P
4.  in line assembly language or extensions that allow you to  enable and disable interrupts     uCOS is priority driven and always runs the highest priority task that is ready to run   uCOS is also fully preemptive  which means that interrupts can suspend the execution of a  task and  if a higher priority task is awakened as a result of the interrupt  it will run as  soon as the interrupt completes  uCOS also allows nested interrupts  Despite its flexibility   I find uCOS comparable in performance to commercially available packages  For a  10MHz 80188 system  interrupt latency is less than 450 CPU bus cycles     Another important characteristic of a real time kernel is determinism  The execution time  of uCOS functions does not depend on the number of tasks in an application  the task   scheduling time is constant  uCOS supports systems with up to 63 user definable tasks   Since uCOS was originally targeted for an 8 bit microcontroller  only required kernel  services can be included in an application  which keeps the amount of EPROM and RAM  to a minimum  The stack size for each task can also be independently specified  which  further reduces the amount of RAM required     uCOS provides a number of system services  including mailboxes  queues  semaphores   and time related functions  Most of these system services will be covered in next month s  article  The kernel is also very easy to set up  as will be demonstrated later     I ll be the first to admit that uCOS has certain li
5.  its own stack but  just as important  each stack can be of any size  Some  commercially available kernels assume that all stacks are the same size unless you write  complex hooks  This limitation becomes wasteful of RAM when all tasks have different    stack requirements because the largest anticipated stack size has to be allocated for all  tasks     OSTCBStat contains the state of the task  When OSTCBStat is zero  the task is ready to  run  Each bit within OSTCBStat has a special meaning  see OS_STAT         OSTCBPrio contains the task priority  A high priority task has a low priority number  the  lower the number  the higher the actual priority      OSTCBDly is used when a task must be delayed for a certain number of system ticks or is  to wait for an event to occur with a timeout  In this case  this field contains the number of  system ticks that the task is allowed to wait for the event to occur  When this value is  zero  the task is not delayed     OSTCBNext and OSTCBPrev are used to doubly link OSTCBs when tasks are created   This chain of OSTCBs is used by OSTimeTick    described later  to update the  OSTCBD ly field for each task     When uCOS is in the process of updating critical data structures  it must ensure that no  interruptions will occur  In this case  interrupts are disabled prior to executing this code  and reenabled when it is finished executing  The macros OS_ENTER_CRITICAL  and  OS_EXIT _CRITICALQ  in UCOS186C H  are used to disable and enable interrup
6. ERFORMANCE ISSUES    A number of criteria can alter the performance of a real time kernel  Context switch time   interrupt latency  system services execution time  and task scheduling time all have some  effect     The context switch time is really determined by the microprocessor and typically doesn t  change from one kernel to another  Saving and restoring a processor s context depends on  how many registers it has  In my experience  it s not very meaningful when a kernel vendor  quotes performance based on the context switch time     An important criterion for a multi tasking kernel is how long it takes to respond to an  interrupt and start executing user code for the ISR  This procedure is known as interrupt  latency  A real time kernel always disables interrupts when manipulating critical sections  of code  For uCOS  interrupts are disabled for a maximum of 450 CPU bus cycles  In  addition to the period when interrupts are disabled  if uCOS services are required  you  must also include the overhead for an ISR preamble  uCOS requires an additional 200  cycles before it starts executing user code  Interrupt latency for uCOS is thus about 650  bus cycles  or 65 microseconds for a 10MHZ 80188 system     Another important performance issue in a real time kernel is determinism  Kernel services  should be deterministic by specifying how long each service call will take to execute  The  execution time of uCOS s kernel services does not depend on the number of tasks in an  applic
7. Embedded Systems Programming    A Portable Real Time Kernel in C    Just how much is a real time multitasking kernel worth to you  If you re like many  developers  the benefits of using a commercial real time operaing system or executive are  obvious  In exchange for a licensing fee  you get a debugged product with documentation  and technical support  Unfortunately  many developers find themselves in a SituatiOn  where they need a real time operating system  but have virtually no budget for purchasing  one  What do you do in that situation  For many developers  the answer lies in creating  their own kernel     Rolling your own executive or operating system can be appealing  Everyone likes to create  something new  But this approach isn t always practical and  in some cases  can be  downright dangerous  For example  it isn t often that you re given enough time to create  an operating system and complete your original project  On the few occasions when your  schedule is changed to reflect the extra work  the schedule may still be overly optimistic    It is a sad but well established rule in our business that programmers will always  underestimate the time a project will take   Worse  when you roll your own executive   you re also volunteering for extra debugging and maintenance     Despite the dangers I just mentioned  developers continue to take the plunge and develop  their own operating systems  I know this for a fact  because I ve done it myself  The good  news is that you
8. ased on my experience and  seemed a good fit for embedded microcontroller applications  Your experience may be  different  I ve provided the source code so you can make your own modifications  For   example  all of the projects that I ve worked on have had less than 35 tasks  Hence  the    kernel limit of 63 tasks seemed quite adequate  If needed  however  uCOS can easily be  upgraded to handle up to 127 user tasks  To make such changes easier  I ve stressed  readability over  optimization   I hope you find the results useful     BY JEAN J  LABROSSE   Jean J  Labrosse has a Master s degree in Electrical Engineering from the University of  Sherbrooke in Quebec  Canada  and has been developing real time software for over 10  years  He is intimately familiar with the Z 80  680x  80x86  680x0  6805 and 68HC11  microprocessors  Labrosse is employed by Dynalco Controls in Fort Lauderdale  Fla    where he designs control software for large industrial reciprocating engines     BIBLIOGRAPHY    Bal Sathe  Dhananjay   Fast Algorithm Determines Priority   India EDN  Sept  1988   p 237     iAPX 186 188 User s Manual and Programmer s Reference  Santa Clara  Calif   Intel  Corp   1983       Listing 1  A multitasking test program      include  INCLUDES H      define OS_MAX_TASKS 10    define STK_SIZE 500   OS_TCB OSTCBTbI OS_MAX_TASKS    UWORD OSIdleTaskStk STK_SIZE    UWORD Stk1 STK_SIZE     UWORD Stk2 STK_SIZE     UWORD Stk3 STK_SIZE     UWORD Stk4 STK_SIZE     UWORD Stk5 STK_SIZE      cha
9. at a task stack is initially set up to look as if an interrupt occurred   see Figure 2   OsCtxSw expects the current task s stacks and the new highest priority  task that is ready to run to look pretty much the same  The INT instruction pushed the  processor s PSW and the current task s code segment and offset onto the stack  OSCtxSw  starts by saving the rest of the current task s context onto the stack  The processor s stack  pointer for the current task is finally saved in the current task s TCB  The stack pointer of  the next task to run is restored from its TCB  the new task s context is restored   At this  point  the lower priority task s information is stored on the stack  OSCtxSw finally  executes a return from interrupt to resume execution of the highest priority task     INTERRUPT PROCESSING    When an interrupt occurs  the processor will automatically save the current PSW  CS  and  IP onto the current task s stack  then fetch the interrupt vector from the interrupt vector  table  If an ISR needs to use the kernel s services  it should immediately enable interrupts  to allow interrupt nesting  and reduce interrupt latency  and call OSIntEnter    UCOS C   to notify uCOS that it has started servicing an interrupt  The user s ISR code should  follow  followed by a call to OSIntExit    UCOS C   The ISR code must be written in  assembly language under uCOS as follows     ISRx PROC FAR    STI   Enable interrupts  PUSHA   Save CPU s context  PUSH ES  CALL _OSIntEnter   Not
10. ation  This characteristic is desirable  since you don t want the kernel s performance  to degrade as the number of tasks in an application increases  Table 1 lists the execution  time of the services described in this article  It was obtained by inspecting the code  generated by the compiler and adding up the number of cycles for each instruction  An  Intel 80188 processor with zero wait states is assumed  To find the execution time of each  kernel service  simply divide the number of cycles given by the processor bus frequency     The time required by uCOS to find the highest priority task that is ready to run is constant   If the current task has the highest priority and is ready to run  for example  no context  switch is required  then OSSched   executes in about 250 bus cycles  If a context switch is  required  execution time is about 500 bus cycles     MEMORY REQUIREMENTS    Given the limited amount of memory typically found in embedded systems  especially with  8 bit microprocessors  the amount Of program and data memory a kernel requires must be  kept to a minimum  The RAM requirements for a small model 80188 implementation of  uCOS is fairly simple to calculate     RAM   uCOS requirements    Task stacks     Storage of OS_TCBs for all tasks    150   SUM Task Stacks      OS_TCB size     N   1     where N is the number of tasks created for the application  uCOS requires 150 bytes for  its internal data structures and variables  The size of an OS_TCB is 10 bytes and one 
11. de     if  OSRdyTbl  p  gt  gt  3   amp     OSMapTbl p  amp  0x07     0   OSRdyGrp  amp    OSMapTbl p  gt  gt  3      and clears the bit in OSRdyGrp if all tasks in a group are not ready to run  Instead of  scanning through the table starting with OSRdyTbI O  to find the highest priority task that  is ready to run  a table lookup method is used  OSUnMapTbl 256  is a priority resolution  table  Eight bitsare used to represent tasks that are ready  The least significant bit has the  highest priority  Using this byte to index the table returns the bit position of the highest  priority bit set  a number between zero and seven  To avoid a context switch  OSSched    verities that the highest priority task is not the current task     All of the code in OSSched   is considered a critical section  Interrupts are disabled to  prevent ISRs from setting the ready bit of one or more tasks while the highest priority task  that is ready to run is being determined  OSSched   could have been written in assembly  language  since task scheduling time and interrupt latency are directly proportional to the  execution time of this function  This code was kept in C to make it more readable for the  purpose of this article     CONTEXT SWITCHING    When a context switch from OSSched   is required  OS_TASK_SW   is executed   OS_TASK_SW0    which is actually a macro defining an INT instruction  vectors to the  assembly language ISR OSCtxSw  UCOS186A ASM   which performs the context  switch  Remember th
12. extra  OS_TCB is required to hold the idle task  The total stack requirement is the sum of the  stack requirement for each task  For example  a 20 task application using 256 bytes for  each stack would require     RAM   150   10  20   1    21  256     5 736 bytes     uCOS requires less than 1 000 bytes of EPROM  excluding the kernel services that I ll  describe next month  Our example application requires an additional 300 bytes  excluding  the library functions      StiLL TO COME    Next month  we ll conclude our look at uCOS with a tour of the system services  If you re  planning to use the kernel in a project  you might want to hold off on your customization  efforts until you examine those services  If you re in a hurry  the code presented this month  allows you to run the example shown in Listing 1  TEST1 C  This code creates five tasks   Each task delays for one BIOS tick  approximately 55 milliseconds  and displays its  priority number at random positions on the screen  The same code is used for each task  and the displayed task priority is passed to the task when it is created through the data  argument  This type of code can be used for multiple instances of a task as long as the task  is reentrant  The code in the example works  even though the functions used are not  reentrant  trust me on this   Be careful when using floating point math in your application    Turbo C     s math library is nonreentrant     The selection of services and other system parameters are b
13. ify uCOS of ISR  CALL _ User ISRCode   Execute user code  CALL _OSIntExit   Notify uCOS of  end of ISR   POP ES   Restore CPU s     context  POPA  IRET   Return from     interrupt    OSIntEnter   is used to notify uCOS that an ISR has started  allowing uCOS to keep track  of the interrupt nesting level  uCOS allows nesting of up to 255 interrupts  When the ISR  completes  it calls OSIntExit    which decrements the nesting level  When all interrupts  have completed  uCOS finds the highest priority task that is ready to run and switches to  that task  Notice that OSIntExit   calls OSIntCtxSw Q  instead of OSCtxSw  This call is  made because uCOS allocates local storage for variables on the stack that are used by  OSinExit    These variables must be deallocated prior to returning to the interrupted task  or the highest priority task     SYSTEM TICK    UCOS allows tasks to suspend execution for a number of system ticks or wait until events  occur with a timeout  A system tick is typically provided by a periodic interrupt  The time  between interrupts is application specific and is typically between 10 milliseconds and 100  milliseconds  the faster the tick rate  the higher the overhead imposed on the system   Overhead imposed by uCOS is about 3   worst case  when the tick rate is 20Hz  50  milliseconds   The ISR OSTickISR  UCOS186A ASM  shows how to implement a  system tick interrupt under uCOS  Notice that OSTime Tick   is called  This function is  used to decrement the OSTCBDly
14. mitations  For example  tasks that execute  under the kernel must have a unique priority number  No two tasks can have the same  priority  Also  uCOS system calls cannot be made from nonmaskable interrupts because  the kernel needs to disable interrupts to execute critical sections of code   By the way  this  limitation also exists in most commercially available kernels   The execution time of the  function used to process a system tick depends on the number of tasks in an application     CONVENTIONS   The following conventions are adopted in uCOS  All variables  functions  and macros in  uCOS start with OS  for example  OS Start    OSInit    OS_STAT_RDY  and so on   This  way  uCOS functions can be easily identified in the user s application code    Since the kernel is written in C  the size of certain data types are target compiler specific   To avoid confusion about the size of certain quantities  the following data types are  defined for the 80186 188 in UCOS186C H      BYTE  signed 8 bit value     UBYTE  unsigned 8 bit value     WORD  signed 16 bit value     UWORD  unsigned 16 bit value     LONG  signed 32 bit value     ULONG  unsigned 32 bit value   TASK CONTROL BLOCKS   Tasks under uCOS are characterized by the task control block data structure OS_EB   which is found in UCOS H  An OS_TCB is used to hold the state of a task and other  system related information    OSTCBStkPtr contains a pointer to the current top of the stack for the task  uCOS allows  each task to have
15. r Datal   1      char Data2    2      char Data3    3    char Data4    4    char Data5    5    void far Task void  data      void interrupt   OldTickISR  void    void main void        UBYTE err    clrscr      OldTickISR   getvect 0x08    setvect UCOS   void interrupt      void  OSCtxSw     setvect OxF2  OldTickISR    OSInit  amp OSIdleTaskStk STK_SIZE    OS_MAX_TASKS    OSTaskCreate Task   void    amp Datal    void    amp Stk1 STK_SIZE   1    OSTaskCreate Task   void    amp Data2    void    amp Stk2 STK_SIZE   2    OSTaskCreate Task   void    amp Data3      void    amp Stk3 STK_SIZE   3      OSTaskCreate Task   void    amp Data4    void    amp Stk4 STK_SIZE   4    OSTaskCreate Task   void    amp Datas    void    amp StkS STK_ SIZE   5    OSStart        void far Task void  data      setvect 0x08   void interrupt      void  OSTickISR    while  1     OSTimeDly 1    gotoxy rand     79   1 rand     25   1    putch   char   data    if  kbhitQ     setvect 0x08  OldTickISR      exit O      
16. to the task s  OS_TCB is placed in OSTCBPrioTbl    UCOS C  using the task priority as the index   The task s OS_TCB is then inserted in a doubly linked list with OSTCBList  UCOS C   pointing to the most recently created task  The task is then inserted in a ready list and the  scheduler is called to determine if the created task is now the highest priority task that is  ready to run     TASK SCHEDULING    Task scheduling is performed by OSSched    UCOS C   uCOS s task scheduling time is  constant regardless of the number of tasks created in an application  up to 63 user tasks    Each task is assigned a unique priority level between zero and 63  Task priority 63 is  always assigned to uCOS s idle task when the kernel is initialized     Task priorities are grouped  eight tasks per group  in OSRdyGrp  UCOS C   Each bit in  OSBdyGrp is used to indicate that a task in a group is ready to run  When a task is ready  to run  it also sets its corresponding bit in the ready list table  OSRdyTbl    To determine  which priority  and thus which task  will run next  the scheduler determines the lowest  priority number that has its bit set in OSRdyTbl     Tasks are made ready to run by  executing the following section of code     OSRdyGrp I OSMapTbl p  gt  gt  3    OSRdyTbl p  gt  gt  3   OSMapTbl p  amp  0x07      This code sets the ready bit of the task in OSRdyTbI 8  based on its priority number  p   Similarly  a task is removed from the ready list by executing the following section of co
17. ts   respectively  These macros are included for portability     TASK STATES    Figure 1 shows the state transition diagram for tasks under uCOS  At any given time  a  task can be in any one of five states  The nOR MINI state for a task corresponds to a task  that resides in EPROM but has not been made available to uCOS  A task is made available  to uCOS by calling OS TaskCreate    which can be found in UCOS 18 6C C  When a task  is created  it is made ready to run  If the created task is the highest priority task that is  ready to run  it is immediately given the RUNNING state  and the task s code is executed  by the CPU  While the task is running  it may request from uCOS to wait for an event to  occur  PEND  or delay execution for a number of system ticks     When a task requests such a service from uCOS  the next highest priority task is given  control of the CPU  When the event PENDed on occurs  the task is again made ready to  run and if it is the highest priority task  it is again given control of the CPU  Other services  are available to user tasks to notify other tasks that certain events have occured  A running  task may be interrupted  in which case the interrupt service routine  ISR  takes control of  the CPU  The ISR may make one or more tasks ready to run by signaling that one or more  events occurred  In this case  before returning from the ISR  uCOS determines if the  interrupted task is still the highest priority task that is ready to run  If a higher priorit
18. y task  is made ready to run by the ISR  the previous task is preempted and the new highest  priority task is resumed  Otherwise  the interrupted task is resumed     When all tasks are either waiting for events or delayed for a number of system ticks  uCOS  executes an idle task  OSTaskldle       TASK CREATION    As previously mentioned  tasks are created by calling OSTask Create    Tasks can be  created prior to the start of multitasking or by a running task  A task cannot be created by  an ISR  OSTaskCreate   is passed four arguments  task is a pointer to the task s code  data  is a pointer to a user definable data area  which is used to pass arguments to the task  pstk  is a pointer to the task s stack area  which is used to store local variables and CPU  registers during an interrupt  The size of this stack is defined by the task requirements and  the anticipated interrupt nesting  Determining the size of the stack involves knowing how  many bytes are required to store the local variables for the task  all nested functions  and  the requirements for interrupts  accounting for nesting   p is the task priority  A unique  priority number must be assigned to each task  the lower the number  the higher the  priority     When a task is created  it is assigned an OS_TCB  which is then initialized  The task stack  is initialized to make it look as if an interrupt occurred and the CPU registers were saved  onto it  The stack frame of a created task is shown in Figure 2  A pointer 
    
Download Pdf Manuals
 
 
    
Related Search
    
Related Contents
n°2 – septembre 2001  Vornado SF-435W User's Manual  —Near miss“: repercussões e percepção da assistência  Revision 2.26.06 - Anderson Ford Motorsport  Philips 2000 series DVP2800/12  RT55HD MV3 (En.Fr.De.Es)-1.ai  Famille Concessionnaire - Présentation générale  T'nB Bubble  BARACK OBAMA: LE STRATÈGE, L`ESPOIR, LE PRODUIT LE    Copyright © All rights reserved. 
   Failed to retrieve file