Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
59
Добавлен:
14.04.2015
Размер:
1.37 Mб
Скачать
void (*func_array[])() = { func2 };

Keil Software — Cx51 Compiler User’s Guide

375

 

 

Appendix F. Hints, Tips, and

Techniques

This section lists a number of illustrations and tips which commonly require further explanation. Items in this section are listed in no particular order and are merely intended to be referenced if you experience similar problems.

Recursive Code Reference Error

The following program example:

#pragma code symbols debug oe

void func1(unsigned char *msg ) { ; }

void func2( void ) { unsigned char uc; func1("xxxxxxxxxxxxxxx");

}

code void (*func_array[])() = { func2 };

void main( void ) { (*func_array[0])();

}

when compiled and linked using the following command lines:

C51 EXAMPLE1.C

BL51 EXAMPLE1.OBJ IX

fails and display the following error message.

F

***WARNING 13: RECURSIVE CALL TO SEGMENT SEGMENT: ?CO?EXAMPLE1

CALLER: ?PR?FUNC2?EXAMPLE1

In this program example, func2 defines a constant string (“xxx…xxx”) which is directed into the constant code segment ?CO?EXAMPLE1. The definition code

yields a reference between segment ?CO?EXAMPLE1 (where the code table is located) and the executable code segment ?PR?FUNC2?EXAMPLE1. Because func2 also refers to segment ?CO?EXAMPLE1, BL51 assumes that there is a recursive call.

376 Appendix F. Hints, Tips, and Techniques

To avoid this problem, link using the following command line:

Lx51 EXAMPLE1.OBJ IX OVERLAY &

(?CO?EXAMPLE1 ~ FUNC2, MAIN ! FUNC2)

?CO?EXAMPLE1 ~ FUNC2 deletes the implied call reference between func2 and the code constant segment in the example. Then, MAIN ! FUNC2 adds an additional call to the reference listing between MAIN and FUNC2 instead. Refer to the Ax51 Macro Assembler User’s Guide for more information.

In summary, automatic overlay analysis cannot be successfully accomplished when references are made via pointers to functions. References of this type must be manually implemented, as in the example above.

 

 

Problems Using the printf Routines

 

 

The printf functions are implemented using a variable-length argument list.

 

 

Arguments specified after the format string are passed using their inherent data

 

 

type. This can cause problems when the format specification expects a data

 

 

object of a different type than was passed. For example, the following code:

 

 

 

 

 

printf ("%c %d %u %bu", 'A', 1, 2, 3);

 

 

does not print the string “A 1 2 3”. This is because the Cx51 compiler passes the

 

 

arguments 1, 2, and 3 all as 8-bit byte types. The format specifiers %d and

 

 

%u both expect 16-bit int types.

F

 

To avoid this type of problem, you must explicitly define the data type to pass to

 

the printf function. To do this, you must type cast the above values. For

 

 

example:

 

 

 

 

 

printf ("%c %d %u %bu", 'A',(int) 1, (unsigned int) 2, (char) 3);

 

 

If you are uncertain of the size of the argument that is passed, you may cast the

 

 

value to the desired size.

Keil Software — Cx51 Compiler User’s Guide

377

 

 

Uncalled Functions

It is common practice during the development process to write but not call additional functions. While the compiler permits this without error, the Linker/Locator does not treat this code casually because of the support for data overlaying, and emits a warning message.

Interrupt functions are never called, they are invoked by the hardware. An uncalled routine is treated as a potential interrupt routine by the linker. This means that the function is assigned non-overlayable data space for its local variables. This quickly exhausts all available data memory (depending upon the memory model used).

If you unexpectedly run out of memory, be sure to check for linker warnings relating to uncalled or unused routines. You can use the linker’s IXREF directive to include a cross reference list in the linker map (.M51) file.

Using Monitor-51

If you want to test a C program with Monitor-51 and if the Monitor-51 is installed at code address 0, consider the following rules (the specification refers to a target system where the available code memory for user programs starts at address 8000H):

 

All C modules which contain interrupt functions must be translated with the

F

 

directive INTVECTOR (0x8000).

 

In STARTUP.A51, the statement CSEG AT 0 must be replaced with CSEG

 

AT 8000H. Then, this file must be assembled and linked with your program

 

 

 

 

as specified in the file header.

 

378 Appendix F. Hints, Tips, and Techniques

Trouble with the bdata Memory Type

Some users have reported difficulties in using the bdata memory type. Using bdata is similar to using the sfr modifier. The most common error is encountered when referencing a bdata variable defined in another module. For example:

extern bdata char xyz_flag;

sbit xyz_bit1 = xyz_flag^1;

In order to generate the appropriate instructions, the compiler must have the absolute value of the reference to be generated. In the above example, this cannot be done, as this address of xyz_flag cannot be known until after the linking phase has been completed. Follow the rules below to avoid this problem.

1. A bdata variable (defined and used in the same way as an sfr) must be defined in global space; not within the scope of a procedure.

2. A bdata bit variable (defined and used in the same way as an sbit) must also be defined in global space, and cannot be located within the scope of a procedure.

3. The definition of the bdata variable and the creation of its sbit access component name must be accomplished where the compiler has a “view” of both the variable and the component.

F

 

For example, declare the bdata variable and the bit component in the same

 

source module:

 

 

 

 

 

 

 

bdata char xyz_flag;

 

 

sbit xyz_bit1 = xyz_flag^1;

 

 

Then, declare the bit component external:

 

 

 

 

 

extern bit xyz_bit1;

 

 

As with any other declared and named C variable that reserves space, simply

 

 

define your bdata variable and its component sbits in a module. Then, use the

 

 

extern bit specifier to reference it as the need arises.

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