Firmware

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 codesourcery.com. 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 https://svn.gnumonks.org/trunk/librfid/ librfid.hw $ svn co -r1999 https://svn.gnumonks.org/trunk/librfid/ librfid.host $ svn co -r314 http://svn.openpcd.org/trunk/firmware

Then configure librfid:

$ cd librfid.hw $ ./autogen.sh $ ./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.

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

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 LIBRFID_DIR:=../librfid.hw

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 http://www.openbeacon.org/git-view/openbeacon/plain/firmware/at91sam7/at91flash/at91flash $ chmod 755 at91flash $ ./at91flash main_dumbreader.samba

Afterwards compile librfid for your host

$ cd ../librfid.host $ ./autogen.sh $ 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; DEBUGP_INTERRUPT_FLAG("irq_en",irq); - 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 https://svn.gnumonks.org/trunk/librfid/ librfid.host cd librfid.host patch -p0 < ../path-to-patch/librfid-r2149-fixed-openpcd-support.patch

Preconditions
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 http://www.openpcd.org/releases.0.html and build it:

$ wget http://people.openpcd.org/laforge/releases/dfu-programmer/0.3.0-hmw4/dfu-programmer-0.3.0-hmw4.tar.bz2 $ 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 looking for 16c0:076b determining device status: state = 2, status = 0 dfuIDLE, continuing wTransferSize = 0x0100 Starting download: [################################################################################################
 * 1) ./dfu-programmer openpcd dfu_dnload /path/to/openpcd/firmware/main_dumbreader.bin
 * 1) ] finished!

Flashing a complete flash image (using SAM-BA)
Get the latest sam7utils package from http://www.openpcd.org/releases.0.html and build it curl -O http:///dl/sam7utils-0.2.1-bm.tar.bz2 tar -xvjf sam7utils-0.2.1-bm.tar.bz2 cd sam7utils ./configure --prefix=/usr/local make sudo make install

Before running make apply this patch (with $ patch -p0 Strg-D) --- main.c     2006-07-16 03:01:42.000000000 -0400 +++ main.new.c 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 ) { break; @@ -116,7 +117,7 @@   printf( "usage: sam7 [options]\n" ); printf( " -e|--exec   execute cmd instead of entering interactive mode.\n"); printf( " -l|--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 http://www.openpcd.org/releases.0.html):
 * 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: Bus 001 Device 009: ID 03eb:6124 Atmel Corp.
 * 1) lsusb

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

Availability
The OpenPCD svn repository includes the source code to the firmware at http://svn.openpcd.org/trunk/firmware/. For occasional browsing, please use the web interface at http://svnweb.openpcd.org/trunk/firmware/. From time to time there will be releases publicized at http://www.openpcd.org/releases.0.html

To get the latest firmware, make sure that you have a Subversion client installed (http://subversion.tigris.org/). Please use the following command to check out the latest sources: svn co http://svn.openpcd.org/trunk/firmware

Organization
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)

Compilation
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).

DFU
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:

make DEBUG=n BOARD=b TARGET=t

where 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 and flash the result using the SAM-BA procedure described above.
 * 1) cat dfu.bin main_dumbreader.bin > myfirmware.samba