05 September 2006

Introduction to SDCC: Small Device C Compiler

SDCC is a Freeware, retargettable, optimizing ANSI - C compiler that targets the Intel 8051, Maxim 80DS390, Zilog Z80 and the Motorola 68HC08 based MCUs. Work is in progress on supporting the Microchip PIC16 and PIC18 series. AVR and gbz80 ports are no longer maintained. The entire source code for the compiler is distributed under GPL.

Some of the features include:

  • ASXXXX and ASLINK, a Freeware, retargettable assembler and linker.

  • extensive MCU specific language extensions, allowing effective use of the underlying hardware.

  • a host of standard optimizations such as global sub expression elimination, loop optimizations (loop invariant, strength reduction of induction variables and loop reversing ), constant folding and propagation, copy propagation, dead code elimination and jump tables for 'switch' statements.

  • MCU specific optimisations, including a global register allocator.

  • adaptable MCU specific backend that should be well suited for other 8 bit MCUs

  • independent rule based peep hole optimizer.

  • a full range of data types: char (8 bits, 1 byte), short (16 bits, 2 bytes), int (16 bits, 2 bytes), long (32 bit, 4 bytes) and float (4 byte IEEE).

  • the ability to add inline assembler code anywhere in a function.

  • the ability to report on the complexity of a function to help decide what should be re-written in assembler.

  • a good selection of automated regression tests.

SDCC also comes with the source level debugger SDCDB, using the current version of Daniel's s51 simulator. (Currently not available on Win32 platforms).

SDCC was written by Sandeep Dutta and released under a GPL license. Since its initial release there have been numerous bug fixes and improvements. As of December 1999, the code was moved to SourceForge where all the "users turned developers" can access the same source tree. SDCC is constantly being updated with all the users' and developers' input.

SDCC Homepage
- http://sdcc.sourceforge.net/

7 comments:

Deepak Barua said...

Hi i am working on the linux platform for my P89V51RD2FN processor i need to know if the output of sdcc can be linked to asem-51 basically it is not recognizing the asm format ... ?

MCU Programmer said...

SDCC has its own Assembler (see how to insert assembler code). You can embed the assembler in your C source file.

Anonymous said...

Hi I want to know how to include my own library into my project using SDCC. I tried to put the *.h header file in the same folder as the *.c main program file. The *.h header file only contains functions declarations. Where must I put the *.c file containing functions definitions? I see you put all the functions declarations and definitions in the *.h header file, unlike standard C. Can you explain it please.

Unknown said...
This comment has been removed by the author.
Unknown said...

Hi, i'm trying to download and execute a small lcd code on my development board built with
P89V51RD2 MCU. But i'm facing a strange problem that the hex file (either .hex or .ihx ) i'm getting here is not showing any kind of output on my board.
And if i download the same code using keil compiled hex file, it is working fine.
can anybody help me regarding this asap??
thanks,
Mayur

MCU Programmer said...

Hi MakS,

SDCC and Keil C have some differences in language mechanism. Sometimes the same source code may not work with both SDCC and Keil C.

Krunal Patel said...

WHEN I COMPILE THIS CODE GIVEN BELOW IT GIVES ERRORS LIKE

error 52: Actual Argument type different from declaration 2 from type 'unsigned-char generic*' to type 'unsigned-char'

#include<8051.h>
//---------------------------------------------------------------------------
#include "Kernel.h"
#include "Task.h"
#include "AVX.H"

//---------------------------------------------------------------------------

extern xdata unsigned char taskRdyQue[64];
extern unsigned char taskRdyMatrixIndex;
extern xdata unsigned char taskRdyMatrix[8] ;

unsigned char TaskCreate(TaskFunc pTaskFunc,unsigned char priority,unsigned char idata *InternalSP,unsigned char xdata *ExternalSP)

{

if (g_Kernel.TaskCount >= OS_TASK_COUNT) return 0;

#ifdef PREEMPTIVE

priority = 63 - priority ;

taskRdyMatrixIndex |= ( 1<< (priority >> 3) );

taskRdyMatrix[priority >> 3] |= ( 1<<(priority & 7) );

taskRdyQue[priority]=g_Kernel.TaskCount;

#endif

// Initialize the Task object. // Push low byte of pTaskFunc.

(unsigned char)*(IntSP) = (unsigned short)pTaskFunc; // Push high byte of pTaskFunc. *(IntSP + 1) = (unsigned short)pTaskFunc >> 8; // The size of all registers is 13 bytes.

g_Kernel.Tasks[g_Kernel.TaskCount].InternalSP =(IntSP + 0x0E) ; g_Kernel.Tasks[g_Kernel.TaskCount].ExternalSP = ExternalSP;

*(g_Kernel.Tasks[g_Kernel.TaskCount].ExternalSP) = *(IntSP);//*( InternalSP - 1); *(g_Kernel.Tasks[g_Kernel.TaskCount].ExternalSP + 1 ) = *(IntSP + 1);//*( InternalSP );

g_Kernel.TaskCount++;

return 1;
} //---------------------------------------------------------------------------
///*
unsigned char TaskPrioritySet(unsigned char old_priority, unsigned char new_priority)
{

if( new_priority>63 || new_priority<0 ) return 0;

old_priority = 63 - old_priority ; // convert pseudo priority

// check if any other bit is set if set then don't update task ready mat. index // reseting the bit which shows task is present

if( !( taskRdyMatrix[old_priority >> 3] &= (~( 1<<(old_priority & 7) ))) ) taskRdyMatrixIndex &= (~( 1<< (old_priority >> 3) ));

new_priority = 63 - new_priority ; // convert pseudo priority

taskRdyMatrixIndex |= ( 1<< (new_priority >> 3) ); //update with new value

//update task ready matrix table taskRdyMatrix[new_priority >> 3] |= ( 1<<(new_priority & 7) );

// update task ready queue with earlier tcb array index taskRdyQue[new_priority] = taskRdyQue[old_priority];

taskRdyQue[old_priority] = 0; // reset older tcb array index

TF0 = 1; // call context switcher

return 1;
}

unsigned char TaskPend(unsigned char priority) {

if( priority>63 || priority<0 ) return 0;

priority = 63 - priority;

// check if any other bit is set if set then don't update task ready mat. index // reseting the bit which shows task is present

if( !( taskRdyMatrix[priority >> 3] &= (~( 1<<(priority & 7) ))) ) taskRdyMatrixIndex &= (~( 1<< (priority >> 3) ));

TF0 = 1; // call context switcher return 1;

}

unsigned char TaskResume(unsigned char priority) {

if( priority>63 || priority<0 ) return 0;

priority = 63 - priority ;

if( taskRdyQue[priority] ) // CHECK FOR TASK SIGNATURE {

taskRdyMatrix[priority >> 3] |= ( 1<<(priority & 7) );

taskRdyMatrixIndex |= ( 1<< (priority >> 3) ); //update with new value

TF0 = 1; // call context switcher

return 1; } }

unsigned char TaskDelete(unsigned char priority) {

if( priority<63 && priority>=0 ) { priority = 63 - priority;

// check if any other bit is set if set then don't update task ready mat. index // reseting the bit which shows task is present

if( !( taskRdyMatrix[priority >> 3] &= (~( 1<<(priority & 7) ))) ) taskRdyMatrixIndex &= (~( 1<< (priority >> 3) ));

taskRdyQue[priority] = 0;

TF0 = 1; // call context switcher return 1;

} }

+++++____+++++++++++++__)))))))))))++++|||||||||||+++++

TASH.H FILE

//---------------------------------------------------------------------------
#ifndef TaskH
#define TaskH
//---------------------------------------------------------------------------
// Task function pointer.

#define PREEMPTIVE

typedef void (code *TaskFunc)();

typedef struct _Task
{ unsigned char idata *InternalSP; // Internal stack pointer. unsigned char xdata * ExternalSP; // External stack pointer(for reentrant function).
} Task;

// Create a Task object.
// Parameter:
// pTaskFunc: The Task function pointer.
// InternalSP: Internal stack pointer.
// ExternalSP: External stack pointer.
// Return value:
// 0: Error.
// 1: Success.
unsigned char TaskCreate(TaskFunc pTaskFunc,unsigned char priority,unsigned char idata *InternalSP;unsigned char xdata *ExternalSP);
unsigned char taskPrioritySet(unsigned char old_priority, unsigned char new_priority);
unsigned char tickRateSet(unsigned char milli_sec);
unsigned char taskDelete(unsigned char priority);

//---------------------------------------------------------------------------
#endif // ThreadH