PIC
PIC microcontrollers are a relatively popular line of RISC microcontrollers from Microchip Technology. Different toolchains are required to build code between the 8-bit, 16-bit, and 32-bit data size lines. They are used in ECE 2504 Introduction to Computer Engineering and ECE 4534 Embedded System Design.
Contents
Toolchains
8-Bit
The freeware MCC18 toolchain from Microchip provides libraries and will compile and link for the 8-bit data word chips such as PIC18 devices. MCC18 can be run on Linux using wine. sdcc is a software libre toolchain that supports a number of PIC18 devices.
16-Bit
To build a nonfree toolchain for Linux, use the instructions at [1]. To build a completely software libre toolchain for the PIC24 or dsPIC, follow the steps below.
sudo apt-get install build-essential tofrodos mkdir ~/prj/pic30 cd ~/prj/pic30 wget http://ww1.microchip.com/downloads/en/DeviceDoc/mplabalc30v3_31.tar.gz wget http://ww1.microchip.com/downloads/en/DeviceDoc/mplabc30v3_31.tar.gz wget http://www.electricrock.co.nz/c30/pic30-binutils-v01.tar.bz2 wget http://www.electricrock.co.nz/c30/pic30-gcc-v01.tar.bz2 tar xf mplabalc30v3_31.tar.gz tar xf mplabc30v3_31.tar.gz find . -type f -exec fromdos {} \; # We don't need to "fix" the search path by adding -nonfree directories tar xf pic30-binutils-v01.tar.bz2 --exclude=search-path-fix.diff tar xf pic30-gcc-v01.tar.bz2 --exclude=search-path-fix.diff for p in pic30-binutils-v01/patches/*; do patch -p0 < $p; done for p in pic30-gcc-v01/patches/*; do patch -p0 < $p; done cd acme CFLAGS=-DMCHP_VERSION=v3.31-Debian ./configure --prefix="${HOME}/prj/pic30/build" --target=pic30-coff make cd .. cd gcc-4.0.2/gcc-4.0.2 CFLAGS=-DMCHP_VERSION=v3.31-Debian ./configure --prefix="${HOME}/prj/pic30/build" --target=pic30-coff --enable-languages=c make cd ../..
32-Bit
Programmers
See the PICKit 2 article for programming your hex file natively using pk2cmd
.
Integrated Development Environments
MPLAB is the freeware IDE written by Microchip. Only Windows versions of older versions were made available, although those could be run with wine and with a Windows virtual machine. The newer MPLAB X is cross-platform freeware. Piklab is a software libre IDE for PIC microcontrollers.
Compiling Code
MPLAB is the IDE recommended by the ECE department. It can be run inside a Virtual Machine, programming using USB passthrough. It can also be installed under wine and the compiler used from the commandline. sdcc is a GPL C compiler with some support for PIC devices. Some GNU utilities (namely the assembler and linker, but not compiler) have been modified to support Microchip's microprocessors as part of the gputils project. Piklab is an IDE with support for both open source toolchains.
MPLABX, the current version of MPLAB, runs natively under Linux.
Using Wine to Run the Toolchain
The MCC18 toolchain can be run using wine. This page should be updated to give more detailed instructions.
Makefile Using Wine
The file below is a work in progress.
# Hacked up makefile for Linux export WINEPREFIX = /home/user/class/embedded/pic/toolchain MCCPATH = $(WINEPREFIX)/drive_c/MCC18/bin CC = wine $(MCCPATH)/mcc18.exe CFLAGS = --extended -Opa- # -D__DEBUG -Ou- -Ot- -Ob- -Op- -Or- -Od- -Opa- LD = wine $(MCCPATH)/mplink.exe AR = wine $(MCCPATH)/mplib.exe PK2PATH = /home/user/class/embedded/pic/pk2cmd/pk2cmdv1.20LinuxMacSource PK2CMD = $(PK2PATH)/pk2cmd RM = rm Proj1.cof : main.o messages.o interSecure Shellrupts.o user_interrupts.o my_uart.o uart_thread.o timer1_thread.o timer0_thread.o my_i2c.o $(LD) /p18F2680 /l"C:\MCC18\lib" "main.o" "messages.o" "interrupts.o" "user_interrupts.o" "my_uart.o" "uart_thread.o" "timer1_thread.o" "timer0_thread.o" "my_i2c.o" /u_CRUNTIME /u_EXTENDEDMODE /z__MPLAB_BUILD=1 /m"Proj1.map" /w /o"Proj1.cof" main.o : main.c ../toolchain/drive_c/MCC18/h/stdio.h ../toolchain/drive_c/MCC18/h/usart.h ../toolchain/drive_c/MCC18/h/i2c.h ../toolchain/drive_c/MCC18/h/timers.h messages.h my_uart.h my_i2c.h uart_thread.h timer1_thread.h timer0_thread.h main.c maindefs.h ../toolchain/drive_c/MCC18/h/p18f2680.h ../toolchain/drive_c/MCC18/h/stdarg.h ../toolchain/drive_c/MCC18/h/stddef.h ../toolchain/drive_c/MCC18/h/pconfig.h interrupts.h $(CC) -p=18F2680 "main.c" -fo="main.o" $(CFLAGS) messages.o : messages.c messages.h messages.c maindefs.h ../toolchain/drive_c/MCC18/h/p18f2680.h interrupts.h $(CC) -p=18F2680 "messages.c" -fo="messages.o" $(CFLAGS) interrupts.o : interrupts.c messages.h my_uart.h interrupts.c maindefs.h ../toolchain/drive_c/MCC18/h/p18f2680.h interrupts.h user_interrupts.h $(CC) -p=18F2680 "interrupts.c" -fo="interrupts.o" $(CFLAGS) user_interrupts.o : user_interrupts.c ../toolchain/drive_c/MCC18/h/timers.h messages.h my_uart.h user_interrupts.c maindefs.h ../toolchain/drive_c/MCC18/h/p18f2680.h ../toolchain/drive_c/MCC18/h/pconfig.h user_interrupts.h $(CC) -p=18F2680 "user_interrupts.c" -fo="user_interrupts.o" $(CFLAGS) my_uart.o : my_uart.c ../toolchain/drive_c/MCC18/h/usart.h messages.h my_uart.h my_uart.c maindefs.h ../toolchain/drive_c/MCC18/h/p18f2680.h ../toolchain/drive_c/MCC18/h/pconfig.h $(CC) -p=18F2680 "my_uart.c" -fo="my_uart.o" $(CFLAGS) uart_thread.o : uart_thread.c ../toolchain/drive_c/MCC18/h/stdio.h uart_thread.h uart_thread.c maindefs.h ../toolchain/drive_c/MCC18/h/p18f2680.h ../toolchain/drive_c/MCC18/h/stdarg.h ../toolchain/drive_c/MCC18/h/stddef.h $(CC) -p=18F2680 "uart_thread.c" -fo="uart_thread.o" $(CFLAGS) timer1_thread.o : timer1_thread.c ../toolchain/drive_c/MCC18/h/stdio.h messages.h timer1_thread.h timer1_thread.c maindefs.h ../toolchain/drive_c/MCC18/h/p18f2680.h ../toolchain/drive_c/MCC18/h/stdarg.h ../toolchain/drive_c/MCC18/h/stddef.h $(CC) -p=18F2680 "timer1_thread.c" -fo="timer1_thread.o" $(CFLAGS) timer0_thread.o : timer0_thread.c ../toolchain/drive_c/MCC18/h/stdio.h timer0_thread.h timer0_thread.c maindefs.h ../toolchain/drive_c/MCC18/h/p18f2680.h ../toolchain/drive_c/MCC18/h/stdarg.h ../toolchain/drive_c/MCC18/h/stddef.h $(CC) -p=18F2680 "timer0_thread.c" -fo="timer0_thread.o" $(CFLAGS) my_i2c.o : my_i2c.c ../toolchain/drive_c/MCC18/h/i2c.h messages.h my_i2c.h my_i2c.c maindefs.h ../toolchain/drive_c/MCC18/h/p18f2680.h ../toolchain/drive_c/MCC18/h/pconfig.h $(CC) -p=18F2680 "my_i2c.c" -fo="my_i2c.o" $(CFLAGS) clean : $(RM) "main.o" "messages.o" "interrupts.o" "user_interrupts.o" "my_uart.o" "uart_thread.o" "timer1_thread.o" "timer0_thread.o" "my_i2c.o" "Proj1.cof" "Proj1.hex" "Proj1.map" prog : Proj1.hex $(PK2CMD) -A3.3 -B$(PK2PATH) -P -M -FProj1.hex -Y -T
Programming
See the PICKit 2 article for programming your hex file natively using pk2cmd
. The PICKit 3 has superceded the PICKit 2 but is lacking certain features.
Debugging Hardware
Reading printf-style debugging messages over UART with the PICKit 2 is possible from a Windows virtual machine with USB passthrough.
I2C
here's a variety of useful hardware available for debugging I2C:
- The Aardvark I2C/SPI Host Adapter is capable of acting as either an I2C master or slave and reading and writing data over USB. There is an AUR package for the Aardvark GUI for 32-bit machines. VTLUUG mirrors other Aardvark files since they are no longer available on the vendor's website. The Aardvark also works well in a VM with USB passthrough.
- A Raspberry Pi has two onboard I2C buses and should be able to act as a master or slave. Performance and reliability may be suboptimal.
- A Bus Pirate can act as an I2C master or slave and is suitable for human-speed interaction.
UART
UART can easily be debugged using an RS232 and a level shifter in the MAX232 family. For computers without hardware serial ports, USB to serial adapters have near-universal Linux support. For a simpler hardware setup, it may be desirable to use a Bus Pirate or Raspberry Pi as they both support 3v3 CMOS-level UART.
External Links
- How-to Program PICs using Linux - Hackaday (see article and comments)
- Bounty on a libre pic30 toolchain BitBake recipe