hsk-libs-dev  270
High Speed Karlsruhe XC878 library collection
Using the Small Device C Compiler (SDCC)

This section describes how to compile code for the XC878 with the Small Device C Compiler. SDCC is an open source compiler supporting several 8 bit architectures.

This section is about using the compiler and maintaining C51 compatibility. Refer to The Project Makefile to build this project using SDCC.

See also
SDCC project: http://sdcc.sf.net
Small Device C Compiler Manual: sdccman.pdf

Processor Architecture

The 8051 architecture is selected with the parameter -mmcs51. Additionally the compiler needs to be invoked with the correct memory architecture, XRAM starts at addres 0xF000 and is 3kb wide. For this the parameters --xram-loc and --xram-size are provided:

-mmcs51 --xram-loc 0xF000 --xram-size 3072

SDCC Header File for XC878

This projects includes the file Infineon/XC878.h in the inc/ directory, which contains the SFR definitions for the XC878. It is a modified version of the XC878.h file proivided by Keil µVision, which in turn is a Dave generated file.

The modification is an #ifdef SDCC block, with some compatibility glue to allow using the C51 code mostly unmodified.

To make the header available to sdcc the inc/ should be added to the include search path with the -I parameter:

-mmcs51 --xram-loc 0xF000 --xram-size 3072 -I inc/

Compiling Code

Code is compiled using the -c parameter:

sdcc -mmcs51 --xram-loc 0xF000 --xram-size 3072 -I inc/ -o builddir/ -c example.c

The compiler will generate a number of files in builddir, among them example.asm and example.rel, the object file.

Instead of the build dir the output parameter -o can also take the name of the object file as a parameter.

SDCC can only compile one .c file at a time, thus every .c file must be compiled separately and linked in a separate step later.

Linking

Linking can be done by giving all required object files as parameters. The output file name will be based on the first input file or can explicitely be stated:

sdcc -mmcs51 --xram-loc 0xF000 --xram-size 3072 -I inc/ -o builddir/ -c example.rel lib1.rel lib2.rel

The output file would be builddir/example.ihx (Intel HEX). -o builddir/example.hex can be used to change the filename suffix to .hex, which is more convenient when using XC800_FLOAD to flash the µC.

Programming

Whereas µVision as an IDE covers flashing, SDCC users need a separate tool to do so. One such tool is Infineon's XC800_FLOAD. FLOAD also requires DAS.

The use of FLOAD is very straightforward, make the following settings:

XC800_FLOAD.png
XC800_FLOAD Flash Programming Tool

The important functions of FLOAD are:

See also
FLOAD download: http://www.infineon.com/cms/en/product/microcontrollers/development-tools,-software-and-kits/xc800-development-tools,-software-and-kits/software-downloads/channel.html?channel=db3a304319c6f18c011a0b54923431e5
Infineon DAS Tool Interface website: http://www.infineon.com/das/

Memory Usage Compatibility

In order to write compatible code, the compatiblity glue in the Infineon/XC878.h header maps keywords like data, idata, xdata etc. to their SDCC equivalents __data, __idata and __xdata.

Starting with SDCC 3.x C51 code and SDCC __code are largely interchangeable. This wasn't always the case, which results in two different styles for using code.

E.g. putting a variable into code space, C51 style:

ubyte code foo = 0x2A;

SDCC style:

const ubyte foo = 0x2A;

The C51 style is consistent with other variable space assignments and portable (it did not work with SDCC 2.x, but works with 3.x). The SDCC style is more logical in terms of writing code that communicates what one intends to do. The recommendation within this project is to use a redundant style, which also worked with SDCC 2.x with some C macro magic:

const ubyte code foo = 0x2A;

Function pointers are a special case. To SDCC all function pointers refer to code, C51 uses (slower, larger) generic pointers if the code keyword is missing. Unfortunately there is no compatible syntax to place code in a function pointer declaration. This can be circumvented with preprocessor instructions:

/*
* SDCC does not like the \c code keyword for function pointers, C51 needs it
* or it will use generic pointers.
*/
#ifdef SDCC
#undef code
#define code
#endif /* SDCC */

A function pointer declaration may look like this:

void (code *foo)(void);

Take care to restore code before the end of a .h file:

/*
* Restore the usual meaning of \c code.
*/
#ifdef SDCC
#undef code
#define code __code
#endif /* SDCC */

Interrupts

The most significant difference between interrupt handling in SDCC and C51 is that prototypes for the interrupts must be visible in the context of the main() function.

These prototypes can be enclosed in an #ifdef:

#ifndef _HSK_ISR_ISR_
#define _HSK_ISR_ISR_
void ISR_hsk_isr5(void) interrupt 5 using 1;
void ISR_hsk_isr6(void) interrupt 6 using 1;
void ISR_hsk_isr8(void) interrupt 8 using 1;
void ISR_hsk_isr9(void) interrupt 9 using 1;
void ISR_hsk_isr14(void) interrupt 14 using 2;
#endif /* _HSK_ISR_ISR_ */

In this project the issue is solved by placing the prototypes in a dedicated file with the file name suffix .isr. It is then included in the relevant headers in the following fashion:

/*
* Required for SDCC to propagate ISR prototypes.
*/
#ifdef SDCC
#include "../hsk_isr/hsk_isr.isr"
#endif /* SDCC */

By not placing the ISR prototypes directly in the header file, unwanted and otherwise unnecessary inclusion of headers can be avoided. Only the small file with the ISR prototypes needs to be included in header files of ISR using code.

According to the SDCC manual functions called by ISRs must be reentrant or protected from memory overlay. This is done with a compiler instruction:

#pragma save
#pragma nooverlay
void isr_callback(void) using 1 {
[...]
}
#pragma restore

Unfortunately this causes a compiler warning when using C51:

..\src\main.c(49): warning C245: unknown #pragma, line ignored

This can be avoided by making nooverlay conditional:

#pragma save
#ifdef SDCC
#pragma nooverlay
#endif
void isr_callback(void) using 1 {
[...]
}
#pragma restore