Файл: Programming Microcontrollers in C, 2-nd edit (Ted Van Sickle, 2001).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 15.06.2025

Просмотров: 4072

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Header File 221

EXERCISES

1.Write a header file that contains definitions of all vectors shown on page 3 of the HC11 E Series Programming Reference Guide, M68HC11ERG/AD found on the CD-ROM. This file should be in­ cluded with any program that is intended to make use of interrupts.

2.Create a small program that uses the function vector(a,b). Compile the function and observe the assembly language code gen­ erated to accomplish this operation.

The Cosmic Compiler

The Cosmic compiler was originally known as the Whitesmiths compiler. Cosmic retained the maintenance contract on this com­ piler through a couple of corporate owners, and now has the rights to the compiler. This compiler used for the MC68HC11 family is some­ what more complicated to use than the ByteCraft compiler used with the C68HC05. The compiler should be installed using the install pro­ gram that comes with it. You should allow the compiler to modify your autoexec.bat and config.sys files unless you plan to do it your­ self. The system path should contain the path to the bin directory in the directory that contains the compiler. There are also two set com­ mands that should be inserted into the autoexec.bat file. These changes, once completed, will make compilation of programs rather easy. This compiler creates an intermediate assembly language pro­ gram that must be assembled. The result of the assembly is a relocatable object module. This module must be linked with other modules of the program and basic library modules to comprise the final program. The linking phase of the compilation places all of the parts of the program in their proper memory location.

Fortunately, the compiler can make use of command files to control the compilation sequence. These files relieve the programmer of the need to remember the dozens of little details that must go into each compilation. We will start with the highest level of the command files and work down into the lower levels. The basic command file to compile a program and create an S Record version of the program is as follows:

222Chapter 5 Programming Large 8-Bit Systems

c -dlistcs +o %1.c lnkh11 < %1.lnk

hexh11 -s -o %1.hex %1.h11

This file is called comp.bat and it is invoked by

comp <filename>

The %1 in the command file will be replaced by <filename> when the command file is run. The first line of the command file tells the compiler, named c, to execute with the options -dlistcs and +o. The name of the file will be the filename entered on the command line with a .c extension. The -dlistcs option causes a listing file to be generated and saved in a file of the same name filename but with an extension .ls. The +o option informs the compiler to create a relocatable object module of the program.

The basic invocation syntax of the compiler is

c [options] file.[c | s | o ] [filen. [ c | s | o ] ]

Any portion of the command line in the above sequence that is enclosed in square brackets [ ] is optional. Therefore, the only required command line entry following the c call is the file name. (Refer to the compiler manual for the variety of options that can be used on this command line.)

Several files can be included on the command line. Each of these files can have one of three extensions, c, s, or o. If the extension is .c, the compiler expects a C program. If it is .s, the compiler will process an assembly language program. When the extension is

.o, the compiler invokes the linker.

The compiler creates a relocatable object module that is linked by the next line in the command file.

lnkh11 < %1.lnk

The direct call to the linker lnkh11 is handed a command file to control the linking. Each program must have its own link command file, and the extension of this file is .lnk. An example linker command file is shown below. This command file is for a program developed later in this chapter.


Header File 223

#

# link command file for motorfr program

#

+h # multi-segment output

-o motorfr.h11 # output file name +text -b 0xd000 # program start address +data -b 0x0000 # data start address crtsmot.o # start-up routine

motorfr.o # application program libi.h11 # integer library libm.h11 # machine library

+text -b 0xffd6 # vectors start address interrup.o # interrupt vectors

+def __memory=__bss__ # symbol used by library

Comment lines are preceded with a # in this command file. The first executable line of code in the file contains a command +h which notifies the linker that the program will be in multiple memory segments rather than in a single block in memory. The second line

-o motorfr.h11

tells the linker to write the output file to motorfr.h11. This particular linker file is for a program named motorfr. The +text option places the beginning of the code portion of the next module to be linked at the offset 0xd000. The +data option places the data memory for the next module at the offset 0x0000. Finally, the names of the modules to be linked are next. The module crtsmot.o is a relocatable object module version of a start-up program. This routine will be discussed below. The next module to be linked is motorfr.o which is the output of the compiler. This line is followed by the invocation of two library calls. The first is to the integer library, and the second is to the machine library. These libraries will provide necessary code for function calls that are not contained directly in the program. Another library named libf.h11 contains floating point operations that might be needed in your program.

Another +text option will force the beginning of the code linked next to the address 0xffd6. This address is the beginning of the MC68HC11 vector table, and the code linked at this point is the vector function discussed earlier. This entry will create the vector table at

224 Chapter 5 Programming Large 8-Bit Systems

the correct location in memory, and it will also place the addresses of the designated vectors in the proper locations in the table.

The start-up routine mentioned earlier is shown below. This routine is patterned after one provided with the compiler. This assembly language program contains all of the code necessary to begin the operation of the C program to which it is linked. But note this point on syntax: within C, all function and memory names generated by the code are modified by the addition of an underscore _ at the beginning of the name. Therefore, if the function main() in the C program were to be referred to by an assembly program, the assembly program would be required to use _main. You will notice that there are many names beginning with both single and double underscores. For example _main has a single underscore, and __memory has a double underscore in the external statement that follows. Whenever an assembly language memory location or function name has underscores preceding the name, one of the underscores must be discarded when this same memory or function name is used in a C program to be linked to the module.

Here you see an example of why the programmer should not use an underscore for the first character of a name. The compiler writer assumes complete freedom to use the single underscore to begin any name needed by the operation of the compiler, and the programmer should concede this freedom to the compiler writer by avoiding the use of the underscore for the first character of a name anywhere in his program.

An example of this linkage has already been seen. In a previous section where the vector table was programmed, the entry point into the program was the function _stext(). Note in the code that follows that the function name in the assembly language part of the program is __stext with a double underscore. This start-up routine has been modified for use with a program that we will use later in the text. The most significant modification is the first two executable instructions which set the y register to the beginning of the I/O register memory area and then sets bits 0 and 1 of the location offset 36 (0x24) from the y register content. These instructions set the prescaler of the timer counter to 4 so that the timer will increment at the slowest possible rate. These two instructions modify the contents of TFLG2 and they must be changed within 64 bus cycles after the microcontroller exits reset. These changes and others needed in the INIT register, the


Header File 225

OPTION register, and the CONFIG register must be placed in this location in the program. These registers become read only memory locations after the first 64 bus cycles following reset.

The value __memory is calculated in the command file motorfr.lnk and it is the number of bytes of memory that the program uses for volatile memory. The start of the base memory section is _sbss and it is zero for this program. The instruction sequence starting with ldx #__sbss and ending with bne zbcl will clear all of the volatile memory used by the program. Finally the stack pointer is set to a value of 0xff and the C program is executed by the jsr _main call.

.processor m68hc11

;

; C START-UP FOR MC68HC11

;

.external _main, __memory

.public _exit, __stext, __return

;

.psect _bss __sbss:

.psect _text __stext: ldy #4096

bset 1,36,y ; set the prescaler to /4 clra ; reset the bss

ldx #__sbss ; start of bss bra loop ; start loop zbcl:

staa 0,x ; clear byte inx ; next byte loop:

cpx #__memory ; up to the end bne zbcl ; and loop

prog:

sts __sdata ; save sp for monitor return xgdx ; initialize stack pointer

ldd #00ffH ; put stack pointer at ff for HC11E9 xgdx

226Chapter 5 Programming Large 8-Bit Systems

txs

jsr _main ; execute main _exit:

lds __sdata ; restore stack pointer rts ; and return to calling program __return:

rti ; used by default interrupt vector

;

.psect _data __sdata:

.word 0 ; avoid any pointer to null

.end

The start-up program must be written to account for any special problems that might be needed for your program. Through this routine, memory can be initialized with data stored in ROM, the special registers that must be processed within the first 64 bus cycles can be set, the stack can be placed where the programmer desires, and so forth. The code at the end of the routine restores the stack pointer to the value it contained when the start-up routine was entered and executes an rts, return to subroutine, to return control of the processor to a monitor that started the program if one exists.

The location __sdata is the first byte following the volatile memory used by the program. This value will be used by the memory allocation functions to provide memory on the system heap.

Finally, the last line of the compiler command file

hexh11 -s -o %1.hex %1.h11

causes execution of the program hexh11 , which converts the object module from machine code to an S record format that can be written into an evaluation module or used to burn an EPROM version of the microcontroller. This S record file can also be delivered to the factory and used to define a mask for a mask ROM version of the microcontroller. The file created by this line of code will have an extension .hex.

EXERCISES

1.Write and compile a small program that will show some bit manipu­ lations in PORTA. Make the program test, set, and clear bits in this

Header File 227

port. Does the assembly language generated by the compiler appear to be efficient? If not, what can be done to improve the code?

2.Write and compile a program that uses Output Compare 3 to gener­ ate a periodic interrupt. This interrupt should occur each millisecond.

3.With the time tick generated by the results of Example 2 above, create a clock that will keep track of the time of day accurate to the nearest one-hundredth of a second.

The Compiler Optimizer and Volatile

The compiler optimizer that is a part of the Cosmic C compiler does an excellent job of reducing code size. One of the steps involved is to remove code required to change values that are not changed by the pro­ gram. Recall that the volatile qualifier identifies varibles that should not be optimized. The following code sequence will show this problem:

volatile char able; char baker

test(void)

{

char dog;

dog = able; dog = able; able = 0; able = 0; dog = baker; dog = baker; baker = 0; baker = 0;

}

Note that this function makes multiple assignments of dog, able, and baker. The assignments involving able show how the compiler responds to a volatile variable, and baker to a nonvolatile variable. The following listing is the compilation of the above program:

1 ; Compilateur C pour MC68HC11 (COSMIC-France)

32 .include”macro.h11"


228Chapter 5 Programming Large 8-Bit Systems

3 .list +

4 .psect _text

5; 1 volatile char able;

6; 2 char baker ;

7; 3

8; 4 test(void)

9; 5 {

10_test:

110000 3C pshx

120001 34 des

130002 30 tsx

14.set OFST=1

15; 6 char dog;

16; 7

17; 8 dog = able;

180003 F60000 ldab _able

19LL4:

200006 E700 stab OFST-1,x

21; 9 dog = able;

220008 F60000 ldab _able

23LL6:

24000B E700 stab OFST-1,x

25; 10 able = 0;

26000D 7F0000 clr _able

27LL01:

28; 11 able = 0;

290010 7F0000 clr _able

30LL21:

31; 12 dog = baker;

320013 F60001 ldab _baker

33; 13 dog = baker;

340016 E700 stab OFST-1,x

35; 14 baker = 0;

36; 15 baker = 0;

370018 7F0001 clr _baker

38; 16 }

39001B 31 ins

40001C 38 pulx

41001D 39 rts

Header File 229

42 ; 17

43 .public _test

44 .psect _bss

45_baker:

460000 .byte [1]

47.public _baker

48.psect _data

49_able:

50.byte [1]

51.public _able

52.end

Lines 17 through 24 correspond to the two lines

dog = able; dog = able;

The memory location of able in the program is _able, and the memory location for dog is at OFST-1,x. Note that the value in _able is read and placed into dog twice as the program stated. Also, the instruction clr _able is executed twice to account for the two lines

able = 0; able = 0;

This code is what you should expect when the volatile keyword is used when able is declared. On the other hand, lines 31 through 34 show the compilation of the two C lines

dog = baker; dog = baker;

In this case, you will note that the value for baker, stored at _baker, is placed into the address of dog only once even though the code line is repeated. Similarly, the two lines

baker = 0; baker = 0;

result in assembly code that clears the location _baker only once. This type of optimization will save you much code space. It is certainly a problem whenever there is a memory location that can be changed from outside the program. The volatile keyword will cause the