Bluetooth Hacking?

From OpenPCD

Jump to: navigation, search


About the Firmware

The OpenPCD Firmware is the code that actually runs on the hardware, specifically the SAM7. It has been written in the C programming language, and is compiled using GNU GCC for ARM. We are not utilizing any OS (such as real time OS), but are actually coding everything by hand, which gives us full control and minimal overhead.

Compilation environment

You'll need GNU ARM toolchain (not the Linux ARM toolchain).

Download and install gcc, binutils and newlib (tested with GCC 4.1 toolchain). A good prebuilt GCC EABI toolchain can be found at . Once the toolchain is installed and in your PATH, create a directory, e.g. "myenv" and move to this directory

$ mkdir env
$ cd env

We then download the sources:

$ svn co -r1999 librfid.hw
$ svn co -r1999
$ svn co -r314

Then configure librfid:

$ cd librfid.hw
$ ./
$ ./configure --with-firmware=../firmware --enable-firmware --target=arm-none-eabi --host=arm-none-eabi

You can get the ARM toolchain in binary form from .Make sure to get the EABI version from the download section.

Once you have downloaded and installed the ARM toolchain you may need to update your $PATH to where you installed the toolchain.

$ export PATH=$PATH:path to installation/bin

You may also need to change some of the commands in the Makefile and Makefile.dfu as the commands in your toolchain may be different. Below is an example of a changed Makefile from line 334 to 349 and Makefile.dfu from line 295 to 304. Note the # (comment) denotes the old commands.

# Define programs and commands.
SHELL = sh
#CC = arm-elf-gcc
CC = arm-none-eabi-gcc
#CPP = arm-elf-g++
CPP = arm-none-eabi-g++
#OBJCOPY = arm-elf-objcopy
OBJCOPY = arm-none-eabi-objcopy
#OBJDUMP = arm-elf-objdump
OBJDUMP = arm-none-eabi-objdump
#SIZE = arm-elf-size
SIZE = arm-none-eabi-size
#NM = arm-elf-nm
NM = arm-none-eabi-nm
REMOVE = rm -f
COPY = cp

We can now compile librfid:

$ make

Then we configure and compile the firmware itself.Go in the firmware directory:

$ cd ../firmware

Specify the correct librfid source directory in the Makefile: search for the line "LIBRFID_DIR:=...." and replace it with


Compile your firmware, for example main_dumbreader without debug support:

$ make BOARD=PCD TARGET=main_dumbreader
$ make -f Makefile.dfu BOARD=PCD
$ cat dfu.bin main_dumbreader.bin > main_dumbreader.samba

For re-flashing a blank device from scratch (make sure that the sam7 tool from sam7utils is installed):

$ curl -O
$ chmod 755 at91flash
$ ./at91flash main_dumbreader.samba

Afterwards compile librfid for your host

$ cd ../
$ ./
$  CC="gcc -m32" CXX="c++ -m32" ./configure

SVN Problem + Patch

The SVN head of librfid has broken support for OpenPCD since revision 1999. The following patch allows you to use the current svn HEAD version of librfid (revision 2150) with your OpenPCD (and not just revision 1999.) The patch is a temporary work around so that you can use the HEAD version of librfid with the HEAD version of openpcd.

--- 23:00, 19 February 2009 (UTC) Notserpe this patch is slightly smaller than the one I posted to the mailing list. I'm currently working on a real fix and not just a workaround.

Index: src/rc632.h
--- src/rc632.h    (revision 2150)
+++ src/rc632.h    (working copy)
@@ -70,8 +70,8 @@
 enum rc632_reg_status {
   RC632_STAT_LOALERT      = 0x01,
   RC632_STAT_HIALERT      = 0x02,
-  RC632_STAT_ERR          = 0x04,
-  RC632_STAT_IRQ          = 0x08,
+  RC632_STAT_IRQ          = 0x04,
+  RC632_STAT_ERR          = 0x08,
 #define RC632_STAT_MODEM_MASK     0x70
   RC632_STAT_MODEM_IDLE       = 0x00,
   RC632_STAT_MODEM_TXSOF      = 0x10,
Index: src/rfid_asic_rc632.c
--- src/rfid_asic_rc632.c  (revision 2150)
+++ src/rfid_asic_rc632.c  (working copy)
@@ -258,7 +258,7 @@
   ret = rc632_clear_irqs(handle, RC632_IRQ_TIMER);

   /* enable timer IRQ */
-  ret |= rc632_reg_write(handle, RC632_REG_INTERRUPT_EN, RC632_IRQ_SET | RC632_IRQ_TIMER);
+  // ret |= rc632_reg_write(handle, RC632_REG_INTERRUPT_EN, RC632_IRQ_SET | RC632_IRQ_TIMER);

   ret |= rc632_reg_write(handle, RC632_REG_TIMER_RELOAD, divisor);

@@ -276,12 +276,12 @@
       return ret;

-  ret = rc632_reg_write(handle, RC632_REG_INTERRUPT_EN, RC632_IRQ_SET
+  /* ret = rc632_reg_write(handle, RC632_REG_INTERRUPT_EN, RC632_IRQ_SET
               | RC632_IRQ_TIMER
               | RC632_IRQ_IDLE
               | RC632_IRQ_RX );
   if (ret < 0)
-      return ret;
+      return ret; */

   while (1) {
       rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &stat);
@@ -308,7 +308,7 @@

           if (irq & RC632_IRQ_TIMER && !(irq & RC632_IRQ_RX)) {
               DEBUGP("timer expired before RX!!\n");
-              rc632_clear_irqs(handle, RC632_IRQ_TIMER);
+              // rc632_clear_irqs(handle, RC632_IRQ_TIMER);
               return -ETIMEDOUT;

You can apply the patch by saving it to a file (called for example "librfid-r2149-fixed-openpcd-support.patch") and then executing the standard patch command to apply it to the latest svn head...

svn co -rHEAD
patch -p0 < ../path-to-patch/librfid-r2149-fixed-openpcd-support.patch

Firmware installation

Flashing the application program (using DFU)


NOTE: This is obviously only possible if you have already installed the DFU loader program (called sam7dfu) using some different means. If you have purchased an OpenPCD reader from the OpenPCD Webshop, then sam7dfu will already be pre-installed.

If you built your unit yorself, or you have received one of the early prototypes, then please follow the SAM-BA instructions to install dfu.bin into the flash first.

Actual DFU flash process

Get the latest dfu-programmer from and build it:

$ wget
$ tar xjvf dfu-programmer-0.3.0-hmw4.tar.bz2
$ cd dfu-programmer-0.3.0-hmw4
$ ./configure
$ make
$ cd src

Note that this version of dfu-programmer has been modified to support sam7dfu, and a vanilla upstream dfu-programmer will not work.

In order to put the OpenPCD device into firmware update mode, you have to

1. unplug the USB Device
2. press the button marked as "BOOTLOADER" and keep it pressed
3. power on the USB Device by plugging it into USB
4. the red LED will turn itself on
5. you may now release the "BOOTLOADER" button
6. If you have a serial cable attached, it should print a message about sam7dfu. This is optional.
7. Call dfu-programmer like described below
8. unplug and replug (without pressing any button)

After compiling dfu-programmer you can call it like

# ./dfu-programmer openpcd dfu_dnload /path/to/openpcd/firmware/main_dumbreader.bin
looking for 16c0:076b
determining device status: state = 2, status = 0
dfuIDLE, continuing
wTransferSize = 0x0100
Starting download: [################################################################################################
#################################################] finished!

Flashing a complete flash image (using SAM-BA)

Get the latest sam7utils package from and build it

curl -O
tar -xvjf sam7utils-0.2.1-bm.tar.bz2
cd sam7utils
./configure --prefix=/usr/local
sudo make install

Before running make apply this patch (with $ patch -p0 <paste patch text> Strg-D)

--- main.c      2006-07-16 03:01:42.000000000 -0400
+++  2008-03-05 15:48:27.000000000 -0500
@@ -54,10 +54,11 @@
     int option_index;
     static struct option long_options[] = {
       { "line", 1, 0, 'l' },
+      { "help", 0, 0, 'h' },
       { "exec", 1, 0, 'e' }

-    c = getopt_long( argc, argv, "l:e:", long_options, &option_index );
+    c = getopt_long( argc, argv, "l:e:h", long_options, &option_index ); 

     if( c == -1 ) {
@@ -116,7 +117,7 @@
   printf( "usage: sam7 [options]\n" );
   printf( "  -e|--exec <cmd>   execute cmd instead of entering interactive mode.\n");
   printf( "  -l|--line <line>  specifies the line/tty which the boot agent resides.\n");
-  printf( "                     only used for posix IO." );
+  printf( "                     only used for posix IO.\n" );
   printf( "  -h|--help         dislay this message and exit.\n");

Following these steps to reset the internal USB bootloader (see also 'at91flash'-Script inside our sam7utils package at

  1. unplug the USB cable and insert the SAM-BA jumper (Pin 1 2)
  2. attach the USB cable
  3. wait ten seconds
  4. unplug the USB cable
  5. remove the SAM-BA jumper
  6. attach the USB cable
  7. wait several seconds to allow the device to be detected by Linux

Verify with lsusb that your computer detected the OpenPCD reader:

# lsusb
Bus 001 Device 009: ID 03eb:6124 Atmel Corp.

To make sure that the OpenPCD board will be recognized by the Linux Kernel please add the following line to /etc/modprobe.conf.local (or /etc/modprobe.conf if this file doesnt exist):

options usbserial vendor=0x03EB product=0x6124

(Re)Plug the OpenPCD device to make sure it will be detected properly. Find out which serial port we're connected to (see last line - it's ttyUSB2 in this particular case):

dmesg | grep ttyUSB
usb 3-1: pl2303 converter now attached to ttyUSB0
usb 5-2: FTDI USB Serial Device converter now attached to ttyUSB1
usb 1-7.2: generic converter now attached to ttyUSB2

Install the latest firmware image:

sam7 -l /dev/ttyUSB2
  Chip Version: 0
  Embedded Processor: ARM7TDMI
  NVRAM Region 1 Size: 128 K
  NVRAM Region 2 Size: 0 K
  SRAM Size: 128 K
  Series: AT91SAM7Sxx
  Page Size: 256 bytes
  Lock Regions: 8
sam7> set_clock
sam7> unlock_regions 
   unlocking region 0: done
   unlocking region 1: done
sam7> flash myfirmware.samba

Note: Check Creating SAM-BA Images to see how to convert a *.bin to a valid *.samba firmware image

Firmware source code


The OpenPCD svn repository includes the source code to the firmware at For occasional browsing, please use the web interface at From time to time there will be releases publicized at

To get the latest firmware , make sure that you have a Subversion client installed ( Please use the following command to check out the latest sources:

svn co


lib/        - low-level 'access library' routines, ARM7 / SAM7 specific
link/       - Linker scripts
src/os/     - Common routines shared between PCD and PICC (some of them generic SAM7)
src/pcd/    - PCD (reader) firmware code
src/picc/   - PICC (transponder) firmware code
src/dfu/    - USB device firmware update
src/start/  - low-level startup code (mostly ARM assembly)


The SAM7 flash is split in two partitions. The first partition is 4kB in size and contains the USB DFU (Device Firmware Upgrade) software. The second partition consists of all remaining flash space (128k-4k or 256k-4k, depending on used SAM7 version).


You can produce an image for the DFU block called "dfu.bin" using

make -f Makefile.dfu BOARD=PCD

Main program

The generic syntax for building a specific main/application program image is:



n (0..1) - disable/enable debug
b OLIMEX|PCD|PICC - specify the board hardware
t main_reqa|main_pwm|main_dumbreader|main_openpicc - which firmware to build

Creating SAM-BA Images

If you have both dfu.bin and a main program such as main_dumbreader.bin, you can just concatenate them like

# cat dfu.bin main_dumbreader.bin > myfirmware.samba

and flash the result using the SAM-BA procedure described above.