Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Made many correction to formatting

This chapter describes some of the structural aspects of µC/OS-II. You will learn:

  • how µC/OS-II handles access to critical sections of code,
  • what a task is, and how µC/OS-II knows about your tasks,
  • how tasks are scheduled,
  • how µC/OS-II determines the percent CPU your application is using,
  • how to write Interrupt Service Routines (ISRs),
  • what a clock tick is and how µC/OS-II handles it,
  • how to initialize µC/OS-II, and
  • how to start multitasking.

...

Figure 3.1 shows the µC/OS-II architecture and its relationship with the hardware. When you use µC/OS-II in an application, you are responsible for providing the Application Software and the µC/OS-II Configuration sections. This book and CD contain all the source code for the Processor-Independent Code section as well as the Processor-Specific Code section for the Intel 80x86, real mode, large model. If you intend to use µC/OS-II on a different processor, you need to either obtain a copy of a port for the processor you intend to use or write one yourself if the desired processor port is not available. Check the official µC/OS-II Web site at www.uCOS-IImicrium.com for a list of available ports.

...

µC/OS-II, like all real-time kernels, needs to disable interrupts in order to access critical sections of code and to reenable re-enable interrupts when done. This allows µC/OS-II to protect critical code from being entered simultaneously from either multiple tasks or ISRs. The interrupt disable time is one of the most important specifications that a real-time kernel vendor can provide because it affects the responsiveness of your system to real-time events. µC/OS-II tries to keep the interrupt disable time to a minimum, but with µC/OS-II, interrupt disable time is largely dependent on the processor architecture and the quality of the code generated by the compiler.

...

The PUSH PSW instruction pushes the ‘Processor Startus Status Word’, PSW (also known as the condition code register or, processor flags) onto the stack. The DI instruction stands for ‘Disable Interrupts’. Finally, the POP PSW instruction is assumed to restore the original state of the interrupt flag from the stack. The instructions I used are only for illustration purposes and may not be actual processor instructions.

...

contains a pointer to the current top-of-stack for the task. µC/OS-II allows each task to have its own stack, but just as important, each stack can be any size. Some commercial kernels assume that all stacks are the same size unless you write complex hooks. This limitation wastes RAM when all tasks have different stack requirements because the largest anticipated stack size has to be allocated for all tasks. .OSTCBStkPtr should be the only field in the OS_TCB data structure that which is accessed from assembly language code (from the context-switching code). I decided to place .OSTCBStkPtr as the first entry in the structure to make accessing this field easier from assembly language code (it ought to be at offset zero).

...

is a pointer to the bottom of the task’s stack. If the processor’s stack grows from high-to-low memory locations, then .OSTCBStkBottom will point at the lowest valid memory location for the stack. Similarly, if the processor’s stack grows from low-to-high memory locations, then .OSTCBStkBottom will point at the highest valid stack address. .OSTCBStkBottom is used by OSTaskStkChk() to check the size of a task’s stack at run time. This allows you to determine the amount of free stack space available for each stack. Stack checking can only occur if you create a task with OSTaskCreateExt(), so you need to set OS_TASK_CREATE_EXT_EN in OS_CFG.H to 1 to enable this field.

...

The maximum number of tasks (OS_MAX_TASKS) that an application can have is specified in OS_CFG.H and determines the number of OS_TCBs allocated for your application. You can reduce the amount of RAM needed by setting OS_MAX_TASKS to the actual number of tasks needed in your application. All OS_TCBs are placed in OSTCBTbl[]. Note that µC/OS-II allocates OS_N_SYS_TASKS (see uCOS_II.H) extra OS_TCBs for internal use. Currently, one is used for the idle task, and another is used for the statistic task (if OS_TASK_STAT_EN in OS_CFG.H is set to 1). When µC/OS-II is initialized, all OS_TCBs in the table are linked in a singly-linked list of free OS_TCBs, as shown in Figure 3.3. When a task is created, the OS_TCB pointed to by OSTCBFreeList is assigned to the task, and OSTCBFreeList is adjusted to point to the next OS_TCB in the chain. When a task is deleted, its OS_TCB is returned to the list of free OS_TCBs.

...

(9) In V2.04, I added a call to a function that can be defined in the processor’s port file – OSTCBInitHook(). This allows you to add extensions to the OS_TCB. For example, you could initialize and store the contents of floating-point registers, MMU registers, or anything else that can be associated with a task. However, you would typically store this additional information in memory that would be allocated by your application. Note that interrupts are enabled when OS_TCBInit() calls OSTCBInitHook().

(10) OS_TCBInit() disables interrupts when it needs to insert the OS_TCB into the doubly linked list of tasks that have been created. 

(11) OS_TCBInit() then calls OSTaskCreateHook(), which is a user-specified function that allows you to extend the functionality of OSTaskCreate() or OSTaskCreateExt(). OSTaskCreateHook() can be declared either in OS_CPU_C.C (if OS_CPU_HOOKS_EN is set to 1) or elsewhere (if OS_CPU_HOOKS_EN is set to 0). Note that interrupts are enabled when OS_TCBInit() calls OSTaskCreateHook().

You should note that I could have called only one of the two hook functions: OSTCBInitHook() or OSTaskCreateHook(). The reason there are two functions is to allow you to group (i.e. encapsulate) items that are tied with the OS_TCB in OSTCBInitHook() and other task related initialization in OSTaskCreateHook().(11)

(12) OS_TCBInit() disables interrupts when it needs to insert the OS_TCB into the doubly linked list of tasks that have been created. The list starts at OSTCBList, and the OS_TCB of a new task is always inserted at the beginning of the list.

(13) (14) Finally, the task is made ready to run, and OS_TCBInit() returns to its caller [OSTaskCreate() or OSTaskCreateExt()] with a code indicating that an OS_TCB has been allocated and initialized.

...

You can obtain the current version of µC/OS-II from your application by calling OSVersion() (Listing 3.29). OSVersion() returns the version number multiplied by 10010000. In other words, version 2.52 is returned as 25225200.

To find out about the latest version of µC/OS-II and how to obtain an upgrade, you should either contact the publisher or check the official µC/OS-II Web site at http://www.micrium.com.