Programming PIC’s in Linux using C with SDCC
April 25th, 2005
In my last article, Programming PIC Microcontrollers in Linux, I talked about using using gputils and gpsim to assemble and simulate a basic PIC program. After writing this article, I recieved an email from Martyn Welch regarding the article he recently wrote: Installing and using SDCC on Linux. SDCCs a free C compiler for several small devices, including the PIC microcontroller.
In the past, I have worked a little bit in C for PIC's using the PICC Lite compiler. The PICC Lite compiler, which is the freeware version of the PICC compiler, ONLY supports the following processors: 16F877, 16F877A, 12F675, 12F629, 16F627, 16F627A, 16F684, 16C84, 16F84 and 16F84A. This is fine for many of us hobby PIC programmers, however, I have decided to use the Small Device C Compiler (SDCC) instead because it is open source, release under GPL, which means it's free and will remain free. I always try to support open-source software when I can, and for the work I do with robotics and hobby electronics, there is no drawbacks to using SDCC.
This tutorial is written to take Martyn's article on installing SDCC to the next step. We'll compile another blinking LED program, this time written in C, and simulate it using gpsim.
Target Audience
In this article I will assume that you have already installed and tested gpsim. If you have not, see my article: Programming PIC Microcontrollers in Linux. I'm also assuming that you know a little bit of the C language. If you don't, that's okay, just don't expect to learn C from this article. You will need to be comfortable with installing software from source in Linux (as is discussed in the last article) and enter commands in a terminal. This article IS NOT an introduction to PIC programming, Linux, or C Programming. It's just to get you started compiling the programs with SDCC and simulating them with gpsim.
Resources
The information in this article is from my personal experience with setting up SDCC and gpsim. The following websites were used as references.
Installing SDCC
I'm not going to re-invent the wheel here. Please refer to Installing and using SDCC on Linux - By: Martyn Welch for an overview on installing SDCC. I used his article with the following exceptions:
- I didn't use the CVS to download SDCC. Instead, I downloaded version 2.4.0 from the Sourceforge download page.
- I was using Fedora, and not Debian, therefore my paths were different. GPUTILS and SDCC were installed to the default dir of /usr/local/share/ on my distribution, and not /usr/share/. If you're not too familiar with Linux, and don't know where they are installed, simply do a file search from your main menu looking for 'gputils' for example.
Also, pay attention to part 'Setting up PIC File Headers', as that's an importatnt part. What you're doing there, is downloading inc2h.pl and copying it to the folder where your sdcc is installed. In my case, I downloaded it to /usr/local/share. This is a perl script which takes all the header files from gputils and creates the *.h header files you will be using in your C programs. Being a script, it will need to be executable. Issue a chmod a+x inc2h.pl command to make it executable. So, assuming you have installed SDCC and downloaded inc2h.pl to the sdcc installation folder, your sequence of commands to run inc2h.pl might look like:
cd /usr/local/share/sdcc chmod a+x inc2h.pl cd /usr/local/share/sdcc/include mkdir pic cd pic for file in `ls /usr/local/share/gputils/header/p*.inc` do export picstring=`echo $file | sed "s//usr/local/share/gputils/header/p//; s/.inc//"` ../../inc2h.pl $picstring /usr/local/share/gputils > pic$picstring.h done
To test that SDCC is working, copy and paste the below code into a file called 'test.c':
char test;
void main(void) {
test=0;
}
And then compile the code using:
sdcc test.c
That simple little program is a minimal C program to verify that SDCC is installed. We still could have more problems if we did not get our libraries and/or headers properly installed. See the SDCC Online Manual for additional information on the installation procedure.
Compiling a C Program for the PIC - toggle_led.c
Now, copy the below code into another file, this time called 'toggle_led.c' (or download toggle_led.c.tar.gz):
/*
toggle_led.c
Micah Carrick - <script language="JavaScript" type="text/javascript"> <!-- var prefix = 'ma' + 'il' + 'to'; var path = 'hr' + 'ef' + '='; var addy81227 = 'email' + '@' + 'micahcarrick' + '.' + 'com'; document.write( '<a ' + path + ''' + prefix + ':' + addy81227 + ''>' + addy81227 + '</a>' ); //--> </script><a href="mailto:email@micahcarrick.com">email@micahcarrick.com</a><noscript>This email address is being protected from spam bots, you need Javascript enabled to view it</noscript>
04.25.2005
Toggles an LED on Pin 1 of PORTB on a PIC16F627. Written
as a sample for the article on using SDCC and GPSIM in
Linux. http://www.micahcarrick.com/v2/content/view/14/4/
Compile: sdcc --debug -mpic14 -p16f627 toggle_led.c
Simulate: gpsim -pp16f627 -s toggle_led.cod toggle_led.asm
*/
/* Define processor and include header file. */
#define __16f627
#include"pic/pic16f627.h"
/* Setup chip configuration */
typedef unsigned int config;
config at 0x2007 __CONFIG = _CP_OFF &
_WDT_OFF &
_BODEN_OFF &
_PWRTE_OFF &
_ER_OSC_CLKOUT &
_MCLRE_ON &
_LVP_OFF;
#define b1 0x02 /* pin 1 on PORTB */
#define B_OUTPUTS 0xFD /* value used to setup TRISB */
void main(void) {
/* PORTB.1 is an output pin */
TRISB = B_OUTPUTS;
while(1) { /* Loop forever */
/* toggle bit 1 */
PORTB = (PORTB ^ b1);
}
}
This is a simple little C program (take note: I'm not very good at C!) that will simple toggle pin 1 on PORTB on and off, much like our program written in PIC assembly in Programming PIC Microcontrollers in Linux. So, now we compile our program with:
sdcc --debug -mpic14 -p16f627 toggle_led.c
The --debug option gives us the debug information that is useful during the development process. -mpic14 specifies the "port" to use, in this case for PIC microcontrollers. -p16f627 tells us which processor we are using, in this case, a PIC16F627. (If you don't actually have a PIC16F627 that's okay, we're just simulating in this article. You don't need to physically have ANY chip!). The output should have looked something like:
Processor: 16f627 message: using default linker script "/usr/local/share/gputils/lkr/16f627.lkr"
Now, if you issue the ls command, you should see a bunch of new files. Notable, toggle_led.hex which is the program we would be "burning" into the chip, and toggle_led.cod which is what we'll pass to gpsim so that we have code show up in the Source Browser window. So, let's do that...
Simulating the toggle_led.c Program with gpsim
Just like we did in Programming PIC Microcontrollers in Linux, we're going to simulate the program by passing gpsim the hex file, which is the actual machine code instructions, aswell as the cod file which contains information needed to step through the source code. Issue the following command to start the simulator with our program:
gpsim -pp16f627 -s toggle_led.cod toggle_led.asm
This will start up gpsim. If the windows don't open automatically, open the Source Browser window and the Breadboard window from the 'Windows' menu. When you first start gpsim, it should look something like the image below:
Notice how unlike the last tutorial, the Source Browser now shows our C code AND the assembly code. If you step through the program you'll see the PORTB.1 change to an output (indicated by the arrow pointing away from the chip in the Breadboard window) and then you'll see the pin toggle from high to low (indicating by red for high, and green for low). If you have the C code displayed in the Source Window as you step through the code, each step isn't one instruction, but rather one chucnk of instructions which make up a given line in the C code. To see this, change to the toggle_led.asm tag in the Source Browser window and step through the code.
As you can see now when each step is just 1 assembly instruction. This is VERY handy as it allows us to see how the code we wrote in C is translated to assembly. In our example, it is clear that our line to toggle the pin in C:
PORTB = (PORTB ^ b1)
Is compiled into the following assembly code by SDCC:
<span style="color: #666666; font-style: italic">;#CSRC toggle_led.c 41</span><br style="color: #666666; font-style: italic" /><span style="color: #666666; font-style: italic">; PORTB = (PORTB ^ b1); </span> MOVLW 0x02 BCF STATUS,5 XORWF _PORTB,F
As you see in the comments which sdcc put in there, this code is created from toggle_led.c on line 41. This is a great way to optimize your code and really understand what it's doing!
So, now you're on your own. Good luck!
Categories
Popular Posts
RSS Feeds
Archives

October 31st, 2007 at 9:39 am
Hello,
i have tried out your example, for simulating C-Source in gpsim. It seems that the actual compiler is not abel to produce cdb files. Every debug-information is extracted from the asm files. Is there any way to extract the debug-information from the c-files?
thanks
Florian Hillen
October 31st, 2007 at 12:13 pm
I'm afraid it's been a couple of years since I've worked with GPSIM or PICs. I really couldn't answer that one. But you could ask in the gnupic mailing list--those guys are likely to know. They might even know on the piclist mailing list.
November 11th, 2007 at 6:02 am
Hi,
When I try to compile the example in the .pdf doc called "Testing the SDCC compiler" I have an error with this command line:
sdcc -mpic14 -p16f627 test.c
The error is:
"libsdcc.lib: No such file or directory"
Could you help me?
I am working on Debian Etch.
Thank you very much
January 1st, 2008 at 12:17 am
hey im trying to run this program but i dont have the header files. I need the 18F452.h and 16F877A.h file....does anyone have this file or kno where i can get it from. This program is a PIC microcontroller code that i need for my alarm system design.
February 15th, 2008 at 11:55 am
Hi,
I have the same problem as "rooster57" posted. I am using Piklab with sdcc and gputils, but am not able to involve the linker. On the command line i have same error as through Piclab's autogenrated toolchain for sdcc :
#sdcc -mpic14 -p16f871 -V test16f871.c
+ "/usr/libexec/sdcc/sdcpp" -nostdinc -Wall -std=c99 -obj-ext=.o -DSDCC_MODEL_SMALL DSDCC=260 -DSDCC_pic14 -D__pic14 -DSDCC_PROCESSOR="16f871" I"/usr/libexec/sdcc/../share/sdcc/include/pic14" -I"/usr/share/sdcc/include/pic14" -I"/usr/libexec/sdcc/../share/sdcc/include" -I"/usr/share/sdcc/include" -I"/usr/libexec/sdcc/../share/sdcc/include/pic" -I"/usr/share/sdcc/include/pic" "test16f871.c"
+ "gpasm" -c "test16f871.asm"
+ "gplink" -I"/usr/libexec/sdcc/../share/sdcc/lib" -I"/usr/share/sdcc/lib" -I"/usr/libexec/sdcc/../share/sdcc/lib/pic" -I"/usr/share/sdcc/lib/pic" -o test16f871 test16f871.o
libsdcc.lib pic16f871.lib
libsdcc.lib: No such file or directory
#locate libsdcc.lib
/usr/share/sdcc/lib/ds390/libsdcc.lib
/usr/share/sdcc/lib/ds400/libsdcc.lib
/usr/share/sdcc/lib/large/libsdcc.lib
/usr/share/sdcc/lib/medium/libsdcc.lib
/usr/share/sdcc/lib/small/libsdcc.lib
/usr/share/sdcc/lib/small-stack-auto/libsdcc.lib
Obviously there is an libstdcc.lib available, but not found by the linker etc. I don't know what small, medium and large means.
I use a very simplistic sourcecode - no extra includes:
void main() {
int i = 0;
}
Has somebody an idea?
Thanks!
February 15th, 2008 at 12:00 pm
I forgot to tell that i am running on Fedora 8; gputils and sdcc installed from repository (not from source).
lg, Raoul
June 14th, 2008 at 9:45 pm
thanks for the instructions! i have now blinking leds using PIC16f84a... thank you so much...
June 20th, 2008 at 9:54 pm
Fantastic write up, Thanks a lot !
Quick question: Has anyone got this tool chain going on OpenSolaris yet ?
See: www.opensolaris.com
Also, Is anyone using this tool chain as the backend to the NetBeans 6.1 C/C++ Pack yet ?
If so, I really would like to have a little chat on your setup please.
Thanks,
Edward.
September 1st, 2008 at 4:00 am
I am getting Actual Argument type different from declaration in sdcc compiler and when i compile on keil ,program get compile without any error.
September 7th, 2008 at 3:25 am
C code is not trivially portable from one PIC compiler to another, so it's not surprising that you're running into a problem.
In this case, it might even be the case that they sizes of the datatype that is exhibiting the problem are different between these two compiles. And that's just one of the many possibilities.
From what I understand, you need to understand how both compilers/environments work when moving any non-trivial code from one to another.
good luck,
-e