Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2012 / uCOS / uCOSII_ebook.pdf
Скачиваний:
90
Добавлен:
10.02.2015
Размер:
1.08 Mб
Скачать

INT32U

OSIdleCtr

INT32U

OSIdleCtrRun;

INT32U

OSIdleCtrMax;

The compiler is thus told to allocate storage for these variables. When the compiler processes any other .C files, the header file (uCOS_II.H) looks as shown below because OS_GLOBALS is not defined and thus OS_EXT is set to extern.

extern INT32U

OSIdleCtr

extern INT32U

OSIdleCtrRun;

extern INT32U

OSIdleCtrMax;

In this case, no storage is allocated and any .C file can access these variables. The nice thing about this technique is that the declaration for the variables is done in only one file, the .H file.

1.04 OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL()

Throughout the source code provided in this book, you will see calls to the following macros:

OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL(). OS_ENTER_CRITICAL()

is a macro that disables interrupts and OS_EXIT_CRITICAL() is a macro that enables interrupts. Disabling and enabling interrupts is done to protect critical sections of code. These macros are obviously processor specific and are different for each processor. These macros are found inOS_CPU.H. Listing 1.3

shows the declarations of these macros for the 80x86 processor. Section 9.03.02 discusses why there are two ways of declaring these macros.

#define

OS_CRITICAL_METHOD

2

 

#if

OS_CRITICAL_METHOD == 1

 

#define

OS_ENTER_CRITICAL()

asm

CLI

#define

OS_EXIT_CRITICAL()

asm

STI

#endif

 

 

 

#if

OS_CRITICAL_METHOD == 2

 

#define

OS_ENTER_CRITICAL()

asm {PUSHF; CLI}

#define

OS_EXIT_CRITICAL()

asm

POPF

#endif

 

 

 

Listing 1.3, Macros to access critical sections.

Your application code can make use of these macros as long as you realize that they are used to disable and enable interrupts. Disabling interrupts obviously affect interrupt latency so be careful. You can also protect critical sections using semaphores.

1.05 PC Based Services

The files PC.C and PC.H (in the \SOFTWARE\BLOCKS\PC\SOURCE directory) contain PC compatible services that I used throughout the examples. Unlike the first version of µC/OS-II (i.e. µC/OS), I decided to encapsulate these functions (as they should have been) to avoid redefining them in every example and also, to allow you to easily adapt the code to a different compiler. PC.C basically contains three types of services: character based display, elapsed time measurement and, miscellaneous. All functions start with the prefix PC_.

1.05.01 PC Based Services, Character Based Display

The display functions perform direct writes to video RAM for performance reasons. On a VGA monitor, video memory starts at absolute memory location 0x000B8000 (or using a segment:offset notation, B800:0000). You can use this code on a monochrome monitor by changing the #define constant

DISP_BASE from 0xB800 to 0xB000.

The display functions in PC.C are used to write ASCII (and special) characters anywhere on the screen using X and Y coordinates. A PC’s display can hold up to 2000 characters organized as 25 rows (i.e. Y) by 80 columns (i.e. X). Each character requires two bytes to display. The first byte is the character that you want to display while the second byte is an attribute that determines the foreground/background color combination of the character. The foreground color is specified in the lower 4 bits of the attribute while the background color appears in bits 4 to 6. Finally, the most-significant bit determines whether the character will blink (when 1) or not (when 0). You should use the #define constants declared in PC.C (FGND means foreground and BGND is background). PC.C contains the following four functions:

PC_DispClrScr()

PC_DispClrLine()

PC_DispChar()

PC_DispStr()

To clear the screen

To clear a single row (or line)

To display a single ASCII character anywhere on the screen To display an ASCII string anywhere on the screen

PC_ElapsedStart()

1.05.02 PC Based Services, Elapsed Time Measurement

The elapsed time measurement functions are used to determine how much time a function takes to execute. Time measurement is performed by using the PC’s 82C54 timer #2. You make time measurement by wrapping the code to measure by the two functions and PC_ElapsedStop(). However, before you can use these two functions, you need to call the function PC_ElapsedInit(). PC_ElapsedInit()basically computes the overhead associated with the other two functions. This way, the execution time returned by PC_ElapsedStop() consist exclusively of the code you are measuring. Note that none of these functions are reentrant and thus, you must be careful that you do not invoke them from multiple tasks at the same time. The example in listing 1.4 shows how you could measure the execution time of PC_DispChar(). Note that time is in microseconds (µS).

INT16U time;

PC_ElapsedInit();

.

.

PC_ElapsedStart();

PC_DispChar(40, 24, ‘A’, DISP_FGND_WHITE); time = PC_ElapsedStop();

Listing 1.4, Measuring code execution time.

1.05.03 PC Based Services, Miscellaneous

A µC/OS-II application looks just like any other DOS application. In other words, you compile and link your code just as if you would do a single threaded application running under DOS. The .EXE file that you create is loaded and executed by DOS and execution of your application starts from main(). Because µC/OS-II performs multitasking and needs to create a stack for each task, the single threaded DOS environment must be stored in case your application wishes to quit µC/OS-II, and return to DOS. Saving the DOS environment is done by calling PC_DOSSaveReturn(). When your application needs to return to DOS (and exit µC/OS-II), you simply call PC_DOSReturn(). PC.C makes use of the ANSI C setjmp() and longjmp() functions to save and restore the DOS environment, respectively. These functions are provided by the Borland C/C++ compiler library and should be available on most other compilers.

You should note that a crashed application or invoking exit(0) without using PC_DOSReturn()

can leave DOS is a corrupted state. This may lead to a crash of DOS, or the DOS window within Windows 95.

PC_GetDateTime() is a function that obtains the PC’s current date and time, and formats this

information into an ASCII string. The format is “MM-DD-YY HH:MM:SS” and you will need at least 19 characters (including the NUL character) to hold this string. PC_GetDateTime() uses the Borland

PC_VectSet()
PC_GetKey()
C/C++ library functions DOS compilers.

gettime() and getdate() which should have their equivalent on other

is a function that checks to see if a key was pressed and if so, obtains that key, and returns it to the caller. PC_GetKey() uses the Borland C/C++ library functions kbhit() and getch() which again, have their equivalent on other DOS compilers.

PC_SetTickRate() allows you to change the tick rate for µC/OS-II by specifying the desired

frequency. Under DOS, a tick occurs 18.20648 times per second or, every 54.925 mS. This is because the 82C54 chip used didn’t get its counter initialized and the default value of 65535 takes effect. Had the chip been initialized with a divide by 59659, the tick rate would have been a very nice 20.000 Hz! I decided to change the tick rate to something more ‘exciting’and thus, decided to use about 200 Hz (actually 199.9966). You will note that the function OSTickISR() found in OS_CPU_A.ASM contains code to call the DOS tick handler one time out of 11. This is done to ensure that some of the housekeeping needed in DOS is maintained. You would not need to do this if you were to set the tick rate to 20 Hz. Before returning to DOS, PC_SetTickRate() is called by specifying 18 as the desired frequency. PC_SetTickRate() will know that you actually mean 18.2 Hz and will correctly set the 82C54.

The last two functions in PC.C are used to get and set an interrupt vector. library functions do accomplish this but, the PC_VectGet() and changed to accommo date a different compiler.

Again, I used Borland C/C++ can easily be

1.06 µC/OS-II Examples

The examples provided in this chapter was compiled using the Borland C/C++ V3.1 compiler in a DOS box on a Windows 95 platform. The executable code is found in the OBJ subdirectory of each example’s directory. The code was actually compiled under the Borland IDE (Integrated Development Environment) with the following options:

Compiler:

Code generation:

 

Model

: Large

Options

: Treat enums as ints

Assume SS Equals DS

: Default for memory model

Advanced code generation:

 

Floating point

: Emulation

Instruction set

: 80186

Options

: Generate underbars

 

Debug info in OBJs

 

Fast floating point

Optimizations:

Optimizations:

Global register allocation

Invariant code motion

Induction variables

Loop optimization

Suppress redundant loads

Copy propagation

Dead code elimination

Jump optimization

Inline intrinsic functions

Register variables:

Automatic

Common subexpressions:

Optimize globally

Optimize for:

Speed

It is assumed that the Borland C/C++ compiler is installed in the C:\CPP directory. If your compiler is located in a different directory, you will need to change the path in the Options/Directories menu of the IDE.

µC/OS-II is a scalable operating system which means that the code size of µC/OS-II can be reduced if you are not using all of its services. Code reduction is done by setting the #defines OS_???_EN to 0 in OS_CFG.H. You do this to disable code generation for the services that you will not be using. The examples in this chapter makes use of this feature and thus, each example declares their OS_???_EN appropriately.

Соседние файлы в папке uCOS