How-to: Program PICs using Linux

Arguably, Microchip’s PIC microcontrollers do not get enough posts here. One of the drawbacks for some of us is that Linux support for PICs is not very well known. The information is out there, but no one has laid out the process of going from writing C code to programming a chip. Written for Linux users that are familiar with microcontrollers, basic circuits, the C programming language, and can read a datasheet, this how-to should get you up and programming a PIC quickly with Linux.

The Compiler:

The Small Device C Compiler, sdcc is what will be used to create the .hex file needed to program a PIC. Support for PICs is still growing, and still in beta, so be aware that things outside the code and chips of this article may need some debugging. However, like every other open source project out there, more contributing users will help the project. Best of all, it is free, with ports to Windows and MacOS X, this is a compiler that handles many architectures and devices without the program limit of free versions of for-pay compilers that are limited to Windows. Sdcc is available through various distributions’ package managers including Ubuntu and Fedora.

To install sdcc on Ubuntu:

sudo apt-get install sdcc

To install sdcc on Fedora:

sudo yum install sdcc

The Chips:

Three different PIC chips were used in the writing of this tutorial: the 40 pin PIC16F887, the 14 pin PIC16F688, and the 8 pin PIC12F675. You can follow along with any of these chips as well as other chips.

The Programmer:

We will be using two programmers, Olimex’s PICStart+ compatible PIC-MCP-USB programmer, and Microchip’s PICkit 2. Both programmers have been tested to work with the three chips used here.

The PICStart+ programmers use the picp program. Most any PICStart+ compatible programmer will work with picp. Easily installed in Ubuntu with:

<pre>sudo apt-get install picp

For Fedora and other distributions may have to download and install it from source. So, in an empty directory of your choosing:

tar -xzf picp-0.6.8.tar.gz
cd picp-0.6.8
sudo make install

The source is on [Jeff Post]’s Development Tools for PIC programmers page along with other programming options.

If you will be using the PIC16F887 and picp, you will need to modify your /etc/picp/picdevrc file by adding the following lines:

0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

20 00 3f ff 3f ff 00 7f
00 7f 3f ff 3f ff 00 ff
00 ff 00 00 00 00 00 00
0D 10 20 00 04 20 07 02
00 00 01 00 00 00 00 00
00 01 22 0f

3f ff 07 00 00 00 00 00
00 00 00 00 00 00 00 00
3f ff 07 00 00 00 00 00
00 00 00 00 00 00 00 00

The above lines are  modified parameters for PIC16F886 found in a post by [Al Williams]. For chips not already in /etc/picp/picdevrc, additional parameters will need to be added to /etc/picp/picdevrc.

PICkit 2 programmers will work with another program called pk2cmd hosted by Microchip here. You will need to install pk2cmd from source. so in a directory of your choosing:

tar -xzf pk2cmdv1.20LinuxMacSource.tar.gz
cd pk2cmdv1.20LinuxMacSource
make linux
sudo make install

Note that Microchip touts the PICkit 3 as a replacement for the PICkit 2. It is not a replacement for the PICkit 2 as there are no Linux drivers for the PICkit 3, so do not buy the PICkit 3 thinking it will work in Linux.

There is also another program that claims to work with a range of DIY PIC programmers: PICPgm. We have not tried this program or any of the DIY programmers at this point. We know there are other PIC programmers out there, both cheap and expensive, that have not been mentioned. Perhaps a PIC programmer roundup is in need of writing.

The Code:

The code for this how-to is a kind of hello world program using LEDs. The code for this is hosted on Github, you can follow along with the blink.c file for the PIC16F887, PIC16F688, or PIC12F675. Also included are working .hex files. Here is the PIC16F887 code as a reference as we walk through each major operation:

//Simple program to get started programming
//PIC microcontrollers in Linux.
//Written by Devlin Thyne.
//Released to the public domain.

#include "pic/pic16f887.h"

//Use these configuration words:
//0x2ff4 0x3fff

//Set the configuration words:
unsigned int at _CONFIG1 configWord1 = 0x2FF4;
unsigned int at _CONFIG2 configWord2 = 0x3fff;

//To compile:
//sdcc -mpic14 -p16f887 blink.c

//To program the chip using picp:
//Assuming /dev/ttyUSB0 is the serial port.

//Erase the chip:
//picp /dev/ttyUSB0 16f887 -ef

//Write the program:
//picp /dev/ttyUSB0 16f887 -wp blink.hex

//Write the configuration words (optional):
//picp /dev/ttyUSB0 16f887 -wc 0x2ff4 0x3fff

//Doing it all at once: erasing, programming, and reading back config words:
//picp /dev/ttyUSB0 16f887 -ef -wp blink.hex -rc

//To program the chip using pk2cmd:
//pk2cmd -M -PPIC16f887 -Fblink.hex

//Setup variables
unsigned char ucharCount = 0;
unsigned int uintDelayCount = 0;

void main(void)
	//Set PORTC to all outputs
	TRISC = 0x00;

	ucharCount = 0;
	uintDelayCount = 0;

	//Loop forever
	while ( 1 )
		//Delay Loop
		while ( uintDelayCount < 10000 )
			//Increment the loop counter

		//Reset delay loop counter
		uintDelayCount = 0;

		//Increment the count

		//Display the count on the PORTC pins
		PORTC = ucharCount;



The first line is the #include for the header file of the particular chip you will be using. It tells the compiler which registers are available and where they are located in memory. In most systems, the header files will be in /usr/share/sdcc/include.

Then we setup the configuration word or words fuses. They are only able to be written when the chip is programmed, but we can define them here so we don’t have to manually program them later. The PIC16F887 has the address for the configuration words defined in its header file as _CONFIG1 and _CONFIG2. The PIC16F688 and PIC12F675 do not have the configuration word address defined in their header (we said sdcc was in beta, didn’t we?), so we just use the address of the configuration word: 0x2007. The configuration words are specific to the chip model and application and are described in the chapter “Special Features of the CPU” in each of the respective chips’ datasheets. In the blink.c samples, the configuration word is just a 16bit hexadecimal word, but the word can be made more human readable by ANDing together the configuration options. Check out the chips’ header files for the names of the options.

Next, we setup some global variables, one for the value that will be output on the LEDs and the other for a delay counter.

In the void main(), we set the PORTC tristate register, TRISC to all outputs. The PIC12F675 has only one port, GPIO, and its tristate register is TRISIO. After setting the tristate register, we enter an infinite loop with while(1). Inside that loop is a delay loop so that we can see the LEDs changing. Following the delay loop, the display counter is incremented and then written to PORTC (or GPIO) for display on the LEDs.

Compiling the Code:

Now that we have reviewed the code, it is time to turn it into something a PIC can use. sdcc will take the blink.c file and make a bunch of files. One of these files will be blink.hex which will be what the PIC device programmer will be writing to the PIC. Here’s how:

For the PIC16F887:

sdcc -mpic14 -p16f887 blink.c

For the PIC16F688:

sdcc -mpic14 -p16f688 blink.c

For the PIC12F675:

sdcc -mpic14 -p12f675 blink.c

The -mpic14 option tells sdcc that it will be compiling for the 14-bit instructions of the PIC16 and PIC12 families. The second option is the specific chip that code will be compiled for. The last thing on the line is the file containing the C code that will be compiled.

Programming the Chip:

To program a chip you will take your device programmer and connect the chip you want to load with your program. Unless you are using a socket programmer like the PIC-MCP-USB, you will need to consult the datasheets of the programmer and the chip to be programmed for the proper connection. Once properly connected, you will need to run the program to run the programmer:

For a PICStart+ programmer on /dev/ttyUSB0 programming a PIC16F887 :


For a PICkit 2 programmer programming a PIC16F887:

pk2cmd -M -PPIC16f887 -Fblink.hex

If you are programming another chip, or the PICStart+ programmer is on a port besides /dev/ttyUSB0, you will need to make corresponding changes to the commands.

Note: The code provided for the PIC16F887 disables low-voltage programming. Some of the programmers available but not directly mentioned only perform low-voltage programming. If you have one of these programmers, you will need to change the code so that the low-voltage programming bit in the configuration words allows for low-voltage programming. The low-voltage programming pin on the microcontroller will also need to be pulled low during normal operation.

Wire the Circuit:

The circuit for this project with the code provided is really simple to breadboard. Below are the schematics for the three chips:

Start out by connecting the Vdd pins to a positive voltage source between 4.5 volts and 6 volts and the Vss pin to ground. The 40 pin PIC16F887 and the 14 pin PIC16F688 will both need a pullup resistor on their master clear pin. To any one or all of the PORTC pins (or GPIO pins for the PIC12F675), connect LEDs with current-limiting resistors to ground. Note that pin 4 of the PIC12F675 is only an input and will not light an LED. The current out of any pin of the three chips used is limited to 20mA, so the current-limiting resistors are optional for most cheap jellybean LEDs. What you should see when you power up the circuit are blinking LEDs. The LEDs should be lighting to a binary count.

Your turn!

Now that we have given you a start with programming PICs using Linux, we hope to see more projects using these chips and the tools we have mentioned above. Though this article was written for Linux users, Windows and MacOS X users should be able to use sdcc for their PIC programming needs.

Image information: The Tux logo is by Larry Ewing, Simon Budig, and Anja Gerwinski, via Wikimedia Commons. The Microchip logo is a registered trademark of Microchip Technology Incorporated.

87 thoughts on “How-to: Program PICs using Linux

  1. @Squirrel

    What “ARM”? .. All the different “ARM” vendors have loads of different parts, each vendor has their own in-circuit programming methods,.. if you wrote such a tutorial you would have to choose one brand and probably one of that brands ARM families unless you want to write a million page how-to.

    Building a tool chain is fairly easy if you have a part that doesn’t have a hardware FPU or anything fancy like that. You can easily google up instructions on how to build binutils, gcc, gdb, newlib etc. Startup code etc.. you’re on your own, hope you like reading datasheets.


    Why PIC when you can get decent free tools for AVR? ;) SDCC supports very few of the PIC families AFAIK.

  2. It should be noted that you can compile the compilers for the PIC24, PIC30, and PIC33 on a Linux machine. They are built from GCC, the only downside is you don’t get Microchip’s standard library or the DSP functions. Unfortunatly I have a RealICE in circuit emulator/debugger and am forced to use Windows in Virtualbox, but that works well.

  3. @cantido

    all the ARM7 i met (Analog Devices, ST and NXP) use the same programming method and this method is serial port. So you don’t need anything but a MAX232-type translater to start working with ARM7.

    I began to work with a Cortex-M3 from ST and I use my ARM7 programmer before migrating to JTAG that is also available on all models.

    ARM is a standard and there are not so much differences between models. The compatibility goes even further with Cortex models, where more than the core must be standard between manufacturers.

    Regarding compilers,it’s very very easy to begin with Code Sourcery g++ lite that is available for free and handles FPUs

    Regarding AVR, I fully agree ;-)

  4. HI-TECH PIC Compiler is available for Linux. It is the “official” compiler for some families, and works with most PICs. It is not FLOSS, and there are limitations for the unlicensed free-as-in-beer version (regarding code optimization, not a big deal). There is also HI-TIDE, an Eclipse-based IDE for PIC, that runs in Linux, worth to check. I just wish my ICD3 programmer/debugger could be used in Linux. I currently use a virtual machine running Window$ to make it work.

    Regarding ARM, LPCXpresso is an IDE, aslo eclipse-based that works with NXP’s ARM-based LPC microcontrollers. It works in Linux, and has some stupid limitations on the binary size (128KB after registration), probably enough for most Cortex M0/M3 based MCUs.

  5. These past days have also seen some progress on using a buspirate to program a pic uC (I’ve already personally used one BP to program another bricked one). The BusPirate project is quickly becoming a very good swiss army knife of electric engineers! :)

  6. What is so good about PICs that you’d want to use one over an ATtiny or other AVR (or picaxe)?

    ..I thought they died out with the 90’s

    id like to see a tutorial based on the ARM cortex M0

  7. You forget about:

    – JALv2, a very good compilar using JAL language. Also there is a project called Jallib with a lot of very nice libraries for JALv2:

    – PIC-GCC, a port of gcc to the 8bit family of microchip:

    – Pinguino project, based on arduino and using sdcc:

    I think that’s enought for starting in linux, but there are even more alternatives.

    Good luck.

  8. VERY GOOD TUTORIAL! I am a huge fan of the Microchip PIC who has a tremendous dislike for the micro$oft based operating systems.

    I have had limited success with pickit2 and other online tutorials.

    I was excited about the new mplabx until I learned that It was discontinuing support for the pickit2.

    Keep up the good work.

  9. @ftorama

    > all the ARM7 i met (Analog Devices, ST and NXP)

    You can program them via the serial port.. but I’m pretty sure NXP’s serial bootloader isn’t the same as everyone else. The LPC tool I use can write some other ARM7 parts, but there’s no universal tool AFAIK.. and that’s just the ARM7TDMI parts.

    Settings for different ARM parts differ when using OpenOCD+Your favorite JTAG dongle too.

  10. I must say, if the main thing keeping you from using a PIC is linux support, you’re an idiot.

    Imagine that – You work as an engineer. There’s this PIC that would work great for your application, but you choose not to use it for the “linux” reason. The next day, you report this to your project manager.

    He fires you for being an idiot. Lol.

  11. Arguably??? PIC Certainly donesn’t get enough posts!

    And yes, the latest mplabx is, though beta, java-based – cross-platform and is generally a much improve ide!

    Bring on more PIC posts!

  12. @ftorama: ARM might be a standard, but programming the internal flash in an ARM MCU is certainly not. Try using the serial bootloader method with a STR9 or STR7 from ST, or with a AT91SAM from Atmel. Or even with a LM3S from Luminary (now TI).

  13. I think it’s amazing there’s so much religious zealotry here. I use the AVR and PIC. They’re NOT that different. I have designs based on both…

    I’m loving that there is a Microchip product for Mac OS coming, though. That’s the one thing that has kept me from using the PIC recently, I just got tired of the virtual machine.

  14. If you have Win2K or XP install disks, there’s a much easier way to do this. Install VirtualBox, and the Guest Additions, under Linux. (You’ll need the free-as-in-beer version from Oracle, not the community version, because you need the Guest Additions to get USB support working).

    After that’s done, install the latest MPLab from Microchip. I use this on my Debian system, and its performance is indistinguishable from that of my stock Win2K box.

    VirtualBox + Micro$oft also gives me the ability to run some critical Windows programs, such as filter design and analysis apps, that have no Linux equivalents.

  15. Here is the problem I had with PIC. It is near impossible to figure out exactly what you need to start with as a beginner. PICs, programmers, compilers, programming language, IDE’s…etc. There are just too many options with too little compatibility across the PIC families and too little guidance. This was a good tutorial.

    If you want to make tutorials for PIC’s, how about one on how to pick the right PIC for your project.

  16. Nice “topic” ;)
    I have one LPCxpresso 1768 board sitting in its packing because I dont have time to study it during the university, but I would love to know about some nice and free gcc compilers, as the arm-gcc is pretty old an as I see the last update is from 2004..

  17. “The current out of any pin of the three chips used is limited to 20mA”

    Wouldn’t count on it. That note in the datasheet almost always means “it is your responsability to limit the current to 20mA”. My 2c? Buy some resistors.

  18. Well this would’ve been very useful to me a few years ago when I was trying to get started with the pics; I grew frustrated and gave up for this very reason. I ended up going with the avr. they work great with linux, no restrictions and the usb-tinyISP I use to program it was about $20 and ladyada has linux instructions for it’s use right on the site. This looks like a good tutorial, but for me if I’m going to invest the time to learn something new It’d be a more powerful and featureful arm not an about equivilent pic. Same reason you won’t find me driving a chevy truck ;)

  19. Here is an ARM tutorial for the mc13224v:

    1). Buy an Econotag (or 2):

    2). Build/get an ARM7 toolchain. E.g.:

    3). Get the libmc1322x code:

    git clone git://

    4). Build it:

    make -C libmc1322x/tests

    5). Plug in the Econotag.

    6a). Run some code from RAM: -f rftest-tx_redbee-econotag.bin -c ‘bbmc -l redbee-econotag reset’

    6b.) Flash your code: -f flasher_redbee-econotag.bin -s rftest-tx_redbee-econotag.bin -c ‘bbmc -l redbee-econotag reset’

    6c.) Erase your code because you just flashed it:

    bbmc -l redbee-econotag erase

    7) _optional_ Debug with OpenOCD (using the econtag’s on-board ft2232):

    openocd -f board/redbee-econotag.cfg

    (see also:

    8) Run rftest-rx on the other econtag you bought (you bought two right?) and receive your packets.

    9) go on from there. write your own wireless apps. Use Contiki (mc13224v is part of the main distro or get the development branch: git://
    ). Use linux the linux 802.15.4 stack. (


    If you want to make some blinky lights and “get a foot in the door” check out the Make it Last build @ make dot com. This approach uses the “buy parts and build it” method.
    You will need a PICkit 2 or 3. These are ultra affordable programmer / debuggers. 2 offers some tools not currently finished on the 3. But these tools are coming. (logic tool, analyzer , uart tool) Both have programmer to go as of today.

    There are other options. Rather then buying a breadboard , parts, etc etc etc and then a programmer, there is the “know it works” method.
    There are various beginner packages including a programmer , board, uchip, IDE, compiler. The honest truth is the IDE, and compilers are FREE either way. Use the free compilers for now, as they are renovating their compiler offerings in the next year. So for the kits , and an idea of when to choose which.

    Low pin count usb kit with pickit 2.
    Learn to make usb devices. (included are lessons, guiding you threw making what you know as an FTDI cable, minus the FTDI) This includes a debug chip, and every thing you need to learn MPLAB, the usb stack, your prorammer etc. Pretty steep learning curve.

    PICkit2 with a board.
    Non usb chip with lessons. Nice little dev board to get familiar with.

    PICkit3 with a board.
    similar to above with a PICkit3.

    For a start , the kits are more affordable. For ongoing development the build it method is probably cheaper in the long run , but more expensive to start. (programmer , chip, bread board, components etc)

    As for what compilers and IDE to use, I use Mplab, and the Compiler that Microchip offers for the chip im using. Microchip is in the process of refining their compiler offerings to 1 compiler per chip class. They purchased Hitec and are currently offering for instance C18 , and Hitec for the same class chip. I generally use PIC18’s so I generally use C18 (MCC18). All of them have free options, use them for now.


    That is a really sticky request. What chip you pick is entirely dependent on how efficient you want to be with the project and what you want to do. The best thing you can do is understand there is ALWAYS a more efficient way to do it. You are going to have extra pins. The good news is if you ask in PIC related forum some one is sure to point you to a decent chip to start playing with. For instance:

    for DIP USB capable (with internal regulator)
    Check out 18f14k50 (low pin count usb kit)

    For more pins , but same as above with out a regulator
    check out 18f26j50

    For a simpler non usb chip, with tons of pins and a tutorial on MAKE with eeprom internal,
    check out 18LF25K22

    At first try to understand how to use it. Not how to engineer the perfect chip for the device. There are tools at microchip dot com to help choose parts after you understand more. It isnt that big of a deal to design something and decide to use a diff chip. The cost difference is pretty small, and porting code from device to device is pretty easy and how I learned .

  21. @sHitler, who said: “What is so good about PICs that you’d want to use one over an ATtiny or other AVR (or picaxe)?”

    PIC is cheaper than AVR for parts of approximately equal capabilities.

    PIC has a much larger selection of parts available in DIP packages, if you prefer not to use SMD for either ease of soldering, or ease of part reuse (without the trouble or added expense of SMD adapters).

    And regardless of what package style you want, chances are you can actually find the exact PIC you want, because they’re better stocked by distributors.

    If any of the above are important to you, then PIC indeed has an advantage over AVR.

    I find it a bit ironic that Linux folks, with their supposedly greater technical savvy, tend to choose AVR over PIC *solely* because they can’t figure out or can’t be bothered to learn how to program a PIC under Linux! Use a Windows box, or a virtual machine running Windows if you have to. I’m a Windows man and run Ubuntu in a VM when necessary, it’s just not a big deal. Plus extending trial periods in a VM is easy; need I say more?

    And I were a project manager for something that would become a mass-produced product, and an engineer told me he was choosing an AVR that costs more and has longer lead times than an equivalent PIC, just because he wanted to program in Linux instead of Windows, he would definitely get the boot!

    So I’m glad to see this tutorial. And now that Microchip is addressing cross-platform development, it will be interesting to see what happens to the relative popularity of PIC/AVR.

  22. I never quite understood why people are writing their programs for these types of devices in C given how simple their instruction sets are. I was able to pick up ARM assembly in about a night just reading disassemblies in IDA and Fujitsu FR in about a week (mostly took longer because IDA incorrectly lists operands for add2 and a few other minor problems). Compared to the clusterfuck of trying to do anything meaningful with Intel/AMD SSE/AVR/whatever crap they added while I was writing assembly for these microcontrollers is actually pleasant but I rarely see it mentioned.

  23. Nice tutorial. Thanks HaD!

    @Jake, you’re probably just trolling, but I’ll bite.

    This tutorial is useful to me at least. I’m not an engineer, and I (like many others) do not run Windows – haven’t since the mid 90s. Windows-only dev tools are therefore a serious show-stopper for me, unless they can be made to work under Wine or something similar. (And that slows things down pretty considerably.) It’s not a religious position, it’s purely practical at this point.

    Of course if I were an EE I’d have no choice but to pursue PIC regardless of these issues if it happened to be the optimal choice for an application. But fyi this is not an IEEE forum.

  24. The official Microchip gcc compiler runs just fine in wine. Here is an example makefile that runs gcc under wine:

    PRG = dspic_oscope
    OBJS = main.o uart-multiplex.o adc.o spi.o spi_drivers.o readline.o
    CC = wine pic30-gcc
    BIN2HEX = wine pic30-bin2hex
    C30LIB="C:\Program Files\Microchip\MPLAB C30\lib"
    CFLAGS = -mcpu=$(MCU) -x c -Wall -Os -std=gnu99
    LDFLAGS = -mcpu=$(MCU) -Wl,-L$(C30LIB),-Tp$(MCU).gld,--defsym=__MPLAB_BUILD=1,-Map="$(PRG).map"
    #LIBS = -ldsp-coff
    LIBS =
    all: $(PRG).hex
    flash: all
        pk2cmd -F$(PRG).hex -M -PF6 -W -R
        rm -f $(OBJS) $(PRG).cof $(PRG).hex $(PRG).map
    %.hex: %.cof
        $(BIN2HEX) $<
    $(PRG).cof: $(OBJS)
        $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
        $(CC) $(CFLAGS) -c $<
  25. I’ve got a good reason for choosing PIC over AVR: You can sample or order pretty much any device they made in the last 20 years direct from the factory with a credit card at list price. With AVR I have no idea whether the part I designed for will be available next year or will have been replaced with a ‘compatible’ device which will still require me to pore over an app note describing the migration path and force me to resurrect the tool chain I used.

    Oh, and I think on balance PIC’s peripherals have the edge. I do tend to use AVR more for hobby projects though because of the free tool chain.

  26. I’m sure most people will agree with me here, but for microchip to actually gain any momentum, they’ll need to put in the ‘external memory bus’ (something people have been arguing for, for a LONG time. Microchip just seems to want to fight this idea for some reason. I mean hay!… Why go with a 32 bit pic when your really not getting any thing at all from what’s already been a part of their line for a while now>???? It just seems like a white elephant to me.

  27. I’ve only been using microcontrollers for a few years now, but from what I’ve seen PICs and AVRs seem pretty similar. I just personally use PICs because that’s what the professor who started me on them knew. And so when he taught at school, everyone learned PICs and I helped run labs that use them, so I use PICS. But I have a friend who loves using AVRs; so it seems to me like a lot of it is what you start with. Personally I’m extremely glad to have seen this article, if just to realize Microchip is making a linux version of MPLAB. One of the partitions of my machine was Windows just because of programs like this, where it’s much easier to use them in Windows then to figure out the intricacies of getting them to consistently work in Linux.

Leave a Reply


You are commenting using your account. Log Out / Change )

Twitter picture


Facebook photo


Google+ photo


Connecting to %s