SDCC

From OLPC
Jump to: navigation, search


Pencil.png NOTE: The contents of this page are not set in stone, and are subject to change!

This page is a draft in active flux ...
Please leave suggestions on the talk page.

Pencil.png

SDCC is a small Device C Compiler that was specifically designed to the needs of 8 Bit Micros like Intel 8051, Maxim 80DS390, Zilog Z80 among others. SDCC comes with SDCDB a source level debugger and ucSim a free open source simulator for Intel 8051 and other micro-controllers

Installation

Debian

apt-get install sdcc

Note: may be necessary to install sdcc-doc and sdcc-ucsim

Fedora

yum install sdcc

Working with SDCC

Compiling a program

Write this in an ASCII editor and call the archive test.c (Or whatever name you want):

char test;
void main(void) {
   test=0;
}

Then:

sdcc-sdcc -c test.c

The -c option is for disable the linker, the next step is trying without the linker:

sdcc-sdcc test.c

Final test, modify the test file and include the following (if all goes without warnings SDCC is well installed):

#include <string.h>
char str1[10];
void main(void) {
 strcpy(str1, "testing");
}

this is needed to test that SDCC supports libraries.

For OLPC we are going to work with the 8051 processor, for single source file 8051 projects you can Compile your programs with the following command:

sdcc-sdcc sourcefile.c   

When doing this command the output files are as follows:

  • sourcefile.asm - Assembler source file created by the compiler
  • sourcefile.lst - Assembler listing file created by the Assembler
  • sourcefile.rst - Assembler listing file updated with linkedit information, created by linkage editor
  • sourcefile.sym - symbol listing for the sourcefile, created by the assembler
  • sourcefile.rel or sourcefile.o - Object file created by the assembler, input to Linkage editor
  • sourcefile.map - The memory map for the load module, created by the Linker
  • sourcefile.mem - A file with a summary of the memory usage
  • sourcefile.ihx - The load module in Intel hex format (you can select the Motorola S19 format with --out-fmt-s19. If you need another format you might want to use objdump or srecord).
  • sourcefile.adb - An intermediate file containing debug information needed to create the .cdb file (with --debug)
  • sourcefile.cdb - An optional file (with --debug) containing debug information.
  • sourcefile. - (no extension) An optional AOMF or AOMF51 file containing debug information (generated with option --debug). The (Intel) absolute object module format is a sub-format of the OMF51 format and is commonly used by third party tools (debuggers, simulators, emulators).
  • sourcefile.dump* - Dump file to debug the compiler itself (generated with option --dumpall)

Multiple Source file projects

SDCC can compile only ONE file at a time. For example assume that you have a project containing the following files:

  • Ex1.c (contains some functions)
  • Ex2.c (contains some more functions)
  • Exmain.c (with more functions and the function main)

The first two files will need to be compiled separately with the commands:

  • sdcc -c Ex1.c
  • sdcc -c Ex2.c

Then compile the source file containing the main() function and link the files together with the following command: sdcc Exmain.c Ex1.rel Ex2.rel Alternatively, Exmain.c can be separately compiled as well:

  • sdcc -c Exmain.c
  • sdcc Exmain.rel Ex1.rel Ex2.rel

The file containing the main() function Must be the First file specified in the command line, since the linkage editor processes file in the order they are presented to it. The linker is invoked from SDCC using a script file with extension .lnk. You can view this file to troubleshoot linking problems such as those arising from missing libraries.

Additional Libraries

Some reusable routines may be compiled into a library. Libraries created in this manner can be included in the command line. Make sure you include the -L <library-path> option to tell the linker where to look for these files if they are not in the current directory. Here is an example, assuming you have the source file Exmain.c and a library Exlib.lib in the directory mylib (if that is not the same as your current project):

sdcc Exmain.c Exlib.lib -L mylib

Note here that mylib must be an absolute path name. The most efficient way to use libraries is to keep separate modules in separate source files. The lib file now should name all the modules.rel files. For an example see the standard library file libsdcc.lib in the directory <installdir>/share/lib/small. (For me <installdir> = /usr)

Memory models for the MCS51 family

SDCC allows three memory models for MCS51 code (Including the 8051), small, medium and large. Modules compiled with different memory models should never be combined together or the results would be unpredictable. The library routines supplied with the compiler are compiled as small, medium and large. The compiled library modules are contained in separate directories as small, medium and large so that you can link to the appropriate set. When the medium or large model is used all variables declared without a storage class will be allocated into the external ram, this includes all parameters and local variables (for non-reentrant functions). When the small model is used variables without storage class are allocated in the internal ram. Judicious usage of the processor specific storage classes and the ’reentrant’ function type will yield much more efficient code, than using the large model. Several optimizations are disabled when the program is compiled using the large model, it is therefore recommended that the small model be used unless absolutely required.

Storage Class Languages Extensions

These are specific to the 8051

  • Xdata / far

Variables declared with this storage class will be placed in the external RAM. This is the default storage class for the Large Memory model, e.g.: (For our purpose this class should be crucial)

      __xdata unsigned char test_xdata;  (In this case test_xdata ==> 0x01)

Writing 0x01 to this variable generates the assembly code:

      90s00r00      mov dptr,#_test_xdata
      74 01         mov a,#0x01
      F0            movx @dptr,a
  • Code

’Variables’ declared with this storage class will be placed in the code memory:

      __code unsigned char test_code;

Read access to this variable generates the assembly code:

      90s00r6F      mov dptr,#_test_code
      E4            clr a
      93            movc a,@a+dptr

char indexed arrays of characters in code memory can be accessed efficiently:

      __code char test_array[] = {’c’,’h’,’e’,’a’,’p’};

Read access to this array using an 8-bit unsigned index generates the assembly code:

      E5*00         mov a,_index
      90s00r41      mov dptr,#_test_array
      93            movc a,@a+dptr


Related Documentation

If you want to see more documentation specifically for the 8051 try this file (This depends on your machine) :

/usr/share/sdcc/include/mcs51/

Some .c examples

/usr/share/sdcc/lib/src

SDCDB

Compilling for Debugging

--debug When this option is used the compiler will generate debug information. The debug information collected in a file with .cdb extension can be used with the SDCDB. Another file with no extension contains debug information in AOMF or AOMF51 format which is commonly used by third party tools.

Assembler Interface

  • First we have this example code
unsigned char __far __at(0x7f00) buf[0x100];
unsigned char head, tail;                 
void to_buffer( unsigned char c )
{
                                                                                         !
   if( head != (unsigned char)(tail-1) ) /* cast needed to avoid promotion to integer */
       buf[ head++ ] = c;                /* access to a 256 byte aligned array */
}
  • Then we do a cut and paste form an .asm file, we have to begin the code with _asm and finish it with _endasm we define a new function to_buffer_asm(). Also we hand-optimize the assembly code and insert an #define USE_ASSEMBLY finally we have:
unsigned char __far __at(0x7f00) buf[0x100];
unsigned char head, tail;
#define USE_ASSEMBLY (1)
#if !USE_ASSEMBLY
void to_buffer( unsigned char c )
{
   if( head != (unsigned char)(tail-1) )
       buf[ head++ ] = c;
}
#else
void to_buffer( unsigned char c )
{
   c; // to avoid warning:  unreferenced function argument
   _asm
       ; save used registers here.
      
; if( head != (unsigned char)(tail-1) )
       mov  a,_tail
       dec  a
       xrl  a,_head
       ; we could do an ANL a,#0x0f here to use a smaller buffer (see below)
       jz   t_b_end$
; buf[ head++ ] = c;
       mov a,dpl         ; dpl holds lower byte of function argument
       mov  dpl,_head    ; buf is 0x100 byte aligned so head can be used directly
       mov dph,#(_buf> >8)
       movx @dptr,a
       inc  _head
       ; we could do an ANL _head,#0x0f here to use a smaller buffer (see above)
t_b_end$:
       ; restore used registers here
   _endasm;
}
#endif


Ucsim

Links