⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readme.txt

📁 embed in keil
💻 TXT
字号:


        		uC/OS-II V2.51 Ported to the 80C52
			==================================

This file contains information on how to port uC/OS-II, version 2.51, to the
80C52 family of processors, using the IAR Systems Embedded Workbench 2.2.

The port files will only work with the specified development tool. Other compilers
will require modifications on some of the target-specific functions.

The information contained herein may be devided into three main areas:

A: Microcontroller internal configuration.
B: Target-specific code.
C: Target-independent code.

To further clarify the operations, I have included sample code to illustrate how to
taylor the software tools to get the best results, and a small demo program which I
have successfully run on a hardware platform featuring a Dallas 80C320 device at 24MHz. 



                    A.- Microcontroller Internal Configuration.
		    -------------------------------------------	

This port uses some specific internal memory locations which may not be changed:

- The internal Stack Pointer is set at 60h. 
- The internal memory is used in the following way:

   Addresses 40h-41h hold the pointer to the base of current task's external stack.
   Addresses 42h-43h are timer #0 reload buffers (Timer#0 is reserved as the system tick).
   Addresses 44h-47h are the work area of the port assembly code functions.

   This leaves addresses 48h to 5Fh as the "data" type of variables in your application.
   (variables reserved in internal RAM).

- I normally reserve the first bit-addressable byte (20h) for internal flag bits. This
  leaves you addresses 21h to 3Fh for all your bit-variable requirements.

All these memory constrains are best specified to the development tool by the use of
a "Linker Control File". I am attaching a sample one ("lnk8051.xcl") which defines all
the memory segments described so far. In addition, my test board uses only 64KB of total
external memory: the lower 32KB are in a flash device to hold the code, and the upper 32KB
is simply the data RAM. You can edit the linker control file and adapt it to your specific
requirements.

Note that I am assigning the beginning of the XDATA segment to address 9000h, since I am
using locations 8000h to 8FFFh to place the tasks' external stacks required by the kernel.
 
You must use the "Large Memory Model" in the IAR Systems tool. This means that the linker 
will use the run-time library called CL8051L.R03 to generate the executable file. At this
point, a word of caution is in order:

The run-time library contains one module called CSTARTUP. This is very important for two
reasons:

- IAR Systems provides the source code of this module so you can define some low-level
  initialisations specific to your hardware.

- This module defines the label "init_C" which is the beginning of all the compiler
  generated code. We need to use this label as our reset vector. This will be explained
  more in depth later.

I am including a modified source code for the CSTARTUP module ("_cstart.s03"), where I have
only included a call to a module called "Init_Board" (contained in the attached file
"brd_init.s03"). This module performs basic initialisations, and is the best place to
locate the hardware diagnostic code, since it executes before any other compiler-generated
code, and also way before the kernel is even started.

Following IAR Systems documentation, you have to use the XLIB tool to generate a modified
version of the run-time library where you will have substituted the default CSTARTUP
module by the one I am providing, or even your own one.

I also strongly recommend that the interrupt service routines be coded in assembly language.
This will enhance system speed and reliability. In addition, using uC/OS-II (or any other
real-time kernel) places some constrains on how interrupts are handled.

To make this point clear, I have included the file "isr.s03", which includes code for two
interrupts: 

- Timer #0 interrupt. This is a requirement of uC/OS-II, since this will be the system tick.

- The serial port interrupt. This is just a "skeleton" routine, very dependent on the
  specific hardware, that needs to be completed. 

You must follow the pattern of register saving/restoring and kernel calls, to code all the
other interrupt service routines.

The file "isr.s03" not only contains the interrupt service routines. In fact it defines
the absolute beginning of the program, as it fixes the reset vector. The branch address
happens to be the label "init_C", which the linker assigns to a call to our initialisation
code.



           			B.- Target-Specific Code
				------------------------	

This code actually implements the porting of uC/OS-II to the IAR Systems toolchain. Two
files contain the code:

- The 'C' functions are contained in the file "os_cpu_c.c". The main function in this 
  file is "OSTaskStkInit". This function is called every time a task is created, and it
  prepares the task' stack. All it does is initialise the stack reserving space for
  all registers that need to be saved/restored at every context switch, and in the
  required order. The main addresses saved by the function are: the very address of
  the task code, and a pointer  that the task will regard as a parameter. For exemple,
  suppose a task called "My_Task" is created with:

                OSTaskCreate(My_Task, (void *)parms, TaskStack, prio)
				
  When "My_Task" first executes, it will think that it was called by the compiler as:
                        
                            My_Task((void *)parms);  

  This is because the IAR Systems parameter-passing convention is observed at stack
  creation.

  The remaining functions in the file are basically user "hooks", pertaining to uC/OS-II
  version 2.51, available to the user so he/she may include some control code at specific
  execution times.

- The assembly language functions are contained in the file "uCOS_asm.s03". Only three
  functions need to be coded in assembly language, and they are all quite similar:

  OSStartHighRdy: This function loads the internal stack with the external stack of the
                  highest-priority task ready to run (initialises the first context), and
                  jumps to execute it.   


  OSCtxSw       : This function performs a task-level context switch (saves current context)
                  in current task' stack, and loads the new context from next task' stack.   


  OSIntCtxSw    : Same thing but called at interrupt level.



           			C.- Target-Independent Code
				---------------------------	

As the name implies, target-independent code is by definition platform-independent.
However, not living in an ideal world, I have found that some minor changes need to be
done on this code to make it run in the IAR Systems compiler.

First of all, the identifier "pdata" happens to be an extended keyword (the same as 
"code", "data", "idata"...etc) and can not be used to name variables. As it is used 
in some function declarations, you will have to sort them out, and change them to 
something like "pfdata", "psemdata",... or whatever you like.

Secondly, in what appears to be a flaw in the IAR Systems development tool, the compiler
seems to have a hard time handling read/modify pointers to structures in a single line. 
The compiler doesn't complain, but it doesn't do it right either. Specifically, the
following functions had to be changed:

- void OSTCBInit(void): (in file "os_core.c")

  The sentences:

    ptcb->OSTCBY         = prio >> 3;                  /* Pre-compute X, Y, BitX and BitY          */
    ptcb->OSTCBBitY      = OSMapTbl[ptcb->OSTCBY];
    ptcb->OSTCBX         = prio & 0x07;
    ptcb->OSTCBBitX      = OSMapTbl[ptcb->OSTCBX];

  are not handled correctly by the compiler.

  I had to add two support variables (offsety and offsetx) as follows:

    offsety              = prio >> 3;
    offsetx              = prio & 0x07;
                                                       
    ptcb->OSTCBY         = offsety;                          /* Pre-compute X, Y, BitX and BitY          */
    ptcb->OSTCBBitY      = OSMapTbl[offsety];
    ptcb->OSTCBX         = offsetx;
    ptcb->OSTCBBitX      = OSMapTbl[offsetx];


- void OSTimeTick(void): (in file "os_core.c")

  In the following "while" construct:

    while (ptcb->OSTCBPrio != OS_IDLE_PRIO) {              /* Go through all TCBs in TCB list          */
        OS_ENTER_CRITICAL();
        if (ptcb->OSTCBDly != 0) {                         /* Delayed or waiting for event with TO     */
            if (--ptcb->OSTCBDly == 0) {                   /* Decrement nbr of ticks to end of delay   */
                if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == 0x00) {   /* Is task suspended?             */
                    OSRdyGrp               |= ptcb->OSTCBBitY; /* No,  Make task Rdy to Run (timed out)*/
                    OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
                } else {                                       /* Yes, Leave 1 tick to prevent ...     */
                    ptcb->OSTCBDly = 1;                        /* ... loosing the task when the ...    */
                }                                              /* ... suspension is removed.           */
            }
        }
        ptcb = ptcb->OSTCBNext;                                /* Point at next TCB in TCB list        */
        OS_EXIT_CRITICAL();
    }


  
  the second "if" [ if (--ptcb->OSTCBDly == 0) ] doesn't seem to work. Likewise I had to add
  a variable called "delay", and recode as follows:

 while (ptcb->OSTCBPrio != OS_IDLE_PRIO)                     /* Go through all TCBs in TCB list          */
      {
       OS_ENTER_CRITICAL();
       delay = ptcb->OSTCBDly;
       if (delay != 0)                                       /* Delayed or waiting for event with TO     */
         {  
          delay--;
          if ((ptcb->OSTCBDly = delay) == 0)                 /* Decrement nbr of ticks to end of delay   */
            {    
             if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == 0x00)  /* Is task suspended?                     */
               {
                OSRdyGrp               |= ptcb->OSTCBBitY;     /* No,  Make task Rdy to Run (timed out)  */
                OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
               } 
         
             else                                              /* Yes, Leave 1 tick to prevent ...       */
               ptcb->OSTCBDly = 1;                             /* ... loosing the task when the ...      */
                                                               /* ... suspension is removed.             */
            }
     
         }




 
I hope these remarks do not seem too intimidating. Based on my experience with this porting,
I can openly affirm that uC/OS-II, version 2.51, is an extremely efficient, reliable and
friendly piece of software. I want therefore, to express appreciation and gratitude to
Mr. Jean Labrosse for his work with uC/OS-II.

 P.S.
 The sample code in files "main.c" and "tasks.c" is self documented.


 A. Fuentes / November 2001
 (antonio_fuentes@msl-vlc.com)












⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -