PIC

From the Linux and Unix Users Group at Virginia Teck Wiki
Jump to: navigation, search

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.

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