summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorlaforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2006-09-12 17:35:30 +0000
committerlaforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2006-09-12 17:35:30 +0000
commitd256545b2fd62d78910efcc6273c3b70abd3aa13 (patch)
treea05e17ec752cfbcc0b79fdbfba81fb949545a112 /firmware
parent04e0441914eeb25e042189679b55c9577fc96d2a (diff)
move to new directory
git-svn-id: https://svn.openpcd.org:2342/trunk@191 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
Diffstat (limited to 'firmware')
-rw-r--r--firmware/Makefile574
-rw-r--r--firmware/README8
-rw-r--r--firmware/TODO27
-rw-r--r--firmware/doc/bitpattern.txt102
-rw-r--r--firmware/doc/dfu.txt89
-rw-r--r--firmware/doc/piccsim-todo.txt34
-rw-r--r--firmware/doc/piccsim.txt42
-rw-r--r--firmware/include/AT91SAM7.h1935
-rw-r--r--firmware/include/asm/assembler.h97
-rw-r--r--firmware/include/asm/atomic.h106
-rw-r--r--firmware/include/asm/bitops.h225
-rw-r--r--firmware/include/asm/compiler.h7
-rw-r--r--firmware/include/asm/ctype.h54
-rw-r--r--firmware/include/asm/div64.h48
-rw-r--r--firmware/include/asm/linkage.h18
-rw-r--r--firmware/include/asm/ptrace.h128
-rw-r--r--firmware/include/asm/system.h109
-rw-r--r--firmware/include/board.h13
-rw-r--r--firmware/include/cl_rc632.h237
-rw-r--r--firmware/include/lib_AT91SAM7.h3476
-rw-r--r--firmware/include/librfid/rfid.h24
-rw-r--r--firmware/include/librfid/rfid_layer2.h76
-rw-r--r--firmware/include/librfid/rfid_layer2_iso14443a.h87
-rw-r--r--firmware/include/librfid/rfid_layer2_iso14443b.h85
-rw-r--r--firmware/include/librfid/rfid_layer2_iso15693.h55
-rw-r--r--firmware/include/librfid/rfid_protocol_mifare_classic.h28
-rw-r--r--firmware/include/openpcd.h85
-rw-r--r--firmware/include/openpicc.h31
-rw-r--r--firmware/include/usb_ch9.h550
-rw-r--r--firmware/include/usb_dfu.h81
-rw-r--r--firmware/lib/bitops.h33
-rw-r--r--firmware/lib/changebit.S21
-rw-r--r--firmware/lib/clearbit.S22
-rw-r--r--firmware/lib/copy_template.S255
-rw-r--r--firmware/lib/ctype.c34
-rw-r--r--firmware/lib/div64.S200
-rw-r--r--firmware/lib/lib1funcs.S338
-rw-r--r--firmware/lib/lib_AT91SAM7.c405
-rw-r--r--firmware/lib/memcpy.S59
-rw-r--r--firmware/lib/memset.S80
-rw-r--r--firmware/lib/setbit.S22
-rw-r--r--firmware/lib/string.c41
-rw-r--r--firmware/lib/testchangebit.S18
-rw-r--r--firmware/lib/testclearbit.S18
-rw-r--r--firmware/lib/testsetbit.S18
-rw-r--r--firmware/lib/vsprintf.c830
-rw-r--r--firmware/link/AT91SAM7S256-RAM.ld131
-rw-r--r--firmware/link/AT91SAM7S256-ROM-dfu-fullimage.ld152
-rw-r--r--firmware/link/AT91SAM7S256-ROM.ld134
-rw-r--r--firmware/link/AT91SAM7S64-RAM.ld146
-rw-r--r--firmware/link/AT91SAM7S64-ROM.ld151
-rw-r--r--firmware/src/main_usb.c48
-rw-r--r--firmware/src/openpcd.h165
-rw-r--r--firmware/src/os/dbgu.c303
-rw-r--r--firmware/src/os/dbgu.h44
-rw-r--r--firmware/src/os/dfu.c681
-rw-r--r--firmware/src/os/dfu.h80
-rw-r--r--firmware/src/os/fifo.c108
-rw-r--r--firmware/src/os/fifo.h28
-rw-r--r--firmware/src/os/flash.c45
-rw-r--r--firmware/src/os/led.c85
-rw-r--r--firmware/src/os/led.h9
-rw-r--r--firmware/src/os/main.c47
-rw-r--r--firmware/src/os/main.h8
-rw-r--r--firmware/src/os/pcd_enumerate.c605
-rw-r--r--firmware/src/os/pcd_enumerate.h56
-rw-r--r--firmware/src/os/pio_irq.c122
-rw-r--r--firmware/src/os/pio_irq.h13
-rw-r--r--firmware/src/os/pit.c38
-rw-r--r--firmware/src/os/pit.h7
-rw-r--r--firmware/src/os/power.h8
-rw-r--r--firmware/src/os/pwm.c165
-rw-r--r--firmware/src/os/pwm.h11
-rw-r--r--firmware/src/os/req_ctx.c50
-rw-r--r--firmware/src/os/req_ctx.h49
-rw-r--r--firmware/src/os/syscalls.c169
-rw-r--r--firmware/src/os/tc_cdiv.c92
-rw-r--r--firmware/src/os/tc_cdiv.h26
-rw-r--r--firmware/src/os/trigger.c17
-rw-r--r--firmware/src/os/trigger.h7
-rw-r--r--firmware/src/os/usb_benchmark.c57
-rw-r--r--firmware/src/os/usb_handler.c88
-rw-r--r--firmware/src/os/usb_handler.h17
-rw-r--r--firmware/src/os/wdt.c23
-rw-r--r--firmware/src/pcd.h35
-rw-r--r--firmware/src/pcd/main_analog.c85
-rw-r--r--firmware/src/pcd/main_dumbreader.c63
-rw-r--r--firmware/src/pcd/main_pwm.c257
-rw-r--r--firmware/src/pcd/main_reqa.c265
-rw-r--r--firmware/src/pcd/rc632.c624
-rw-r--r--firmware/src/pcd/rc632.h31
-rw-r--r--firmware/src/pcd/rc632_highlevel.c1473
-rw-r--r--firmware/src/pcd/rfid_layer2_iso14443a.c319
-rw-r--r--firmware/src/picc/adc.c145
-rw-r--r--firmware/src/picc/decoder.c65
-rw-r--r--firmware/src/picc/decoder.h32
-rw-r--r--firmware/src/picc/decoder_miller.c112
-rw-r--r--firmware/src/picc/decoder_nrzl.c91
-rw-r--r--firmware/src/picc/iso14443a_manchester.c106
-rw-r--r--firmware/src/picc/load_modulation.c29
-rw-r--r--firmware/src/picc/load_modulation.h7
-rw-r--r--firmware/src/picc/main_openpicc.c215
-rw-r--r--firmware/src/picc/piccsim.h23
-rw-r--r--firmware/src/picc/pll.c40
-rw-r--r--firmware/src/picc/pll.h8
-rw-r--r--firmware/src/picc/poti.c58
-rw-r--r--firmware/src/picc/poti.h7
-rw-r--r--firmware/src/picc/ssc_picc.c384
-rw-r--r--firmware/src/picc/ssc_picc.h15
-rw-r--r--firmware/src/picc/tc_fdt.c50
-rw-r--r--firmware/src/picc/tc_fdt.h9
-rw-r--r--firmware/src/start/Cstartup.S386
-rw-r--r--firmware/src/start/Cstartup_SAM7.c89
113 files changed, 19833 insertions, 0 deletions
diff --git a/firmware/Makefile b/firmware/Makefile
new file mode 100644
index 0000000..3d8c42d
--- /dev/null
+++ b/firmware/Makefile
@@ -0,0 +1,574 @@
+# Hey Emacs, this is a -*- makefile -*-
+#
+# WinARM makefile for the FreeRTOS-demo on LPC2138
+# based in information from the FreeRTOS LPC2106 example
+#
+# by Martin Thomas, Kaiserslautern, Germany
+# <eversmith@heizung-thomas.de>
+#
+# based on the WinAVR makefile written by Eric B. Weddington, Jörg Wunsch, et al.
+# Released to the Public Domain
+# Please read the make user manual!
+#
+#
+# On command line:
+#
+# make all = Make software.
+#
+# make clean = Clean out built project files.
+#
+# make program = Download the hex file to the device
+#
+# (TODO: make filename.s = Just compile filename.c into the assembler code only)
+#
+# To rebuild project do "make clean" then "make all".
+#
+# Changelog:
+# - 17. Feb. 2005 - added thumb-interwork support (mth)
+# - 28. Apr. 2005 - added C++ support (mth)
+# - 29. Arp. 2005 - changed handling for lst-Filename (mth)
+# - 1. Nov. 2005 - exception-vector placement options (mth)
+# - 15. Nov. 2005 - added library-search-path (EXTRA_LIB...) (mth)
+# - 2. Dec. 2005 - fixed ihex and binary file extensions (mth)
+# - 22. Feb. 2006 - added AT91LIBNOWARN setting (mth)
+# - 19. Apr. 2006 - option FLASH_TOOL (default lpc21isp); variable IMGEXT (mth)
+# - 19. Mai. 2006 - USE_THUMB_MODE switch, ROM_RUN->RUN_FROM_ROM RAM_RUN->RUN_FROM_RAM
+
+
+FLASH_TOOL = AT91FLASH
+#FLASH_TOOL = UVISION
+#FLASH_TOOL = OPENOCD
+
+# MCU name and submodel
+MCU = arm7tdmi
+#SUBMDL = AT91SAM7S64
+SUBMDL = AT91SAM7S256
+
+USE_THUMB_MODE = NO
+#USE_THUMB_MODE = YES
+
+## Create ROM-Image (final)
+RUN_MODE=RUN_FROM_ROM
+## Create RAM-Image (debugging) - not used in this example
+#RUN_MODE=RUN_FROM_RAM
+
+## We want to produce a full-flash image, but including DFU
+IMGTYPE=-dfu-fullimage
+
+# with / at end
+PATH_TO_LINKSCRIPTS=link/
+
+#### not used in this example:
+## Exception-Vector placement only supported for "ROM_RUN"
+## (placement settings ignored when using "RAM_RUN")
+## - Exception vectors in ROM:
+#VECTOR_LOCATION=VECTORS_IN_ROM
+## - Exception vectors in RAM:
+#VECTOR_LOCATION=VECTORS_IN_RAM
+
+# Target file name (without extension).
+TARGET:=main_reqa
+
+# List C source files here. (C dependencies are automatically generated.)
+# use file-extension c for "c-only"-files
+SRC =
+
+# List C source files here which must be compiled in ARM-Mode.
+# use file-extension c for "c-only"-files
+
+# First, build library ...
+SRCARM = lib/lib_AT91SAM7.c
+ifdef DEBUG
+SRCARM += lib/vsprintf.c lib/ctype.c lib/string.c
+endif
+
+# then, OS ...
+SRCARM += src/os/pcd_enumerate.c src/os/fifo.c src/os/dbgu.c \
+ src/os/led.c src/os/req_ctx.c src/os/trigger.c \
+ src/os/main.c src/os/syscalls.c src/os/usb_handler.c \
+ src/os/usb_benchmark.c src/os/dfu.c src/start/Cstartup_SAM7.c \
+ src/os/tc_cdiv.c src/os/pit.c src/os/pwm.c src/os/pio_irq.c
+
+ifeq ($(BOARD), PCD)
+# PCD support code
+SRCARM += src/pcd/rc632.c src/pcd/rc632_highlevel.c \
+ src/pcd/rfid_layer2_iso14443a.c
+# finally, the actual main application
+SRCARM += src/pcd/$(TARGET).c
+endif
+
+ifeq ($(BOARD), PICC)
+# PICC support code
+SRCARM += src/picc/tc_fdt.c src/picc/ssc_picc.c src/picc/adc.c \
+ src/picc/decoder.c src/picc/decoder_miller.c \
+ src/picc/load_modulation.c \
+ src/picc/decoder_nrzl.c src/picc/poti.c src/picc/pll.c
+# finally, the actual main application
+SRCARM += src/picc/$(TARGET).c
+endif
+
+
+# List C++ source files here.
+# use file-extension cpp for C++-files (use extension .cpp)
+CPPSRC =
+
+# List C++ source files here which must be compiled in ARM-Mode.
+# use file-extension cpp for C++-files (use extension .cpp)
+#CPPSRCARM = $(TARGET).cpp
+CPPSRCARM =
+
+# List Assembler source files here.
+# Make them always end in a capital .S. Files ending in a lowercase .s
+# will not be considered source files but generated files (assembler
+# output from the compiler), and will be deleted upon "make clean"!
+# Even though the DOS/Win* filesystem matches both .s and .S the same,
+# it will preserve the spelling of the filenames, and gcc itself does
+# care about how the name is spelled on its command-line.
+ASRC =
+
+ASRCLIB = lib/changebit.S lib/clearbit.S lib/setbit.S lib/testchangebit.S \
+ lib/testclearbit.S lib/testsetbit.S
+ifdef DEBUG
+#ASRCLIB += lib/memcpy.S lib/memset.S lib/lib1funcs.S lib/div64.S
+ASRCLIB += lib/lib1funcs.S lib/div64.S
+endif
+
+# List Assembler source files here which must be assembled in ARM-Mode..
+ASRCARM = src/start/Cstartup.S $(ASRCLIB)
+
+## Output format. (can be ihex or binary)
+## (binary i.e. for openocd and SAM-BA, hex i.e. for lpc21isp and uVision)
+#FORMAT = ihex
+FORMAT = binary
+
+# Optimization level, can be [0, 1, 2, 3, s].
+# 0 = turn off optimization. s = optimize for size.
+# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
+OPT = s
+#OPT = 0
+
+# Debugging format.
+# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
+# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
+#DEBUGF = stabs
+DEBUGF = dwarf-2
+
+# List any extra directories to look for include files here.
+# Each directory must be seperated by a space.
+#### FreeRTOS
+EXTRAINCDIRS =
+
+# List any extra directories to look for library files here.
+# Each directory must be seperated by a space.
+#EXTRA_LIBDIRS = ../arm7_efsl_0_2_4
+EXTRA_LIBDIRS =
+
+## Using the Atmel AT91_lib produces warning with
+## the default warning-levels.
+## yes - disable these warnings; no - keep default settings
+AT91LIBNOWARN = yes
+#AT91LIBNOWARN = no
+
+# Compiler flag to set the C Standard level.
+# c89 - "ANSI" C
+# gnu89 - c89 plus GCC extensions
+# c99 - ISO C99 standard (not yet fully implemented)
+# gnu99 - c99 plus GCC extensions
+CSTANDARD = -std=gnu99
+
+# Place -D or -U options for C here
+CDEFS = -D$(RUN_MODE) -D__MS_types__ -D__LIBRFID__
+
+ifdef DEBUG
+CDEFS += -DDEBUG
+endif
+
+ifdef OLIMEX
+CDEFS += -DOLIMEX
+endif
+
+ifeq ($(BOARD),PICC)
+CDEFS += -DPICC
+endif
+
+ifeq ($(BOARD),PCD)
+CDEFS += -DPCD
+endif
+
+# Place -I options here
+CINCS = -Iinclude -Isrc
+
+# Place -D or -U options for ASM here
+ADEFS = -D$(RUN_MODE)
+
+ifdef VECTOR_LOCATION
+CDEFS += -D$(VECTOR_LOCATION)
+ADEFS += -D$(VECTOR_LOCATION)
+endif
+
+CDEFS += -D__$(SUBMDL)__
+ADEFS += -D__$(SUBMDL)__
+
+
+# Compiler flags.
+# -g*: generate debugging information
+# -O*: optimization level
+# -f...: tuning, see GCC manual and avr-libc documentation
+# -Wall...: warning level
+# -Wa,...: tell GCC to pass this to the assembler.
+# -adhlns...: create assembler listing
+#
+# Flags for C and C++ (arm-elf-gcc/arm-elf-g++)
+CFLAGS = -g$(DEBUGF)
+CFLAGS += $(CDEFS) $(CINCS)
+CFLAGS += -O$(OPT)
+CFLAGS += -Wall -Wextra -Wcast-align -Wimplicit -Wunused
+CFLAGS += -Wpointer-arith -Wswitch
+CFLAGS += -Wredundant-decls -Wreturn-type -Wshadow
+CFLAGS += -Wbad-function-cast -Wsign-compare -Waggregate-return
+CFLAGS += -Wa,-adhlns=$(subst $(suffix $<),.lst,$<)
+CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+#CFLAGS += -ffunction-sections -fdata-sections
+
+# flags only for C
+CONLYFLAGS += -Wnested-externs
+CONLYFLAGS += $(CSTANDARD)
+
+ifneq ($(AT91LIBNOWARN),yes)
+#AT91-lib warnings with:
+CFLAGS += -Wcast-qual
+CONLYFLAGS += -Wmissing-prototypes
+CONLYFLAGS += -Wstrict-prototypes
+CONLYFLAGS += -Wmissing-declarations
+endif
+
+# flags only for C++ (arm-elf-g++)
+# CPPFLAGS = -fno-rtti -fno-exceptions
+CPPFLAGS =
+
+# Assembler flags.
+# -Wa,...: tell GCC to pass this to the assembler.
+# -ahlns: create listing
+# -g$(DEBUGF): have the assembler create line number information
+ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:.S=.lst),--g$(DEBUGF) -Iinclude/ -D__ASSEMBLY__
+
+
+#Additional libraries.
+
+# Extra libraries
+# Each library-name must be seperated by a space.
+# To add libxyz.a, libabc.a and libefsl.a:
+# EXTRA_LIBS = xyz abc efsl
+#EXTRA_LIBS = efsl
+EXTRA_LIBS =
+
+#Support for newlibc-lpc (file: libnewlibc-lpc.a)
+#NEWLIBLPC = -lnewlib-lpc
+
+MATH_LIB = #-lm
+
+# CPLUSPLUS_LIB = -lstdc++
+
+
+# Linker flags.
+# -Wl,...: tell GCC to pass this to linker.
+# -Map: create map file
+# --cref: add cross reference to map file
+LDFLAGS = -nostartfiles -Wl,-Map=$(TARGET).map,--cref
+LDFLAGS += $(NEWLIBLPC) $(MATH_LIB)
+LDFLAGS += -lc -lgcc
+LDFLAGS += $(CPLUSPLUS_LIB)
+LDFLAGS += $(patsubst %,-L%,$(EXTRA_LIBDIRS))
+LDFLAGS += $(patsubst %,-l%,$(EXTRA_LIBS))
+#LDFLAGS += --gc-sections
+
+# Set Linker-Script Depending On Selected Memory and Controller
+ifeq ($(RUN_MODE),RUN_FROM_RAM)
+LDFLAGS +=-T$(PATH_TO_LINKSCRIPTS)$(SUBMDL)-RAM.ld
+else
+LDFLAGS +=-T$(PATH_TO_LINKSCRIPTS)$(SUBMDL)-ROM$(IMGTYPE).ld
+endif
+
+
+# ---------------------------------------------------------------------------
+# Flash-Programming support using lpc21isp by Martin Maurer
+# only for Philips LPC and Analog ADuC ARMs
+#
+# Settings and variables:
+#LPC21ISP = lpc21isp
+LPC21ISP = lpc21isp
+LPC21ISP_PORT = com1
+LPC21ISP_BAUD = 38400
+LPC21ISP_XTAL = 12000
+LPC21ISP_FLASHFILE = $(TARGET).hex
+# verbose output:
+#LPC21ISP_DEBUG = -debug
+# enter bootloader via RS232 DTR/RTS (only if hardware supports this
+# feature - see Philips AppNote):
+LPC21ISP_CONTROL = -control
+# ---------------------------------------------------------------------------
+
+
+# Define directories, if needed.
+## DIRARM = c:/WinARM/
+## DIRARMBIN = $(DIRAVR)/bin/
+## DIRAVRUTILS = $(DIRAVR)/utils/bin/
+
+# Define programs and commands.
+SHELL = sh
+CC = arm-elf-gcc
+CPP = arm-elf-g++
+OBJCOPY = arm-elf-objcopy
+OBJDUMP = arm-elf-objdump
+SIZE = arm-elf-size
+NM = arm-elf-nm
+REMOVE = rm -f
+COPY = cp
+
+# Define Messages
+# English
+MSG_ERRORS_NONE = Errors: none
+MSG_BEGIN = "-------- begin (mode: $(RUN_MODE)) --------"
+MSG_END = -------- end --------
+MSG_SIZE_BEFORE = Size before:
+MSG_SIZE_AFTER = Size after:
+MSG_FLASH = Creating load file for Flash:
+MSG_EXTENDED_LISTING = Creating Extended Listing:
+MSG_SYMBOL_TABLE = Creating Symbol Table:
+MSG_LINKING = Linking:
+MSG_COMPILING = Compiling C:
+MSG_COMPILING_ARM = "Compiling C (ARM-only):"
+MSG_COMPILINGCPP = Compiling C++:
+MSG_COMPILINGCPP_ARM = "Compiling C++ (ARM-only):"
+MSG_ASSEMBLING = Assembling:
+MSG_ASSEMBLING_ARM = "Assembling (ARM-only):"
+MSG_CLEANING = Cleaning project:
+MSG_FORMATERROR = Can not handle output-format
+MSG_LPC21_RESETREMINDER = You may have to bring the target in bootloader-mode now.
+
+# Define all object files.
+COBJ = $(SRC:.c=.o)
+AOBJ = $(ASRC:.S=.o)
+COBJARM = $(SRCARM:.c=.o)
+AOBJARM = $(ASRCARM:.S=.o)
+CPPOBJ = $(CPPSRC:.cpp=.o)
+CPPOBJARM = $(CPPSRCARM:.cpp=.o)
+
+# Define all listing files.
+LST = $(ASRC:.S=.lst) $(ASRCARM:.S=.lst) $(SRC:.c=.lst) $(SRCARM:.c=.lst)
+LST += $(CPPSRC:.cpp=.lst) $(CPPSRCARM:.cpp=.lst)
+
+# Compiler flags to generate dependency files.
+### GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d
+GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+ALL_CFLAGS = -mcpu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
+ALL_ASFLAGS = -mcpu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
+
+
+# Default target.
+all: begin gccversion sizebefore build sizeafter finished end
+
+ifeq ($(FORMAT),ihex)
+build: elf hex lss sym
+hex: $(TARGET).hex
+IMGEXT=hex
+else
+ifeq ($(FORMAT),binary)
+build: elf bin lss sym
+bin: $(TARGET).bin
+IMGEXT=bin
+else
+$(error "$(MSG_FORMATERROR) $(FORMAT)")
+endif
+endif
+
+elf: $(TARGET).elf
+lss: $(TARGET).lss
+sym: $(TARGET).sym
+
+# Eye candy.
+begin:
+ @echo
+ @echo $(MSG_BEGIN)
+
+finished:
+ @echo $(MSG_ERRORS_NONE)
+
+end:
+ @echo $(MSG_END)
+ @echo
+
+
+# Display size of file.
+HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
+ELFSIZE = $(SIZE) -A $(TARGET).elf
+sizebefore:
+ @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
+
+sizeafter:
+ @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
+
+
+# Display compiler version information.
+gccversion :
+ @$(CC) --version
+
+
+# Program the device.
+# Program the device by using our relais card robot over USB
+ifeq ($(FLASH_TOOL),AT91FLASH)
+program: $(TARGET).$(IMGEXT)
+ ls -l $(TARGET).$(IMGEXT)
+ at91flash $(TARGET).$(IMGEXT)
+else
+ifeq ($(FLASH_TOOL),UVISION)
+# Program the device with Keil's uVision (needs configured uVision-Workspace).
+program: $(TARGET).$(IMGEXT)
+ @echo
+ @echo "Programming with uVision"
+ C:\Keil\uv3\Uv3.exe -f uvisionflash.Uv2 -ouvisionflash.txt
+else
+ifeq ($(FLASH_TOOL),OPENOCD)
+# Program the device with Dominic Rath's OPENOCD in "batch-mode", needs cfg and "reset-script".
+program: $(TARGET).$(IMGEXT)
+ @echo
+ @echo "Programming with OPENOCD"
+ C:\WinARM\utils\openocd\openocd_svn59\openocd.exe -f oocd_sam7_flash.cfg
+else
+# Program the device. - lpc21isp will not work for SAM7
+program: $(TARGET).$(IMGEXT)
+ @echo
+ @echo $(MSG_LPC21_RESETREMINDER)
+ $(LPC21ISP) $(LPC21ISP_OPTIONS) $(LPC21ISP_DEBUG) $(LPC21ISP_FLASHFILE) $(LPC21ISP_PORT) $(LPC21ISP_BAUD) $(LPC21ISP_XTAL)
+endif
+endif
+endif
+
+
+# Create final output file (.hex) from ELF output file.
+%.hex: %.elf
+ @echo
+ @echo $(MSG_FLASH) $@
+ $(OBJCOPY) -O $(FORMAT) $< $@
+
+# Create final output file (.bin) from ELF output file.
+%.bin: %.elf
+ @echo
+ @echo $(MSG_FLASH) $@
+ $(OBJCOPY) -O $(FORMAT) $< $@
+
+
+# Create extended listing file from ELF output file.
+# testing: option -C
+%.lss: %.elf
+ @echo
+ @echo $(MSG_EXTENDED_LISTING) $@
+ $(OBJDUMP) -h -S -C $< > $@
+
+
+# Create a symbol table from ELF output file.
+%.sym: %.elf
+ @echo
+ @echo $(MSG_SYMBOL_TABLE) $@
+ $(NM) -n $< > $@
+
+
+# Link: create ELF output file from object files.
+.SECONDARY : $(TARGET).elf
+.PRECIOUS : $(AOBJARM) $(AOBJ) $(COBJARM) $(COBJ) $(CPPOBJ) $(CPPOBJARM)
+%.elf: $(AOBJARM) $(AOBJ) $(COBJARM) $(COBJ) $(CPPOBJ) $(CPPOBJARM)
+ @echo
+ @echo $(MSG_LINKING) $@
+ $(CC) $(ALL_CFLAGS) $(AOBJARM) $(AOBJ) $(COBJARM) $(COBJ) $(CPPOBJ) $(CPPOBJARM) --output $@ $(LDFLAGS)
+
+# Compile: create object files from C source files. ARM/Thumb
+$(COBJ) : %.o : %.c
+ @echo
+ @echo $(MSG_COMPILING) $<
+ $(CC) -c $(ALL_CFLAGS) $(CONLYFLAGS) $< -o $@
+
+# Compile: create object files from C source files. ARM-only
+$(COBJARM) : %.o : %.c
+ @echo
+ @echo $(MSG_COMPILING_ARM) $<
+ $(CC) -c $(ALL_CFLAGS) $(CONLYFLAGS) $< -o $@
+
+# Compile: create object files from C++ source files. ARM/Thumb
+$(CPPOBJ) : %.o : %.cpp
+ @echo
+ @echo $(MSG_COMPILINGCPP) $<
+ $(CPP) -c $(ALL_CFLAGS) $(CPPFLAGS) $< -o $@
+
+# Compile: create object files from C++ source files. ARM-only
+$(CPPOBJARM) : %.o : %.cpp
+ @echo
+ @echo $(MSG_COMPILINGCPP_ARM) $<
+ $(CPP) -c $(ALL_CFLAGS) $(CPPFLAGS) $< -o $@
+
+
+# Compile: create assembler files from C source files. ARM/Thumb
+## does not work - TODO - hints welcome
+##$(COBJ) : %.s : %.c
+## $(CC) $(THUMB) -S $(ALL_CFLAGS) $< -o $@
+
+
+# Assemble: create object files from assembler source files. ARM/Thumb
+$(AOBJ) : %.o : %.S
+ @echo
+ @echo $(MSG_ASSEMBLING) $<
+ $(CC) -c $(ALL_ASFLAGS) $< -o $@
+
+
+# Assemble: create object files from assembler source files. ARM-only
+$(AOBJARM) : %.o : %.S
+ @echo
+ @echo $(MSG_ASSEMBLING_ARM) $<
+ $(CC) -c $(ALL_ASFLAGS) $< -o $@
+
+
+# Target: clean project.
+clean: begin clean_list finished end
+
+
+clean_list :
+ @echo
+ @echo $(MSG_CLEANING)
+ $(REMOVE) $(TARGET).hex
+ $(REMOVE) $(TARGET).bin
+ $(REMOVE) $(TARGET).obj
+ $(REMOVE) $(TARGET).elf
+ $(REMOVE) $(TARGET).map
+ $(REMOVE) $(TARGET).obj
+ $(REMOVE) $(TARGET).a90
+ $(REMOVE) $(TARGET).sym
+ $(REMOVE) $(TARGET).lnk
+ $(REMOVE) $(TARGET).lss
+ $(REMOVE) $(COBJ)
+ $(REMOVE) $(CPPOBJ)
+ $(REMOVE) $(AOBJ)
+ $(REMOVE) $(COBJARM)
+ $(REMOVE) $(CPPOBJARM)
+ $(REMOVE) $(AOBJARM)
+ $(REMOVE) $(LST)
+ $(REMOVE) $(SRC:.c=.s)
+ $(REMOVE) $(SRC:.c=.d)
+ $(REMOVE) $(SRCARM:.c=.s)
+ $(REMOVE) $(SRCARM:.c=.d)
+ $(REMOVE) $(CPPSRC:.cpp=.s)
+ $(REMOVE) $(CPPSRC:.cpp=.d)
+ $(REMOVE) $(CPPSRCARM:.cpp=.s)
+ $(REMOVE) $(CPPSRCARM:.cpp=.d)
+ $(REMOVE) .dep/*
+
+
+# Include the dependency files.
+-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
+
+
+# Listing of phony targets.
+.PHONY : all begin finish end sizebefore sizeafter gccversion \
+build elf hex bin lss sym clean clean_list program
+
diff --git a/firmware/README b/firmware/README
new file mode 100644
index 0000000..9f7d93f
--- /dev/null
+++ b/firmware/README
@@ -0,0 +1,8 @@
+Different Targets can be built by implementing a _init_func() and _main_func()_
+function in src/main_foo.c
+
+The resulting binary main_foo.bin can be built by issuing
+ make TARGET=main_foo
+
+If you want to add debugging support (debug unit aka DBGU, RS232), add DEBUG=1
+
diff --git a/firmware/TODO b/firmware/TODO
new file mode 100644
index 0000000..eea1974
--- /dev/null
+++ b/firmware/TODO
@@ -0,0 +1,27 @@
+SPI:
+- use PDC DMA for SPI transfers
+- use real SPI clock divisor (4.8MHz) rather than current 320kHz clock
+
+RC632:
+- Fix locking between 'atomic' ops like set/clear bit and RC632 IRQ
+- Implement VFIFO handling
+
+USB:
+- don't busy-wait for EP2/EP3 transfers but rather use TX completion IRQ
+- Implement VFIFO handling
+- Add DFU descriptor to host
+
+DFU:
+- implement DFU protocol for memory and flash
+- add capability to copy and execute DFU from RAM
+
+Generic:
+-
+
+Later, for PICCsim:
+- Implement SSC code for sampling subcarrier
+- Implement SSC code for generating subcarrier
+- Implement Manchester coding
+
+Way Later, for librfid:
+- Implement parts (or all of) 14443 in firmware as alternative configuration
diff --git a/firmware/doc/bitpattern.txt b/firmware/doc/bitpattern.txt
new file mode 100644
index 0000000..2594a4c
--- /dev/null
+++ b/firmware/doc/bitpattern.txt
@@ -0,0 +1,102 @@
+DATA CODING
+
+ISO 14443 A bit patterns PCD -> PICC direction:
+
+Sequence X After time of 64/fC a "pause" shall occur
+Sequence Y for the full bit duration (128/fC) no modulation shall occur
+Sequence Z at the beginning of the bit duration a pause shall occur
+
+
+logic 1 Sequence X
+logic 0 Sequence Y with two exceptions:
+ - if there are two or more contiguous '0, Z used from the second on
+ - if the first bit after SOF is 0, sequence Z used for all contig. 0's
+SOF Sequence Z
+EOF Logic 0 followed by Sequence Y
+No Inform At least two sequences Y
+
+
+
+FRAME TYPES
+
+During anti collision we have two frame types:
+
+1) REQA/WUPA (short frame)
+
+Short frame is seven bits with SOF/EOF "SOF 0 1 2 3 4 5 6 EOF"
+
+REQA 0x26 S 0101010 E Z ZXYXYXY ZY
+WUPA 0x52 S 0100101 E Z ZXYZXYX YY
+REQA_t 0x35 S 1001110 E Z XYZXXXY ZY
+
+2) ANTICOL/SELET (standard frame)
+
+Standard frame: minimum "SOF byte parity EOF", e.g.
+
+ S 01234567 P 01234567 P 01234567 P E
+
+Anticol frame: like standard frame, but
+ - frame splitted between PCD and PICC
+ - total bit length is 56
+ - length of PCD part: 16 data bits to 55 data bits
+ - length of PICC part: 1 data bit to 40 data bits
+ - split can occur at any bit position
+ - full byte: split after complete byte: Parity added after last PCD bit
+ - split byte: No Parity is added after last PCD bit
+ - each half of the split frame has its own SOF / EOF
+
+BIT TIMING
+
+One bit clock is fC/128, i.e. 105937.5 kHz, resulting in 9.43uS bit time
+
+The "pause" has to be min. 2uS, or 21.2% of the bit duration.
+
+
+SAMPLING
+
+Given the pause is only 21.2%, four samples per bit clock are not really enough
+to catch the pause under all circumstances.
+
+Given four-times and eight-times oversampling, we get:
+
+ 4-over 8-over
+Sequence X 0010 00001000 (00000100)
+Sequence Y 0000 00000000
+Sequence Z 1000 10000000 (01000000)
+
+
+
+Ideas:
+- if we ignore final 'Y' sequence, DATLEN is 32 (8 clocks, four bits each), therefore
+ we can just configure SSC to sample one frame of 32 sample bits after the start condition
+ was met.
+
+
+SAMPLING DURING STANDARD FRAMES
+
+The maxiumum frame size is 256 data bytes. We have to add two bytes CRC (=258
+bytes), plus parity (2064bits, plus 258 bits parity, equals 2322 data bits. Add
+SOF / EOF with three bit clocks, and we have 2325 total data bits for a
+maximum-sized frame. At four-times oversampling, this is 9300 sampled bits,
+equals to 1162.5 bytes (eight-times oversampling consequently 2325 bytes).
+
+
+
+BIT SYNCHRONOUS RESPONSE IN SPLIT FRAME
+
+For some stupid reasons, the frame delay time for synchronous frames is not in
+relation to the bit clock but in relation to the last rising edge of a
+modulation pause.
+
+Therefore we need some trickery. Every rising edge resets TC2 of the SAM7, which
+is clocked by the carrier clock. Once RA compare is true, TIOA2 will see a
+rising edge, which is connected to TF, the SSC Tx Framer.
+
+On The Tx side we have to run the SSC always at 847.5kHz
+
+
+
+
+thoughts:
+falling edge of demodulated signal: counter reset, TIOB set
+RB Compare: TIOB reset
diff --git a/firmware/doc/dfu.txt b/firmware/doc/dfu.txt
new file mode 100644
index 0000000..9b40c3c
--- /dev/null
+++ b/firmware/doc/dfu.txt
@@ -0,0 +1,89 @@
+- data that is needed from both app and dfu mode
+- code that is needed from both app and dfu mode
+ - function pointers
+ - copy code to RAM in case of DFU switch
+- data that is only needed in DFU mode
+ - can be overwritten in case of reset-to-application
+- data that is only needed in app mode
+ - can be overwritten with DFU data in case of DFU switch
+- code that is only needed in DFU mode
+ - has to be copied to ram in case of DFU switch
+- code that is only needed in app mode
+ - can be read from flash, no action required
+
+
+=> abandoned that complicated idea.
+now all DFU functions are __ramfunc's and thus always present.
+
+
+interaction between app and dfu code:
+
+- dfu_switch(void)
+- dfu_status (can be put in accessor function, if required)
+- dfu_cfg_descriptor
+- dfu_dev_descriptor
+- dfu_ep0_handler()
+
+
+order of events at boot;
+
+- start at reset vector in flash
+ - AT91F_LowLevelInit()
+- setup stack for each mode
+- relocate 'data' of bootloader, including ramfunc/vectram
+- clear 'bss' of bootloader
+- call remap command
+ - call usb initialization (irq, clock)
+ - if keypress,
+ - call dfu_main()
+ - wait for ep0 / busreset interrupt
+ - else call main()
+
+
+memory layout:
+
+0: lowlevel startup code
+ Cstartup.o 0x00bc
+ Cstartup_SAM7.o 0x0100
+ dfufunc 0x1dcc
+ dfustruct 0x0038
+
+ text text 0x0070
+data data 0x0000
+bss bss 0x000c
+
+flash = text + data (= 8k)
+ram/rel = data + bss (12 bytes)
+
+
+If we drop the DFU-can-flash-DFU requirement, we can leave all DFU related code
+in flash. no need for any function to be permanently in RAM. However, not
+preventing this feature in some future version, we shouldn't do that.
+
+
+Function DFU runtime
+udp_init x x RAM
+udp_ep0_send_data x x RAM
+udp_ep0_send_zlp x x RAM
+udp_sp0_send_stall x x RAM
+handle_dnload x - flash/relocated
+handle_upload x - flash/relocated
+handle_getstatus x - flash/relocated
+handle_getstate x - flash/relocated
+dfu_ep0_handler x x RAM
+
+dfu_dev_descriptor x - flash/relocated
+dfu_cfg_descriptor x - flash/relocated
+dfu_udp_ep0_handler x - flash/relocated
+dfu_udp_irq x - flash/relocated
+dfu_switch - x RAM
+dfu_main x - flash/relocated
+vectram x x flash/relocated/switched
+IRQ_Handler_EntryR x x flash/relocated/switched
+_remap x - flash/reloaded
+
+dfu_api x x flash (const anyway)
+dfu_state x x RAM
+
+
+
diff --git a/firmware/doc/piccsim-todo.txt b/firmware/doc/piccsim-todo.txt
new file mode 100644
index 0000000..a009b7d
--- /dev/null
+++ b/firmware/doc/piccsim-todo.txt
@@ -0,0 +1,34 @@
+- code to control digital potentiometers via SPI [MM]
+ - chip select not SPI CS
+
+- idea: use comparator to determine voltage range, then reconfigure amplifier
+ - later
+
+- problem: capacitance of digital poti
+ - idea 1:
+ - idea 2: logarithmic amplifier using transistor
+
+- ADC driver
+ - core [MM]
+ - trigger function (we want to read all values ASAP)
+ - callback function (once new values are available)
+ - init function (initialize ADC)
+ - USB integration [HW]
+ - simple READ_ADC command
+ - one reply packet with all ADC channels
+
+- OS timer
+ - how often?
+
+- 'load modulation' driver
+ x set PA2/PA3 to binary 0..3
+
+x add IO definitions for
+ - PLL INHIBIT low
+ - SPI_SS1_GAIN
+ - SPI_SS2_DATA_THRESHOLD
+ - BOOTLDR
+
+- sampled data continuous output into file / stdout
+ - trigger sampling by raising/falling edge (configurable)
+ - sample only one buffer
diff --git a/firmware/doc/piccsim.txt b/firmware/doc/piccsim.txt
new file mode 100644
index 0000000..3f149da
--- /dev/null
+++ b/firmware/doc/piccsim.txt
@@ -0,0 +1,42 @@
+PICCSIM design
+
+ISO14443 anticollision:
+- Configure TC
+ - to reset TC2 on every falling edge
+ - to use FORCE_FAST for TC IRQ
+ - to enable TC2 ETRGS
+- CARRIER_DIV is switched to 212kHz / 424kHz
+ - this results in SSC Rx is 4x (2x?) oversampling
+- Set SSC Rx start condition to 4x/2x SOF pattern
+- upon reception of first falling edge, we
+ - end up in TC FIQ
+ - read out TC0 current value
+ - reconfigure TC0 RA/RB to be in-phase with previously-read TC0
+ value (subtracting some fixed offset depending on FIQ latency)
+ - reconfigure TC2
+ - to use external event on every rising edge
+ - to reset(trigger) on every external event
+ - to clear TIOA2 on RC compare (RC is high)
+ - to set TIOA2 on RA compare (RA set later)
+ - disable TC2 IRQ (and FIQ FAST_FORCE)
+- Wait for SSC Rx Interrupt (DMA complete, or PIO)
+ - Read and decode single 32bit word
+ - determine whether it is REQA or WUPA
+ - abort if not, start over
+ - depending on last bit 0/1, configure TC2 RA (FDT)
+ - recconfig TC0 to produce 1.6MHz CARRIER_DIV clock for SSC Tx
+ - make sure this is done synchronously
+ -
+ - set up SSC Tx
+ - DMA with pre-encoded (and user-configured) ATQA
+ - start Tx at a rising edge of TF (asserted by TC2 RA)
+ - Send Interrupt once TX DMA is done
+- Once TC2 RA compare happens, the rising edge of TIOA2 will trigger SSC
+- Wait for SSC Tx DMA to finish
+- Repeat similar steps for ANTICOL/SELECT command, differences:
+ - single-byte compare after frame Rx is not sufficient
+ - evaluate number of valid bits ASAP
+ - we might receive and transmit split frame at non-byte-boundaries
+ - just shift a prepared ANTICOL/Select response
+ - make sure parity is handled correctly!
+- Once we've completed the select, we go on with normal
diff --git a/firmware/include/AT91SAM7.h b/firmware/include/AT91SAM7.h
new file mode 100644
index 0000000..56b738e
--- /dev/null
+++ b/firmware/include/AT91SAM7.h
@@ -0,0 +1,1935 @@
+// ----------------------------------------------------------------------------
+// ATMEL Microcontroller Software Support - ROUSSET -
+// ----------------------------------------------------------------------------
+// DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+// DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// ----------------------------------------------------------------------------
+// File Name : AT91SAM7S64.h
+// Object : AT91SAM7S64 definitions
+// Generated : AT91 SW Application Group 08/30/2005 (15:52:59)
+//
+// CVS Reference : /AT91SAM7S64.pl/1.21/Tue Aug 30 11:55:03 2005//
+// CVS Reference : /SYS_SAM7S.pl/1.2/Tue Feb 1 17:01:52 2005//
+// CVS Reference : /MC_SAM7S.pl/1.3/Fri May 20 14:12:30 2005//
+// CVS Reference : /PMC_SAM7S_USB.pl/1.4/Tue Feb 8 13:58:22 2005//
+// CVS Reference : /RSTC_SAM7S.pl/1.2/Wed Jul 13 14:57:40 2005//
+// CVS Reference : /UDP_SAM7S.pl/1.1/Tue May 10 11:34:52 2005//
+// CVS Reference : /PWM_SAM7S.pl/1.1/Tue May 10 11:53:07 2005//
+// CVS Reference : /RTTC_6081A.pl/1.2/Tue Nov 9 14:43:58 2004//
+// CVS Reference : /PITC_6079A.pl/1.2/Tue Nov 9 14:43:56 2004//
+// CVS Reference : /WDTC_6080A.pl/1.3/Tue Nov 9 14:44:00 2004//
+// CVS Reference : /VREG_6085B.pl/1.1/Tue Feb 1 16:05:48 2005//
+// CVS Reference : /AIC_6075B.pl/1.3/Fri May 20 14:01:30 2005//
+// CVS Reference : /PIO_6057A.pl/1.2/Thu Feb 3 10:18:28 2005//
+// CVS Reference : /DBGU_6059D.pl/1.1/Mon Jan 31 13:15:32 2005//
+// CVS Reference : /US_6089C.pl/1.1/Mon Jul 12 18:23:26 2004//
+// CVS Reference : /SPI_6088D.pl/1.3/Fri May 20 14:08:59 2005//
+// CVS Reference : /SSC_6078A.pl/1.1/Tue Jul 13 07:45:40 2004//
+// CVS Reference : /TC_6082A.pl/1.7/Fri Mar 11 12:52:17 2005//
+// CVS Reference : /TWI_6061A.pl/1.1/Tue Jul 13 07:38:06 2004//
+// CVS Reference : /PDC_6074C.pl/1.2/Thu Feb 3 08:48:54 2005//
+// CVS Reference : /ADC_6051C.pl/1.1/Fri Oct 17 09:12:38 2003//
+// ----------------------------------------------------------------------------
+
+#ifndef __AT91SAM7_H__
+#define __AT91SAM7_H__
+
+typedef volatile unsigned int AT91_REG;// Hardware register definition
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR System Peripherals
+// *****************************************************************************
+typedef struct _AT91S_SYS {
+ AT91_REG AIC_SMR[32]; // Source Mode Register
+ AT91_REG AIC_SVR[32]; // Source Vector Register
+ AT91_REG AIC_IVR; // IRQ Vector Register
+ AT91_REG AIC_FVR; // FIQ Vector Register
+ AT91_REG AIC_ISR; // Interrupt Status Register
+ AT91_REG AIC_IPR; // Interrupt Pending Register
+ AT91_REG AIC_IMR; // Interrupt Mask Register
+ AT91_REG AIC_CISR; // Core Interrupt Status Register
+ AT91_REG Reserved0[2]; //
+ AT91_REG AIC_IECR; // Interrupt Enable Command Register
+ AT91_REG AIC_IDCR; // Interrupt Disable Command Register
+ AT91_REG AIC_ICCR; // Interrupt Clear Command Register
+ AT91_REG AIC_ISCR; // Interrupt Set Command Register
+ AT91_REG AIC_EOICR; // End of Interrupt Command Register
+ AT91_REG AIC_SPU; // Spurious Vector Register
+ AT91_REG AIC_DCR; // Debug Control Register (Protect)
+ AT91_REG Reserved1[1]; //
+ AT91_REG AIC_FFER; // Fast Forcing Enable Register
+ AT91_REG AIC_FFDR; // Fast Forcing Disable Register
+ AT91_REG AIC_FFSR; // Fast Forcing Status Register
+ AT91_REG Reserved2[45]; //
+ AT91_REG DBGU_CR; // Control Register
+ AT91_REG DBGU_MR; // Mode Register
+ AT91_REG DBGU_IER; // Interrupt Enable Register
+ AT91_REG DBGU_IDR; // Interrupt Disable Register
+ AT91_REG DBGU_IMR; // Interrupt Mask Register
+ AT91_REG DBGU_CSR; // Channel Status Register
+ AT91_REG DBGU_RHR; // Receiver Holding Register
+ AT91_REG DBGU_THR; // Transmitter Holding Register
+ AT91_REG DBGU_BRGR; // Baud Rate Generator Register
+ AT91_REG Reserved3[7]; //
+ AT91_REG DBGU_CIDR; // Chip ID Register
+ AT91_REG DBGU_EXID; // Chip ID Extension Register
+ AT91_REG DBGU_FNTR; // Force NTRST Register
+ AT91_REG Reserved4[45]; //
+ AT91_REG DBGU_RPR; // Receive Pointer Register
+ AT91_REG DBGU_RCR; // Receive Counter Register
+ AT91_REG DBGU_TPR; // Transmit Pointer Register
+ AT91_REG DBGU_TCR; // Transmit Counter Register
+ AT91_REG DBGU_RNPR; // Receive Next Pointer Register
+ AT91_REG DBGU_RNCR; // Receive Next Counter Register
+ AT91_REG DBGU_TNPR; // Transmit Next Pointer Register
+ AT91_REG DBGU_TNCR; // Transmit Next Counter Register
+ AT91_REG DBGU_PTCR; // PDC Transfer Control Register
+ AT91_REG DBGU_PTSR; // PDC Transfer Status Register
+ AT91_REG Reserved5[54]; //
+ AT91_REG PIOA_PER; // PIO Enable Register
+ AT91_REG PIOA_PDR; // PIO Disable Register
+ AT91_REG PIOA_PSR; // PIO Status Register
+ AT91_REG Reserved6[1]; //
+ AT91_REG PIOA_OER; // Output Enable Register
+ AT91_REG PIOA_ODR; // Output Disable Registerr
+ AT91_REG PIOA_OSR; // Output Status Register
+ AT91_REG Reserved7[1]; //
+ AT91_REG PIOA_IFER; // Input Filter Enable Register
+ AT91_REG PIOA_IFDR; // Input Filter Disable Register
+ AT91_REG PIOA_IFSR; // Input Filter Status Register
+ AT91_REG Reserved8[1]; //
+ AT91_REG PIOA_SODR; // Set Output Data Register
+ AT91_REG PIOA_CODR; // Clear Output Data Register
+ AT91_REG PIOA_ODSR; // Output Data Status Register
+ AT91_REG PIOA_PDSR; // Pin Data Status Register
+ AT91_REG PIOA_IER; // Interrupt Enable Register
+ AT91_REG PIOA_IDR; // Interrupt Disable Register
+ AT91_REG PIOA_IMR; // Interrupt Mask Register
+ AT91_REG PIOA_ISR; // Interrupt Status Register
+ AT91_REG PIOA_MDER; // Multi-driver Enable Register
+ AT91_REG PIOA_MDDR; // Multi-driver Disable Register
+ AT91_REG PIOA_MDSR; // Multi-driver Status Register
+ AT91_REG Reserved9[1]; //
+ AT91_REG PIOA_PPUDR; // Pull-up Disable Register
+ AT91_REG PIOA_PPUER; // Pull-up Enable Register
+ AT91_REG PIOA_PPUSR; // Pull-up Status Register
+ AT91_REG Reserved10[1]; //
+ AT91_REG PIOA_ASR; // Select A Register
+ AT91_REG PIOA_BSR; // Select B Register
+ AT91_REG PIOA_ABSR; // AB Select Status Register
+ AT91_REG Reserved11[9]; //
+ AT91_REG PIOA_OWER; // Output Write Enable Register
+ AT91_REG PIOA_OWDR; // Output Write Disable Register
+ AT91_REG PIOA_OWSR; // Output Write Status Register
+ AT91_REG Reserved12[469]; //
+ AT91_REG PMC_SCER; // System Clock Enable Register
+ AT91_REG PMC_SCDR; // System Clock Disable Register
+ AT91_REG PMC_SCSR; // System Clock Status Register
+ AT91_REG Reserved13[1]; //
+ AT91_REG PMC_PCER; // Peripheral Clock Enable Register
+ AT91_REG PMC_PCDR; // Peripheral Clock Disable Register
+ AT91_REG PMC_PCSR; // Peripheral Clock Status Register
+ AT91_REG Reserved14[1]; //
+ AT91_REG PMC_MOR; // Main Oscillator Register
+ AT91_REG PMC_MCFR; // Main Clock Frequency Register
+ AT91_REG Reserved15[1]; //
+ AT91_REG PMC_PLLR; // PLL Register
+ AT91_REG PMC_MCKR; // Master Clock Register
+ AT91_REG Reserved16[3]; //
+ AT91_REG PMC_PCKR[3]; // Programmable Clock Register
+ AT91_REG Reserved17[5]; //
+ AT91_REG PMC_IER; // Interrupt Enable Register
+ AT91_REG PMC_IDR; // Interrupt Disable Register
+ AT91_REG PMC_SR; // Status Register
+ AT91_REG PMC_IMR; // Interrupt Mask Register
+ AT91_REG Reserved18[36]; //
+ AT91_REG RSTC_RCR; // Reset Control Register
+ AT91_REG RSTC_RSR; // Reset Status Register
+ AT91_REG RSTC_RMR; // Reset Mode Register
+ AT91_REG Reserved19[5]; //
+ AT91_REG RTTC_RTMR; // Real-time Mode Register
+ AT91_REG RTTC_RTAR; // Real-time Alarm Register
+ AT91_REG RTTC_RTVR; // Real-time Value Register
+ AT91_REG RTTC_RTSR; // Real-time Status Register
+ AT91_REG PITC_PIMR; // Period Interval Mode Register
+ AT91_REG PITC_PISR; // Period Interval Status Register
+ AT91_REG PITC_PIVR; // Period Interval Value Register
+ AT91_REG PITC_PIIR; // Period Interval Image Register
+ AT91_REG WDTC_WDCR; // Watchdog Control Register
+ AT91_REG WDTC_WDMR; // Watchdog Mode Register
+ AT91_REG WDTC_WDSR; // Watchdog Status Register
+ AT91_REG Reserved20[5]; //
+ AT91_REG VREG_MR; // Voltage Regulator Mode Register
+} AT91S_SYS, *AT91PS_SYS;
+
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Advanced Interrupt Controller
+// *****************************************************************************
+typedef struct _AT91S_AIC {
+ AT91_REG AIC_SMR[32]; // Source Mode Register
+ AT91_REG AIC_SVR[32]; // Source Vector Register
+ AT91_REG AIC_IVR; // IRQ Vector Register
+ AT91_REG AIC_FVR; // FIQ Vector Register
+ AT91_REG AIC_ISR; // Interrupt Status Register
+ AT91_REG AIC_IPR; // Interrupt Pending Register
+ AT91_REG AIC_IMR; // Interrupt Mask Register
+ AT91_REG AIC_CISR; // Core Interrupt Status Register
+ AT91_REG Reserved0[2]; //
+ AT91_REG AIC_IECR; // Interrupt Enable Command Register
+ AT91_REG AIC_IDCR; // Interrupt Disable Command Register
+ AT91_REG AIC_ICCR; // Interrupt Clear Command Register
+ AT91_REG AIC_ISCR; // Interrupt Set Command Register
+ AT91_REG AIC_EOICR; // End of Interrupt Command Register
+ AT91_REG AIC_SPU; // Spurious Vector Register
+ AT91_REG AIC_DCR; // Debug Control Register (Protect)
+ AT91_REG Reserved1[1]; //
+ AT91_REG AIC_FFER; // Fast Forcing Enable Register
+ AT91_REG AIC_FFDR; // Fast Forcing Disable Register
+ AT91_REG AIC_FFSR; // Fast Forcing Status Register
+} AT91S_AIC, *AT91PS_AIC;
+
+// -------- AIC_SMR : (AIC Offset: 0x0) Control Register --------
+#define AT91C_AIC_PRIOR ((unsigned int) 0x7 << 0) // (AIC) Priority Level
+#define AT91C_AIC_PRIOR_LOWEST ((unsigned int) 0x0) // (AIC) Lowest priority level
+#define AT91C_AIC_PRIOR_HIGHEST ((unsigned int) 0x7) // (AIC) Highest priority level
+#define AT91C_AIC_SRCTYPE ((unsigned int) 0x3 << 5) // (AIC) Interrupt Source Type
+#define AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL ((unsigned int) 0x0 << 5) // (AIC) Internal Sources Code Label High-level Sensitive
+#define AT91C_AIC_SRCTYPE_EXT_LOW_LEVEL ((unsigned int) 0x0 << 5) // (AIC) External Sources Code Label Low-level Sensitive
+#define AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE ((unsigned int) 0x1 << 5) // (AIC) Internal Sources Code Label Positive Edge triggered
+#define AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE ((unsigned int) 0x1 << 5) // (AIC) External Sources Code Label Negative Edge triggered
+#define AT91C_AIC_SRCTYPE_HIGH_LEVEL ((unsigned int) 0x2 << 5) // (AIC) Internal Or External Sources Code Label High-level Sensitive
+#define AT91C_AIC_SRCTYPE_POSITIVE_EDGE ((unsigned int) 0x3 << 5) // (AIC) Internal Or External Sources Code Label Positive Edge triggered
+// -------- AIC_CISR : (AIC Offset: 0x114) AIC Core Interrupt Status Register --------
+#define AT91C_AIC_NFIQ ((unsigned int) 0x1 << 0) // (AIC) NFIQ Status
+#define AT91C_AIC_NIRQ ((unsigned int) 0x1 << 1) // (AIC) NIRQ Status
+// -------- AIC_DCR : (AIC Offset: 0x138) AIC Debug Control Register (Protect) --------
+#define AT91C_AIC_DCR_PROT ((unsigned int) 0x1 << 0) // (AIC) Protection Mode
+#define AT91C_AIC_DCR_GMSK ((unsigned int) 0x1 << 1) // (AIC) General Mask
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Peripheral DMA Controller
+// *****************************************************************************
+typedef struct _AT91S_PDC {
+ AT91_REG PDC_RPR; // Receive Pointer Register
+ AT91_REG PDC_RCR; // Receive Counter Register
+ AT91_REG PDC_TPR; // Transmit Pointer Register
+ AT91_REG PDC_TCR; // Transmit Counter Register
+ AT91_REG PDC_RNPR; // Receive Next Pointer Register
+ AT91_REG PDC_RNCR; // Receive Next Counter Register
+ AT91_REG PDC_TNPR; // Transmit Next Pointer Register
+ AT91_REG PDC_TNCR; // Transmit Next Counter Register
+ AT91_REG PDC_PTCR; // PDC Transfer Control Register
+ AT91_REG PDC_PTSR; // PDC Transfer Status Register
+} AT91S_PDC, *AT91PS_PDC;
+
+// -------- PDC_PTCR : (PDC Offset: 0x20) PDC Transfer Control Register --------
+#define AT91C_PDC_RXTEN ((unsigned int) 0x1 << 0) // (PDC) Receiver Transfer Enable
+#define AT91C_PDC_RXTDIS ((unsigned int) 0x1 << 1) // (PDC) Receiver Transfer Disable
+#define AT91C_PDC_TXTEN ((unsigned int) 0x1 << 8) // (PDC) Transmitter Transfer Enable
+#define AT91C_PDC_TXTDIS ((unsigned int) 0x1 << 9) // (PDC) Transmitter Transfer Disable
+// -------- PDC_PTSR : (PDC Offset: 0x24) PDC Transfer Status Register --------
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Debug Unit
+// *****************************************************************************
+typedef struct _AT91S_DBGU {
+ AT91_REG DBGU_CR; // Control Register
+ AT91_REG DBGU_MR; // Mode Register
+ AT91_REG DBGU_IER; // Interrupt Enable Register
+ AT91_REG DBGU_IDR; // Interrupt Disable Register
+ AT91_REG DBGU_IMR; // Interrupt Mask Register
+ AT91_REG DBGU_CSR; // Channel Status Register
+ AT91_REG DBGU_RHR; // Receiver Holding Register
+ AT91_REG DBGU_THR; // Transmitter Holding Register
+ AT91_REG DBGU_BRGR; // Baud Rate Generator Register
+ AT91_REG Reserved0[7]; //
+ AT91_REG DBGU_CIDR; // Chip ID Register
+ AT91_REG DBGU_EXID; // Chip ID Extension Register
+ AT91_REG DBGU_FNTR; // Force NTRST Register
+ AT91_REG Reserved1[45]; //
+ AT91_REG DBGU_RPR; // Receive Pointer Register
+ AT91_REG DBGU_RCR; // Receive Counter Register
+ AT91_REG DBGU_TPR; // Transmit Pointer Register
+ AT91_REG DBGU_TCR; // Transmit Counter Register
+ AT91_REG DBGU_RNPR; // Receive Next Pointer Register
+ AT91_REG DBGU_RNCR; // Receive Next Counter Register
+ AT91_REG DBGU_TNPR; // Transmit Next Pointer Register
+ AT91_REG DBGU_TNCR; // Transmit Next Counter Register
+ AT91_REG DBGU_PTCR; // PDC Transfer Control Register
+ AT91_REG DBGU_PTSR; // PDC Transfer Status Register
+} AT91S_DBGU, *AT91PS_DBGU;
+
+// -------- DBGU_CR : (DBGU Offset: 0x0) Debug Unit Control Register --------
+#define AT91C_US_RSTRX ((unsigned int) 0x1 << 2) // (DBGU) Reset Receiver
+#define AT91C_US_RSTTX ((unsigned int) 0x1 << 3) // (DBGU) Reset Transmitter
+#define AT91C_US_RXEN ((unsigned int) 0x1 << 4) // (DBGU) Receiver Enable
+#define AT91C_US_RXDIS ((unsigned int) 0x1 << 5) // (DBGU) Receiver Disable
+#define AT91C_US_TXEN ((unsigned int) 0x1 << 6) // (DBGU) Transmitter Enable
+#define AT91C_US_TXDIS ((unsigned int) 0x1 << 7) // (DBGU) Transmitter Disable
+#define AT91C_US_RSTSTA ((unsigned int) 0x1 << 8) // (DBGU) Reset Status Bits
+// -------- DBGU_MR : (DBGU Offset: 0x4) Debug Unit Mode Register --------
+#define AT91C_US_PAR ((unsigned int) 0x7 << 9) // (DBGU) Parity type
+#define AT91C_US_PAR_EVEN ((unsigned int) 0x0 << 9) // (DBGU) Even Parity
+#define AT91C_US_PAR_ODD ((unsigned int) 0x1 << 9) // (DBGU) Odd Parity
+#define AT91C_US_PAR_SPACE ((unsigned int) 0x2 << 9) // (DBGU) Parity forced to 0 (Space)
+#define AT91C_US_PAR_MARK ((unsigned int) 0x3 << 9) // (DBGU) Parity forced to 1 (Mark)
+#define AT91C_US_PAR_NONE ((unsigned int) 0x4 << 9) // (DBGU) No Parity
+#define AT91C_US_PAR_MULTI_DROP ((unsigned int) 0x6 << 9) // (DBGU) Multi-drop mode
+#define AT91C_US_CHMODE ((unsigned int) 0x3 << 14) // (DBGU) Channel Mode
+#define AT91C_US_CHMODE_NORMAL ((unsigned int) 0x0 << 14) // (DBGU) Normal Mode: The USART channel operates as an RX/TX USART.
+#define AT91C_US_CHMODE_AUTO ((unsigned int) 0x1 << 14) // (DBGU) Automatic Echo: Receiver Data Input is connected to the TXD pin.
+#define AT91C_US_CHMODE_LOCAL ((unsigned int) 0x2 << 14) // (DBGU) Local Loopback: Transmitter Output Signal is connected to Receiver Input Signal.
+#define AT91C_US_CHMODE_REMOTE ((unsigned int) 0x3 << 14) // (DBGU) Remote Loopback: RXD pin is internally connected to TXD pin.
+// -------- DBGU_IER : (DBGU Offset: 0x8) Debug Unit Interrupt Enable Register --------
+#define AT91C_US_RXRDY ((unsigned int) 0x1 << 0) // (DBGU) RXRDY Interrupt
+#define AT91C_US_TXRDY ((unsigned int) 0x1 << 1) // (DBGU) TXRDY Interrupt
+#define AT91C_US_ENDRX ((unsigned int) 0x1 << 3) // (DBGU) End of Receive Transfer Interrupt
+#define AT91C_US_ENDTX ((unsigned int) 0x1 << 4) // (DBGU) End of Transmit Interrupt
+#define AT91C_US_OVRE ((unsigned int) 0x1 << 5) // (DBGU) Overrun Interrupt
+#define AT91C_US_FRAME ((unsigned int) 0x1 << 6) // (DBGU) Framing Error Interrupt
+#define AT91C_US_PARE ((unsigned int) 0x1 << 7) // (DBGU) Parity Error Interrupt
+#define AT91C_US_TXEMPTY ((unsigned int) 0x1 << 9) // (DBGU) TXEMPTY Interrupt
+#define AT91C_US_TXBUFE ((unsigned int) 0x1 << 11) // (DBGU) TXBUFE Interrupt
+#define AT91C_US_RXBUFF ((unsigned int) 0x1 << 12) // (DBGU) RXBUFF Interrupt
+#define AT91C_US_COMM_TX ((unsigned int) 0x1 << 30) // (DBGU) COMM_TX Interrupt
+#define AT91C_US_COMM_RX ((unsigned int) 0x1 << 31) // (DBGU) COMM_RX Interrupt
+// -------- DBGU_IDR : (DBGU Offset: 0xc) Debug Unit Interrupt Disable Register --------
+// -------- DBGU_IMR : (DBGU Offset: 0x10) Debug Unit Interrupt Mask Register --------
+// -------- DBGU_CSR : (DBGU Offset: 0x14) Debug Unit Channel Status Register --------
+// -------- DBGU_FNTR : (DBGU Offset: 0x48) Debug Unit FORCE_NTRST Register --------
+#define AT91C_US_FORCE_NTRST ((unsigned int) 0x1 << 0) // (DBGU) Force NTRST in JTAG
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Parallel Input Output Controler
+// *****************************************************************************
+typedef struct _AT91S_PIO {
+ AT91_REG PIO_PER; // PIO Enable Register
+ AT91_REG PIO_PDR; // PIO Disable Register
+ AT91_REG PIO_PSR; // PIO Status Register
+ AT91_REG Reserved0[1]; //
+ AT91_REG PIO_OER; // Output Enable Register
+ AT91_REG PIO_ODR; // Output Disable Registerr
+ AT91_REG PIO_OSR; // Output Status Register
+ AT91_REG Reserved1[1]; //
+ AT91_REG PIO_IFER; // Input Filter Enable Register
+ AT91_REG PIO_IFDR; // Input Filter Disable Register
+ AT91_REG PIO_IFSR; // Input Filter Status Register
+ AT91_REG Reserved2[1]; //
+ AT91_REG PIO_SODR; // Set Output Data Register
+ AT91_REG PIO_CODR; // Clear Output Data Register
+ AT91_REG PIO_ODSR; // Output Data Status Register
+ AT91_REG PIO_PDSR; // Pin Data Status Register
+ AT91_REG PIO_IER; // Interrupt Enable Register
+ AT91_REG PIO_IDR; // Interrupt Disable Register
+ AT91_REG PIO_IMR; // Interrupt Mask Register
+ AT91_REG PIO_ISR; // Interrupt Status Register
+ AT91_REG PIO_MDER; // Multi-driver Enable Register
+ AT91_REG PIO_MDDR; // Multi-driver Disable Register
+ AT91_REG PIO_MDSR; // Multi-driver Status Register
+ AT91_REG Reserved3[1]; //
+ AT91_REG PIO_PPUDR; // Pull-up Disable Register
+ AT91_REG PIO_PPUER; // Pull-up Enable Register
+ AT91_REG PIO_PPUSR; // Pull-up Status Register
+ AT91_REG Reserved4[1]; //
+ AT91_REG PIO_ASR; // Select A Register
+ AT91_REG PIO_BSR; // Select B Register
+ AT91_REG PIO_ABSR; // AB Select Status Register
+ AT91_REG Reserved5[9]; //
+ AT91_REG PIO_OWER; // Output Write Enable Register
+ AT91_REG PIO_OWDR; // Output Write Disable Register
+ AT91_REG PIO_OWSR; // Output Write Status Register
+} AT91S_PIO, *AT91PS_PIO;
+
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Clock Generator Controler
+// *****************************************************************************
+typedef struct _AT91S_CKGR {
+ AT91_REG CKGR_MOR; // Main Oscillator Register
+ AT91_REG CKGR_MCFR; // Main Clock Frequency Register
+ AT91_REG Reserved0[1]; //
+ AT91_REG CKGR_PLLR; // PLL Register
+} AT91S_CKGR, *AT91PS_CKGR;
+
+// -------- CKGR_MOR : (CKGR Offset: 0x0) Main Oscillator Register --------
+#define AT91C_CKGR_MOSCEN ((unsigned int) 0x1 << 0) // (CKGR) Main Oscillator Enable
+#define AT91C_CKGR_OSCBYPASS ((unsigned int) 0x1 << 1) // (CKGR) Main Oscillator Bypass
+#define AT91C_CKGR_OSCOUNT ((unsigned int) 0xFF << 8) // (CKGR) Main Oscillator Start-up Time
+// -------- CKGR_MCFR : (CKGR Offset: 0x4) Main Clock Frequency Register --------
+#define AT91C_CKGR_MAINF ((unsigned int) 0xFFFF << 0) // (CKGR) Main Clock Frequency
+#define AT91C_CKGR_MAINRDY ((unsigned int) 0x1 << 16) // (CKGR) Main Clock Ready
+// -------- CKGR_PLLR : (CKGR Offset: 0xc) PLL B Register --------
+#define AT91C_CKGR_DIV ((unsigned int) 0xFF << 0) // (CKGR) Divider Selected
+#define AT91C_CKGR_DIV_0 ((unsigned int) 0x0) // (CKGR) Divider output is 0
+#define AT91C_CKGR_DIV_BYPASS ((unsigned int) 0x1) // (CKGR) Divider is bypassed
+#define AT91C_CKGR_PLLCOUNT ((unsigned int) 0x3F << 8) // (CKGR) PLL Counter
+#define AT91C_CKGR_OUT ((unsigned int) 0x3 << 14) // (CKGR) PLL Output Frequency Range
+#define AT91C_CKGR_OUT_0 ((unsigned int) 0x0 << 14) // (CKGR) Please refer to the PLL datasheet
+#define AT91C_CKGR_OUT_1 ((unsigned int) 0x1 << 14) // (CKGR) Please refer to the PLL datasheet
+#define AT91C_CKGR_OUT_2 ((unsigned int) 0x2 << 14) // (CKGR) Please refer to the PLL datasheet
+#define AT91C_CKGR_OUT_3 ((unsigned int) 0x3 << 14) // (CKGR) Please refer to the PLL datasheet
+#define AT91C_CKGR_MUL ((unsigned int) 0x7FF << 16) // (CKGR) PLL Multiplier
+#define AT91C_CKGR_USBDIV ((unsigned int) 0x3 << 28) // (CKGR) Divider for USB Clocks
+#define AT91C_CKGR_USBDIV_0 ((unsigned int) 0x0 << 28) // (CKGR) Divider output is PLL clock output
+#define AT91C_CKGR_USBDIV_1 ((unsigned int) 0x1 << 28) // (CKGR) Divider output is PLL clock output divided by 2
+#define AT91C_CKGR_USBDIV_2 ((unsigned int) 0x2 << 28) // (CKGR) Divider output is PLL clock output divided by 4
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Power Management Controler
+// *****************************************************************************
+typedef struct _AT91S_PMC {
+ AT91_REG PMC_SCER; // System Clock Enable Register
+ AT91_REG PMC_SCDR; // System Clock Disable Register
+ AT91_REG PMC_SCSR; // System Clock Status Register
+ AT91_REG Reserved0[1]; //
+ AT91_REG PMC_PCER; // Peripheral Clock Enable Register
+ AT91_REG PMC_PCDR; // Peripheral Clock Disable Register
+ AT91_REG PMC_PCSR; // Peripheral Clock Status Register
+ AT91_REG Reserved1[1]; //
+ AT91_REG PMC_MOR; // Main Oscillator Register
+ AT91_REG PMC_MCFR; // Main Clock Frequency Register
+ AT91_REG Reserved2[1]; //
+ AT91_REG PMC_PLLR; // PLL Register
+ AT91_REG PMC_MCKR; // Master Clock Register
+ AT91_REG Reserved3[3]; //
+ AT91_REG PMC_PCKR[3]; // Programmable Clock Register
+ AT91_REG Reserved4[5]; //
+ AT91_REG PMC_IER; // Interrupt Enable Register
+ AT91_REG PMC_IDR; // Interrupt Disable Register
+ AT91_REG PMC_SR; // Status Register
+ AT91_REG PMC_IMR; // Interrupt Mask Register
+} AT91S_PMC, *AT91PS_PMC;
+
+// -------- PMC_SCER : (PMC Offset: 0x0) System Clock Enable Register --------
+#define AT91C_PMC_PCK ((unsigned int) 0x1 << 0) // (PMC) Processor Clock
+#define AT91C_PMC_UDP ((unsigned int) 0x1 << 7) // (PMC) USB Device Port Clock
+#define AT91C_PMC_PCK0 ((unsigned int) 0x1 << 8) // (PMC) Programmable Clock Output
+#define AT91C_PMC_PCK1 ((unsigned int) 0x1 << 9) // (PMC) Programmable Clock Output
+#define AT91C_PMC_PCK2 ((unsigned int) 0x1 << 10) // (PMC) Programmable Clock Output
+// -------- PMC_SCDR : (PMC Offset: 0x4) System Clock Disable Register --------
+// -------- PMC_SCSR : (PMC Offset: 0x8) System Clock Status Register --------
+// -------- CKGR_MOR : (PMC Offset: 0x20) Main Oscillator Register --------
+// -------- CKGR_MCFR : (PMC Offset: 0x24) Main Clock Frequency Register --------
+// -------- CKGR_PLLR : (PMC Offset: 0x2c) PLL B Register --------
+// -------- PMC_MCKR : (PMC Offset: 0x30) Master Clock Register --------
+#define AT91C_PMC_CSS ((unsigned int) 0x3 << 0) // (PMC) Programmable Clock Selection
+#define AT91C_PMC_CSS_SLOW_CLK ((unsigned int) 0x0) // (PMC) Slow Clock is selected
+#define AT91C_PMC_CSS_MAIN_CLK ((unsigned int) 0x1) // (PMC) Main Clock is selected
+#define AT91C_PMC_CSS_PLL_CLK ((unsigned int) 0x3) // (PMC) Clock from PLL is selected
+#define AT91C_PMC_PRES ((unsigned int) 0x7 << 2) // (PMC) Programmable Clock Prescaler
+#define AT91C_PMC_PRES_CLK ((unsigned int) 0x0 << 2) // (PMC) Selected clock
+#define AT91C_PMC_PRES_CLK_2 ((unsigned int) 0x1 << 2) // (PMC) Selected clock divided by 2
+#define AT91C_PMC_PRES_CLK_4 ((unsigned int) 0x2 << 2) // (PMC) Selected clock divided by 4
+#define AT91C_PMC_PRES_CLK_8 ((unsigned int) 0x3 << 2) // (PMC) Selected clock divided by 8
+#define AT91C_PMC_PRES_CLK_16 ((unsigned int) 0x4 << 2) // (PMC) Selected clock divided by 16
+#define AT91C_PMC_PRES_CLK_32 ((unsigned int) 0x5 << 2) // (PMC) Selected clock divided by 32
+#define AT91C_PMC_PRES_CLK_64 ((unsigned int) 0x6 << 2) // (PMC) Selected clock divided by 64
+// -------- PMC_PCKR : (PMC Offset: 0x40) Programmable Clock Register --------
+// -------- PMC_IER : (PMC Offset: 0x60) PMC Interrupt Enable Register --------
+#define AT91C_PMC_MOSCS ((unsigned int) 0x1 << 0) // (PMC) MOSC Status/Enable/Disable/Mask
+#define AT91C_PMC_LOCK ((unsigned int) 0x1 << 2) // (PMC) PLL Status/Enable/Disable/Mask
+#define AT91C_PMC_MCKRDY ((unsigned int) 0x1 << 3) // (PMC) MCK_RDY Status/Enable/Disable/Mask
+#define AT91C_PMC_PCK0RDY ((unsigned int) 0x1 << 8) // (PMC) PCK0_RDY Status/Enable/Disable/Mask
+#define AT91C_PMC_PCK1RDY ((unsigned int) 0x1 << 9) // (PMC) PCK1_RDY Status/Enable/Disable/Mask
+#define AT91C_PMC_PCK2RDY ((unsigned int) 0x1 << 10) // (PMC) PCK2_RDY Status/Enable/Disable/Mask
+// -------- PMC_IDR : (PMC Offset: 0x64) PMC Interrupt Disable Register --------
+// -------- PMC_SR : (PMC Offset: 0x68) PMC Status Register --------
+// -------- PMC_IMR : (PMC Offset: 0x6c) PMC Interrupt Mask Register --------
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Reset Controller Interface
+// *****************************************************************************
+typedef struct _AT91S_RSTC {
+ AT91_REG RSTC_RCR; // Reset Control Register
+ AT91_REG RSTC_RSR; // Reset Status Register
+ AT91_REG RSTC_RMR; // Reset Mode Register
+} AT91S_RSTC, *AT91PS_RSTC;
+
+// -------- RSTC_RCR : (RSTC Offset: 0x0) Reset Control Register --------
+#define AT91C_RSTC_PROCRST ((unsigned int) 0x1 << 0) // (RSTC) Processor Reset
+#define AT91C_RSTC_PERRST ((unsigned int) 0x1 << 2) // (RSTC) Peripheral Reset
+#define AT91C_RSTC_EXTRST ((unsigned int) 0x1 << 3) // (RSTC) External Reset
+#define AT91C_RSTC_KEY ((unsigned int) 0xFF << 24) // (RSTC) Password
+// -------- RSTC_RSR : (RSTC Offset: 0x4) Reset Status Register --------
+#define AT91C_RSTC_URSTS ((unsigned int) 0x1 << 0) // (RSTC) User Reset Status
+#define AT91C_RSTC_BODSTS ((unsigned int) 0x1 << 1) // (RSTC) Brownout Detection Status
+#define AT91C_RSTC_RSTTYP ((unsigned int) 0x7 << 8) // (RSTC) Reset Type
+#define AT91C_RSTC_RSTTYP_POWERUP ((unsigned int) 0x0 << 8) // (RSTC) Power-up Reset. VDDCORE rising.
+#define AT91C_RSTC_RSTTYP_WAKEUP ((unsigned int) 0x1 << 8) // (RSTC) WakeUp Reset. VDDCORE rising.
+#define AT91C_RSTC_RSTTYP_WATCHDOG ((unsigned int) 0x2 << 8) // (RSTC) Watchdog Reset. Watchdog overflow occured.
+#define AT91C_RSTC_RSTTYP_SOFTWARE ((unsigned int) 0x3 << 8) // (RSTC) Software Reset. Processor reset required by the software.
+#define AT91C_RSTC_RSTTYP_USER ((unsigned int) 0x4 << 8) // (RSTC) User Reset. NRST pin detected low.
+#define AT91C_RSTC_RSTTYP_BROWNOUT ((unsigned int) 0x5 << 8) // (RSTC) Brownout Reset occured.
+#define AT91C_RSTC_NRSTL ((unsigned int) 0x1 << 16) // (RSTC) NRST pin level
+#define AT91C_RSTC_SRCMP ((unsigned int) 0x1 << 17) // (RSTC) Software Reset Command in Progress.
+// -------- RSTC_RMR : (RSTC Offset: 0x8) Reset Mode Register --------
+#define AT91C_RSTC_URSTEN ((unsigned int) 0x1 << 0) // (RSTC) User Reset Enable
+#define AT91C_RSTC_URSTIEN ((unsigned int) 0x1 << 4) // (RSTC) User Reset Interrupt Enable
+#define AT91C_RSTC_ERSTL ((unsigned int) 0xF << 8) // (RSTC) User Reset Length
+#define AT91C_RSTC_BODIEN ((unsigned int) 0x1 << 16) // (RSTC) Brownout Detection Interrupt Enable
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Real Time Timer Controller Interface
+// *****************************************************************************
+typedef struct _AT91S_RTTC {
+ AT91_REG RTTC_RTMR; // Real-time Mode Register
+ AT91_REG RTTC_RTAR; // Real-time Alarm Register
+ AT91_REG RTTC_RTVR; // Real-time Value Register
+ AT91_REG RTTC_RTSR; // Real-time Status Register
+} AT91S_RTTC, *AT91PS_RTTC;
+
+// -------- RTTC_RTMR : (RTTC Offset: 0x0) Real-time Mode Register --------
+#define AT91C_RTTC_RTPRES ((unsigned int) 0xFFFF << 0) // (RTTC) Real-time Timer Prescaler Value
+#define AT91C_RTTC_ALMIEN ((unsigned int) 0x1 << 16) // (RTTC) Alarm Interrupt Enable
+#define AT91C_RTTC_RTTINCIEN ((unsigned int) 0x1 << 17) // (RTTC) Real Time Timer Increment Interrupt Enable
+#define AT91C_RTTC_RTTRST ((unsigned int) 0x1 << 18) // (RTTC) Real Time Timer Restart
+// -------- RTTC_RTAR : (RTTC Offset: 0x4) Real-time Alarm Register --------
+#define AT91C_RTTC_ALMV ((unsigned int) 0x0 << 0) // (RTTC) Alarm Value
+// -------- RTTC_RTVR : (RTTC Offset: 0x8) Current Real-time Value Register --------
+#define AT91C_RTTC_CRTV ((unsigned int) 0x0 << 0) // (RTTC) Current Real-time Value
+// -------- RTTC_RTSR : (RTTC Offset: 0xc) Real-time Status Register --------
+#define AT91C_RTTC_ALMS ((unsigned int) 0x1 << 0) // (RTTC) Real-time Alarm Status
+#define AT91C_RTTC_RTTINC ((unsigned int) 0x1 << 1) // (RTTC) Real-time Timer Increment
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Periodic Interval Timer Controller Interface
+// *****************************************************************************
+typedef struct _AT91S_PITC {
+ AT91_REG PITC_PIMR; // Period Interval Mode Register
+ AT91_REG PITC_PISR; // Period Interval Status Register
+ AT91_REG PITC_PIVR; // Period Interval Value Register
+ AT91_REG PITC_PIIR; // Period Interval Image Register
+} AT91S_PITC, *AT91PS_PITC;
+
+// -------- PITC_PIMR : (PITC Offset: 0x0) Periodic Interval Mode Register --------
+#define AT91C_PITC_PIV ((unsigned int) 0xFFFFF << 0) // (PITC) Periodic Interval Value
+#define AT91C_PITC_PITEN ((unsigned int) 0x1 << 24) // (PITC) Periodic Interval Timer Enabled
+#define AT91C_PITC_PITIEN ((unsigned int) 0x1 << 25) // (PITC) Periodic Interval Timer Interrupt Enable
+// -------- PITC_PISR : (PITC Offset: 0x4) Periodic Interval Status Register --------
+#define AT91C_PITC_PITS ((unsigned int) 0x1 << 0) // (PITC) Periodic Interval Timer Status
+// -------- PITC_PIVR : (PITC Offset: 0x8) Periodic Interval Value Register --------
+#define AT91C_PITC_CPIV ((unsigned int) 0xFFFFF << 0) // (PITC) Current Periodic Interval Value
+#define AT91C_PITC_PICNT ((unsigned int) 0xFFF << 20) // (PITC) Periodic Interval Counter
+// -------- PITC_PIIR : (PITC Offset: 0xc) Periodic Interval Image Register --------
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Watchdog Timer Controller Interface
+// *****************************************************************************
+typedef struct _AT91S_WDTC {
+ AT91_REG WDTC_WDCR; // Watchdog Control Register
+ AT91_REG WDTC_WDMR; // Watchdog Mode Register
+ AT91_REG WDTC_WDSR; // Watchdog Status Register
+} AT91S_WDTC, *AT91PS_WDTC;
+
+// -------- WDTC_WDCR : (WDTC Offset: 0x0) Periodic Interval Image Register --------
+#define AT91C_WDTC_WDRSTT ((unsigned int) 0x1 << 0) // (WDTC) Watchdog Restart
+#define AT91C_WDTC_KEY ((unsigned int) 0xFF << 24) // (WDTC) Watchdog KEY Password
+// -------- WDTC_WDMR : (WDTC Offset: 0x4) Watchdog Mode Register --------
+#define AT91C_WDTC_WDV ((unsigned int) 0xFFF << 0) // (WDTC) Watchdog Timer Restart
+#define AT91C_WDTC_WDFIEN ((unsigned int) 0x1 << 12) // (WDTC) Watchdog Fault Interrupt Enable
+#define AT91C_WDTC_WDRSTEN ((unsigned int) 0x1 << 13) // (WDTC) Watchdog Reset Enable
+#define AT91C_WDTC_WDRPROC ((unsigned int) 0x1 << 14) // (WDTC) Watchdog Timer Restart
+#define AT91C_WDTC_WDDIS ((unsigned int) 0x1 << 15) // (WDTC) Watchdog Disable
+#define AT91C_WDTC_WDD ((unsigned int) 0xFFF << 16) // (WDTC) Watchdog Delta Value
+#define AT91C_WDTC_WDDBGHLT ((unsigned int) 0x1 << 28) // (WDTC) Watchdog Debug Halt
+#define AT91C_WDTC_WDIDLEHLT ((unsigned int) 0x1 << 29) // (WDTC) Watchdog Idle Halt
+// -------- WDTC_WDSR : (WDTC Offset: 0x8) Watchdog Status Register --------
+#define AT91C_WDTC_WDUNF ((unsigned int) 0x1 << 0) // (WDTC) Watchdog Underflow
+#define AT91C_WDTC_WDERR ((unsigned int) 0x1 << 1) // (WDTC) Watchdog Error
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Voltage Regulator Mode Controller Interface
+// *****************************************************************************
+typedef struct _AT91S_VREG {
+ AT91_REG VREG_MR; // Voltage Regulator Mode Register
+} AT91S_VREG, *AT91PS_VREG;
+
+// -------- VREG_MR : (VREG Offset: 0x0) Voltage Regulator Mode Register --------
+#define AT91C_VREG_PSTDBY ((unsigned int) 0x1 << 0) // (VREG) Voltage Regulator Power Standby Mode
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Memory Controller Interface
+// *****************************************************************************
+typedef struct _AT91S_MC {
+ AT91_REG MC_RCR; // MC Remap Control Register
+ AT91_REG MC_ASR; // MC Abort Status Register
+ AT91_REG MC_AASR; // MC Abort Address Status Register
+ AT91_REG Reserved0[21]; //
+ AT91_REG MC_FMR; // MC Flash Mode Register
+ AT91_REG MC_FCR; // MC Flash Command Register
+ AT91_REG MC_FSR; // MC Flash Status Register
+} AT91S_MC, *AT91PS_MC;
+
+// -------- MC_RCR : (MC Offset: 0x0) MC Remap Control Register --------
+#define AT91C_MC_RCB ((unsigned int) 0x1 << 0) // (MC) Remap Command Bit
+// -------- MC_ASR : (MC Offset: 0x4) MC Abort Status Register --------
+#define AT91C_MC_UNDADD ((unsigned int) 0x1 << 0) // (MC) Undefined Addess Abort Status
+#define AT91C_MC_MISADD ((unsigned int) 0x1 << 1) // (MC) Misaligned Addess Abort Status
+#define AT91C_MC_ABTSZ ((unsigned int) 0x3 << 8) // (MC) Abort Size Status
+#define AT91C_MC_ABTSZ_BYTE ((unsigned int) 0x0 << 8) // (MC) Byte
+#define AT91C_MC_ABTSZ_HWORD ((unsigned int) 0x1 << 8) // (MC) Half-word
+#define AT91C_MC_ABTSZ_WORD ((unsigned int) 0x2 << 8) // (MC) Word
+#define AT91C_MC_ABTTYP ((unsigned int) 0x3 << 10) // (MC) Abort Type Status
+#define AT91C_MC_ABTTYP_DATAR ((unsigned int) 0x0 << 10) // (MC) Data Read
+#define AT91C_MC_ABTTYP_DATAW ((unsigned int) 0x1 << 10) // (MC) Data Write
+#define AT91C_MC_ABTTYP_FETCH ((unsigned int) 0x2 << 10) // (MC) Code Fetch
+#define AT91C_MC_MST0 ((unsigned int) 0x1 << 16) // (MC) Master 0 Abort Source
+#define AT91C_MC_MST1 ((unsigned int) 0x1 << 17) // (MC) Master 1 Abort Source
+#define AT91C_MC_SVMST0 ((unsigned int) 0x1 << 24) // (MC) Saved Master 0 Abort Source
+#define AT91C_MC_SVMST1 ((unsigned int) 0x1 << 25) // (MC) Saved Master 1 Abort Source
+// -------- MC_FMR : (MC Offset: 0x60) MC Flash Mode Register --------
+#define AT91C_MC_FRDY ((unsigned int) 0x1 << 0) // (MC) Flash Ready
+#define AT91C_MC_LOCKE ((unsigned int) 0x1 << 2) // (MC) Lock Error
+#define AT91C_MC_PROGE ((unsigned int) 0x1 << 3) // (MC) Programming Error
+#define AT91C_MC_NEBP ((unsigned int) 0x1 << 7) // (MC) No Erase Before Programming
+#define AT91C_MC_FWS ((unsigned int) 0x3 << 8) // (MC) Flash Wait State
+#define AT91C_MC_FWS_0FWS ((unsigned int) 0x0 << 8) // (MC) 1 cycle for Read, 2 for Write operations
+#define AT91C_MC_FWS_1FWS ((unsigned int) 0x1 << 8) // (MC) 2 cycles for Read, 3 for Write operations
+#define AT91C_MC_FWS_2FWS ((unsigned int) 0x2 << 8) // (MC) 3 cycles for Read, 4 for Write operations
+#define AT91C_MC_FWS_3FWS ((unsigned int) 0x3 << 8) // (MC) 4 cycles for Read, 4 for Write operations
+#define AT91C_MC_FMCN ((unsigned int) 0xFF << 16) // (MC) Flash Microsecond Cycle Number
+// -------- MC_FCR : (MC Offset: 0x64) MC Flash Command Register --------
+#define AT91C_MC_FCMD ((unsigned int) 0xF << 0) // (MC) Flash Command
+#define AT91C_MC_FCMD_START_PROG ((unsigned int) 0x1) // (MC) Starts the programming of th epage specified by PAGEN.
+#define AT91C_MC_FCMD_LOCK ((unsigned int) 0x2) // (MC) Starts a lock sequence of the sector defined by the bits 4 to 7 of the field PAGEN.
+#define AT91C_MC_FCMD_PROG_AND_LOCK ((unsigned int) 0x3) // (MC) The lock sequence automatically happens after the programming sequence is completed.
+#define AT91C_MC_FCMD_UNLOCK ((unsigned int) 0x4) // (MC) Starts an unlock sequence of the sector defined by the bits 4 to 7 of the field PAGEN.
+#define AT91C_MC_FCMD_ERASE_ALL ((unsigned int) 0x8) // (MC) Starts the erase of the entire flash.If at least a page is locked, the command is cancelled.
+#define AT91C_MC_FCMD_SET_GP_NVM ((unsigned int) 0xB) // (MC) Set General Purpose NVM bits.
+#define AT91C_MC_FCMD_CLR_GP_NVM ((unsigned int) 0xD) // (MC) Clear General Purpose NVM bits.
+#define AT91C_MC_FCMD_SET_SECURITY ((unsigned int) 0xF) // (MC) Set Security Bit.
+#define AT91C_MC_PAGEN ((unsigned int) 0x3FF << 8) // (MC) Page Number
+#define AT91C_MC_KEY ((unsigned int) 0xFF << 24) // (MC) Writing Protect Key
+// -------- MC_FSR : (MC Offset: 0x68) MC Flash Command Register --------
+#define AT91C_MC_SECURITY ((unsigned int) 0x1 << 4) // (MC) Security Bit Status
+#define AT91C_MC_GPNVM0 ((unsigned int) 0x1 << 8) // (MC) Sector 0 Lock Status
+#define AT91C_MC_GPNVM1 ((unsigned int) 0x1 << 9) // (MC) Sector 1 Lock Status
+#define AT91C_MC_GPNVM2 ((unsigned int) 0x1 << 10) // (MC) Sector 2 Lock Status
+#define AT91C_MC_GPNVM3 ((unsigned int) 0x1 << 11) // (MC) Sector 3 Lock Status
+#define AT91C_MC_GPNVM4 ((unsigned int) 0x1 << 12) // (MC) Sector 4 Lock Status
+#define AT91C_MC_GPNVM5 ((unsigned int) 0x1 << 13) // (MC) Sector 5 Lock Status
+#define AT91C_MC_GPNVM6 ((unsigned int) 0x1 << 14) // (MC) Sector 6 Lock Status
+#define AT91C_MC_GPNVM7 ((unsigned int) 0x1 << 15) // (MC) Sector 7 Lock Status
+#define AT91C_MC_LOCKS0 ((unsigned int) 0x1 << 16) // (MC) Sector 0 Lock Status
+#define AT91C_MC_LOCKS1 ((unsigned int) 0x1 << 17) // (MC) Sector 1 Lock Status
+#define AT91C_MC_LOCKS2 ((unsigned int) 0x1 << 18) // (MC) Sector 2 Lock Status
+#define AT91C_MC_LOCKS3 ((unsigned int) 0x1 << 19) // (MC) Sector 3 Lock Status
+#define AT91C_MC_LOCKS4 ((unsigned int) 0x1 << 20) // (MC) Sector 4 Lock Status
+#define AT91C_MC_LOCKS5 ((unsigned int) 0x1 << 21) // (MC) Sector 5 Lock Status
+#define AT91C_MC_LOCKS6 ((unsigned int) 0x1 << 22) // (MC) Sector 6 Lock Status
+#define AT91C_MC_LOCKS7 ((unsigned int) 0x1 << 23) // (MC) Sector 7 Lock Status
+#define AT91C_MC_LOCKS8 ((unsigned int) 0x1 << 24) // (MC) Sector 8 Lock Status
+#define AT91C_MC_LOCKS9 ((unsigned int) 0x1 << 25) // (MC) Sector 9 Lock Status
+#define AT91C_MC_LOCKS10 ((unsigned int) 0x1 << 26) // (MC) Sector 10 Lock Status
+#define AT91C_MC_LOCKS11 ((unsigned int) 0x1 << 27) // (MC) Sector 11 Lock Status
+#define AT91C_MC_LOCKS12 ((unsigned int) 0x1 << 28) // (MC) Sector 12 Lock Status
+#define AT91C_MC_LOCKS13 ((unsigned int) 0x1 << 29) // (MC) Sector 13 Lock Status
+#define AT91C_MC_LOCKS14 ((unsigned int) 0x1 << 30) // (MC) Sector 14 Lock Status
+#define AT91C_MC_LOCKS15 ((unsigned int) 0x1 << 31) // (MC) Sector 15 Lock Status
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Serial Parallel Interface
+// *****************************************************************************
+typedef struct _AT91S_SPI {
+ AT91_REG SPI_CR; // Control Register
+ AT91_REG SPI_MR; // Mode Register
+ AT91_REG SPI_RDR; // Receive Data Register
+ AT91_REG SPI_TDR; // Transmit Data Register
+ AT91_REG SPI_SR; // Status Register
+ AT91_REG SPI_IER; // Interrupt Enable Register
+ AT91_REG SPI_IDR; // Interrupt Disable Register
+ AT91_REG SPI_IMR; // Interrupt Mask Register
+ AT91_REG Reserved0[4]; //
+ AT91_REG SPI_CSR[4]; // Chip Select Register
+ AT91_REG Reserved1[48]; //
+ AT91_REG SPI_RPR; // Receive Pointer Register
+ AT91_REG SPI_RCR; // Receive Counter Register
+ AT91_REG SPI_TPR; // Transmit Pointer Register
+ AT91_REG SPI_TCR; // Transmit Counter Register
+ AT91_REG SPI_RNPR; // Receive Next Pointer Register
+ AT91_REG SPI_RNCR; // Receive Next Counter Register
+ AT91_REG SPI_TNPR; // Transmit Next Pointer Register
+ AT91_REG SPI_TNCR; // Transmit Next Counter Register
+ AT91_REG SPI_PTCR; // PDC Transfer Control Register
+ AT91_REG SPI_PTSR; // PDC Transfer Status Register
+} AT91S_SPI, *AT91PS_SPI;
+
+// -------- SPI_CR : (SPI Offset: 0x0) SPI Control Register --------
+#define AT91C_SPI_SPIEN ((unsigned int) 0x1 << 0) // (SPI) SPI Enable
+#define AT91C_SPI_SPIDIS ((unsigned int) 0x1 << 1) // (SPI) SPI Disable
+#define AT91C_SPI_SWRST ((unsigned int) 0x1 << 7) // (SPI) SPI Software reset
+#define AT91C_SPI_LASTXFER ((unsigned int) 0x1 << 24) // (SPI) SPI Last Transfer
+// -------- SPI_MR : (SPI Offset: 0x4) SPI Mode Register --------
+#define AT91C_SPI_MSTR ((unsigned int) 0x1 << 0) // (SPI) Master/Slave Mode
+#define AT91C_SPI_PS ((unsigned int) 0x1 << 1) // (SPI) Peripheral Select
+#define AT91C_SPI_PS_FIXED ((unsigned int) 0x0 << 1) // (SPI) Fixed Peripheral Select
+#define AT91C_SPI_PS_VARIABLE ((unsigned int) 0x1 << 1) // (SPI) Variable Peripheral Select
+#define AT91C_SPI_PCSDEC ((unsigned int) 0x1 << 2) // (SPI) Chip Select Decode
+#define AT91C_SPI_FDIV ((unsigned int) 0x1 << 3) // (SPI) Clock Selection
+#define AT91C_SPI_MODFDIS ((unsigned int) 0x1 << 4) // (SPI) Mode Fault Detection
+#define AT91C_SPI_LLB ((unsigned int) 0x1 << 7) // (SPI) Clock Selection
+#define AT91C_SPI_PCS ((unsigned int) 0xF << 16) // (SPI) Peripheral Chip Select
+#define AT91C_SPI_DLYBCS ((unsigned int) 0xFF << 24) // (SPI) Delay Between Chip Selects
+// -------- SPI_RDR : (SPI Offset: 0x8) Receive Data Register --------
+#define AT91C_SPI_RD ((unsigned int) 0xFFFF << 0) // (SPI) Receive Data
+#define AT91C_SPI_RPCS ((unsigned int) 0xF << 16) // (SPI) Peripheral Chip Select Status
+// -------- SPI_TDR : (SPI Offset: 0xc) Transmit Data Register --------
+#define AT91C_SPI_TD ((unsigned int) 0xFFFF << 0) // (SPI) Transmit Data
+#define AT91C_SPI_TPCS ((unsigned int) 0xF << 16) // (SPI) Peripheral Chip Select Status
+// -------- SPI_SR : (SPI Offset: 0x10) Status Register --------
+#define AT91C_SPI_RDRF ((unsigned int) 0x1 << 0) // (SPI) Receive Data Register Full
+#define AT91C_SPI_TDRE ((unsigned int) 0x1 << 1) // (SPI) Transmit Data Register Empty
+#define AT91C_SPI_MODF ((unsigned int) 0x1 << 2) // (SPI) Mode Fault Error
+#define AT91C_SPI_OVRES ((unsigned int) 0x1 << 3) // (SPI) Overrun Error Status
+#define AT91C_SPI_ENDRX ((unsigned int) 0x1 << 4) // (SPI) End of Receiver Transfer
+#define AT91C_SPI_ENDTX ((unsigned int) 0x1 << 5) // (SPI) End of Receiver Transfer
+#define AT91C_SPI_RXBUFF ((unsigned int) 0x1 << 6) // (SPI) RXBUFF Interrupt
+#define AT91C_SPI_TXBUFE ((unsigned int) 0x1 << 7) // (SPI) TXBUFE Interrupt
+#define AT91C_SPI_NSSR ((unsigned int) 0x1 << 8) // (SPI) NSSR Interrupt
+#define AT91C_SPI_TXEMPTY ((unsigned int) 0x1 << 9) // (SPI) TXEMPTY Interrupt
+#define AT91C_SPI_SPIENS ((unsigned int) 0x1 << 16) // (SPI) Enable Status
+// -------- SPI_IER : (SPI Offset: 0x14) Interrupt Enable Register --------
+// -------- SPI_IDR : (SPI Offset: 0x18) Interrupt Disable Register --------
+// -------- SPI_IMR : (SPI Offset: 0x1c) Interrupt Mask Register --------
+// -------- SPI_CSR : (SPI Offset: 0x30) Chip Select Register --------
+#define AT91C_SPI_CPOL ((unsigned int) 0x1 << 0) // (SPI) Clock Polarity
+#define AT91C_SPI_NCPHA ((unsigned int) 0x1 << 1) // (SPI) Clock Phase
+#define AT91C_SPI_CSAAT ((unsigned int) 0x1 << 3) // (SPI) Chip Select Active After Transfer
+#define AT91C_SPI_BITS ((unsigned int) 0xF << 4) // (SPI) Bits Per Transfer
+#define AT91C_SPI_BITS_8 ((unsigned int) 0x0 << 4) // (SPI) 8 Bits Per transfer
+#define AT91C_SPI_BITS_9 ((unsigned int) 0x1 << 4) // (SPI) 9 Bits Per transfer
+#define AT91C_SPI_BITS_10 ((unsigned int) 0x2 << 4) // (SPI) 10 Bits Per transfer
+#define AT91C_SPI_BITS_11 ((unsigned int) 0x3 << 4) // (SPI) 11 Bits Per transfer
+#define AT91C_SPI_BITS_12 ((unsigned int) 0x4 << 4) // (SPI) 12 Bits Per transfer
+#define AT91C_SPI_BITS_13 ((unsigned int) 0x5 << 4) // (SPI) 13 Bits Per transfer
+#define AT91C_SPI_BITS_14 ((unsigned int) 0x6 << 4) // (SPI) 14 Bits Per transfer
+#define AT91C_SPI_BITS_15 ((unsigned int) 0x7 << 4) // (SPI) 15 Bits Per transfer
+#define AT91C_SPI_BITS_16 ((unsigned int) 0x8 << 4) // (SPI) 16 Bits Per transfer
+#define AT91C_SPI_SCBR ((unsigned int) 0xFF << 8) // (SPI) Serial Clock Baud Rate
+#define AT91C_SPI_DLYBS ((unsigned int) 0xFF << 16) // (SPI) Delay Before SPCK
+#define AT91C_SPI_DLYBCT ((unsigned int) 0xFF << 24) // (SPI) Delay Between Consecutive Transfers
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Analog to Digital Convertor
+// *****************************************************************************
+typedef struct _AT91S_ADC {
+ AT91_REG ADC_CR; // ADC Control Register
+ AT91_REG ADC_MR; // ADC Mode Register
+ AT91_REG Reserved0[2]; //
+ AT91_REG ADC_CHER; // ADC Channel Enable Register
+ AT91_REG ADC_CHDR; // ADC Channel Disable Register
+ AT91_REG ADC_CHSR; // ADC Channel Status Register
+ AT91_REG ADC_SR; // ADC Status Register
+ AT91_REG ADC_LCDR; // ADC Last Converted Data Register
+ AT91_REG ADC_IER; // ADC Interrupt Enable Register
+ AT91_REG ADC_IDR; // ADC Interrupt Disable Register
+ AT91_REG ADC_IMR; // ADC Interrupt Mask Register
+ AT91_REG ADC_CDR0; // ADC Channel Data Register 0
+ AT91_REG ADC_CDR1; // ADC Channel Data Register 1
+ AT91_REG ADC_CDR2; // ADC Channel Data Register 2
+ AT91_REG ADC_CDR3; // ADC Channel Data Register 3
+ AT91_REG ADC_CDR4; // ADC Channel Data Register 4
+ AT91_REG ADC_CDR5; // ADC Channel Data Register 5
+ AT91_REG ADC_CDR6; // ADC Channel Data Register 6
+ AT91_REG ADC_CDR7; // ADC Channel Data Register 7
+ AT91_REG Reserved1[44]; //
+ AT91_REG ADC_RPR; // Receive Pointer Register
+ AT91_REG ADC_RCR; // Receive Counter Register
+ AT91_REG ADC_TPR; // Transmit Pointer Register
+ AT91_REG ADC_TCR; // Transmit Counter Register
+ AT91_REG ADC_RNPR; // Receive Next Pointer Register
+ AT91_REG ADC_RNCR; // Receive Next Counter Register
+ AT91_REG ADC_TNPR; // Transmit Next Pointer Register
+ AT91_REG ADC_TNCR; // Transmit Next Counter Register
+ AT91_REG ADC_PTCR; // PDC Transfer Control Register
+ AT91_REG ADC_PTSR; // PDC Transfer Status Register
+} AT91S_ADC, *AT91PS_ADC;
+
+// -------- ADC_CR : (ADC Offset: 0x0) ADC Control Register --------
+#define AT91C_ADC_SWRST ((unsigned int) 0x1 << 0) // (ADC) Software Reset
+#define AT91C_ADC_START ((unsigned int) 0x1 << 1) // (ADC) Start Conversion
+// -------- ADC_MR : (ADC Offset: 0x4) ADC Mode Register --------
+#define AT91C_ADC_TRGEN ((unsigned int) 0x1 << 0) // (ADC) Trigger Enable
+#define AT91C_ADC_TRGEN_DIS ((unsigned int) 0x0) // (ADC) Hradware triggers are disabled. Starting a conversion is only possible by software
+#define AT91C_ADC_TRGEN_EN ((unsigned int) 0x1) // (ADC) Hardware trigger selected by TRGSEL field is enabled.
+#define AT91C_ADC_TRGSEL ((unsigned int) 0x7 << 1) // (ADC) Trigger Selection
+#define AT91C_ADC_TRGSEL_TIOA0 ((unsigned int) 0x0 << 1) // (ADC) Selected TRGSEL = TIAO0
+#define AT91C_ADC_TRGSEL_TIOA1 ((unsigned int) 0x1 << 1) // (ADC) Selected TRGSEL = TIAO1
+#define AT91C_ADC_TRGSEL_TIOA2 ((unsigned int) 0x2 << 1) // (ADC) Selected TRGSEL = TIAO2
+#define AT91C_ADC_TRGSEL_TIOA3 ((unsigned int) 0x3 << 1) // (ADC) Selected TRGSEL = TIAO3
+#define AT91C_ADC_TRGSEL_TIOA4 ((unsigned int) 0x4 << 1) // (ADC) Selected TRGSEL = TIAO4
+#define AT91C_ADC_TRGSEL_TIOA5 ((unsigned int) 0x5 << 1) // (ADC) Selected TRGSEL = TIAO5
+#define AT91C_ADC_TRGSEL_EXT ((unsigned int) 0x6 << 1) // (ADC) Selected TRGSEL = External Trigger
+#define AT91C_ADC_LOWRES ((unsigned int) 0x1 << 4) // (ADC) Resolution.
+#define AT91C_ADC_LOWRES_10_BIT ((unsigned int) 0x0 << 4) // (ADC) 10-bit resolution
+#define AT91C_ADC_LOWRES_8_BIT ((unsigned int) 0x1 << 4) // (ADC) 8-bit resolution
+#define AT91C_ADC_SLEEP ((unsigned int) 0x1 << 5) // (ADC) Sleep Mode
+#define AT91C_ADC_SLEEP_NORMAL_MODE ((unsigned int) 0x0 << 5) // (ADC) Normal Mode
+#define AT91C_ADC_SLEEP_MODE ((unsigned int) 0x1 << 5) // (ADC) Sleep Mode
+#define AT91C_ADC_PRESCAL ((unsigned int) 0x3F << 8) // (ADC) Prescaler rate selection
+#define AT91C_ADC_STARTUP ((unsigned int) 0x1F << 16) // (ADC) Startup Time
+#define AT91C_ADC_SHTIM ((unsigned int) 0xF << 24) // (ADC) Sample & Hold Time
+// -------- ADC_CHER : (ADC Offset: 0x10) ADC Channel Enable Register --------
+#define AT91C_ADC_CH0 ((unsigned int) 0x1 << 0) // (ADC) Channel 0
+#define AT91C_ADC_CH1 ((unsigned int) 0x1 << 1) // (ADC) Channel 1
+#define AT91C_ADC_CH2 ((unsigned int) 0x1 << 2) // (ADC) Channel 2
+#define AT91C_ADC_CH3 ((unsigned int) 0x1 << 3) // (ADC) Channel 3
+#define AT91C_ADC_CH4 ((unsigned int) 0x1 << 4) // (ADC) Channel 4
+#define AT91C_ADC_CH5 ((unsigned int) 0x1 << 5) // (ADC) Channel 5
+#define AT91C_ADC_CH6 ((unsigned int) 0x1 << 6) // (ADC) Channel 6
+#define AT91C_ADC_CH7 ((unsigned int) 0x1 << 7) // (ADC) Channel 7
+// -------- ADC_CHDR : (ADC Offset: 0x14) ADC Channel Disable Register --------
+// -------- ADC_CHSR : (ADC Offset: 0x18) ADC Channel Status Register --------
+// -------- ADC_SR : (ADC Offset: 0x1c) ADC Status Register --------
+#define AT91C_ADC_EOC0 ((unsigned int) 0x1 << 0) // (ADC) End of Conversion
+#define AT91C_ADC_EOC1 ((unsigned int) 0x1 << 1) // (ADC) End of Conversion
+#define AT91C_ADC_EOC2 ((unsigned int) 0x1 << 2) // (ADC) End of Conversion
+#define AT91C_ADC_EOC3 ((unsigned int) 0x1 << 3) // (ADC) End of Conversion
+#define AT91C_ADC_EOC4 ((unsigned int) 0x1 << 4) // (ADC) End of Conversion
+#define AT91C_ADC_EOC5 ((unsigned int) 0x1 << 5) // (ADC) End of Conversion
+#define AT91C_ADC_EOC6 ((unsigned int) 0x1 << 6) // (ADC) End of Conversion
+#define AT91C_ADC_EOC7 ((unsigned int) 0x1 << 7) // (ADC) End of Conversion
+#define AT91C_ADC_OVRE0 ((unsigned int) 0x1 << 8) // (ADC) Overrun Error
+#define AT91C_ADC_OVRE1 ((unsigned int) 0x1 << 9) // (ADC) Overrun Error
+#define AT91C_ADC_OVRE2 ((unsigned int) 0x1 << 10) // (ADC) Overrun Error
+#define AT91C_ADC_OVRE3 ((unsigned int) 0x1 << 11) // (ADC) Overrun Error
+#define AT91C_ADC_OVRE4 ((unsigned int) 0x1 << 12) // (ADC) Overrun Error
+#define AT91C_ADC_OVRE5 ((unsigned int) 0x1 << 13) // (ADC) Overrun Error
+#define AT91C_ADC_OVRE6 ((unsigned int) 0x1 << 14) // (ADC) Overrun Error
+#define AT91C_ADC_OVRE7 ((unsigned int) 0x1 << 15) // (ADC) Overrun Error
+#define AT91C_ADC_DRDY ((unsigned int) 0x1 << 16) // (ADC) Data Ready
+#define AT91C_ADC_GOVRE ((unsigned int) 0x1 << 17) // (ADC) General Overrun
+#define AT91C_ADC_ENDRX ((unsigned int) 0x1 << 18) // (ADC) End of Receiver Transfer
+#define AT91C_ADC_RXBUFF ((unsigned int) 0x1 << 19) // (ADC) RXBUFF Interrupt
+// -------- ADC_LCDR : (ADC Offset: 0x20) ADC Last Converted Data Register --------
+#define AT91C_ADC_LDATA ((unsigned int) 0x3FF << 0) // (ADC) Last Data Converted
+// -------- ADC_IER : (ADC Offset: 0x24) ADC Interrupt Enable Register --------
+// -------- ADC_IDR : (ADC Offset: 0x28) ADC Interrupt Disable Register --------
+// -------- ADC_IMR : (ADC Offset: 0x2c) ADC Interrupt Mask Register --------
+// -------- ADC_CDR0 : (ADC Offset: 0x30) ADC Channel Data Register 0 --------
+#define AT91C_ADC_DATA ((unsigned int) 0x3FF << 0) // (ADC) Converted Data
+// -------- ADC_CDR1 : (ADC Offset: 0x34) ADC Channel Data Register 1 --------
+// -------- ADC_CDR2 : (ADC Offset: 0x38) ADC Channel Data Register 2 --------
+// -------- ADC_CDR3 : (ADC Offset: 0x3c) ADC Channel Data Register 3 --------
+// -------- ADC_CDR4 : (ADC Offset: 0x40) ADC Channel Data Register 4 --------
+// -------- ADC_CDR5 : (ADC Offset: 0x44) ADC Channel Data Register 5 --------
+// -------- ADC_CDR6 : (ADC Offset: 0x48) ADC Channel Data Register 6 --------
+// -------- ADC_CDR7 : (ADC Offset: 0x4c) ADC Channel Data Register 7 --------
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Synchronous Serial Controller Interface
+// *****************************************************************************
+typedef struct _AT91S_SSC {
+ AT91_REG SSC_CR; // Control Register
+ AT91_REG SSC_CMR; // Clock Mode Register
+ AT91_REG Reserved0[2]; //
+ AT91_REG SSC_RCMR; // Receive Clock ModeRegister
+ AT91_REG SSC_RFMR; // Receive Frame Mode Register
+ AT91_REG SSC_TCMR; // Transmit Clock Mode Register
+ AT91_REG SSC_TFMR; // Transmit Frame Mode Register
+ AT91_REG SSC_RHR; // Receive Holding Register
+ AT91_REG SSC_THR; // Transmit Holding Register
+ AT91_REG Reserved1[2]; //
+ AT91_REG SSC_RSHR; // Receive Sync Holding Register
+ AT91_REG SSC_TSHR; // Transmit Sync Holding Register
+ AT91_REG SSC_RC0R; // Receive Compare 0 Register
+ AT91_REG SSC_RC1R; // Receive Compare 1 Register
+ AT91_REG SSC_SR; // Status Register
+ AT91_REG SSC_IER; // Interrupt Enable Register
+ AT91_REG SSC_IDR; // Interrupt Disable Register
+ AT91_REG SSC_IMR; // Interrupt Mask Register
+ AT91_REG Reserved3[44]; //
+ AT91_REG SSC_RPR; // Receive Pointer Register
+ AT91_REG SSC_RCR; // Receive Counter Register
+ AT91_REG SSC_TPR; // Transmit Pointer Register
+ AT91_REG SSC_TCR; // Transmit Counter Register
+ AT91_REG SSC_RNPR; // Receive Next Pointer Register
+ AT91_REG SSC_RNCR; // Receive Next Counter Register
+ AT91_REG SSC_TNPR; // Transmit Next Pointer Register
+ AT91_REG SSC_TNCR; // Transmit Next Counter Register
+ AT91_REG SSC_PTCR; // PDC Transfer Control Register
+ AT91_REG SSC_PTSR; // PDC Transfer Status Register
+} AT91S_SSC, *AT91PS_SSC;
+
+// -------- SSC_CR : (SSC Offset: 0x0) SSC Control Register --------
+#define AT91C_SSC_RXEN ((unsigned int) 0x1 << 0) // (SSC) Receive Enable
+#define AT91C_SSC_RXDIS ((unsigned int) 0x1 << 1) // (SSC) Receive Disable
+#define AT91C_SSC_TXEN ((unsigned int) 0x1 << 8) // (SSC) Transmit Enable
+#define AT91C_SSC_TXDIS ((unsigned int) 0x1 << 9) // (SSC) Transmit Disable
+#define AT91C_SSC_SWRST ((unsigned int) 0x1 << 15) // (SSC) Software Reset
+// -------- SSC_RCMR : (SSC Offset: 0x10) SSC Receive Clock Mode Register --------
+#define AT91C_SSC_CKS ((unsigned int) 0x3 << 0) // (SSC) Receive/Transmit Clock Selection
+#define AT91C_SSC_CKS_DIV ((unsigned int) 0x0) // (SSC) Divided Clock
+#define AT91C_SSC_CKS_TK ((unsigned int) 0x1) // (SSC) TK Clock signal
+#define AT91C_SSC_CKS_RK ((unsigned int) 0x2) // (SSC) RK pin
+#define AT91C_SSC_CKO ((unsigned int) 0x7 << 2) // (SSC) Receive/Transmit Clock Output Mode Selection
+#define AT91C_SSC_CKO_NONE ((unsigned int) 0x0 << 2) // (SSC) Receive/Transmit Clock Output Mode: None RK pin: Input-only
+#define AT91C_SSC_CKO_CONTINOUS ((unsigned int) 0x1 << 2) // (SSC) Continuous Receive/Transmit Clock RK pin: Output
+#define AT91C_SSC_CKO_DATA_TX ((unsigned int) 0x2 << 2) // (SSC) Receive/Transmit Clock only during data transfers RK pin: Output
+#define AT91C_SSC_CKI ((unsigned int) 0x1 << 5) // (SSC) Receive/Transmit Clock Inversion
+#define AT91C_SSC_START ((unsigned int) 0xF << 8) // (SSC) Receive/Transmit Start Selection
+#define AT91C_SSC_START_CONTINOUS ((unsigned int) 0x0 << 8) // (SSC) Continuous, as soon as the receiver is enabled, and immediately after the end of transfer of the previous data.
+#define AT91C_SSC_START_TX ((unsigned int) 0x1 << 8) // (SSC) Transmit/Receive start
+#define AT91C_SSC_START_LOW_RF ((unsigned int) 0x2 << 8) // (SSC) Detection of a low level on RF input
+#define AT91C_SSC_START_HIGH_RF ((unsigned int) 0x3 << 8) // (SSC) Detection of a high level on RF input
+#define AT91C_SSC_START_FALL_RF ((unsigned int) 0x4 << 8) // (SSC) Detection of a falling edge on RF input
+#define AT91C_SSC_START_RISE_RF ((unsigned int) 0x5 << 8) // (SSC) Detection of a rising edge on RF input
+#define AT91C_SSC_START_LEVEL_RF ((unsigned int) 0x6 << 8) // (SSC) Detection of any level change on RF input
+#define AT91C_SSC_START_EDGE_RF ((unsigned int) 0x7 << 8) // (SSC) Detection of any edge on RF input
+#define AT91C_SSC_START_0 ((unsigned int) 0x8 << 8) // (SSC) Compare 0
+#define AT91C_SSC_STTDLY ((unsigned int) 0xFF << 16) // (SSC) Receive/Transmit Start Delay
+#define AT91C_SSC_PERIOD ((unsigned int) 0xFF << 24) // (SSC) Receive/Transmit Period Divider Selection
+// -------- SSC_RFMR : (SSC Offset: 0x14) SSC Receive Frame Mode Register --------
+#define AT91C_SSC_DATLEN ((unsigned int) 0x1F << 0) // (SSC) Data Length
+#define AT91C_SSC_LOOP ((unsigned int) 0x1 << 5) // (SSC) Loop Mode
+#define AT91C_SSC_MSBF ((unsigned int) 0x1 << 7) // (SSC) Most Significant Bit First
+#define AT91C_SSC_DATNB ((unsigned int) 0xF << 8) // (SSC) Data Number per Frame
+#define AT91C_SSC_FSLEN ((unsigned int) 0xF << 16) // (SSC) Receive/Transmit Frame Sync length
+#define AT91C_SSC_FSOS ((unsigned int) 0x7 << 20) // (SSC) Receive/Transmit Frame Sync Output Selection
+#define AT91C_SSC_FSOS_NONE ((unsigned int) 0x0 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: None RK pin Input-only
+#define AT91C_SSC_FSOS_NEGATIVE ((unsigned int) 0x1 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Negative Pulse
+#define AT91C_SSC_FSOS_POSITIVE ((unsigned int) 0x2 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Positive Pulse
+#define AT91C_SSC_FSOS_LOW ((unsigned int) 0x3 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Driver Low during data transfer
+#define AT91C_SSC_FSOS_HIGH ((unsigned int) 0x4 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Driver High during data transfer
+#define AT91C_SSC_FSOS_TOGGLE ((unsigned int) 0x5 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Toggling at each start of data transfer
+#define AT91C_SSC_FSEDGE ((unsigned int) 0x1 << 24) // (SSC) Frame Sync Edge Detection
+// -------- SSC_TCMR : (SSC Offset: 0x18) SSC Transmit Clock Mode Register --------
+// -------- SSC_TFMR : (SSC Offset: 0x1c) SSC Transmit Frame Mode Register --------
+#define AT91C_SSC_DATDEF ((unsigned int) 0x1 << 5) // (SSC) Data Default Value
+#define AT91C_SSC_MSBF ((unsigned int) 0x1 << 7) // (SSC) MSB First
+#define AT91C_SSC_FSDEN ((unsigned int) 0x1 << 23) // (SSC) Frame Sync Data Enable
+// -------- SSC_SR : (SSC Offset: 0x40) SSC Status Register --------
+#define AT91C_SSC_TXRDY ((unsigned int) 0x1 << 0) // (SSC) Transmit Ready
+#define AT91C_SSC_TXEMPTY ((unsigned int) 0x1 << 1) // (SSC) Transmit Empty
+#define AT91C_SSC_ENDTX ((unsigned int) 0x1 << 2) // (SSC) End Of Transmission
+#define AT91C_SSC_TXBUFE ((unsigned int) 0x1 << 3) // (SSC) Transmit Buffer Empty
+#define AT91C_SSC_RXRDY ((unsigned int) 0x1 << 4) // (SSC) Receive Ready
+#define AT91C_SSC_OVRUN ((unsigned int) 0x1 << 5) // (SSC) Receive Overrun
+#define AT91C_SSC_ENDRX ((unsigned int) 0x1 << 6) // (SSC) End of Reception
+#define AT91C_SSC_RXBUFF ((unsigned int) 0x1 << 7) // (SSC) Receive Buffer Full
+#define AT91C_SSC_CP0 ((unsigned int) 0x1 << 8) // (SSC) Compare 0
+#define AT91C_SSC_CP1 ((unsigned int) 0x1 << 9) // (SSC) Compare 1
+#define AT91C_SSC_TXSYN ((unsigned int) 0x1 << 10) // (SSC) Transmit Sync
+#define AT91C_SSC_RXSYN ((unsigned int) 0x1 << 11) // (SSC) Receive Sync
+#define AT91C_SSC_TXENA ((unsigned int) 0x1 << 16) // (SSC) Transmit Enable
+#define AT91C_SSC_RXENA ((unsigned int) 0x1 << 17) // (SSC) Receive Enable
+// -------- SSC_IER : (SSC Offset: 0x44) SSC Interrupt Enable Register --------
+// -------- SSC_IDR : (SSC Offset: 0x48) SSC Interrupt Disable Register --------
+// -------- SSC_IMR : (SSC Offset: 0x4c) SSC Interrupt Mask Register --------
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Usart
+// *****************************************************************************
+typedef struct _AT91S_USART {
+ AT91_REG US_CR; // Control Register
+ AT91_REG US_MR; // Mode Register
+ AT91_REG US_IER; // Interrupt Enable Register
+ AT91_REG US_IDR; // Interrupt Disable Register
+ AT91_REG US_IMR; // Interrupt Mask Register
+ AT91_REG US_CSR; // Channel Status Register
+ AT91_REG US_RHR; // Receiver Holding Register
+ AT91_REG US_THR; // Transmitter Holding Register
+ AT91_REG US_BRGR; // Baud Rate Generator Register
+ AT91_REG US_RTOR; // Receiver Time-out Register
+ AT91_REG US_TTGR; // Transmitter Time-guard Register
+ AT91_REG Reserved0[5]; //
+ AT91_REG US_FIDI; // FI_DI_Ratio Register
+ AT91_REG US_NER; // Nb Errors Register
+ AT91_REG Reserved1[1]; //
+ AT91_REG US_IF; // IRDA_FILTER Register
+ AT91_REG Reserved2[44]; //
+ AT91_REG US_RPR; // Receive Pointer Register
+ AT91_REG US_RCR; // Receive Counter Register
+ AT91_REG US_TPR; // Transmit Pointer Register
+ AT91_REG US_TCR; // Transmit Counter Register
+ AT91_REG US_RNPR; // Receive Next Pointer Register
+ AT91_REG US_RNCR; // Receive Next Counter Register
+ AT91_REG US_TNPR; // Transmit Next Pointer Register
+ AT91_REG US_TNCR; // Transmit Next Counter Register
+ AT91_REG US_PTCR; // PDC Transfer Control Register
+ AT91_REG US_PTSR; // PDC Transfer Status Register
+} AT91S_USART, *AT91PS_USART;
+
+// -------- US_CR : (USART Offset: 0x0) Debug Unit Control Register --------
+#define AT91C_US_STTBRK ((unsigned int) 0x1 << 9) // (USART) Start Break
+#define AT91C_US_STPBRK ((unsigned int) 0x1 << 10) // (USART) Stop Break
+#define AT91C_US_STTTO ((unsigned int) 0x1 << 11) // (USART) Start Time-out
+#define AT91C_US_SENDA ((unsigned int) 0x1 << 12) // (USART) Send Address
+#define AT91C_US_RSTIT ((unsigned int) 0x1 << 13) // (USART) Reset Iterations
+#define AT91C_US_RSTNACK ((unsigned int) 0x1 << 14) // (USART) Reset Non Acknowledge
+#define AT91C_US_RETTO ((unsigned int) 0x1 << 15) // (USART) Rearm Time-out
+#define AT91C_US_DTREN ((unsigned int) 0x1 << 16) // (USART) Data Terminal ready Enable
+#define AT91C_US_DTRDIS ((unsigned int) 0x1 << 17) // (USART) Data Terminal ready Disable
+#define AT91C_US_RTSEN ((unsigned int) 0x1 << 18) // (USART) Request to Send enable
+#define AT91C_US_RTSDIS ((unsigned int) 0x1 << 19) // (USART) Request to Send Disable
+// -------- US_MR : (USART Offset: 0x4) Debug Unit Mode Register --------
+#define AT91C_US_USMODE ((unsigned int) 0xF << 0) // (USART) Usart mode
+#define AT91C_US_USMODE_NORMAL ((unsigned int) 0x0) // (USART) Normal
+#define AT91C_US_USMODE_RS485 ((unsigned int) 0x1) // (USART) RS485
+#define AT91C_US_USMODE_HWHSH ((unsigned int) 0x2) // (USART) Hardware Handshaking
+#define AT91C_US_USMODE_MODEM ((unsigned int) 0x3) // (USART) Modem
+#define AT91C_US_USMODE_ISO7816_0 ((unsigned int) 0x4) // (USART) ISO7816 protocol: T = 0
+#define AT91C_US_USMODE_ISO7816_1 ((unsigned int) 0x6) // (USART) ISO7816 protocol: T = 1
+#define AT91C_US_USMODE_IRDA ((unsigned int) 0x8) // (USART) IrDA
+#define AT91C_US_USMODE_SWHSH ((unsigned int) 0xC) // (USART) Software Handshaking
+#define AT91C_US_CLKS ((unsigned int) 0x3 << 4) // (USART) Clock Selection (Baud Rate generator Input Clock
+#define AT91C_US_CLKS_CLOCK ((unsigned int) 0x0 << 4) // (USART) Clock
+#define AT91C_US_CLKS_FDIV1 ((unsigned int) 0x1 << 4) // (USART) fdiv1
+#define AT91C_US_CLKS_SLOW ((unsigned int) 0x2 << 4) // (USART) slow_clock (ARM)
+#define AT91C_US_CLKS_EXT ((unsigned int) 0x3 << 4) // (USART) External (SCK)
+#define AT91C_US_CHRL ((unsigned int) 0x3 << 6) // (USART) Clock Selection (Baud Rate generator Input Clock
+#define AT91C_US_CHRL_5_BITS ((unsigned int) 0x0 << 6) // (USART) Character Length: 5 bits
+#define AT91C_US_CHRL_6_BITS ((unsigned int) 0x1 << 6) // (USART) Character Length: 6 bits
+#define AT91C_US_CHRL_7_BITS ((unsigned int) 0x2 << 6) // (USART) Character Length: 7 bits
+#define AT91C_US_CHRL_8_BITS ((unsigned int) 0x3 << 6) // (USART) Character Length: 8 bits
+#define AT91C_US_SYNC ((unsigned int) 0x1 << 8) // (USART) Synchronous Mode Select
+#define AT91C_US_NBSTOP ((unsigned int) 0x3 << 12) // (USART) Number of Stop bits
+#define AT91C_US_NBSTOP_1_BIT ((unsigned int) 0x0 << 12) // (USART) 1 stop bit
+#define AT91C_US_NBSTOP_15_BIT ((unsigned int) 0x1 << 12) // (USART) Asynchronous (SYNC=0) 2 stop bits Synchronous (SYNC=1) 2 stop bits
+#define AT91C_US_NBSTOP_2_BIT ((unsigned int) 0x2 << 12) // (USART) 2 stop bits
+#define AT91C_US_MSBF ((unsigned int) 0x1 << 16) // (USART) Bit Order
+#define AT91C_US_MODE9 ((unsigned int) 0x1 << 17) // (USART) 9-bit Character length
+#define AT91C_US_CKLO ((unsigned int) 0x1 << 18) // (USART) Clock Output Select
+#define AT91C_US_OVER ((unsigned int) 0x1 << 19) // (USART) Over Sampling Mode
+#define AT91C_US_INACK ((unsigned int) 0x1 << 20) // (USART) Inhibit Non Acknowledge
+#define AT91C_US_DSNACK ((unsigned int) 0x1 << 21) // (USART) Disable Successive NACK
+#define AT91C_US_MAX_ITER ((unsigned int) 0x1 << 24) // (USART) Number of Repetitions
+#define AT91C_US_FILTER ((unsigned int) 0x1 << 28) // (USART) Receive Line Filter
+// -------- US_IER : (USART Offset: 0x8) Debug Unit Interrupt Enable Register --------
+#define AT91C_US_RXBRK ((unsigned int) 0x1 << 2) // (USART) Break Received/End of Break
+#define AT91C_US_TIMEOUT ((unsigned int) 0x1 << 8) // (USART) Receiver Time-out
+#define AT91C_US_ITERATION ((unsigned int) 0x1 << 10) // (USART) Max number of Repetitions Reached
+#define AT91C_US_NACK ((unsigned int) 0x1 << 13) // (USART) Non Acknowledge
+#define AT91C_US_RIIC ((unsigned int) 0x1 << 16) // (USART) Ring INdicator Input Change Flag
+#define AT91C_US_DSRIC ((unsigned int) 0x1 << 17) // (USART) Data Set Ready Input Change Flag
+#define AT91C_US_DCDIC ((unsigned int) 0x1 << 18) // (USART) Data Carrier Flag
+#define AT91C_US_CTSIC ((unsigned int) 0x1 << 19) // (USART) Clear To Send Input Change Flag
+// -------- US_IDR : (USART Offset: 0xc) Debug Unit Interrupt Disable Register --------
+// -------- US_IMR : (USART Offset: 0x10) Debug Unit Interrupt Mask Register --------
+// -------- US_CSR : (USART Offset: 0x14) Debug Unit Channel Status Register --------
+#define AT91C_US_RI ((unsigned int) 0x1 << 20) // (USART) Image of RI Input
+#define AT91C_US_DSR ((unsigned int) 0x1 << 21) // (USART) Image of DSR Input
+#define AT91C_US_DCD ((unsigned int) 0x1 << 22) // (USART) Image of DCD Input
+#define AT91C_US_CTS ((unsigned int) 0x1 << 23) // (USART) Image of CTS Input
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Two-wire Interface
+// *****************************************************************************
+typedef struct _AT91S_TWI {
+ AT91_REG TWI_CR; // Control Register
+ AT91_REG TWI_MMR; // Master Mode Register
+ AT91_REG Reserved0[1]; //
+ AT91_REG TWI_IADR; // Internal Address Register
+ AT91_REG TWI_CWGR; // Clock Waveform Generator Register
+ AT91_REG Reserved1[3]; //
+ AT91_REG TWI_SR; // Status Register
+ AT91_REG TWI_IER; // Interrupt Enable Register
+ AT91_REG TWI_IDR; // Interrupt Disable Register
+ AT91_REG TWI_IMR; // Interrupt Mask Register
+ AT91_REG TWI_RHR; // Receive Holding Register
+ AT91_REG TWI_THR; // Transmit Holding Register
+} AT91S_TWI, *AT91PS_TWI;
+
+// -------- TWI_CR : (TWI Offset: 0x0) TWI Control Register --------
+#define AT91C_TWI_START ((unsigned int) 0x1 << 0) // (TWI) Send a START Condition
+#define AT91C_TWI_STOP ((unsigned int) 0x1 << 1) // (TWI) Send a STOP Condition
+#define AT91C_TWI_MSEN ((unsigned int) 0x1 << 2) // (TWI) TWI Master Transfer Enabled
+#define AT91C_TWI_MSDIS ((unsigned int) 0x1 << 3) // (TWI) TWI Master Transfer Disabled
+#define AT91C_TWI_SWRST ((unsigned int) 0x1 << 7) // (TWI) Software Reset
+// -------- TWI_MMR : (TWI Offset: 0x4) TWI Master Mode Register --------
+#define AT91C_TWI_IADRSZ ((unsigned int) 0x3 << 8) // (TWI) Internal Device Address Size
+#define AT91C_TWI_IADRSZ_NO ((unsigned int) 0x0 << 8) // (TWI) No internal device address
+#define AT91C_TWI_IADRSZ_1_BYTE ((unsigned int) 0x1 << 8) // (TWI) One-byte internal device address
+#define AT91C_TWI_IADRSZ_2_BYTE ((unsigned int) 0x2 << 8) // (TWI) Two-byte internal device address
+#define AT91C_TWI_IADRSZ_3_BYTE ((unsigned int) 0x3 << 8) // (TWI) Three-byte internal device address
+#define AT91C_TWI_MREAD ((unsigned int) 0x1 << 12) // (TWI) Master Read Direction
+#define AT91C_TWI_DADR ((unsigned int) 0x7F << 16) // (TWI) Device Address
+// -------- TWI_CWGR : (TWI Offset: 0x10) TWI Clock Waveform Generator Register --------
+#define AT91C_TWI_CLDIV ((unsigned int) 0xFF << 0) // (TWI) Clock Low Divider
+#define AT91C_TWI_CHDIV ((unsigned int) 0xFF << 8) // (TWI) Clock High Divider
+#define AT91C_TWI_CKDIV ((unsigned int) 0x7 << 16) // (TWI) Clock Divider
+// -------- TWI_SR : (TWI Offset: 0x20) TWI Status Register --------
+#define AT91C_TWI_TXCOMP ((unsigned int) 0x1 << 0) // (TWI) Transmission Completed
+#define AT91C_TWI_RXRDY ((unsigned int) 0x1 << 1) // (TWI) Receive holding register ReaDY
+#define AT91C_TWI_TXRDY ((unsigned int) 0x1 << 2) // (TWI) Transmit holding register ReaDY
+#define AT91C_TWI_OVRE ((unsigned int) 0x1 << 6) // (TWI) Overrun Error
+#define AT91C_TWI_UNRE ((unsigned int) 0x1 << 7) // (TWI) Underrun Error
+#define AT91C_TWI_NACK ((unsigned int) 0x1 << 8) // (TWI) Not Acknowledged
+// -------- TWI_IER : (TWI Offset: 0x24) TWI Interrupt Enable Register --------
+// -------- TWI_IDR : (TWI Offset: 0x28) TWI Interrupt Disable Register --------
+// -------- TWI_IMR : (TWI Offset: 0x2c) TWI Interrupt Mask Register --------
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Timer Counter Channel Interface
+// *****************************************************************************
+typedef struct _AT91S_TC {
+ AT91_REG TC_CCR; // Channel Control Register
+ AT91_REG TC_CMR; // Channel Mode Register (Capture Mode / Waveform Mode)
+ AT91_REG Reserved0[2]; //
+ AT91_REG TC_CV; // Counter Value
+ AT91_REG TC_RA; // Register A
+ AT91_REG TC_RB; // Register B
+ AT91_REG TC_RC; // Register C
+ AT91_REG TC_SR; // Status Register
+ AT91_REG TC_IER; // Interrupt Enable Register
+ AT91_REG TC_IDR; // Interrupt Disable Register
+ AT91_REG TC_IMR; // Interrupt Mask Register
+} AT91S_TC, *AT91PS_TC;
+
+// -------- TC_CCR : (TC Offset: 0x0) TC Channel Control Register --------
+#define AT91C_TC_CLKEN ((unsigned int) 0x1 << 0) // (TC) Counter Clock Enable Command
+#define AT91C_TC_CLKDIS ((unsigned int) 0x1 << 1) // (TC) Counter Clock Disable Command
+#define AT91C_TC_SWTRG ((unsigned int) 0x1 << 2) // (TC) Software Trigger Command
+// -------- TC_CMR : (TC Offset: 0x4) TC Channel Mode Register: Capture Mode / Waveform Mode --------
+#define AT91C_TC_CLKS ((unsigned int) 0x7 << 0) // (TC) Clock Selection
+#define AT91C_TC_CLKS_TIMER_DIV1_CLOCK ((unsigned int) 0x0) // (TC) Clock selected: TIMER_DIV1_CLOCK
+#define AT91C_TC_CLKS_TIMER_DIV2_CLOCK ((unsigned int) 0x1) // (TC) Clock selected: TIMER_DIV2_CLOCK
+#define AT91C_TC_CLKS_TIMER_DIV3_CLOCK ((unsigned int) 0x2) // (TC) Clock selected: TIMER_DIV3_CLOCK
+#define AT91C_TC_CLKS_TIMER_DIV4_CLOCK ((unsigned int) 0x3) // (TC) Clock selected: TIMER_DIV4_CLOCK
+#define AT91C_TC_CLKS_TIMER_DIV5_CLOCK ((unsigned int) 0x4) // (TC) Clock selected: TIMER_DIV5_CLOCK
+#define AT91C_TC_CLKS_XC0 ((unsigned int) 0x5) // (TC) Clock selected: XC0
+#define AT91C_TC_CLKS_XC1 ((unsigned int) 0x6) // (TC) Clock selected: XC1
+#define AT91C_TC_CLKS_XC2 ((unsigned int) 0x7) // (TC) Clock selected: XC2
+#define AT91C_TC_CLKI ((unsigned int) 0x1 << 3) // (TC) Clock Invert
+#define AT91C_TC_BURST ((unsigned int) 0x3 << 4) // (TC) Burst Signal Selection
+#define AT91C_TC_BURST_NONE ((unsigned int) 0x0 << 4) // (TC) The clock is not gated by an external signal
+#define AT91C_TC_BURST_XC0 ((unsigned int) 0x1 << 4) // (TC) XC0 is ANDed with the selected clock
+#define AT91C_TC_BURST_XC1 ((unsigned int) 0x2 << 4) // (TC) XC1 is ANDed with the selected clock
+#define AT91C_TC_BURST_XC2 ((unsigned int) 0x3 << 4) // (TC) XC2 is ANDed with the selected clock
+#define AT91C_TC_CPCSTOP ((unsigned int) 0x1 << 6) // (TC) Counter Clock Stopped with RC Compare
+#define AT91C_TC_LDBSTOP ((unsigned int) 0x1 << 6) // (TC) Counter Clock Stopped with RB Loading
+#define AT91C_TC_CPCDIS ((unsigned int) 0x1 << 7) // (TC) Counter Clock Disable with RC Compare
+#define AT91C_TC_LDBDIS ((unsigned int) 0x1 << 7) // (TC) Counter Clock Disabled with RB Loading
+#define AT91C_TC_ETRGEDG ((unsigned int) 0x3 << 8) // (TC) External Trigger Edge Selection
+#define AT91C_TC_ETRGEDG_NONE ((unsigned int) 0x0 << 8) // (TC) Edge: None
+#define AT91C_TC_ETRGEDG_RISING ((unsigned int) 0x1 << 8) // (TC) Edge: rising edge
+#define AT91C_TC_ETRGEDG_FALLING ((unsigned int) 0x2 << 8) // (TC) Edge: falling edge
+#define AT91C_TC_ETRGEDG_BOTH ((unsigned int) 0x3 << 8) // (TC) Edge: each edge
+#define AT91C_TC_EEVTEDG ((unsigned int) 0x3 << 8) // (TC) External Event Edge Selection
+#define AT91C_TC_EEVTEDG_NONE ((unsigned int) 0x0 << 8) // (TC) Edge: None
+#define AT91C_TC_EEVTEDG_RISING ((unsigned int) 0x1 << 8) // (TC) Edge: rising edge
+#define AT91C_TC_EEVTEDG_FALLING ((unsigned int) 0x2 << 8) // (TC) Edge: falling edge
+#define AT91C_TC_EEVTEDG_BOTH ((unsigned int) 0x3 << 8) // (TC) Edge: each edge
+#define AT91C_TC_EEVT ((unsigned int) 0x3 << 10) // (TC) External Event Selection
+#define AT91C_TC_EEVT_TIOB ((unsigned int) 0x0 << 10) // (TC) Signal selected as external event: TIOB TIOB direction: input
+#define AT91C_TC_EEVT_XC0 ((unsigned int) 0x1 << 10) // (TC) Signal selected as external event: XC0 TIOB direction: output
+#define AT91C_TC_EEVT_XC1 ((unsigned int) 0x2 << 10) // (TC) Signal selected as external event: XC1 TIOB direction: output
+#define AT91C_TC_EEVT_XC2 ((unsigned int) 0x3 << 10) // (TC) Signal selected as external event: XC2 TIOB direction: output
+#define AT91C_TC_ABETRG ((unsigned int) 0x1 << 10) // (TC) TIOA or TIOB External Trigger Selection
+#define AT91C_TC_ENETRG ((unsigned int) 0x1 << 12) // (TC) External Event Trigger enable
+#define AT91C_TC_WAVESEL ((unsigned int) 0x3 << 13) // (TC) Waveform Selection
+#define AT91C_TC_WAVESEL_UP ((unsigned int) 0x0 << 13) // (TC) UP mode without atomatic trigger on RC Compare
+#define AT91C_TC_WAVESEL_UPDOWN ((unsigned int) 0x1 << 13) // (TC) UPDOWN mode without automatic trigger on RC Compare
+#define AT91C_TC_WAVESEL_UP_AUTO ((unsigned int) 0x2 << 13) // (TC) UP mode with automatic trigger on RC Compare
+#define AT91C_TC_WAVESEL_UPDOWN_AUTO ((unsigned int) 0x3 << 13) // (TC) UPDOWN mode with automatic trigger on RC Compare
+#define AT91C_TC_CPCTRG ((unsigned int) 0x1 << 14) // (TC) RC Compare Trigger Enable
+#define AT91C_TC_WAVE ((unsigned int) 0x1 << 15) // (TC)
+#define AT91C_TC_ACPA ((unsigned int) 0x3 << 16) // (TC) RA Compare Effect on TIOA
+#define AT91C_TC_ACPA_NONE ((unsigned int) 0x0 << 16) // (TC) Effect: none
+#define AT91C_TC_ACPA_SET ((unsigned int) 0x1 << 16) // (TC) Effect: set
+#define AT91C_TC_ACPA_CLEAR ((unsigned int) 0x2 << 16) // (TC) Effect: clear
+#define AT91C_TC_ACPA_TOGGLE ((unsigned int) 0x3 << 16) // (TC) Effect: toggle
+#define AT91C_TC_LDRA ((unsigned int) 0x3 << 16) // (TC) RA Loading Selection
+#define AT91C_TC_LDRA_NONE ((unsigned int) 0x0 << 16) // (TC) Edge: None
+#define AT91C_TC_LDRA_RISING ((unsigned int) 0x1 << 16) // (TC) Edge: rising edge of TIOA
+#define AT91C_TC_LDRA_FALLING ((unsigned int) 0x2 << 16) // (TC) Edge: falling edge of TIOA
+#define AT91C_TC_LDRA_BOTH ((unsigned int) 0x3 << 16) // (TC) Edge: each edge of TIOA
+#define AT91C_TC_ACPC ((unsigned int) 0x3 << 18) // (TC) RC Compare Effect on TIOA
+#define AT91C_TC_ACPC_NONE ((unsigned int) 0x0 << 18) // (TC) Effect: none
+#define AT91C_TC_ACPC_SET ((unsigned int) 0x1 << 18) // (TC) Effect: set
+#define AT91C_TC_ACPC_CLEAR ((unsigned int) 0x2 << 18) // (TC) Effect: clear
+#define AT91C_TC_ACPC_TOGGLE ((unsigned int) 0x3 << 18) // (TC) Effect: toggle
+#define AT91C_TC_LDRB ((unsigned int) 0x3 << 18) // (TC) RB Loading Selection
+#define AT91C_TC_LDRB_NONE ((unsigned int) 0x0 << 18) // (TC) Edge: None
+#define AT91C_TC_LDRB_RISING ((unsigned int) 0x1 << 18) // (TC) Edge: rising edge of TIOA
+#define AT91C_TC_LDRB_FALLING ((unsigned int) 0x2 << 18) // (TC) Edge: falling edge of TIOA
+#define AT91C_TC_LDRB_BOTH ((unsigned int) 0x3 << 18) // (TC) Edge: each edge of TIOA
+#define AT91C_TC_AEEVT ((unsigned int) 0x3 << 20) // (TC) External Event Effect on TIOA
+#define AT91C_TC_AEEVT_NONE ((unsigned int) 0x0 << 20) // (TC) Effect: none
+#define AT91C_TC_AEEVT_SET ((unsigned int) 0x1 << 20) // (TC) Effect: set
+#define AT91C_TC_AEEVT_CLEAR ((unsigned int) 0x2 << 20) // (TC) Effect: clear
+#define AT91C_TC_AEEVT_TOGGLE ((unsigned int) 0x3 << 20) // (TC) Effect: toggle
+#define AT91C_TC_ASWTRG ((unsigned int) 0x3 << 22) // (TC) Software Trigger Effect on TIOA
+#define AT91C_TC_ASWTRG_NONE ((unsigned int) 0x0 << 22) // (TC) Effect: none
+#define AT91C_TC_ASWTRG_SET ((unsigned int) 0x1 << 22) // (TC) Effect: set
+#define AT91C_TC_ASWTRG_CLEAR ((unsigned int) 0x2 << 22) // (TC) Effect: clear
+#define AT91C_TC_ASWTRG_TOGGLE ((unsigned int) 0x3 << 22) // (TC) Effect: toggle
+#define AT91C_TC_BCPB ((unsigned int) 0x3 << 24) // (TC) RB Compare Effect on TIOB
+#define AT91C_TC_BCPB_NONE ((unsigned int) 0x0 << 24) // (TC) Effect: none
+#define AT91C_TC_BCPB_SET ((unsigned int) 0x1 << 24) // (TC) Effect: set
+#define AT91C_TC_BCPB_CLEAR ((unsigned int) 0x2 << 24) // (TC) Effect: clear
+#define AT91C_TC_BCPB_TOGGLE ((unsigned int) 0x3 << 24) // (TC) Effect: toggle
+#define AT91C_TC_BCPC ((unsigned int) 0x3 << 26) // (TC) RC Compare Effect on TIOB
+#define AT91C_TC_BCPC_NONE ((unsigned int) 0x0 << 26) // (TC) Effect: none
+#define AT91C_TC_BCPC_SET ((unsigned int) 0x1 << 26) // (TC) Effect: set
+#define AT91C_TC_BCPC_CLEAR ((unsigned int) 0x2 << 26) // (TC) Effect: clear
+#define AT91C_TC_BCPC_TOGGLE ((unsigned int) 0x3 << 26) // (TC) Effect: toggle
+#define AT91C_TC_BEEVT ((unsigned int) 0x3 << 28) // (TC) External Event Effect on TIOB
+#define AT91C_TC_BEEVT_NONE ((unsigned int) 0x0 << 28) // (TC) Effect: none
+#define AT91C_TC_BEEVT_SET ((unsigned int) 0x1 << 28) // (TC) Effect: set
+#define AT91C_TC_BEEVT_CLEAR ((unsigned int) 0x2 << 28) // (TC) Effect: clear
+#define AT91C_TC_BEEVT_TOGGLE ((unsigned int) 0x3 << 28) // (TC) Effect: toggle
+#define AT91C_TC_BSWTRG ((unsigned int) 0x3 << 30) // (TC) Software Trigger Effect on TIOB
+#define AT91C_TC_BSWTRG_NONE ((unsigned int) 0x0 << 30) // (TC) Effect: none
+#define AT91C_TC_BSWTRG_SET ((unsigned int) 0x1 << 30) // (TC) Effect: set
+#define AT91C_TC_BSWTRG_CLEAR ((unsigned int) 0x2 << 30) // (TC) Effect: clear
+#define AT91C_TC_BSWTRG_TOGGLE ((unsigned int) 0x3 << 30) // (TC) Effect: toggle
+// -------- TC_SR : (TC Offset: 0x20) TC Channel Status Register --------
+#define AT91C_TC_COVFS ((unsigned int) 0x1 << 0) // (TC) Counter Overflow
+#define AT91C_TC_LOVRS ((unsigned int) 0x1 << 1) // (TC) Load Overrun
+#define AT91C_TC_CPAS ((unsigned int) 0x1 << 2) // (TC) RA Compare
+#define AT91C_TC_CPBS ((unsigned int) 0x1 << 3) // (TC) RB Compare
+#define AT91C_TC_CPCS ((unsigned int) 0x1 << 4) // (TC) RC Compare
+#define AT91C_TC_LDRAS ((unsigned int) 0x1 << 5) // (TC) RA Loading
+#define AT91C_TC_LDRBS ((unsigned int) 0x1 << 6) // (TC) RB Loading
+#define AT91C_TC_ETRGS ((unsigned int) 0x1 << 7) // (TC) External Trigger
+#define AT91C_TC_CLKSTA ((unsigned int) 0x1 << 16) // (TC) Clock Enabling
+#define AT91C_TC_MTIOA ((unsigned int) 0x1 << 17) // (TC) TIOA Mirror
+#define AT91C_TC_MTIOB ((unsigned int) 0x1 << 18) // (TC) TIOA Mirror
+// -------- TC_IER : (TC Offset: 0x24) TC Channel Interrupt Enable Register --------
+// -------- TC_IDR : (TC Offset: 0x28) TC Channel Interrupt Disable Register --------
+// -------- TC_IMR : (TC Offset: 0x2c) TC Channel Interrupt Mask Register --------
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Timer Counter Interface
+// *****************************************************************************
+typedef struct _AT91S_TCB {
+ AT91S_TC TCB_TC0; // TC Channel 0
+ AT91_REG Reserved0[4]; //
+ AT91S_TC TCB_TC1; // TC Channel 1
+ AT91_REG Reserved1[4]; //
+ AT91S_TC TCB_TC2; // TC Channel 2
+ AT91_REG Reserved2[4]; //
+ AT91_REG TCB_BCR; // TC Block Control Register
+ AT91_REG TCB_BMR; // TC Block Mode Register
+} AT91S_TCB, *AT91PS_TCB;
+
+// -------- TCB_BCR : (TCB Offset: 0xc0) TC Block Control Register --------
+#define AT91C_TCB_SYNC ((unsigned int) 0x1 << 0) // (TCB) Synchro Command
+// -------- TCB_BMR : (TCB Offset: 0xc4) TC Block Mode Register --------
+#define AT91C_TCB_TC0XC0S ((unsigned int) 0x3 << 0) // (TCB) External Clock Signal 0 Selection
+#define AT91C_TCB_TC0XC0S_TCLK0 ((unsigned int) 0x0) // (TCB) TCLK0 connected to XC0
+#define AT91C_TCB_TC0XC0S_NONE ((unsigned int) 0x1) // (TCB) None signal connected to XC0
+#define AT91C_TCB_TC0XC0S_TIOA1 ((unsigned int) 0x2) // (TCB) TIOA1 connected to XC0
+#define AT91C_TCB_TC0XC0S_TIOA2 ((unsigned int) 0x3) // (TCB) TIOA2 connected to XC0
+#define AT91C_TCB_TC1XC1S ((unsigned int) 0x3 << 2) // (TCB) External Clock Signal 1 Selection
+#define AT91C_TCB_TC1XC1S_TCLK1 ((unsigned int) 0x0 << 2) // (TCB) TCLK1 connected to XC1
+#define AT91C_TCB_TC1XC1S_NONE ((unsigned int) 0x1 << 2) // (TCB) None signal connected to XC1
+#define AT91C_TCB_TC1XC1S_TIOA0 ((unsigned int) 0x2 << 2) // (TCB) TIOA0 connected to XC1
+#define AT91C_TCB_TC1XC1S_TIOA2 ((unsigned int) 0x3 << 2) // (TCB) TIOA2 connected to XC1
+#define AT91C_TCB_TC2XC2S ((unsigned int) 0x3 << 4) // (TCB) External Clock Signal 2 Selection
+#define AT91C_TCB_TC2XC2S_TCLK2 ((unsigned int) 0x0 << 4) // (TCB) TCLK2 connected to XC2
+#define AT91C_TCB_TC2XC2S_NONE ((unsigned int) 0x1 << 4) // (TCB) None signal connected to XC2
+#define AT91C_TCB_TC2XC2S_TIOA0 ((unsigned int) 0x2 << 4) // (TCB) TIOA0 connected to XC2
+#define AT91C_TCB_TC2XC2S_TIOA1 ((unsigned int) 0x3 << 4) // (TCB) TIOA2 connected to XC2
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR PWMC Channel Interface
+// *****************************************************************************
+typedef struct _AT91S_PWMC_CH {
+ AT91_REG PWMC_CMR; // Channel Mode Register
+ AT91_REG PWMC_CDTYR; // Channel Duty Cycle Register
+ AT91_REG PWMC_CPRDR; // Channel Period Register
+ AT91_REG PWMC_CCNTR; // Channel Counter Register
+ AT91_REG PWMC_CUPDR; // Channel Update Register
+ AT91_REG PWMC_Reserved[3]; // Reserved
+} AT91S_PWMC_CH, *AT91PS_PWMC_CH;
+
+// -------- PWMC_CMR : (PWMC_CH Offset: 0x0) PWMC Channel Mode Register --------
+#define AT91C_PWMC_CPRE ((unsigned int) 0xF << 0) // (PWMC_CH) Channel Pre-scaler : PWMC_CLKx
+#define AT91C_PWMC_CPRE_MCK ((unsigned int) 0x0) // (PWMC_CH)
+#define AT91C_PWMC_CPRE_MCKA ((unsigned int) 0xB) // (PWMC_CH)
+#define AT91C_PWMC_CPRE_MCKB ((unsigned int) 0xC) // (PWMC_CH)
+#define AT91C_PWMC_CALG ((unsigned int) 0x1 << 8) // (PWMC_CH) Channel Alignment
+#define AT91C_PWMC_CPOL ((unsigned int) 0x1 << 9) // (PWMC_CH) Channel Polarity
+#define AT91C_PWMC_CPD ((unsigned int) 0x1 << 10) // (PWMC_CH) Channel Update Period
+// -------- PWMC_CDTYR : (PWMC_CH Offset: 0x4) PWMC Channel Duty Cycle Register --------
+#define AT91C_PWMC_CDTY ((unsigned int) 0x0 << 0) // (PWMC_CH) Channel Duty Cycle
+// -------- PWMC_CPRDR : (PWMC_CH Offset: 0x8) PWMC Channel Period Register --------
+#define AT91C_PWMC_CPRD ((unsigned int) 0x0 << 0) // (PWMC_CH) Channel Period
+// -------- PWMC_CCNTR : (PWMC_CH Offset: 0xc) PWMC Channel Counter Register --------
+#define AT91C_PWMC_CCNT ((unsigned int) 0x0 << 0) // (PWMC_CH) Channel Counter
+// -------- PWMC_CUPDR : (PWMC_CH Offset: 0x10) PWMC Channel Update Register --------
+#define AT91C_PWMC_CUPD ((unsigned int) 0x0 << 0) // (PWMC_CH) Channel Update
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR Pulse Width Modulation Controller Interface
+// *****************************************************************************
+typedef struct _AT91S_PWMC {
+ AT91_REG PWMC_MR; // PWMC Mode Register
+ AT91_REG PWMC_ENA; // PWMC Enable Register
+ AT91_REG PWMC_DIS; // PWMC Disable Register
+ AT91_REG PWMC_SR; // PWMC Status Register
+ AT91_REG PWMC_IER; // PWMC Interrupt Enable Register
+ AT91_REG PWMC_IDR; // PWMC Interrupt Disable Register
+ AT91_REG PWMC_IMR; // PWMC Interrupt Mask Register
+ AT91_REG PWMC_ISR; // PWMC Interrupt Status Register
+ AT91_REG Reserved0[55]; //
+ AT91_REG PWMC_VR; // PWMC Version Register
+ AT91_REG Reserved1[64]; //
+ AT91S_PWMC_CH PWMC_CH[4]; // PWMC Channel
+} AT91S_PWMC, *AT91PS_PWMC;
+
+// -------- PWMC_MR : (PWMC Offset: 0x0) PWMC Mode Register --------
+#define AT91C_PWMC_DIVA ((unsigned int) 0xFF << 0) // (PWMC) CLKA divide factor.
+#define AT91C_PWMC_PREA ((unsigned int) 0xF << 8) // (PWMC) Divider Input Clock Prescaler A
+#define AT91C_PWMC_PREA_MCK ((unsigned int) 0x0 << 8) // (PWMC)
+#define AT91C_PWMC_DIVB ((unsigned int) 0xFF << 16) // (PWMC) CLKB divide factor.
+#define AT91C_PWMC_PREB ((unsigned int) 0xF << 24) // (PWMC) Divider Input Clock Prescaler B
+#define AT91C_PWMC_PREB_MCK ((unsigned int) 0x0 << 24) // (PWMC)
+// -------- PWMC_ENA : (PWMC Offset: 0x4) PWMC Enable Register --------
+#define AT91C_PWMC_CHID0 ((unsigned int) 0x1 << 0) // (PWMC) Channel ID 0
+#define AT91C_PWMC_CHID1 ((unsigned int) 0x1 << 1) // (PWMC) Channel ID 1
+#define AT91C_PWMC_CHID2 ((unsigned int) 0x1 << 2) // (PWMC) Channel ID 2
+#define AT91C_PWMC_CHID3 ((unsigned int) 0x1 << 3) // (PWMC) Channel ID 3
+// -------- PWMC_DIS : (PWMC Offset: 0x8) PWMC Disable Register --------
+// -------- PWMC_SR : (PWMC Offset: 0xc) PWMC Status Register --------
+// -------- PWMC_IER : (PWMC Offset: 0x10) PWMC Interrupt Enable Register --------
+// -------- PWMC_IDR : (PWMC Offset: 0x14) PWMC Interrupt Disable Register --------
+// -------- PWMC_IMR : (PWMC Offset: 0x18) PWMC Interrupt Mask Register --------
+// -------- PWMC_ISR : (PWMC Offset: 0x1c) PWMC Interrupt Status Register --------
+
+// *****************************************************************************
+// SOFTWARE API DEFINITION FOR USB Device Interface
+// *****************************************************************************
+typedef struct _AT91S_UDP {
+ AT91_REG UDP_NUM; // Frame Number Register
+ AT91_REG UDP_GLBSTATE; // Global State Register
+ AT91_REG UDP_FADDR; // Function Address Register
+ AT91_REG Reserved0[1]; //
+ AT91_REG UDP_IER; // Interrupt Enable Register
+ AT91_REG UDP_IDR; // Interrupt Disable Register
+ AT91_REG UDP_IMR; // Interrupt Mask Register
+ AT91_REG UDP_ISR; // Interrupt Status Register
+ AT91_REG UDP_ICR; // Interrupt Clear Register
+ AT91_REG Reserved1[1]; //
+ AT91_REG UDP_RSTEP; // Reset Endpoint Register
+ AT91_REG Reserved2[1]; //
+ AT91_REG UDP_CSR[4]; // Endpoint Control and Status Register
+ AT91_REG Reserved3[4]; //
+ AT91_REG UDP_FDR[4]; // Endpoint FIFO Data Register
+ AT91_REG Reserved4[5]; //
+ AT91_REG UDP_TXVC; // Transceiver Control Register
+} AT91S_UDP, *AT91PS_UDP;
+
+// -------- UDP_FRM_NUM : (UDP Offset: 0x0) USB Frame Number Register --------
+#define AT91C_UDP_FRM_NUM ((unsigned int) 0x7FF << 0) // (UDP) Frame Number as Defined in the Packet Field Formats
+#define AT91C_UDP_FRM_ERR ((unsigned int) 0x1 << 16) // (UDP) Frame Error
+#define AT91C_UDP_FRM_OK ((unsigned int) 0x1 << 17) // (UDP) Frame OK
+// -------- UDP_GLB_STATE : (UDP Offset: 0x4) USB Global State Register --------
+#define AT91C_UDP_FADDEN ((unsigned int) 0x1 << 0) // (UDP) Function Address Enable
+#define AT91C_UDP_CONFG ((unsigned int) 0x1 << 1) // (UDP) Configured
+#define AT91C_UDP_ESR ((unsigned int) 0x1 << 2) // (UDP) Enable Send Resume
+#define AT91C_UDP_RSMINPR ((unsigned int) 0x1 << 3) // (UDP) A Resume Has Been Sent to the Host
+#define AT91C_UDP_RMWUPE ((unsigned int) 0x1 << 4) // (UDP) Remote Wake Up Enable
+// -------- UDP_FADDR : (UDP Offset: 0x8) USB Function Address Register --------
+#define AT91C_UDP_FADD ((unsigned int) 0xFF << 0) // (UDP) Function Address Value
+#define AT91C_UDP_FEN ((unsigned int) 0x1 << 8) // (UDP) Function Enable
+// -------- UDP_IER : (UDP Offset: 0x10) USB Interrupt Enable Register --------
+#define AT91C_UDP_EPINT0 ((unsigned int) 0x1 << 0) // (UDP) Endpoint 0 Interrupt
+#define AT91C_UDP_EPINT1 ((unsigned int) 0x1 << 1) // (UDP) Endpoint 1 Interrupt
+#define AT91C_UDP_EPINT2 ((unsigned int) 0x1 << 2) // (UDP) Endpoint 2 Interrupt
+#define AT91C_UDP_EPINT3 ((unsigned int) 0x1 << 3) // (UDP) Endpoint 3 Interrupt
+#define AT91C_UDP_RXSUSP ((unsigned int) 0x1 << 8) // (UDP) USB Suspend Interrupt
+#define AT91C_UDP_RXRSM ((unsigned int) 0x1 << 9) // (UDP) USB Resume Interrupt
+#define AT91C_UDP_EXTRSM ((unsigned int) 0x1 << 10) // (UDP) USB External Resume Interrupt
+#define AT91C_UDP_SOFINT ((unsigned int) 0x1 << 11) // (UDP) USB Start Of frame Interrupt
+#define AT91C_UDP_WAKEUP ((unsigned int) 0x1 << 13) // (UDP) USB Resume Interrupt
+// -------- UDP_IDR : (UDP Offset: 0x14) USB Interrupt Disable Register --------
+// -------- UDP_IMR : (UDP Offset: 0x18) USB Interrupt Mask Register --------
+// -------- UDP_ISR : (UDP Offset: 0x1c) USB Interrupt Status Register --------
+#define AT91C_UDP_ENDBUSRES ((unsigned int) 0x1 << 12) // (UDP) USB End Of Bus Reset Interrupt
+// -------- UDP_ICR : (UDP Offset: 0x20) USB Interrupt Clear Register --------
+// -------- UDP_RST_EP : (UDP Offset: 0x28) USB Reset Endpoint Register --------
+#define AT91C_UDP_EP0 ((unsigned int) 0x1 << 0) // (UDP) Reset Endpoint 0
+#define AT91C_UDP_EP1 ((unsigned int) 0x1 << 1) // (UDP) Reset Endpoint 1
+#define AT91C_UDP_EP2 ((unsigned int) 0x1 << 2) // (UDP) Reset Endpoint 2
+#define AT91C_UDP_EP3 ((unsigned int) 0x1 << 3) // (UDP) Reset Endpoint 3
+// -------- UDP_CSR : (UDP Offset: 0x30) USB Endpoint Control and Status Register --------
+#define AT91C_UDP_TXCOMP ((unsigned int) 0x1 << 0) // (UDP) Generates an IN packet with data previously written in the DPR
+#define AT91C_UDP_RX_DATA_BK0 ((unsigned int) 0x1 << 1) // (UDP) Receive Data Bank 0
+#define AT91C_UDP_RXSETUP ((unsigned int) 0x1 << 2) // (UDP) Sends STALL to the Host (Control endpoints)
+#define AT91C_UDP_ISOERROR ((unsigned int) 0x1 << 3) // (UDP) Isochronous error (Isochronous endpoints)
+#define AT91C_UDP_STALLSENT ((unsigned int) 0x1 << 3) // (UDP) Stall Sent (Control endpoints)
+#define AT91C_UDP_TXPKTRDY ((unsigned int) 0x1 << 4) // (UDP) Transmit Packet Ready
+#define AT91C_UDP_FORCESTALL ((unsigned int) 0x1 << 5) // (UDP) Force Stall (used by Control, Bulk and Isochronous endpoints).
+#define AT91C_UDP_RX_DATA_BK1 ((unsigned int) 0x1 << 6) // (UDP) Receive Data Bank 1 (only used by endpoints with ping-pong attributes).
+#define AT91C_UDP_DIR ((unsigned int) 0x1 << 7) // (UDP) Transfer Direction
+#define AT91C_UDP_EPTYPE ((unsigned int) 0x7 << 8) // (UDP) Endpoint type
+#define AT91C_UDP_EPTYPE_CTRL ((unsigned int) 0x0 << 8) // (UDP) Control
+#define AT91C_UDP_EPTYPE_ISO_OUT ((unsigned int) 0x1 << 8) // (UDP) Isochronous OUT
+#define AT91C_UDP_EPTYPE_BULK_OUT ((unsigned int) 0x2 << 8) // (UDP) Bulk OUT
+#define AT91C_UDP_EPTYPE_INT_OUT ((unsigned int) 0x3 << 8) // (UDP) Interrupt OUT
+#define AT91C_UDP_EPTYPE_ISO_IN ((unsigned int) 0x5 << 8) // (UDP) Isochronous IN
+#define AT91C_UDP_EPTYPE_BULK_IN ((unsigned int) 0x6 << 8) // (UDP) Bulk IN
+#define AT91C_UDP_EPTYPE_INT_IN ((unsigned int) 0x7 << 8) // (UDP) Interrupt IN
+#define AT91C_UDP_DTGLE ((unsigned int) 0x1 << 11) // (UDP) Data Toggle
+#define AT91C_UDP_EPEDS ((unsigned int) 0x1 << 15) // (UDP) Endpoint Enable Disable
+#define AT91C_UDP_RXBYTECNT ((unsigned int) 0x7FF << 16) // (UDP) Number Of Bytes Available in the FIFO
+// -------- UDP_TXVC : (UDP Offset: 0x74) Transceiver Control Register --------
+#define AT91C_UDP_TXVDIS ((unsigned int) 0x1 << 8) // (UDP)
+
+// *****************************************************************************
+// REGISTER ADDRESS DEFINITION FOR AT91SAM7S64
+// *****************************************************************************
+// ========== Register definition for SYS peripheral ==========
+// ========== Register definition for AIC peripheral ==========
+#define AT91C_AIC_IVR ((AT91_REG *) 0xFFFFF100) // (AIC) IRQ Vector Register
+#define AT91C_AIC_SMR ((AT91_REG *) 0xFFFFF000) // (AIC) Source Mode Register
+#define AT91C_AIC_FVR ((AT91_REG *) 0xFFFFF104) // (AIC) FIQ Vector Register
+#define AT91C_AIC_DCR ((AT91_REG *) 0xFFFFF138) // (AIC) Debug Control Register (Protect)
+#define AT91C_AIC_EOICR ((AT91_REG *) 0xFFFFF130) // (AIC) End of Interrupt Command Register
+#define AT91C_AIC_SVR ((AT91_REG *) 0xFFFFF080) // (AIC) Source Vector Register
+#define AT91C_AIC_FFSR ((AT91_REG *) 0xFFFFF148) // (AIC) Fast Forcing Status Register
+#define AT91C_AIC_ICCR ((AT91_REG *) 0xFFFFF128) // (AIC) Interrupt Clear Command Register
+#define AT91C_AIC_ISR ((AT91_REG *) 0xFFFFF108) // (AIC) Interrupt Status Register
+#define AT91C_AIC_IMR ((AT91_REG *) 0xFFFFF110) // (AIC) Interrupt Mask Register
+#define AT91C_AIC_IPR ((AT91_REG *) 0xFFFFF10C) // (AIC) Interrupt Pending Register
+#define AT91C_AIC_FFER ((AT91_REG *) 0xFFFFF140) // (AIC) Fast Forcing Enable Register
+#define AT91C_AIC_IECR ((AT91_REG *) 0xFFFFF120) // (AIC) Interrupt Enable Command Register
+#define AT91C_AIC_ISCR ((AT91_REG *) 0xFFFFF12C) // (AIC) Interrupt Set Command Register
+#define AT91C_AIC_FFDR ((AT91_REG *) 0xFFFFF144) // (AIC) Fast Forcing Disable Register
+#define AT91C_AIC_CISR ((AT91_REG *) 0xFFFFF114) // (AIC) Core Interrupt Status Register
+#define AT91C_AIC_IDCR ((AT91_REG *) 0xFFFFF124) // (AIC) Interrupt Disable Command Register
+#define AT91C_AIC_SPU ((AT91_REG *) 0xFFFFF134) // (AIC) Spurious Vector Register
+// ========== Register definition for PDC_DBGU peripheral ==========
+#define AT91C_DBGU_TCR ((AT91_REG *) 0xFFFFF30C) // (PDC_DBGU) Transmit Counter Register
+#define AT91C_DBGU_RNPR ((AT91_REG *) 0xFFFFF310) // (PDC_DBGU) Receive Next Pointer Register
+#define AT91C_DBGU_TNPR ((AT91_REG *) 0xFFFFF318) // (PDC_DBGU) Transmit Next Pointer Register
+#define AT91C_DBGU_TPR ((AT91_REG *) 0xFFFFF308) // (PDC_DBGU) Transmit Pointer Register
+#define AT91C_DBGU_RPR ((AT91_REG *) 0xFFFFF300) // (PDC_DBGU) Receive Pointer Register
+#define AT91C_DBGU_RCR ((AT91_REG *) 0xFFFFF304) // (PDC_DBGU) Receive Counter Register
+#define AT91C_DBGU_RNCR ((AT91_REG *) 0xFFFFF314) // (PDC_DBGU) Receive Next Counter Register
+#define AT91C_DBGU_PTCR ((AT91_REG *) 0xFFFFF320) // (PDC_DBGU) PDC Transfer Control Register
+#define AT91C_DBGU_PTSR ((AT91_REG *) 0xFFFFF324) // (PDC_DBGU) PDC Transfer Status Register
+#define AT91C_DBGU_TNCR ((AT91_REG *) 0xFFFFF31C) // (PDC_DBGU) Transmit Next Counter Register
+// ========== Register definition for DBGU peripheral ==========
+#define AT91C_DBGU_EXID ((AT91_REG *) 0xFFFFF244) // (DBGU) Chip ID Extension Register
+#define AT91C_DBGU_BRGR ((AT91_REG *) 0xFFFFF220) // (DBGU) Baud Rate Generator Register
+#define AT91C_DBGU_IDR ((AT91_REG *) 0xFFFFF20C) // (DBGU) Interrupt Disable Register
+#define AT91C_DBGU_CSR ((AT91_REG *) 0xFFFFF214) // (DBGU) Channel Status Register
+#define AT91C_DBGU_CIDR ((AT91_REG *) 0xFFFFF240) // (DBGU) Chip ID Register
+#define AT91C_DBGU_MR ((AT91_REG *) 0xFFFFF204) // (DBGU) Mode Register
+#define AT91C_DBGU_IMR ((AT91_REG *) 0xFFFFF210) // (DBGU) Interrupt Mask Register
+#define AT91C_DBGU_CR ((AT91_REG *) 0xFFFFF200) // (DBGU) Control Register
+#define AT91C_DBGU_FNTR ((AT91_REG *) 0xFFFFF248) // (DBGU) Force NTRST Register
+#define AT91C_DBGU_THR ((AT91_REG *) 0xFFFFF21C) // (DBGU) Transmitter Holding Register
+#define AT91C_DBGU_RHR ((AT91_REG *) 0xFFFFF218) // (DBGU) Receiver Holding Register
+#define AT91C_DBGU_IER ((AT91_REG *) 0xFFFFF208) // (DBGU) Interrupt Enable Register
+// ========== Register definition for PIOA peripheral ==========
+#define AT91C_PIOA_ODR ((AT91_REG *) 0xFFFFF414) // (PIOA) Output Disable Registerr
+#define AT91C_PIOA_SODR ((AT91_REG *) 0xFFFFF430) // (PIOA) Set Output Data Register
+#define AT91C_PIOA_ISR ((AT91_REG *) 0xFFFFF44C) // (PIOA) Interrupt Status Register
+#define AT91C_PIOA_ABSR ((AT91_REG *) 0xFFFFF478) // (PIOA) AB Select Status Register
+#define AT91C_PIOA_IER ((AT91_REG *) 0xFFFFF440) // (PIOA) Interrupt Enable Register
+#define AT91C_PIOA_PPUDR ((AT91_REG *) 0xFFFFF460) // (PIOA) Pull-up Disable Register
+#define AT91C_PIOA_IMR ((AT91_REG *) 0xFFFFF448) // (PIOA) Interrupt Mask Register
+#define AT91C_PIOA_PER ((AT91_REG *) 0xFFFFF400) // (PIOA) PIO Enable Register
+#define AT91C_PIOA_IFDR ((AT91_REG *) 0xFFFFF424) // (PIOA) Input Filter Disable Register
+#define AT91C_PIOA_OWDR ((AT91_REG *) 0xFFFFF4A4) // (PIOA) Output Write Disable Register
+#define AT91C_PIOA_MDSR ((AT91_REG *) 0xFFFFF458) // (PIOA) Multi-driver Status Register
+#define AT91C_PIOA_IDR ((AT91_REG *) 0xFFFFF444) // (PIOA) Interrupt Disable Register
+#define AT91C_PIOA_ODSR ((AT91_REG *) 0xFFFFF438) // (PIOA) Output Data Status Register
+#define AT91C_PIOA_PPUSR ((AT91_REG *) 0xFFFFF468) // (PIOA) Pull-up Status Register
+#define AT91C_PIOA_OWSR ((AT91_REG *) 0xFFFFF4A8) // (PIOA) Output Write Status Register
+#define AT91C_PIOA_BSR ((AT91_REG *) 0xFFFFF474) // (PIOA) Select B Register
+#define AT91C_PIOA_OWER ((AT91_REG *) 0xFFFFF4A0) // (PIOA) Output Write Enable Register
+#define AT91C_PIOA_IFER ((AT91_REG *) 0xFFFFF420) // (PIOA) Input Filter Enable Register
+#define AT91C_PIOA_PDSR ((AT91_REG *) 0xFFFFF43C) // (PIOA) Pin Data Status Register
+#define AT91C_PIOA_PPUER ((AT91_REG *) 0xFFFFF464) // (PIOA) Pull-up Enable Register
+#define AT91C_PIOA_OSR ((AT91_REG *) 0xFFFFF418) // (PIOA) Output Status Register
+#define AT91C_PIOA_ASR ((AT91_REG *) 0xFFFFF470) // (PIOA) Select A Register
+#define AT91C_PIOA_MDDR ((AT91_REG *) 0xFFFFF454) // (PIOA) Multi-driver Disable Register
+#define AT91C_PIOA_CODR ((AT91_REG *) 0xFFFFF434) // (PIOA) Clear Output Data Register
+#define AT91C_PIOA_MDER ((AT91_REG *) 0xFFFFF450) // (PIOA) Multi-driver Enable Register
+#define AT91C_PIOA_PDR ((AT91_REG *) 0xFFFFF404) // (PIOA) PIO Disable Register
+#define AT91C_PIOA_IFSR ((AT91_REG *) 0xFFFFF428) // (PIOA) Input Filter Status Register
+#define AT91C_PIOA_OER ((AT91_REG *) 0xFFFFF410) // (PIOA) Output Enable Register
+#define AT91C_PIOA_PSR ((AT91_REG *) 0xFFFFF408) // (PIOA) PIO Status Register
+// ========== Register definition for CKGR peripheral ==========
+#define AT91C_CKGR_MOR ((AT91_REG *) 0xFFFFFC20) // (CKGR) Main Oscillator Register
+#define AT91C_CKGR_PLLR ((AT91_REG *) 0xFFFFFC2C) // (CKGR) PLL Register
+#define AT91C_CKGR_MCFR ((AT91_REG *) 0xFFFFFC24) // (CKGR) Main Clock Frequency Register
+// ========== Register definition for PMC peripheral ==========
+#define AT91C_PMC_IDR ((AT91_REG *) 0xFFFFFC64) // (PMC) Interrupt Disable Register
+#define AT91C_PMC_MOR ((AT91_REG *) 0xFFFFFC20) // (PMC) Main Oscillator Register
+#define AT91C_PMC_PLLR ((AT91_REG *) 0xFFFFFC2C) // (PMC) PLL Register
+#define AT91C_PMC_PCER ((AT91_REG *) 0xFFFFFC10) // (PMC) Peripheral Clock Enable Register
+#define AT91C_PMC_PCKR ((AT91_REG *) 0xFFFFFC40) // (PMC) Programmable Clock Register
+#define AT91C_PMC_MCKR ((AT91_REG *) 0xFFFFFC30) // (PMC) Master Clock Register
+#define AT91C_PMC_SCDR ((AT91_REG *) 0xFFFFFC04) // (PMC) System Clock Disable Register
+#define AT91C_PMC_PCDR ((AT91_REG *) 0xFFFFFC14) // (PMC) Peripheral Clock Disable Register
+#define AT91C_PMC_SCSR ((AT91_REG *) 0xFFFFFC08) // (PMC) System Clock Status Register
+#define AT91C_PMC_PCSR ((AT91_REG *) 0xFFFFFC18) // (PMC) Peripheral Clock Status Register
+#define AT91C_PMC_MCFR ((AT91_REG *) 0xFFFFFC24) // (PMC) Main Clock Frequency Register
+#define AT91C_PMC_SCER ((AT91_REG *) 0xFFFFFC00) // (PMC) System Clock Enable Register
+#define AT91C_PMC_IMR ((AT91_REG *) 0xFFFFFC6C) // (PMC) Interrupt Mask Register
+#define AT91C_PMC_IER ((AT91_REG *) 0xFFFFFC60) // (PMC) Interrupt Enable Register
+#define AT91C_PMC_SR ((AT91_REG *) 0xFFFFFC68) // (PMC) Status Register
+// ========== Register definition for RSTC peripheral ==========
+#define AT91C_RSTC_RCR ((AT91_REG *) 0xFFFFFD00) // (RSTC) Reset Control Register
+#define AT91C_RSTC_RMR ((AT91_REG *) 0xFFFFFD08) // (RSTC) Reset Mode Register
+#define AT91C_RSTC_RSR ((AT91_REG *) 0xFFFFFD04) // (RSTC) Reset Status Register
+// ========== Register definition for RTTC peripheral ==========
+#define AT91C_RTTC_RTSR ((AT91_REG *) 0xFFFFFD2C) // (RTTC) Real-time Status Register
+#define AT91C_RTTC_RTMR ((AT91_REG *) 0xFFFFFD20) // (RTTC) Real-time Mode Register
+#define AT91C_RTTC_RTVR ((AT91_REG *) 0xFFFFFD28) // (RTTC) Real-time Value Register
+#define AT91C_RTTC_RTAR ((AT91_REG *) 0xFFFFFD24) // (RTTC) Real-time Alarm Register
+// ========== Register definition for PITC peripheral ==========
+#define AT91C_PITC_PIVR ((AT91_REG *) 0xFFFFFD38) // (PITC) Period Interval Value Register
+#define AT91C_PITC_PISR ((AT91_REG *) 0xFFFFFD34) // (PITC) Period Interval Status Register
+#define AT91C_PITC_PIIR ((AT91_REG *) 0xFFFFFD3C) // (PITC) Period Interval Image Register
+#define AT91C_PITC_PIMR ((AT91_REG *) 0xFFFFFD30) // (PITC) Period Interval Mode Register
+// ========== Register definition for WDTC peripheral ==========
+#define AT91C_WDTC_WDCR ((AT91_REG *) 0xFFFFFD40) // (WDTC) Watchdog Control Register
+#define AT91C_WDTC_WDSR ((AT91_REG *) 0xFFFFFD48) // (WDTC) Watchdog Status Register
+#define AT91C_WDTC_WDMR ((AT91_REG *) 0xFFFFFD44) // (WDTC) Watchdog Mode Register
+// ========== Register definition for VREG peripheral ==========
+#define AT91C_VREG_MR ((AT91_REG *) 0xFFFFFD60) // (VREG) Voltage Regulator Mode Register
+// ========== Register definition for MC peripheral ==========
+#define AT91C_MC_ASR ((AT91_REG *) 0xFFFFFF04) // (MC) MC Abort Status Register
+#define AT91C_MC_RCR ((AT91_REG *) 0xFFFFFF00) // (MC) MC Remap Control Register
+#define AT91C_MC_FCR ((AT91_REG *) 0xFFFFFF64) // (MC) MC Flash Command Register
+#define AT91C_MC_AASR ((AT91_REG *) 0xFFFFFF08) // (MC) MC Abort Address Status Register
+#define AT91C_MC_FSR ((AT91_REG *) 0xFFFFFF68) // (MC) MC Flash Status Register
+#define AT91C_MC_FMR ((AT91_REG *) 0xFFFFFF60) // (MC) MC Flash Mode Register
+// ========== Register definition for PDC_SPI peripheral ==========
+#define AT91C_SPI_PTCR ((AT91_REG *) 0xFFFE0120) // (PDC_SPI) PDC Transfer Control Register
+#define AT91C_SPI_TPR ((AT91_REG *) 0xFFFE0108) // (PDC_SPI) Transmit Pointer Register
+#define AT91C_SPI_TCR ((AT91_REG *) 0xFFFE010C) // (PDC_SPI) Transmit Counter Register
+#define AT91C_SPI_RCR ((AT91_REG *) 0xFFFE0104) // (PDC_SPI) Receive Counter Register
+#define AT91C_SPI_PTSR ((AT91_REG *) 0xFFFE0124) // (PDC_SPI) PDC Transfer Status Register
+#define AT91C_SPI_RNPR ((AT91_REG *) 0xFFFE0110) // (PDC_SPI) Receive Next Pointer Register
+#define AT91C_SPI_RPR ((AT91_REG *) 0xFFFE0100) // (PDC_SPI) Receive Pointer Register
+#define AT91C_SPI_TNCR ((AT91_REG *) 0xFFFE011C) // (PDC_SPI) Transmit Next Counter Register
+#define AT91C_SPI_RNCR ((AT91_REG *) 0xFFFE0114) // (PDC_SPI) Receive Next Counter Register
+#define AT91C_SPI_TNPR ((AT91_REG *) 0xFFFE0118) // (PDC_SPI) Transmit Next Pointer Register
+// ========== Register definition for SPI peripheral ==========
+#define AT91C_SPI_IER ((AT91_REG *) 0xFFFE0014) // (SPI) Interrupt Enable Register
+#define AT91C_SPI_SR ((AT91_REG *) 0xFFFE0010) // (SPI) Status Register
+#define AT91C_SPI_IDR ((AT91_REG *) 0xFFFE0018) // (SPI) Interrupt Disable Register
+#define AT91C_SPI_CR ((AT91_REG *) 0xFFFE0000) // (SPI) Control Register
+#define AT91C_SPI_MR ((AT91_REG *) 0xFFFE0004) // (SPI) Mode Register
+#define AT91C_SPI_IMR ((AT91_REG *) 0xFFFE001C) // (SPI) Interrupt Mask Register
+#define AT91C_SPI_TDR ((AT91_REG *) 0xFFFE000C) // (SPI) Transmit Data Register
+#define AT91C_SPI_RDR ((AT91_REG *) 0xFFFE0008) // (SPI) Receive Data Register
+#define AT91C_SPI_CSR ((AT91_REG *) 0xFFFE0030) // (SPI) Chip Select Register
+// ========== Register definition for PDC_ADC peripheral ==========
+#define AT91C_ADC_PTSR ((AT91_REG *) 0xFFFD8124) // (PDC_ADC) PDC Transfer Status Register
+#define AT91C_ADC_PTCR ((AT91_REG *) 0xFFFD8120) // (PDC_ADC) PDC Transfer Control Register
+#define AT91C_ADC_TNPR ((AT91_REG *) 0xFFFD8118) // (PDC_ADC) Transmit Next Pointer Register
+#define AT91C_ADC_TNCR ((AT91_REG *) 0xFFFD811C) // (PDC_ADC) Transmit Next Counter Register
+#define AT91C_ADC_RNPR ((AT91_REG *) 0xFFFD8110) // (PDC_ADC) Receive Next Pointer Register
+#define AT91C_ADC_RNCR ((AT91_REG *) 0xFFFD8114) // (PDC_ADC) Receive Next Counter Register
+#define AT91C_ADC_RPR ((AT91_REG *) 0xFFFD8100) // (PDC_ADC) Receive Pointer Register
+#define AT91C_ADC_TCR ((AT91_REG *) 0xFFFD810C) // (PDC_ADC) Transmit Counter Register
+#define AT91C_ADC_TPR ((AT91_REG *) 0xFFFD8108) // (PDC_ADC) Transmit Pointer Register
+#define AT91C_ADC_RCR ((AT91_REG *) 0xFFFD8104) // (PDC_ADC) Receive Counter Register
+// ========== Register definition for ADC peripheral ==========
+#define AT91C_ADC_CDR2 ((AT91_REG *) 0xFFFD8038) // (ADC) ADC Channel Data Register 2
+#define AT91C_ADC_CDR3 ((AT91_REG *) 0xFFFD803C) // (ADC) ADC Channel Data Register 3
+#define AT91C_ADC_CDR0 ((AT91_REG *) 0xFFFD8030) // (ADC) ADC Channel Data Register 0
+#define AT91C_ADC_CDR5 ((AT91_REG *) 0xFFFD8044) // (ADC) ADC Channel Data Register 5
+#define AT91C_ADC_CHDR ((AT91_REG *) 0xFFFD8014) // (ADC) ADC Channel Disable Register
+#define AT91C_ADC_SR ((AT91_REG *) 0xFFFD801C) // (ADC) ADC Status Register
+#define AT91C_ADC_CDR4 ((AT91_REG *) 0xFFFD8040) // (ADC) ADC Channel Data Register 4
+#define AT91C_ADC_CDR1 ((AT91_REG *) 0xFFFD8034) // (ADC) ADC Channel Data Register 1
+#define AT91C_ADC_LCDR ((AT91_REG *) 0xFFFD8020) // (ADC) ADC Last Converted Data Register
+#define AT91C_ADC_IDR ((AT91_REG *) 0xFFFD8028) // (ADC) ADC Interrupt Disable Register
+#define AT91C_ADC_CR ((AT91_REG *) 0xFFFD8000) // (ADC) ADC Control Register
+#define AT91C_ADC_CDR7 ((AT91_REG *) 0xFFFD804C) // (ADC) ADC Channel Data Register 7
+#define AT91C_ADC_CDR6 ((AT91_REG *) 0xFFFD8048) // (ADC) ADC Channel Data Register 6
+#define AT91C_ADC_IER ((AT91_REG *) 0xFFFD8024) // (ADC) ADC Interrupt Enable Register
+#define AT91C_ADC_CHER ((AT91_REG *) 0xFFFD8010) // (ADC) ADC Channel Enable Register
+#define AT91C_ADC_CHSR ((AT91_REG *) 0xFFFD8018) // (ADC) ADC Channel Status Register
+#define AT91C_ADC_MR ((AT91_REG *) 0xFFFD8004) // (ADC) ADC Mode Register
+#define AT91C_ADC_IMR ((AT91_REG *) 0xFFFD802C) // (ADC) ADC Interrupt Mask Register
+// ========== Register definition for PDC_SSC peripheral ==========
+#define AT91C_SSC_TNCR ((AT91_REG *) 0xFFFD411C) // (PDC_SSC) Transmit Next Counter Register
+#define AT91C_SSC_RPR ((AT91_REG *) 0xFFFD4100) // (PDC_SSC) Receive Pointer Register
+#define AT91C_SSC_RNCR ((AT91_REG *) 0xFFFD4114) // (PDC_SSC) Receive Next Counter Register
+#define AT91C_SSC_TPR ((AT91_REG *) 0xFFFD4108) // (PDC_SSC) Transmit Pointer Register
+#define AT91C_SSC_PTCR ((AT91_REG *) 0xFFFD4120) // (PDC_SSC) PDC Transfer Control Register
+#define AT91C_SSC_TCR ((AT91_REG *) 0xFFFD410C) // (PDC_SSC) Transmit Counter Register
+#define AT91C_SSC_RCR ((AT91_REG *) 0xFFFD4104) // (PDC_SSC) Receive Counter Register
+#define AT91C_SSC_RNPR ((AT91_REG *) 0xFFFD4110) // (PDC_SSC) Receive Next Pointer Register
+#define AT91C_SSC_TNPR ((AT91_REG *) 0xFFFD4118) // (PDC_SSC) Transmit Next Pointer Register
+#define AT91C_SSC_PTSR ((AT91_REG *) 0xFFFD4124) // (PDC_SSC) PDC Transfer Status Register
+// ========== Register definition for SSC peripheral ==========
+#define AT91C_SSC_RHR ((AT91_REG *) 0xFFFD4020) // (SSC) Receive Holding Register
+#define AT91C_SSC_RSHR ((AT91_REG *) 0xFFFD4030) // (SSC) Receive Sync Holding Register
+#define AT91C_SSC_TFMR ((AT91_REG *) 0xFFFD401C) // (SSC) Transmit Frame Mode Register
+#define AT91C_SSC_IDR ((AT91_REG *) 0xFFFD4048) // (SSC) Interrupt Disable Register
+#define AT91C_SSC_THR ((AT91_REG *) 0xFFFD4024) // (SSC) Transmit Holding Register
+#define AT91C_SSC_RCMR ((AT91_REG *) 0xFFFD4010) // (SSC) Receive Clock ModeRegister
+#define AT91C_SSC_IER ((AT91_REG *) 0xFFFD4044) // (SSC) Interrupt Enable Register
+#define AT91C_SSC_TSHR ((AT91_REG *) 0xFFFD4034) // (SSC) Transmit Sync Holding Register
+#define AT91C_SSC_SR ((AT91_REG *) 0xFFFD4040) // (SSC) Status Register
+#define AT91C_SSC_CMR ((AT91_REG *) 0xFFFD4004) // (SSC) Clock Mode Register
+#define AT91C_SSC_TCMR ((AT91_REG *) 0xFFFD4018) // (SSC) Transmit Clock Mode Register
+#define AT91C_SSC_CR ((AT91_REG *) 0xFFFD4000) // (SSC) Control Register
+#define AT91C_SSC_IMR ((AT91_REG *) 0xFFFD404C) // (SSC) Interrupt Mask Register
+#define AT91C_SSC_RFMR ((AT91_REG *) 0xFFFD4014) // (SSC) Receive Frame Mode Register
+// ========== Register definition for PDC_US1 peripheral ==========
+#define AT91C_US1_RNCR ((AT91_REG *) 0xFFFC4114) // (PDC_US1) Receive Next Counter Register
+#define AT91C_US1_PTCR ((AT91_REG *) 0xFFFC4120) // (PDC_US1) PDC Transfer Control Register
+#define AT91C_US1_TCR ((AT91_REG *) 0xFFFC410C) // (PDC_US1) Transmit Counter Register
+#define AT91C_US1_PTSR ((AT91_REG *) 0xFFFC4124) // (PDC_US1) PDC Transfer Status Register
+#define AT91C_US1_TNPR ((AT91_REG *) 0xFFFC4118) // (PDC_US1) Transmit Next Pointer Register
+#define AT91C_US1_RCR ((AT91_REG *) 0xFFFC4104) // (PDC_US1) Receive Counter Register
+#define AT91C_US1_RNPR ((AT91_REG *) 0xFFFC4110) // (PDC_US1) Receive Next Pointer Register
+#define AT91C_US1_RPR ((AT91_REG *) 0xFFFC4100) // (PDC_US1) Receive Pointer Register
+#define AT91C_US1_TNCR ((AT91_REG *) 0xFFFC411C) // (PDC_US1) Transmit Next Counter Register
+#define AT91C_US1_TPR ((AT91_REG *) 0xFFFC4108) // (PDC_US1) Transmit Pointer Register
+// ========== Register definition for US1 peripheral ==========
+#define AT91C_US1_IF ((AT91_REG *) 0xFFFC404C) // (US1) IRDA_FILTER Register
+#define AT91C_US1_NER ((AT91_REG *) 0xFFFC4044) // (US1) Nb Errors Register
+#define AT91C_US1_RTOR ((AT91_REG *) 0xFFFC4024) // (US1) Receiver Time-out Register
+#define AT91C_US1_CSR ((AT91_REG *) 0xFFFC4014) // (US1) Channel Status Register
+#define AT91C_US1_IDR ((AT91_REG *) 0xFFFC400C) // (US1) Interrupt Disable Register
+#define AT91C_US1_IER ((AT91_REG *) 0xFFFC4008) // (US1) Interrupt Enable Register
+#define AT91C_US1_THR ((AT91_REG *) 0xFFFC401C) // (US1) Transmitter Holding Register
+#define AT91C_US1_TTGR ((AT91_REG *) 0xFFFC4028) // (US1) Transmitter Time-guard Register
+#define AT91C_US1_RHR ((AT91_REG *) 0xFFFC4018) // (US1) Receiver Holding Register
+#define AT91C_US1_BRGR ((AT91_REG *) 0xFFFC4020) // (US1) Baud Rate Generator Register
+#define AT91C_US1_IMR ((AT91_REG *) 0xFFFC4010) // (US1) Interrupt Mask Register
+#define AT91C_US1_FIDI ((AT91_REG *) 0xFFFC4040) // (US1) FI_DI_Ratio Register
+#define AT91C_US1_CR ((AT91_REG *) 0xFFFC4000) // (US1) Control Register
+#define AT91C_US1_MR ((AT91_REG *) 0xFFFC4004) // (US1) Mode Register
+// ========== Register definition for PDC_US0 peripheral ==========
+#define AT91C_US0_TNPR ((AT91_REG *) 0xFFFC0118) // (PDC_US0) Transmit Next Pointer Register
+#define AT91C_US0_RNPR ((AT91_REG *) 0xFFFC0110) // (PDC_US0) Receive Next Pointer Register
+#define AT91C_US0_TCR ((AT91_REG *) 0xFFFC010C) // (PDC_US0) Transmit Counter Register
+#define AT91C_US0_PTCR ((AT91_REG *) 0xFFFC0120) // (PDC_US0) PDC Transfer Control Register
+#define AT91C_US0_PTSR ((AT91_REG *) 0xFFFC0124) // (PDC_US0) PDC Transfer Status Register
+#define AT91C_US0_TNCR ((AT91_REG *) 0xFFFC011C) // (PDC_US0) Transmit Next Counter Register
+#define AT91C_US0_TPR ((AT91_REG *) 0xFFFC0108) // (PDC_US0) Transmit Pointer Register
+#define AT91C_US0_RCR ((AT91_REG *) 0xFFFC0104) // (PDC_US0) Receive Counter Register
+#define AT91C_US0_RPR ((AT91_REG *) 0xFFFC0100) // (PDC_US0) Receive Pointer Register
+#define AT91C_US0_RNCR ((AT91_REG *) 0xFFFC0114) // (PDC_US0) Receive Next Counter Register
+// ========== Register definition for US0 peripheral ==========
+#define AT91C_US0_BRGR ((AT91_REG *) 0xFFFC0020) // (US0) Baud Rate Generator Register
+#define AT91C_US0_NER ((AT91_REG *) 0xFFFC0044) // (US0) Nb Errors Register
+#define AT91C_US0_CR ((AT91_REG *) 0xFFFC0000) // (US0) Control Register
+#define AT91C_US0_IMR ((AT91_REG *) 0xFFFC0010) // (US0) Interrupt Mask Register
+#define AT91C_US0_FIDI ((AT91_REG *) 0xFFFC0040) // (US0) FI_DI_Ratio Register
+#define AT91C_US0_TTGR ((AT91_REG *) 0xFFFC0028) // (US0) Transmitter Time-guard Register
+#define AT91C_US0_MR ((AT91_REG *) 0xFFFC0004) // (US0) Mode Register
+#define AT91C_US0_RTOR ((AT91_REG *) 0xFFFC0024) // (US0) Receiver Time-out Register
+#define AT91C_US0_CSR ((AT91_REG *) 0xFFFC0014) // (US0) Channel Status Register
+#define AT91C_US0_RHR ((AT91_REG *) 0xFFFC0018) // (US0) Receiver Holding Register
+#define AT91C_US0_IDR ((AT91_REG *) 0xFFFC000C) // (US0) Interrupt Disable Register
+#define AT91C_US0_THR ((AT91_REG *) 0xFFFC001C) // (US0) Transmitter Holding Register
+#define AT91C_US0_IF ((AT91_REG *) 0xFFFC004C) // (US0) IRDA_FILTER Register
+#define AT91C_US0_IER ((AT91_REG *) 0xFFFC0008) // (US0) Interrupt Enable Register
+// ========== Register definition for TWI peripheral ==========
+#define AT91C_TWI_IER ((AT91_REG *) 0xFFFB8024) // (TWI) Interrupt Enable Register
+#define AT91C_TWI_CR ((AT91_REG *) 0xFFFB8000) // (TWI) Control Register
+#define AT91C_TWI_SR ((AT91_REG *) 0xFFFB8020) // (TWI) Status Register
+#define AT91C_TWI_IMR ((AT91_REG *) 0xFFFB802C) // (TWI) Interrupt Mask Register
+#define AT91C_TWI_THR ((AT91_REG *) 0xFFFB8034) // (TWI) Transmit Holding Register
+#define AT91C_TWI_IDR ((AT91_REG *) 0xFFFB8028) // (TWI) Interrupt Disable Register
+#define AT91C_TWI_IADR ((AT91_REG *) 0xFFFB800C) // (TWI) Internal Address Register
+#define AT91C_TWI_MMR ((AT91_REG *) 0xFFFB8004) // (TWI) Master Mode Register
+#define AT91C_TWI_CWGR ((AT91_REG *) 0xFFFB8010) // (TWI) Clock Waveform Generator Register
+#define AT91C_TWI_RHR ((AT91_REG *) 0xFFFB8030) // (TWI) Receive Holding Register
+// ========== Register definition for TC0 peripheral ==========
+#define AT91C_TC0_SR ((AT91_REG *) 0xFFFA0020) // (TC0) Status Register
+#define AT91C_TC0_RC ((AT91_REG *) 0xFFFA001C) // (TC0) Register C
+#define AT91C_TC0_RB ((AT91_REG *) 0xFFFA0018) // (TC0) Register B
+#define AT91C_TC0_CCR ((AT91_REG *) 0xFFFA0000) // (TC0) Channel Control Register
+#define AT91C_TC0_CMR ((AT91_REG *) 0xFFFA0004) // (TC0) Channel Mode Register (Capture Mode / Waveform Mode)
+#define AT91C_TC0_IER ((AT91_REG *) 0xFFFA0024) // (TC0) Interrupt Enable Register
+#define AT91C_TC0_RA ((AT91_REG *) 0xFFFA0014) // (TC0) Register A
+#define AT91C_TC0_IDR ((AT91_REG *) 0xFFFA0028) // (TC0) Interrupt Disable Register
+#define AT91C_TC0_CV ((AT91_REG *) 0xFFFA0010) // (TC0) Counter Value
+#define AT91C_TC0_IMR ((AT91_REG *) 0xFFFA002C) // (TC0) Interrupt Mask Register
+// ========== Register definition for TC1 peripheral ==========
+#define AT91C_TC1_RB ((AT91_REG *) 0xFFFA0058) // (TC1) Register B
+#define AT91C_TC1_CCR ((AT91_REG *) 0xFFFA0040) // (TC1) Channel Control Register
+#define AT91C_TC1_IER ((AT91_REG *) 0xFFFA0064) // (TC1) Interrupt Enable Register
+#define AT91C_TC1_IDR ((AT91_REG *) 0xFFFA0068) // (TC1) Interrupt Disable Register
+#define AT91C_TC1_SR ((AT91_REG *) 0xFFFA0060) // (TC1) Status Register
+#define AT91C_TC1_CMR ((AT91_REG *) 0xFFFA0044) // (TC1) Channel Mode Register (Capture Mode / Waveform Mode)
+#define AT91C_TC1_RA ((AT91_REG *) 0xFFFA0054) // (TC1) Register A
+#define AT91C_TC1_RC ((AT91_REG *) 0xFFFA005C) // (TC1) Register C
+#define AT91C_TC1_IMR ((AT91_REG *) 0xFFFA006C) // (TC1) Interrupt Mask Register
+#define AT91C_TC1_CV ((AT91_REG *) 0xFFFA0050) // (TC1) Counter Value
+// ========== Register definition for TC2 peripheral ==========
+#define AT91C_TC2_CMR ((AT91_REG *) 0xFFFA0084) // (TC2) Channel Mode Register (Capture Mode / Waveform Mode)
+#define AT91C_TC2_CCR ((AT91_REG *) 0xFFFA0080) // (TC2) Channel Control Register
+#define AT91C_TC2_CV ((AT91_REG *) 0xFFFA0090) // (TC2) Counter Value
+#define AT91C_TC2_RA ((AT91_REG *) 0xFFFA0094) // (TC2) Register A
+#define AT91C_TC2_RB ((AT91_REG *) 0xFFFA0098) // (TC2) Register B
+#define AT91C_TC2_IDR ((AT91_REG *) 0xFFFA00A8) // (TC2) Interrupt Disable Register
+#define AT91C_TC2_IMR ((AT91_REG *) 0xFFFA00AC) // (TC2) Interrupt Mask Register
+#define AT91C_TC2_RC ((AT91_REG *) 0xFFFA009C) // (TC2) Register C
+#define AT91C_TC2_IER ((AT91_REG *) 0xFFFA00A4) // (TC2) Interrupt Enable Register
+#define AT91C_TC2_SR ((AT91_REG *) 0xFFFA00A0) // (TC2) Status Register
+// ========== Register definition for TCB peripheral ==========
+#define AT91C_TCB_BMR ((AT91_REG *) 0xFFFA00C4) // (TCB) TC Block Mode Register
+#define AT91C_TCB_BCR ((AT91_REG *) 0xFFFA00C0) // (TCB) TC Block Control Register
+// ========== Register definition for PWMC_CH3 peripheral ==========
+#define AT91C_PWMC_CH3_CUPDR ((AT91_REG *) 0xFFFCC270) // (PWMC_CH3) Channel Update Register
+#define AT91C_PWMC_CH3_Reserved ((AT91_REG *) 0xFFFCC274) // (PWMC_CH3) Reserved
+#define AT91C_PWMC_CH3_CPRDR ((AT91_REG *) 0xFFFCC268) // (PWMC_CH3) Channel Period Register
+#define AT91C_PWMC_CH3_CDTYR ((AT91_REG *) 0xFFFCC264) // (PWMC_CH3) Channel Duty Cycle Register
+#define AT91C_PWMC_CH3_CCNTR ((AT91_REG *) 0xFFFCC26C) // (PWMC_CH3) Channel Counter Register
+#define AT91C_PWMC_CH3_CMR ((AT91_REG *) 0xFFFCC260) // (PWMC_CH3) Channel Mode Register
+// ========== Register definition for PWMC_CH2 peripheral ==========
+#define AT91C_PWMC_CH2_Reserved ((AT91_REG *) 0xFFFCC254) // (PWMC_CH2) Reserved
+#define AT91C_PWMC_CH2_CMR ((AT91_REG *) 0xFFFCC240) // (PWMC_CH2) Channel Mode Register
+#define AT91C_PWMC_CH2_CCNTR ((AT91_REG *) 0xFFFCC24C) // (PWMC_CH2) Channel Counter Register
+#define AT91C_PWMC_CH2_CPRDR ((AT91_REG *) 0xFFFCC248) // (PWMC_CH2) Channel Period Register
+#define AT91C_PWMC_CH2_CUPDR ((AT91_REG *) 0xFFFCC250) // (PWMC_CH2) Channel Update Register
+#define AT91C_PWMC_CH2_CDTYR ((AT91_REG *) 0xFFFCC244) // (PWMC_CH2) Channel Duty Cycle Register
+// ========== Register definition for PWMC_CH1 peripheral ==========
+#define AT91C_PWMC_CH1_Reserved ((AT91_REG *) 0xFFFCC234) // (PWMC_CH1) Reserved
+#define AT91C_PWMC_CH1_CUPDR ((AT91_REG *) 0xFFFCC230) // (PWMC_CH1) Channel Update Register
+#define AT91C_PWMC_CH1_CPRDR ((AT91_REG *) 0xFFFCC228) // (PWMC_CH1) Channel Period Register
+#define AT91C_PWMC_CH1_CCNTR ((AT91_REG *) 0xFFFCC22C) // (PWMC_CH1) Channel Counter Register
+#define AT91C_PWMC_CH1_CDTYR ((AT91_REG *) 0xFFFCC224) // (PWMC_CH1) Channel Duty Cycle Register
+#define AT91C_PWMC_CH1_CMR ((AT91_REG *) 0xFFFCC220) // (PWMC_CH1) Channel Mode Register
+// ========== Register definition for PWMC_CH0 peripheral ==========
+#define AT91C_PWMC_CH0_Reserved ((AT91_REG *) 0xFFFCC214) // (PWMC_CH0) Reserved
+#define AT91C_PWMC_CH0_CPRDR ((AT91_REG *) 0xFFFCC208) // (PWMC_CH0) Channel Period Register
+#define AT91C_PWMC_CH0_CDTYR ((AT91_REG *) 0xFFFCC204) // (PWMC_CH0) Channel Duty Cycle Register
+#define AT91C_PWMC_CH0_CMR ((AT91_REG *) 0xFFFCC200) // (PWMC_CH0) Channel Mode Register
+#define AT91C_PWMC_CH0_CUPDR ((AT91_REG *) 0xFFFCC210) // (PWMC_CH0) Channel Update Register
+#define AT91C_PWMC_CH0_CCNTR ((AT91_REG *) 0xFFFCC20C) // (PWMC_CH0) Channel Counter Register
+// ========== Register definition for PWMC peripheral ==========
+#define AT91C_PWMC_IDR ((AT91_REG *) 0xFFFCC014) // (PWMC) PWMC Interrupt Disable Register
+#define AT91C_PWMC_DIS ((AT91_REG *) 0xFFFCC008) // (PWMC) PWMC Disable Register
+#define AT91C_PWMC_IER ((AT91_REG *) 0xFFFCC010) // (PWMC) PWMC Interrupt Enable Register
+#define AT91C_PWMC_VR ((AT91_REG *) 0xFFFCC0FC) // (PWMC) PWMC Version Register
+#define AT91C_PWMC_ISR ((AT91_REG *) 0xFFFCC01C) // (PWMC) PWMC Interrupt Status Register
+#define AT91C_PWMC_SR ((AT91_REG *) 0xFFFCC00C) // (PWMC) PWMC Status Register
+#define AT91C_PWMC_IMR ((AT91_REG *) 0xFFFCC018) // (PWMC) PWMC Interrupt Mask Register
+#define AT91C_PWMC_MR ((AT91_REG *) 0xFFFCC000) // (PWMC) PWMC Mode Register
+#define AT91C_PWMC_ENA ((AT91_REG *) 0xFFFCC004) // (PWMC) PWMC Enable Register
+// ========== Register definition for UDP peripheral ==========
+#define AT91C_UDP_IMR ((AT91_REG *) 0xFFFB0018) // (UDP) Interrupt Mask Register
+#define AT91C_UDP_FADDR ((AT91_REG *) 0xFFFB0008) // (UDP) Function Address Register
+#define AT91C_UDP_NUM ((AT91_REG *) 0xFFFB0000) // (UDP) Frame Number Register
+#define AT91C_UDP_FDR ((AT91_REG *) 0xFFFB0050) // (UDP) Endpoint FIFO Data Register
+#define AT91C_UDP_ISR ((AT91_REG *) 0xFFFB001C) // (UDP) Interrupt Status Register
+#define AT91C_UDP_CSR ((AT91_REG *) 0xFFFB0030) // (UDP) Endpoint Control and Status Register
+#define AT91C_UDP_IDR ((AT91_REG *) 0xFFFB0014) // (UDP) Interrupt Disable Register
+#define AT91C_UDP_ICR ((AT91_REG *) 0xFFFB0020) // (UDP) Interrupt Clear Register
+#define AT91C_UDP_RSTEP ((AT91_REG *) 0xFFFB0028) // (UDP) Reset Endpoint Register
+#define AT91C_UDP_TXVC ((AT91_REG *) 0xFFFB0074) // (UDP) Transceiver Control Register
+#define AT91C_UDP_GLBSTATE ((AT91_REG *) 0xFFFB0004) // (UDP) Global State Register
+#define AT91C_UDP_IER ((AT91_REG *) 0xFFFB0010) // (UDP) Interrupt Enable Register
+
+// *****************************************************************************
+// PIO DEFINITIONS FOR AT91SAM7S64
+// *****************************************************************************
+#define AT91C_PIO_PA0 ((unsigned int) 1 << 0) // Pin Controlled by PA0
+#define AT91C_PA0_PWM0 ((unsigned int) AT91C_PIO_PA0) // PWM Channel 0
+#define AT91C_PA0_TIOA0 ((unsigned int) AT91C_PIO_PA0) // Timer Counter 0 Multipurpose Timer I/O Pin A
+#define AT91C_PIO_PA1 ((unsigned int) 1 << 1) // Pin Controlled by PA1
+#define AT91C_PA1_PWM1 ((unsigned int) AT91C_PIO_PA1) // PWM Channel 1
+#define AT91C_PA1_TIOB0 ((unsigned int) AT91C_PIO_PA1) // Timer Counter 0 Multipurpose Timer I/O Pin B
+#define AT91C_PIO_PA10 ((unsigned int) 1 << 10) // Pin Controlled by PA10
+#define AT91C_PA10_DTXD ((unsigned int) AT91C_PIO_PA10) // DBGU Debug Transmit Data
+#define AT91C_PA10_NPCS2 ((unsigned int) AT91C_PIO_PA10) // SPI Peripheral Chip Select 2
+#define AT91C_PIO_PA11 ((unsigned int) 1 << 11) // Pin Controlled by PA11
+#define AT91C_PA11_NPCS0 ((unsigned int) AT91C_PIO_PA11) // SPI Peripheral Chip Select 0
+#define AT91C_PA11_PWM0 ((unsigned int) AT91C_PIO_PA11) // PWM Channel 0
+#define AT91C_PIO_PA12 ((unsigned int) 1 << 12) // Pin Controlled by PA12
+#define AT91C_PA12_MISO ((unsigned int) AT91C_PIO_PA12) // SPI Master In Slave
+#define AT91C_PA12_PWM1 ((unsigned int) AT91C_PIO_PA12) // PWM Channel 1
+#define AT91C_PIO_PA13 ((unsigned int) 1 << 13) // Pin Controlled by PA13
+#define AT91C_PA13_MOSI ((unsigned int) AT91C_PIO_PA13) // SPI Master Out Slave
+#define AT91C_PA13_PWM2 ((unsigned int) AT91C_PIO_PA13) // PWM Channel 2
+#define AT91C_PIO_PA14 ((unsigned int) 1 << 14) // Pin Controlled by PA14
+#define AT91C_PA14_SPCK ((unsigned int) AT91C_PIO_PA14) // SPI Serial Clock
+#define AT91C_PA14_PWM3 ((unsigned int) AT91C_PIO_PA14) // PWM Channel 3
+#define AT91C_PIO_PA15 ((unsigned int) 1 << 15) // Pin Controlled by PA15
+#define AT91C_PA15_TF ((unsigned int) AT91C_PIO_PA15) // SSC Transmit Frame Sync
+#define AT91C_PA15_TIOA1 ((unsigned int) AT91C_PIO_PA15) // Timer Counter 1 Multipurpose Timer I/O Pin A
+#define AT91C_PIO_PA16 ((unsigned int) 1 << 16) // Pin Controlled by PA16
+#define AT91C_PA16_TK ((unsigned int) AT91C_PIO_PA16) // SSC Transmit Clock
+#define AT91C_PA16_TIOB1 ((unsigned int) AT91C_PIO_PA16) // Timer Counter 1 Multipurpose Timer I/O Pin B
+#define AT91C_PIO_PA17 ((unsigned int) 1 << 17) // Pin Controlled by PA17
+#define AT91C_PA17_TD ((unsigned int) AT91C_PIO_PA17) // SSC Transmit data
+#define AT91C_PA17_PCK1 ((unsigned int) AT91C_PIO_PA17) // PMC Programmable Clock Output 1
+#define AT91C_PIO_PA18 ((unsigned int) 1 << 18) // Pin Controlled by PA18
+#define AT91C_PA18_RD ((unsigned int) AT91C_PIO_PA18) // SSC Receive Data
+#define AT91C_PA18_PCK2 ((unsigned int) AT91C_PIO_PA18) // PMC Programmable Clock Output 2
+#define AT91C_PIO_PA19 ((unsigned int) 1 << 19) // Pin Controlled by PA19
+#define AT91C_PA19_RK ((unsigned int) AT91C_PIO_PA19) // SSC Receive Clock
+#define AT91C_PA19_FIQ ((unsigned int) AT91C_PIO_PA19) // AIC Fast Interrupt Input
+#define AT91C_PIO_PA2 ((unsigned int) 1 << 2) // Pin Controlled by PA2
+#define AT91C_PA2_PWM2 ((unsigned int) AT91C_PIO_PA2) // PWM Channel 2
+#define AT91C_PA2_SCK0 ((unsigned int) AT91C_PIO_PA2) // USART 0 Serial Clock
+#define AT91C_PIO_PA20 ((unsigned int) 1 << 20) // Pin Controlled by PA20
+#define AT91C_PA20_RF ((unsigned int) AT91C_PIO_PA20) // SSC Receive Frame Sync
+#define AT91C_PA20_IRQ0 ((unsigned int) AT91C_PIO_PA20) // External Interrupt 0
+#define AT91C_PIO_PA21 ((unsigned int) 1 << 21) // Pin Controlled by PA21
+#define AT91C_PA21_RXD1 ((unsigned int) AT91C_PIO_PA21) // USART 1 Receive Data
+#define AT91C_PA21_PCK1 ((unsigned int) AT91C_PIO_PA21) // PMC Programmable Clock Output 1
+#define AT91C_PIO_PA22 ((unsigned int) 1 << 22) // Pin Controlled by PA22
+#define AT91C_PA22_TXD1 ((unsigned int) AT91C_PIO_PA22) // USART 1 Transmit Data
+#define AT91C_PA22_NPCS3 ((unsigned int) AT91C_PIO_PA22) // SPI Peripheral Chip Select 3
+#define AT91C_PIO_PA23 ((unsigned int) 1 << 23) // Pin Controlled by PA23
+#define AT91C_PA23_SCK1 ((unsigned int) AT91C_PIO_PA23) // USART 1 Serial Clock
+#define AT91C_PA23_PWM0 ((unsigned int) AT91C_PIO_PA23) // PWM Channel 0
+#define AT91C_PIO_PA24 ((unsigned int) 1 << 24) // Pin Controlled by PA24
+#define AT91C_PA24_RTS1 ((unsigned int) AT91C_PIO_PA24) // USART 1 Ready To Send
+#define AT91C_PA24_PWM1 ((unsigned int) AT91C_PIO_PA24) // PWM Channel 1
+#define AT91C_PIO_PA25 ((unsigned int) 1 << 25) // Pin Controlled by PA25
+#define AT91C_PA25_CTS1 ((unsigned int) AT91C_PIO_PA25) // USART 1 Clear To Send
+#define AT91C_PA25_PWM2 ((unsigned int) AT91C_PIO_PA25) // PWM Channel 2
+#define AT91C_PIO_PA26 ((unsigned int) 1 << 26) // Pin Controlled by PA26
+#define AT91C_PA26_DCD1 ((unsigned int) AT91C_PIO_PA26) // USART 1 Data Carrier Detect
+#define AT91C_PA26_TIOA2 ((unsigned int) AT91C_PIO_PA26) // Timer Counter 2 Multipurpose Timer I/O Pin A
+#define AT91C_PIO_PA27 ((unsigned int) 1 << 27) // Pin Controlled by PA27
+#define AT91C_PA27_DTR1 ((unsigned int) AT91C_PIO_PA27) // USART 1 Data Terminal ready
+#define AT91C_PA27_TIOB2 ((unsigned int) AT91C_PIO_PA27) // Timer Counter 2 Multipurpose Timer I/O Pin B
+#define AT91C_PIO_PA28 ((unsigned int) 1 << 28) // Pin Controlled by PA28
+#define AT91C_PA28_DSR1 ((unsigned int) AT91C_PIO_PA28) // USART 1 Data Set ready
+#define AT91C_PA28_TCLK1 ((unsigned int) AT91C_PIO_PA28) // Timer Counter 1 external clock input
+#define AT91C_PIO_PA29 ((unsigned int) 1 << 29) // Pin Controlled by PA29
+#define AT91C_PA29_RI1 ((unsigned int) AT91C_PIO_PA29) // USART 1 Ring Indicator
+#define AT91C_PA29_TCLK2 ((unsigned int) AT91C_PIO_PA29) // Timer Counter 2 external clock input
+#define AT91C_PIO_PA3 ((unsigned int) 1 << 3) // Pin Controlled by PA3
+#define AT91C_PA3_TWD ((unsigned int) AT91C_PIO_PA3) // TWI Two-wire Serial Data
+#define AT91C_PA3_NPCS3 ((unsigned int) AT91C_PIO_PA3) // SPI Peripheral Chip Select 3
+#define AT91C_PIO_PA30 ((unsigned int) 1 << 30) // Pin Controlled by PA30
+#define AT91C_PA30_IRQ1 ((unsigned int) AT91C_PIO_PA30) // External Interrupt 1
+#define AT91C_PA30_NPCS2 ((unsigned int) AT91C_PIO_PA30) // SPI Peripheral Chip Select 2
+#define AT91C_PIO_PA31 ((unsigned int) 1 << 31) // Pin Controlled by PA31
+#define AT91C_PA31_NPCS1 ((unsigned int) AT91C_PIO_PA31) // SPI Peripheral Chip Select 1
+#define AT91C_PA31_PCK2 ((unsigned int) AT91C_PIO_PA31) // PMC Programmable Clock Output 2
+#define AT91C_PIO_PA4 ((unsigned int) 1 << 4) // Pin Controlled by PA4
+#define AT91C_PA4_TWCK ((unsigned int) AT91C_PIO_PA4) // TWI Two-wire Serial Clock
+#define AT91C_PA4_TCLK0 ((unsigned int) AT91C_PIO_PA4) // Timer Counter 0 external clock input
+#define AT91C_PIO_PA5 ((unsigned int) 1 << 5) // Pin Controlled by PA5
+#define AT91C_PA5_RXD0 ((unsigned int) AT91C_PIO_PA5) // USART 0 Receive Data
+#define AT91C_PA5_NPCS3 ((unsigned int) AT91C_PIO_PA5) // SPI Peripheral Chip Select 3
+#define AT91C_PIO_PA6 ((unsigned int) 1 << 6) // Pin Controlled by PA6
+#define AT91C_PA6_TXD0 ((unsigned int) AT91C_PIO_PA6) // USART 0 Transmit Data
+#define AT91C_PA6_PCK0 ((unsigned int) AT91C_PIO_PA6) // PMC Programmable Clock Output 0
+#define AT91C_PIO_PA7 ((unsigned int) 1 << 7) // Pin Controlled by PA7
+#define AT91C_PA7_RTS0 ((unsigned int) AT91C_PIO_PA7) // USART 0 Ready To Send
+#define AT91C_PA7_PWM3 ((unsigned int) AT91C_PIO_PA7) // PWM Channel 3
+#define AT91C_PIO_PA8 ((unsigned int) 1 << 8) // Pin Controlled by PA8
+#define AT91C_PA8_CTS0 ((unsigned int) AT91C_PIO_PA8) // USART 0 Clear To Send
+#define AT91C_PA8_ADTRG ((unsigned int) AT91C_PIO_PA8) // ADC External Trigger
+#define AT91C_PIO_PA9 ((unsigned int) 1 << 9) // Pin Controlled by PA9
+#define AT91C_PA9_DRXD ((unsigned int) AT91C_PIO_PA9) // DBGU Debug Receive Data
+#define AT91C_PA9_NPCS1 ((unsigned int) AT91C_PIO_PA9) // SPI Peripheral Chip Select 1
+
+// *****************************************************************************
+// PERIPHERAL ID DEFINITIONS FOR AT91SAM7S64
+// *****************************************************************************
+#define AT91C_ID_FIQ ((unsigned int) 0) // Advanced Interrupt Controller (FIQ)
+#define AT91C_ID_SYS ((unsigned int) 1) // System Peripheral
+#define AT91C_ID_PIOA ((unsigned int) 2) // Parallel IO Controller
+#define AT91C_ID_3_Reserved ((unsigned int) 3) // Reserved
+#define AT91C_ID_ADC ((unsigned int) 4) // Analog-to-Digital Converter
+#define AT91C_ID_SPI ((unsigned int) 5) // Serial Peripheral Interface
+#define AT91C_ID_US0 ((unsigned int) 6) // USART 0
+#define AT91C_ID_US1 ((unsigned int) 7) // USART 1
+#define AT91C_ID_SSC ((unsigned int) 8) // Serial Synchronous Controller
+#define AT91C_ID_TWI ((unsigned int) 9) // Two-Wire Interface
+#define AT91C_ID_PWMC ((unsigned int) 10) // PWM Controller
+#define AT91C_ID_UDP ((unsigned int) 11) // USB Device Port
+#define AT91C_ID_TC0 ((unsigned int) 12) // Timer Counter 0
+#define AT91C_ID_TC1 ((unsigned int) 13) // Timer Counter 1
+#define AT91C_ID_TC2 ((unsigned int) 14) // Timer Counter 2
+#define AT91C_ID_15_Reserved ((unsigned int) 15) // Reserved
+#define AT91C_ID_16_Reserved ((unsigned int) 16) // Reserved
+#define AT91C_ID_17_Reserved ((unsigned int) 17) // Reserved
+#define AT91C_ID_18_Reserved ((unsigned int) 18) // Reserved
+#define AT91C_ID_19_Reserved ((unsigned int) 19) // Reserved
+#define AT91C_ID_20_Reserved ((unsigned int) 20) // Reserved
+#define AT91C_ID_21_Reserved ((unsigned int) 21) // Reserved
+#define AT91C_ID_22_Reserved ((unsigned int) 22) // Reserved
+#define AT91C_ID_23_Reserved ((unsigned int) 23) // Reserved
+#define AT91C_ID_24_Reserved ((unsigned int) 24) // Reserved
+#define AT91C_ID_25_Reserved ((unsigned int) 25) // Reserved
+#define AT91C_ID_26_Reserved ((unsigned int) 26) // Reserved
+#define AT91C_ID_27_Reserved ((unsigned int) 27) // Reserved
+#define AT91C_ID_28_Reserved ((unsigned int) 28) // Reserved
+#define AT91C_ID_29_Reserved ((unsigned int) 29) // Reserved
+#define AT91C_ID_IRQ0 ((unsigned int) 30) // Advanced Interrupt Controller (IRQ0)
+#define AT91C_ID_IRQ1 ((unsigned int) 31) // Advanced Interrupt Controller (IRQ1)
+#define AT91C_ALL_INT ((unsigned int) 0xC0007FF7) // ALL VALID INTERRUPTS
+
+// *****************************************************************************
+// BASE ADDRESS DEFINITIONS FOR AT91SAM7S64
+// *****************************************************************************
+#define AT91C_BASE_SYS ((AT91PS_SYS) 0xFFFFF000) // (SYS) Base Address
+#define AT91C_BASE_AIC ((AT91PS_AIC) 0xFFFFF000) // (AIC) Base Address
+#define AT91C_BASE_PDC_DBGU ((AT91PS_PDC) 0xFFFFF300) // (PDC_DBGU) Base Address
+#define AT91C_BASE_DBGU ((AT91PS_DBGU) 0xFFFFF200) // (DBGU) Base Address
+#define AT91C_BASE_PIOA ((AT91PS_PIO) 0xFFFFF400) // (PIOA) Base Address
+#define AT91C_BASE_CKGR ((AT91PS_CKGR) 0xFFFFFC20) // (CKGR) Base Address
+#define AT91C_BASE_PMC ((AT91PS_PMC) 0xFFFFFC00) // (PMC) Base Address
+#define AT91C_BASE_RSTC ((AT91PS_RSTC) 0xFFFFFD00) // (RSTC) Base Address
+#define AT91C_BASE_RTTC ((AT91PS_RTTC) 0xFFFFFD20) // (RTTC) Base Address
+#define AT91C_BASE_PITC ((AT91PS_PITC) 0xFFFFFD30) // (PITC) Base Address
+#define AT91C_BASE_WDTC ((AT91PS_WDTC) 0xFFFFFD40) // (WDTC) Base Address
+#define AT91C_BASE_VREG ((AT91PS_VREG) 0xFFFFFD60) // (VREG) Base Address
+#define AT91C_BASE_MC ((AT91PS_MC) 0xFFFFFF00) // (MC) Base Address
+#define AT91C_BASE_PDC_SPI ((AT91PS_PDC) 0xFFFE0100) // (PDC_SPI) Base Address
+#define AT91C_BASE_SPI ((AT91PS_SPI) 0xFFFE0000) // (SPI) Base Address
+#define AT91C_BASE_PDC_ADC ((AT91PS_PDC) 0xFFFD8100) // (PDC_ADC) Base Address
+#define AT91C_BASE_ADC ((AT91PS_ADC) 0xFFFD8000) // (ADC) Base Address
+#define AT91C_BASE_PDC_SSC ((AT91PS_PDC) 0xFFFD4100) // (PDC_SSC) Base Address
+#define AT91C_BASE_SSC ((AT91PS_SSC) 0xFFFD4000) // (SSC) Base Address
+#define AT91C_BASE_PDC_US1 ((AT91PS_PDC) 0xFFFC4100) // (PDC_US1) Base Address
+#define AT91C_BASE_US1 ((AT91PS_USART) 0xFFFC4000) // (US1) Base Address
+#define AT91C_BASE_PDC_US0 ((AT91PS_PDC) 0xFFFC0100) // (PDC_US0) Base Address
+#define AT91C_BASE_US0 ((AT91PS_USART) 0xFFFC0000) // (US0) Base Address
+#define AT91C_BASE_TWI ((AT91PS_TWI) 0xFFFB8000) // (TWI) Base Address
+#define AT91C_BASE_TC0 ((AT91PS_TC) 0xFFFA0000) // (TC0) Base Address
+#define AT91C_BASE_TC1 ((AT91PS_TC) 0xFFFA0040) // (TC1) Base Address
+#define AT91C_BASE_TC2 ((AT91PS_TC) 0xFFFA0080) // (TC2) Base Address
+#define AT91C_BASE_TCB ((AT91PS_TCB) 0xFFFA0000) // (TCB) Base Address
+#define AT91C_BASE_PWMC_CH3 ((AT91PS_PWMC_CH) 0xFFFCC260) // (PWMC_CH3) Base Address
+#define AT91C_BASE_PWMC_CH2 ((AT91PS_PWMC_CH) 0xFFFCC240) // (PWMC_CH2) Base Address
+#define AT91C_BASE_PWMC_CH1 ((AT91PS_PWMC_CH) 0xFFFCC220) // (PWMC_CH1) Base Address
+#define AT91C_BASE_PWMC_CH0 ((AT91PS_PWMC_CH) 0xFFFCC200) // (PWMC_CH0) Base Address
+#define AT91C_BASE_PWMC ((AT91PS_PWMC) 0xFFFCC000) // (PWMC) Base Address
+#define AT91C_BASE_UDP ((AT91PS_UDP) 0xFFFB0000) // (UDP) Base Address
+
+// *****************************************************************************
+// MEMORY MAPPING DEFINITIONS FOR AT91SAM7S64
+// *****************************************************************************
+// ISRAM
+#define AT91C_ISRAM ((char *) 0x00200000) // Internal SRAM base address
+// IFLASH
+#define AT91C_IFLASH ((char *) 0x00100000) // Internal FLASH base address
+
+#ifdef __AT91SAM7S64__
+#define AT91C_ISRAM_SIZE ((unsigned int) 0x00004000) // Internal SRAM size in byte (16 Kbytes)
+#define AT91C_IFLASH_SIZE ((unsigned int) 0x00010000) // Internal FLASH size in byte (64 Kbytes)
+#define AT91C_IFLASH_PAGE_SIZE ((unsigned int) 128) // Internal FLASH Page Size: 128 bytes
+#define AT91C_IFLASH_LOCK_REGION_SIZE ((unsigned int) 4096) // Internal FLASH Lock Region Size: 4 Kbytes
+#define AT91C_IFLASH_NB_OF_PAGES ((unsigned int) 256) // Internal FLASH Number of Pages: 256 bytes
+#define AT91C_IFLASH_NB_OF_LOCK_BITS ((unsigned int) 8) // Internal FLASH Number of Lock Bits: 8 bytes
+#else
+#ifdef __AT91SAM7S256__
+#define AT91C_IFLASH_SIZE ((unsigned int) 0x00040000) // Internal FLASH size in byte (256 Kbytes)
+#define AT91C_IFLASH_PAGE_SIZE ((unsigned int) 256) // Internal FLASH Page Size: 256 bytes
+#define AT91C_IFLASH_LOCK_REGION_SIZE ((unsigned int) 16384) // Internal FLASH Lock Region Size: 16 Kbytes
+#define AT91C_IFLASH_NB_OF_PAGES ((unsigned int) 1024) // Internal FLASH Number of Pages: 1024 bytes
+#define AT91C_IFLASH_NB_OF_LOCK_BITS ((unsigned int) 16) // Internal FLASH Number of Lock Bits: 16 bytes
+#else
+#error Have to define whether AT91SAM7S64 / S256
+#endif
+#endif
+
+#endif/*__AT91SAM7_H__*/
diff --git a/firmware/include/asm/assembler.h b/firmware/include/asm/assembler.h
new file mode 100644
index 0000000..b43f9d1
--- /dev/null
+++ b/firmware/include/asm/assembler.h
@@ -0,0 +1,97 @@
+/*
+ * linux/include/asm-arm/assembler.h
+ *
+ * Copyright (C) 1996-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This file contains arm architecture specific defines
+ * for the different processors.
+ *
+ * Do not include any C declarations in this file - it is included by
+ * assembler source.
+ */
+#ifndef __ASSEMBLY__
+#error "Only include this from assembly code"
+#endif
+
+#include <asm/ptrace.h>
+
+#define pull lsl
+#define push lsr
+#define get_byte_0 lsr #24
+#define get_byte_1 lsr #16
+#define get_byte_2 lsr #8
+#define get_byte_3 lsl #0
+#define put_byte_0 lsl #24
+#define put_byte_1 lsl #16
+#define put_byte_2 lsl #8
+#define put_byte_3 lsl #0
+
+#define PLD(code...)
+
+#define MODE_USR USR_MODE
+#define MODE_FIQ FIQ_MODE
+#define MODE_IRQ IRQ_MODE
+#define MODE_SVC SVC_MODE
+
+#define DEFAULT_FIQ MODE_FIQ
+
+/*
+ * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc})
+ */
+#ifdef __STDC__
+#define LOADREGS(cond, base, reglist...)\
+ ldm##cond base,reglist
+#else
+#define LOADREGS(cond, base, reglist...)\
+ ldm/**/cond base,reglist
+#endif
+
+/*
+ * Build a return instruction for this processor type.
+ */
+#define RETINSTR(instr, regs...)\
+ instr regs
+
+/*
+ * Enable and disable interrupts
+ */
+ .macro disable_irq
+ msr cpsr_c, #PSR_I_BIT | SVC_MODE
+ .endm
+
+ .macro enable_irq
+ msr cpsr_c, #SVC_MODE
+ .endm
+
+/*
+ * Save the current IRQ state and disable IRQs. Note that this macro
+ * assumes FIQs are enabled, and that the processor is in SVC mode.
+ */
+ .macro save_and_disable_irqs, oldcpsr
+ mrs \oldcpsr, cpsr
+ disable_irq
+ .endm
+
+/*
+ * Restore interrupt state previously stored in a register. We don't
+ * guarantee that this will preserve the flags.
+ */
+ .macro restore_irqs, oldcpsr
+ msr cpsr_c, \oldcpsr
+ .endm
+
+/*
+ * These two are used to save LR/restore PC over a user-based access.
+ * The old 26-bit architecture requires that we do. On 32-bit
+ * architecture, we can safely ignore this requirement.
+ */
+ .macro save_lr
+ .endm
+
+ .macro restore_pc
+ mov pc, lr
+ .endm
diff --git a/firmware/include/asm/atomic.h b/firmware/include/asm/atomic.h
new file mode 100644
index 0000000..19e8ce6
--- /dev/null
+++ b/firmware/include/asm/atomic.h
@@ -0,0 +1,106 @@
+/*
+ * linux/include/asm-arm/atomic.h
+ *
+ * Copyright (C) 1996 Russell King.
+ * Copyright (C) 2002 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARM_ATOMIC_H
+#define __ASM_ARM_ATOMIC_H
+
+typedef struct { volatile int counter; } atomic_t;
+
+#define ATOMIC_INIT(i) { (i) }
+
+#define atomic_read(v) ((v)->counter)
+
+#include <asm/system.h>
+#include <asm/compiler.h>
+
+#define atomic_set(v,i) (((v)->counter) = (i))
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+ unsigned long flags;
+ int val;
+
+ local_irq_save(flags);
+ val = v->counter;
+ v->counter = val += i;
+ local_irq_restore(flags);
+
+ return val;
+}
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+ unsigned long flags;
+ int val;
+
+ local_irq_save(flags);
+ val = v->counter;
+ v->counter = val -= i;
+ local_irq_restore(flags);
+
+ return val;
+}
+
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+ int ret;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ ret = v->counter;
+ if (likely(ret == old))
+ v->counter = new;
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *addr &= ~mask;
+ local_irq_restore(flags);
+}
+
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+static inline int atomic_add_unless(atomic_t *v, int a, int u)
+{
+ int c, old;
+
+ c = atomic_read(v);
+ while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
+ c = old;
+ return c != u;
+}
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+#define atomic_add(i, v) (void) atomic_add_return(i, v)
+#define atomic_inc(v) (void) atomic_add_return(1, v)
+#define atomic_sub(i, v) (void) atomic_sub_return(i, v)
+#define atomic_dec(v) (void) atomic_sub_return(1, v)
+
+#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
+#define atomic_inc_return(v) (atomic_add_return(1, v))
+#define atomic_dec_return(v) (atomic_sub_return(1, v))
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
+
+#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0)
+
+/* Atomic operations are already serializing on ARM */
+#define smp_mb__before_atomic_dec() barrier()
+#define smp_mb__after_atomic_dec() barrier()
+#define smp_mb__before_atomic_inc() barrier()
+#define smp_mb__after_atomic_inc() barrier()
+
+#endif
diff --git a/firmware/include/asm/bitops.h b/firmware/include/asm/bitops.h
new file mode 100644
index 0000000..337d800
--- /dev/null
+++ b/firmware/include/asm/bitops.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright 1995, Russell King.
+ * Various bits and pieces copyrights include:
+ * Linus Torvalds (test_bit).
+ * Big endian support: Copyright 2001, Nicolas Pitre
+ * reworked by rmk.
+ *
+ * bit 0 is the LSB of an "unsigned long" quantity.
+ *
+ * Please note that the code in this file should never be included
+ * from user space. Many of these are not implemented in assembler
+ * since they would be too costly. Also, they require privileged
+ * instructions (which are not available from user mode) to ensure
+ * that they are atomic.
+ */
+
+#ifndef __ASM_ARM_BITOPS_H
+#define __ASM_ARM_BITOPS_H
+
+#include <asm/system.h>
+
+#define smp_mb__before_clear_bit() mb()
+#define smp_mb__after_clear_bit() mb()
+
+/*
+ * These functions are the basis of our bit ops.
+ *
+ * First, the atomic bitops. These use native endian.
+ */
+static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p)
+{
+ unsigned long flags;
+ unsigned long mask = 1UL << (bit & 31);
+
+ p += bit >> 5;
+
+ local_irq_save(flags);
+ *p |= mask;
+ local_irq_restore(flags);
+}
+
+static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p)
+{
+ unsigned long flags;
+ unsigned long mask = 1UL << (bit & 31);
+
+ p += bit >> 5;
+
+ local_irq_save(flags);
+ *p &= ~mask;
+ local_irq_restore(flags);
+}
+
+static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p)
+{
+ unsigned long flags;
+ unsigned long mask = 1UL << (bit & 31);
+
+ p += bit >> 5;
+
+ local_irq_save(flags);
+ *p ^= mask;
+ local_irq_restore(flags);
+}
+
+static inline int
+____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p)
+{
+ unsigned long flags;
+ unsigned int res;
+ unsigned long mask = 1UL << (bit & 31);
+
+ p += bit >> 5;
+
+ local_irq_save(flags);
+ res = *p;
+ *p = res | mask;
+ local_irq_restore(flags);
+
+ return res & mask;
+}
+
+static inline int
+____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
+{
+ unsigned long flags;
+ unsigned int res;
+ unsigned long mask = 1UL << (bit & 31);
+
+ p += bit >> 5;
+
+ local_irq_save(flags);
+ res = *p;
+ *p = res & ~mask;
+ local_irq_restore(flags);
+
+ return res & mask;
+}
+
+static inline int
+____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
+{
+ unsigned long flags;
+ unsigned int res;
+ unsigned long mask = 1UL << (bit & 31);
+
+ p += bit >> 5;
+
+ local_irq_save(flags);
+ res = *p;
+ *p = res ^ mask;
+ local_irq_restore(flags);
+
+ return res & mask;
+}
+
+//#include <asm-generic/bitops/non-atomic.h>
+
+/*
+ * A note about Endian-ness.
+ * -------------------------
+ *
+ * When the ARM is put into big endian mode via CR15, the processor
+ * merely swaps the order of bytes within words, thus:
+ *
+ * ------------ physical data bus bits -----------
+ * D31 ... D24 D23 ... D16 D15 ... D8 D7 ... D0
+ * little byte 3 byte 2 byte 1 byte 0
+ * big byte 0 byte 1 byte 2 byte 3
+ *
+ * This means that reading a 32-bit word at address 0 returns the same
+ * value irrespective of the endian mode bit.
+ *
+ * Peripheral devices should be connected with the data bus reversed in
+ * "Big Endian" mode. ARM Application Note 61 is applicable, and is
+ * available from http://www.arm.com/.
+ *
+ * The following assumes that the data bus connectivity for big endian
+ * mode has been followed.
+ *
+ * Note that bit 0 is defined to be 32-bit word bit 0, not byte 0 bit 0.
+ */
+
+/*
+ * Little endian assembly bitops. nr = 0 -> byte 0 bit 0.
+ */
+extern void _set_bit_le(int nr, volatile unsigned long * p);
+extern void _clear_bit_le(int nr, volatile unsigned long * p);
+extern void _change_bit_le(int nr, volatile unsigned long * p);
+extern int _test_and_set_bit_le(int nr, volatile unsigned long * p);
+extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p);
+extern int _test_and_change_bit_le(int nr, volatile unsigned long * p);
+extern int _find_first_zero_bit_le(const void * p, unsigned size);
+extern int _find_next_zero_bit_le(const void * p, int size, int offset);
+extern int _find_first_bit_le(const unsigned long *p, unsigned size);
+extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
+
+/*
+ * Big endian assembly bitops. nr = 0 -> byte 3 bit 0.
+ */
+extern void _set_bit_be(int nr, volatile unsigned long * p);
+extern void _clear_bit_be(int nr, volatile unsigned long * p);
+extern void _change_bit_be(int nr, volatile unsigned long * p);
+extern int _test_and_set_bit_be(int nr, volatile unsigned long * p);
+extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p);
+extern int _test_and_change_bit_be(int nr, volatile unsigned long * p);
+extern int _find_first_zero_bit_be(const void * p, unsigned size);
+extern int _find_next_zero_bit_be(const void * p, int size, int offset);
+extern int _find_first_bit_be(const unsigned long *p, unsigned size);
+extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
+
+/*
+ * The __* form of bitops are non-atomic and may be reordered.
+ */
+#define ATOMIC_BITOP_LE(name,nr,p) \
+ (__builtin_constant_p(nr) ? \
+ ____atomic_##name(nr, p) : \
+ _##name##_le(nr,p))
+
+#define ATOMIC_BITOP_BE(name,nr,p) \
+ (__builtin_constant_p(nr) ? \
+ ____atomic_##name(nr, p) : \
+ _##name##_be(nr,p))
+
+#define NONATOMIC_BITOP(name,nr,p) \
+ (____nonatomic_##name(nr, p))
+
+/*
+ * These are the little endian, atomic definitions.
+ */
+#define set_bit(nr,p) ATOMIC_BITOP_LE(set_bit,nr,p)
+#define clear_bit(nr,p) ATOMIC_BITOP_LE(clear_bit,nr,p)
+#define change_bit(nr,p) ATOMIC_BITOP_LE(change_bit,nr,p)
+#define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
+#define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
+#define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
+#define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
+#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
+#define find_first_bit(p,sz) _find_first_bit_le(p,sz)
+#define find_next_bit(p,sz,off) _find_next_bit_le(p,sz,off)
+
+#define WORD_BITOFF_TO_LE(x) ((x))
+
+#if 0
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/ffs.h>
+
+#include <asm-generic/bitops/fls64.h>
+
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+#endif
+
+#define BITS_PER_LONG 32
+#define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
+
+static inline int test_bit(int nr, const volatile unsigned long *addr)
+{
+ return 1UL & (addr[BITOP_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
+}
+
+#endif /* _ARM_BITOPS_H */
diff --git a/firmware/include/asm/compiler.h b/firmware/include/asm/compiler.h
new file mode 100644
index 0000000..de4dfaa
--- /dev/null
+++ b/firmware/include/asm/compiler.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_COMPILER_H
+#define _ASM_COMPILER_H
+
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
+#endif
diff --git a/firmware/include/asm/ctype.h b/firmware/include/asm/ctype.h
new file mode 100644
index 0000000..afa3639
--- /dev/null
+++ b/firmware/include/asm/ctype.h
@@ -0,0 +1,54 @@
+#ifndef _LINUX_CTYPE_H
+#define _LINUX_CTYPE_H
+
+/*
+ * NOTE! This ctype does not handle EOF like the standard C
+ * library is required to.
+ */
+
+#define _U 0x01 /* upper */
+#define _L 0x02 /* lower */
+#define _D 0x04 /* digit */
+#define _C 0x08 /* cntrl */
+#define _P 0x10 /* punct */
+#define _S 0x20 /* white space (space/lf/tab) */
+#define _X 0x40 /* hex digit */
+#define _SP 0x80 /* hard space (0x20) */
+
+extern unsigned char _ctype[];
+
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
+#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
+#define iscntrl(c) ((__ismask(c)&(_C)) != 0)
+#define isdigit(c) ((__ismask(c)&(_D)) != 0)
+#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
+#define islower(c) ((__ismask(c)&(_L)) != 0)
+#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
+#define ispunct(c) ((__ismask(c)&(_P)) != 0)
+#define isspace(c) ((__ismask(c)&(_S)) != 0)
+#define isupper(c) ((__ismask(c)&(_U)) != 0)
+#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
+
+#define isascii(c) (((unsigned char)(c))<=0x7f)
+#define toascii(c) (((unsigned char)(c))&0x7f)
+
+static inline unsigned char __tolower(unsigned char c)
+{
+ if (isupper(c))
+ c -= 'A'-'a';
+ return c;
+}
+
+static inline unsigned char __toupper(unsigned char c)
+{
+ if (islower(c))
+ c -= 'a'-'A';
+ return c;
+}
+
+#define tolower(c) __tolower(c)
+#define toupper(c) __toupper(c)
+
+#endif
diff --git a/firmware/include/asm/div64.h b/firmware/include/asm/div64.h
new file mode 100644
index 0000000..3682616
--- /dev/null
+++ b/firmware/include/asm/div64.h
@@ -0,0 +1,48 @@
+#ifndef __ASM_ARM_DIV64
+#define __ASM_ARM_DIV64
+
+#include <asm/system.h>
+
+/*
+ * The semantics of do_div() are:
+ *
+ * uint32_t do_div(uint64_t *n, uint32_t base)
+ * {
+ * uint32_t remainder = *n % base;
+ * *n = *n / base;
+ * return remainder;
+ * }
+ *
+ * In other words, a 64-bit dividend with a 32-bit divisor producing
+ * a 64-bit result and a 32-bit remainder. To accomplish this optimally
+ * we call a special __do_div64 helper with completely non standard
+ * calling convention for arguments and results (beware).
+ */
+
+#ifdef __ARMEB__
+#define __xh "r0"
+#define __xl "r1"
+#else
+#define __xl "r0"
+#define __xh "r1"
+#endif
+
+#define do_div(n,base) \
+({ \
+ register unsigned int __base asm("r4") = base; \
+ register unsigned long long __n asm("r0") = n; \
+ register unsigned long long __res asm("r2"); \
+ register unsigned int __rem asm(__xh); \
+ asm( __asmeq("%0", __xh) \
+ __asmeq("%1", "r2") \
+ __asmeq("%2", "r0") \
+ __asmeq("%3", "r4") \
+ "bl __do_div64" \
+ : "=r" (__rem), "=r" (__res) \
+ : "r" (__n), "r" (__base) \
+ : "ip", "lr", "cc"); \
+ n = __res; \
+ __rem; \
+})
+
+#endif
diff --git a/firmware/include/asm/linkage.h b/firmware/include/asm/linkage.h
new file mode 100644
index 0000000..ac1c900
--- /dev/null
+++ b/firmware/include/asm/linkage.h
@@ -0,0 +1,18 @@
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+/* asm-arm/linkage.h */
+
+#define __ALIGN .align 0
+#define __ALIGN_STR ".align 0"
+
+/* linux/linkage.h */
+
+#define ALIGN __ALIGN
+
+#define ENTRY(name) \
+ .globl name; \
+ ALIGN; \
+ name:
+
+#endif
diff --git a/firmware/include/asm/ptrace.h b/firmware/include/asm/ptrace.h
new file mode 100644
index 0000000..f3a654e
--- /dev/null
+++ b/firmware/include/asm/ptrace.h
@@ -0,0 +1,128 @@
+/*
+ * linux/include/asm-arm/ptrace.h
+ *
+ * Copyright (C) 1996-2003 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARM_PTRACE_H
+#define __ASM_ARM_PTRACE_H
+
+/*
+ * PSR bits
+ */
+#define USR26_MODE 0x00000000
+#define FIQ26_MODE 0x00000001
+#define IRQ26_MODE 0x00000002
+#define SVC26_MODE 0x00000003
+#define USR_MODE 0x00000010
+#define FIQ_MODE 0x00000011
+#define IRQ_MODE 0x00000012
+#define SVC_MODE 0x00000013
+#define ABT_MODE 0x00000017
+#define UND_MODE 0x0000001b
+#define SYSTEM_MODE 0x0000001f
+#define MODE32_BIT 0x00000010
+#define MODE_MASK 0x0000001f
+#define PSR_T_BIT 0x00000020
+#define PSR_F_BIT 0x00000040
+#define PSR_I_BIT 0x00000080
+#define PSR_J_BIT 0x01000000
+#define PSR_Q_BIT 0x08000000
+#define PSR_V_BIT 0x10000000
+#define PSR_C_BIT 0x20000000
+#define PSR_Z_BIT 0x40000000
+#define PSR_N_BIT 0x80000000
+#define PCMASK 0
+
+/*
+ * Groups of PSR bits
+ */
+#define PSR_f 0xff000000 /* Flags */
+#define PSR_s 0x00ff0000 /* Status */
+#define PSR_x 0x0000ff00 /* Extension */
+#define PSR_c 0x000000ff /* Control */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are stored on the
+ * stack during a system call. Note that sizeof(struct pt_regs)
+ * has to be a multiple of 8.
+ */
+struct pt_regs {
+ long uregs[18];
+};
+
+#define ARM_cpsr uregs[16]
+#define ARM_pc uregs[15]
+#define ARM_lr uregs[14]
+#define ARM_sp uregs[13]
+#define ARM_ip uregs[12]
+#define ARM_fp uregs[11]
+#define ARM_r10 uregs[10]
+#define ARM_r9 uregs[9]
+#define ARM_r8 uregs[8]
+#define ARM_r7 uregs[7]
+#define ARM_r6 uregs[6]
+#define ARM_r5 uregs[5]
+#define ARM_r4 uregs[4]
+#define ARM_r3 uregs[3]
+#define ARM_r2 uregs[2]
+#define ARM_r1 uregs[1]
+#define ARM_r0 uregs[0]
+#define ARM_ORIG_r0 uregs[17]
+
+#define user_mode(regs) \
+ (((regs)->ARM_cpsr & 0xf) == 0)
+
+#ifdef CONFIG_ARM_THUMB
+#define thumb_mode(regs) \
+ (((regs)->ARM_cpsr & PSR_T_BIT))
+#else
+#define thumb_mode(regs) (0)
+#endif
+
+#define processor_mode(regs) \
+ ((regs)->ARM_cpsr & MODE_MASK)
+
+#define interrupts_enabled(regs) \
+ (!((regs)->ARM_cpsr & PSR_I_BIT))
+
+#define fast_interrupts_enabled(regs) \
+ (!((regs)->ARM_cpsr & PSR_F_BIT))
+
+#define condition_codes(regs) \
+ ((regs)->ARM_cpsr & (PSR_V_BIT|PSR_C_BIT|PSR_Z_BIT|PSR_N_BIT))
+
+/* Are the current registers suitable for user mode?
+ * (used to maintain security in signal handlers)
+ */
+static inline int valid_user_regs(struct pt_regs *regs)
+{
+ if (user_mode(regs) &&
+ (regs->ARM_cpsr & (PSR_F_BIT|PSR_I_BIT)) == 0)
+ return 1;
+
+ /*
+ * Force CPSR to something logical...
+ */
+ regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT;
+
+ return 0;
+}
+
+#define pc_pointer(v) \
+ ((v) & ~PCMASK)
+
+#define instruction_pointer(regs) \
+ (pc_pointer((regs)->ARM_pc))
+
+#define profile_pc(regs) instruction_pointer(regs)
+
+#endif /* __ASSEMBLY__ */
+
+#endif
+
diff --git a/firmware/include/asm/system.h b/firmware/include/asm/system.h
new file mode 100644
index 0000000..2bf0cc5
--- /dev/null
+++ b/firmware/include/asm/system.h
@@ -0,0 +1,109 @@
+#ifndef __ASM_ARM_SYSTEM_H
+#define __ASM_ARM_SYSTEM_H
+
+/* Generic ARM7TDMI (ARMv4T) synchronisation primitives, mostly
+ * taken from Linux kernel source, licensed under GPL */
+
+#define local_irq_save(x) \
+ ({ \
+ unsigned long temp; \
+ (void) (&temp == &x); \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ local_irq_save\n" \
+" orr %1, %0, #128\n" \
+" msr cpsr_c, %1" \
+ : "=r" (x), "=r" (temp) \
+ : \
+ : "memory", "cc"); \
+ })
+
+/*
+ * Enable IRQs
+ */
+#define local_irq_enable() \
+ ({ \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ local_irq_enable\n" \
+" bic %0, %0, #128\n" \
+" msr cpsr_c, %0" \
+ : "=r" (temp) \
+ : \
+ : "memory", "cc"); \
+ })
+
+/*
+ * Disable IRQs
+ */
+#define local_irq_disable() \
+ ({ \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ local_irq_disable\n" \
+" orr %0, %0, #128\n" \
+" msr cpsr_c, %0" \
+ : "=r" (temp) \
+ : \
+ : "memory", "cc"); \
+ })
+
+/*
+ * Enable FIQs
+ */
+#define local_fiq_enable() \
+ ({ \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ stf\n" \
+" bic %0, %0, #64\n" \
+" msr cpsr_c, %0" \
+ : "=r" (temp) \
+ : \
+ : "memory", "cc"); \
+ })
+
+/*
+ * Disable FIQs
+ */
+#define local_fiq_disable() \
+ ({ \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ clf\n" \
+" orr %0, %0, #64\n" \
+" msr cpsr_c, %0" \
+ : "=r" (temp) \
+ : \
+ : "memory", "cc"); \
+ })
+
+/*
+ * Save the current interrupt enable state.
+ */
+#define local_save_flags(x) \
+ ({ \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ local_save_flags" \
+ : "=r" (x) : : "memory", "cc"); \
+ })
+
+/*
+ * restore saved IRQ & FIQ state
+ */
+#define local_irq_restore(x) \
+ __asm__ __volatile__( \
+ "msr cpsr_c, %0 @ local_irq_restore\n" \
+ : \
+ : "r" (x) \
+ : "memory", "cc")
+
+#define irqs_disabled() \
+({ \
+ unsigned long flags; \
+ local_save_flags(flags); \
+ (int)(flags & PSR_I_BIT); \
+})
+
+#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
+
+#endif
diff --git a/firmware/include/board.h b/firmware/include/board.h
new file mode 100644
index 0000000..8dd9182
--- /dev/null
+++ b/firmware/include/board.h
@@ -0,0 +1,13 @@
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+#include <AT91SAM7.h>
+#include <lib_AT91SAM7.h>
+
+/*--------------*/
+/* Master Clock */
+/*--------------*/
+#define EXT_OSC 18432000 // External Crystal Oscillator
+#define MCK 47923200 // Resulting PLL CLock
+
+#endif/*__BOARD_H__*/
diff --git a/firmware/include/cl_rc632.h b/firmware/include/cl_rc632.h
new file mode 100644
index 0000000..47dcc15
--- /dev/null
+++ b/firmware/include/cl_rc632.h
@@ -0,0 +1,237 @@
+/* Register definitions for Philips CL RC632 RFID Reader IC
+ *
+ * (C) 2005 Harald Welte <laforge@gnumonks.org>
+ *
+ * Licensed under GNU General Public License, Version 2
+ */
+
+#ifndef _CLRC632_H
+#define _CLRC632_H
+
+enum rc632_registers {
+ RC632_REG_PAGE0 = 0x00,
+ RC632_REG_COMMAND = 0x01,
+ RC632_REG_FIFO_DATA = 0x02,
+ RC632_REG_PRIMARY_STATUS = 0x03,
+ RC632_REG_FIFO_LENGTH = 0x04,
+ RC632_REG_SECONDARY_STATUS = 0x05,
+ RC632_REG_INTERRUPT_EN = 0x06,
+ RC632_REG_INTERRUPT_RQ = 0x07,
+
+ RC632_REG_PAGE1 = 0x08,
+ RC632_REG_CONTROL = 0x09,
+ RC632_REG_ERROR_FLAG = 0x0a,
+ RC632_REG_COLL_POS = 0x0b,
+ RC632_REG_TIMER_VALUE = 0x0c,
+ RC632_REG_CRC_RESULT_LSB = 0x0d,
+ RC632_REG_CRC_RESULT_MSB = 0x0e,
+ RC632_REG_BIT_FRAMING = 0x0f,
+
+ RC632_REG_PAGE2 = 0x10,
+ RC632_REG_TX_CONTROL = 0x11,
+ RC632_REG_CW_CONDUCTANCE = 0x12,
+ RC632_REG_MOD_CONDUCTANCE = 0x13,
+ RC632_REG_CODER_CONTROL = 0x14,
+ RC632_REG_MOD_WIDTH = 0x15,
+ RC632_REG_MOD_WIDTH_SOF = 0x16,
+ RC632_REG_TYPE_B_FRAMING = 0x17,
+
+ RC632_REG_PAGE3 = 0x18,
+ RC632_REG_RX_CONTROL1 = 0x19,
+ RC632_REG_DECODER_CONTROL = 0x1a,
+ RC632_REG_BIT_PHASE = 0x1b,
+ RC632_REG_RX_THRESHOLD = 0x1c,
+ RC632_REG_BPSK_DEM_CONTROL = 0x1d,
+ RC632_REG_RX_CONTROL2 = 0x1e,
+ RC632_REG_CLOCK_Q_CONTROL = 0x1f,
+
+ RC632_REG_PAGE4 = 0x20,
+ RC632_REG_RX_WAIT = 0x21,
+ RC632_REG_CHANNEL_REDUNDANCY = 0x22,
+ RC632_REG_CRC_PRESET_LSB = 0x23,
+ RC632_REG_CRC_PRESET_MSB = 0x24,
+ RC632_REG_TIME_SLOT_PERIOD = 0x25,
+ RC632_REG_MFOUT_SELECT = 0x26,
+ RC632_REG_PRESET_27 = 0x27,
+
+ RC632_REG_PAGE5 = 0x28,
+ RC632_REG_FIFO_LEVEL = 0x29,
+ RC632_REG_TIMER_CLOCK = 0x2a,
+ RC632_REG_TIMER_CONTROL = 0x2b,
+ RC632_REG_TIMER_RELOAD = 0x2c,
+ RC632_REG_IRQ_PIN_CONFIG = 0x2d,
+ RC632_REG_PRESET_2E = 0x2e,
+ RC632_REG_PRESET_2F = 0x2f,
+
+ RC632_REG_PAGE6 = 0x30,
+
+ RC632_REG_PAGE7 = 0x38,
+ RC632_REG_TEST_ANA_SELECT = 0x3a,
+ RC632_REG_TEST_DIGI_SELECT = 0x3d,
+};
+
+enum rc632_reg_command {
+ RC632_CMD_IDLE = 0x00,
+ RC632_CMD_WRITE_E2 = 0x01,
+ RC632_CMD_READ_E2 = 0x03,
+ RC632_CMD_LOAD_CONFIG = 0x07,
+ RC632_CMD_LOAD_KEY_E2 = 0x0b,
+ RC632_CMD_AUTHENT1 = 0x0c,
+ RC632_CMD_CALC_CRC = 0x12,
+ RC632_CMD_AUTHENT2 = 0x14,
+ RC632_CMD_RECEIVE = 0x16,
+ RC632_CMD_LOAD_KEY = 0x19,
+ RC632_CMD_TRANSMIT = 0x1a,
+ RC632_CMD_TRANSCEIVE = 0x1e,
+ RC632_CMD_STARTUP = 0x3f,
+};
+
+enum rc632_reg_interrupt {
+ RC632_INT_LOALERT = 0x01,
+ RC632_INT_HIALERT = 0x02,
+ RC632_INT_IDLE = 0x04,
+ RC632_INT_RX = 0x08,
+ RC632_INT_TX = 0x10,
+ RC632_INT_TIMER = 0x20,
+ RC632_INT_SET = 0x80,
+};
+
+enum rc632_reg_control {
+ RC632_CONTROL_CRYPTO1_ON = 0x08,
+ RC632_CONTROL_POWERDOWN = 0x10,
+};
+
+enum rc632_reg_error_flag {
+ RC632_ERR_FLAG_COL_ERR = 0x01,
+ RC632_ERR_FLAG_PARITY_ERR = 0x02,
+ RC632_ERR_FLAG_FRAMING_ERR = 0x04,
+ RC632_ERR_FLAG_CRC_ERR = 0x08,
+ RC632_ERR_FLAG_FIFO_OVERFLOW = 0x10,
+ RC632_ERR_FLAG_ACCESS_ERR = 0x20,
+ RC632_ERR_FLAG_KEY_ERR = 0x40,
+};
+
+enum rc632_reg_tx_control {
+ RC632_TXCTRL_TX1_RF_EN = 0x01,
+ RC632_TXCTRL_TX2_RF_EN = 0x02,
+ RC632_TXCTRL_TX2_CW = 0x04,
+ RC632_TXCTRL_TX2_INV = 0x08,
+ RC632_TXCTRL_FORCE_100_ASK = 0x10,
+
+ RC632_TXCTRL_MOD_SRC_LOW = 0x00,
+ RC632_TXCTRL_MOD_SRC_HIGH = 0x20,
+ RC632_TXCTRL_MOD_SRC_INT = 0x40,
+ RC632_TXCTRL_MOD_SRC_MFIN = 0x60,
+};
+
+enum rc632_reg_coder_control {
+ RC632_CDRCTRL_TXCD_NRZ = 0x00,
+ RC632_CDRCTRL_TXCD_14443A = 0x01,
+ RC632_CDRCTRL_TXCD_ICODE_STD = 0x04,
+
+#define RC632_CDRCTRL_RATE_MASK 0x38
+ RC632_CDRCTRL_RATE_848K = 0x00,
+ RC632_CDRCTRL_RATE_424K = 0x08,
+ RC632_CDRCTRL_RATE_212K = 0x10,
+ RC632_CDRCTRL_RATE_106K = 0x18,
+ RC632_CDRCTRL_RATE_14443B = 0x20,
+ RC632_CDRCTRL_RATE_15693 = 0x28,
+ RC632_CDRCTRL_RATE_ICODE_FAST = 0x30,
+};
+
+enum rc632_erg_type_b_framing {
+ RC632_TBFRAMING_SOF_10L_2H = 0x00,
+ RC632_TBFRAMING_SOF_10L_3H = 0x01,
+ RC632_TBFRAMING_SOF_11L_2H = 0x02,
+ RC632_TBFRAMING_SOF_11L_3H = 0x03,
+
+ RC632_TBFRAMING_EOF_10 = 0x00,
+ RC632_TBFRAMING_EOF_11 = 0x20,
+
+ RC632_TBFRAMING_NO_TX_SOF = 0x80,
+ RC632_TBFRAMING_NO_TX_EOF = 0x40,
+};
+#define RC632_TBFRAMING_SPACE_SHIFT 2
+#define RC632_TBFRAMING_SPACE_MASK 7
+
+enum rc632_reg_rx_control1 {
+ RC632_RXCTRL1_GAIN_20DB = 0x00,
+ RC632_RXCTRL1_GAIN_24DB = 0x01,
+ RC632_RXCTRL1_GAIN_31DB = 0x02,
+ RC632_RXCTRL1_GAIN_35DB = 0x03,
+
+ RC632_RXCTRL1_LP_OFF = 0x04,
+ RC632_RXCTRL1_ISO15693 = 0x08,
+ RC632_RXCTRL1_ISO14443 = 0x10,
+
+#define RC632_RXCTRL1_SUBCP_MASK 0xe0
+ RC632_RXCTRL1_SUBCP_1 = 0x00,
+ RC632_RXCTRL1_SUBCP_2 = 0x20,
+ RC632_RXCTRL1_SUBCP_4 = 0x40,
+ RC632_RXCTRL1_SUBCP_8 = 0x60,
+ RC632_RXCTRL1_SUBCP_16 = 0x80,
+};
+
+enum rc632_reg_decoder_control {
+ RC632_DECCTRL_MANCHESTER = 0x00,
+ RC632_DECCTRL_BPSK = 0x01,
+
+ RC632_DECCTRL_RX_INVERT = 0x04,
+
+ RC632_DECCTRL_RXFR_ICODE = 0x00,
+ RC632_DECCTRL_RXFR_14443A = 0x08,
+ RC632_DECCTRL_RXFR_15693 = 0x10,
+ RC632_DECCTRL_RXFR_14443B = 0x18,
+
+ RC632_DECCTRL_ZEROAFTERCOL = 0x20,
+
+ RC632_DECCTRL_RX_MULTIPLE = 0x40,
+};
+
+enum rc632_reg_bpsk_dem_control {
+ RC632_BPSKD_TAUB_SHIFT = 0x00,
+ RC632_BPSKD_TAUB_MASK = 0x03,
+
+ RC632_BPSKD_TAUD_SHIFT = 0x02,
+ RC632_BPSKD_TAUD_MASK = 0x03,
+
+ RC632_BPSKD_FILTER_AMP_DETECT = 0x10,
+ RC632_BPSKD_NO_RX_EOF = 0x20,
+ RC632_BPSKD_NO_RX_EGT = 0x40,
+ RC632_BPSKD_NO_RX_SOF = 0x80,
+};
+
+enum rc632_reg_rx_control2 {
+ RC632_RXCTRL2_DECSRC_LOW = 0x00,
+ RC632_RXCTRL2_DECSRC_INT = 0x01,
+ RC632_RXCTRL2_DECSRC_SUBC_MFIN = 0x10,
+ RC632_RXCTRL2_DECSRC_BASE_MFIN = 0x11,
+
+ RC632_RXCTRL2_AUTO_PD = 0x40,
+ RC632_RXCTRL2_CLK_I = 0x80,
+ RC632_RXCTRL2_CLK_Q = 0x00,
+};
+
+enum rc632_reg_channel_redundancy {
+ RC632_CR_PARITY_ENABLE = 0x01,
+ RC632_CR_PARITY_ODD = 0x02,
+ RC632_CR_TX_CRC_ENABLE = 0x04,
+ RC632_CR_RX_CRC_ENABLE = 0x08,
+ RC632_CR_CRC8 = 0x10,
+ RC632_CR_CRC3309 = 0x20,
+};
+
+enum rc632_reg_timer_control {
+ RC632_TMR_START_TX_BEGIN = 0x01,
+ RC632_TMR_START_TX_END = 0x02,
+ RC632_TMR_STOP_RX_BEGIN = 0x04,
+ RC632_TMR_STOP_RX_END = 0x08,
+};
+
+enum rc632_reg_irq_pin_cfg {
+ RC632_IRQCFG_CMOS = 0x01,
+ RC632_IRQCFG_INV = 0x02,
+};
+
+
+#endif
diff --git a/firmware/include/lib_AT91SAM7.h b/firmware/include/lib_AT91SAM7.h
new file mode 100644
index 0000000..63943e3
--- /dev/null
+++ b/firmware/include/lib_AT91SAM7.h
@@ -0,0 +1,3476 @@
+//* ----------------------------------------------------------------------------
+//* ATMEL Microcontroller Software Support - ROUSSET -
+//* ----------------------------------------------------------------------------
+//* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+//* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+//* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+//* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+//* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+//* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+//* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+//* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+//* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//* ----------------------------------------------------------------------------
+//* File Name : lib_AT91SAM7S64.h
+//* Object : AT91SAM7S64 inlined functions
+//* Generated : AT91 SW Application Group 08/30/2005 (15:52:59)
+//*
+//* CVS Reference : /lib_dbgu.h/1.1/Thu Aug 25 12:56:22 2005//
+//* CVS Reference : /lib_pmc_SAM7S.h/1.4/Tue Aug 30 13:00:43 2005//
+//* CVS Reference : /lib_VREG_6085B.h/1.1/Tue Feb 1 16:20:47 2005//
+//* CVS Reference : /lib_rstc_6098A.h/1.1/Wed Oct 6 10:39:20 2004//
+//* CVS Reference : /lib_ssc.h/1.4/Fri Jan 31 12:19:20 2003//
+//* CVS Reference : /lib_wdtc_6080A.h/1.1/Wed Oct 6 10:38:30 2004//
+//* CVS Reference : /lib_usart.h/1.5/Thu Nov 21 16:01:54 2002//
+//* CVS Reference : /lib_spi2.h/1.2/Tue Aug 23 15:37:28 2005//
+//* CVS Reference : /lib_pitc_6079A.h/1.2/Tue Nov 9 14:43:56 2004//
+//* CVS Reference : /lib_aic_6075b.h/1.2/Thu Jul 7 07:48:22 2005//
+//* CVS Reference : /lib_twi.h/1.3/Mon Jul 19 14:27:58 2004//
+//* CVS Reference : /lib_adc.h/1.6/Fri Oct 17 09:12:38 2003//
+//* CVS Reference : /lib_rttc_6081A.h/1.1/Wed Oct 6 10:39:38 2004//
+//* CVS Reference : /lib_udp.h/1.5/Tue Aug 30 12:13:47 2005//
+//* CVS Reference : /lib_tc_1753b.h/1.1/Fri Jan 31 12:20:02 2003//
+//* CVS Reference : /lib_MC_SAM7S.h/1.1/Thu Mar 25 15:19:14 2004//
+//* CVS Reference : /lib_pio.h/1.3/Fri Jan 31 12:18:56 2003//
+//* CVS Reference : /lib_PWM_SAM.h/1.3/Thu Jan 22 10:10:50 2004//
+//* CVS Reference : /lib_pdc.h/1.2/Tue Jul 2 13:29:40 2002//
+//* ----------------------------------------------------------------------------
+
+#ifndef lib_AT91SAM7S64_H
+#define lib_AT91SAM7S64_H
+
+#include <AT91SAM7.h>
+
+/* *****************************************************************************
+ SOFTWARE API FOR AIC
+ ***************************************************************************** */
+#define AT91C_AIC_BRANCH_OPCODE ((void (*) ()) 0xE51FFF20) // ldr, pc, [pc, #-&F20]
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_ConfigureIt
+//* \brief Interrupt Handler Initialization
+//*----------------------------------------------------------------------------
+extern unsigned int AT91F_AIC_ConfigureIt (
+ AT91PS_AIC pAic, // \arg pointer to the AIC registers
+ unsigned int irq_id, // \arg interrupt number to initialize
+ unsigned int priority, // \arg priority to give to the interrupt
+ unsigned int src_type, // \arg activation and sense of activation
+ void (*newHandler) () ); // \arg address of the interrupt handler
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_EnableIt
+//* \brief Enable corresponding IT number
+//*----------------------------------------------------------------------------
+static inline void AT91F_AIC_EnableIt (
+ AT91PS_AIC pAic, // \arg pointer to the AIC registers
+ unsigned int irq_id ) // \arg interrupt number to initialize
+{
+ //* Enable the interrupt on the interrupt controller
+ pAic->AIC_IECR = 0x1 << irq_id ;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_DisableIt
+//* \brief Disable corresponding IT number
+//*----------------------------------------------------------------------------
+static inline void AT91F_AIC_DisableIt (
+ AT91PS_AIC pAic, // \arg pointer to the AIC registers
+ unsigned int irq_id ) // \arg interrupt number to initialize
+{
+ unsigned int mask = 0x1 << irq_id;
+ //* Disable the interrupt on the interrupt controller
+ pAic->AIC_IDCR = mask ;
+ //* Clear the interrupt on the Interrupt Controller ( if one is pending )
+ pAic->AIC_ICCR = mask ;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_ClearIt
+//* \brief Clear corresponding IT number
+//*----------------------------------------------------------------------------
+static inline void AT91F_AIC_ClearIt (
+ AT91PS_AIC pAic, // \arg pointer to the AIC registers
+ unsigned int irq_id) // \arg interrupt number to initialize
+{
+ //* Clear the interrupt on the Interrupt Controller ( if one is pending )
+ pAic->AIC_ICCR = (0x1 << irq_id);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_AcknowledgeIt
+//* \brief Acknowledge corresponding IT number
+//*----------------------------------------------------------------------------
+static inline void AT91F_AIC_AcknowledgeIt (
+ AT91PS_AIC pAic) // \arg pointer to the AIC registers
+{
+ pAic->AIC_EOICR = pAic->AIC_EOICR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_SetExceptionVector
+//* \brief Configure vector handler
+//*----------------------------------------------------------------------------
+extern unsigned int AT91F_AIC_SetExceptionVector (
+ unsigned int *pVector, // \arg pointer to the AIC registers
+ void (*Handler) () ); // \arg Interrupt Handler
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_Trig
+//* \brief Trig an IT
+//*----------------------------------------------------------------------------
+static inline void AT91F_AIC_Trig (
+ AT91PS_AIC pAic, // \arg pointer to the AIC registers
+ unsigned int irq_id) // \arg interrupt number
+{
+ pAic->AIC_ISCR = (0x1 << irq_id) ;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_IsActive
+//* \brief Test if an IT is active
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_AIC_IsActive (
+ AT91PS_AIC pAic, // \arg pointer to the AIC registers
+ unsigned int irq_id) // \arg Interrupt Number
+{
+ return (pAic->AIC_ISR & (0x1 << irq_id));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_IsPending
+//* \brief Test if an IT is pending
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_AIC_IsPending (
+ AT91PS_AIC pAic, // \arg pointer to the AIC registers
+ unsigned int irq_id) // \arg Interrupt Number
+{
+ return (pAic->AIC_IPR & (0x1 << irq_id));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_Open
+//* \brief Set exception vectors and AIC registers to default values
+//*----------------------------------------------------------------------------
+extern void AT91F_AIC_Open(
+ AT91PS_AIC pAic, // \arg pointer to the AIC registers
+ void (*IrqHandler) (), // \arg Default IRQ vector exception
+ void (*FiqHandler) (), // \arg Default FIQ vector exception
+ void (*DefaultHandler) (), // \arg Default Handler set in ISR
+ void (*SpuriousHandler) (), // \arg Default Spurious Handler
+ unsigned int protectMode); // \arg Debug Control Register
+
+/* *****************************************************************************
+ SOFTWARE API FOR PDC
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_SetNextRx
+//* \brief Set the next receive transfer descriptor
+//*----------------------------------------------------------------------------
+static inline void AT91F_PDC_SetNextRx (
+ AT91PS_PDC pPDC, // \arg pointer to a PDC controller
+ unsigned char *address,// \arg address to the next bloc to be received
+ unsigned int bytes) // \arg number of bytes to be received
+{
+ pPDC->PDC_RNPR = (unsigned int) address;
+ pPDC->PDC_RNCR = bytes;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_SetNextTx
+//* \brief Set the next transmit transfer descriptor
+//*----------------------------------------------------------------------------
+static inline void AT91F_PDC_SetNextTx (
+ AT91PS_PDC pPDC, // \arg pointer to a PDC controller
+ const unsigned char *address,// \arg address to the next bloc to be transmitted
+ unsigned int bytes) // \arg number of bytes to be transmitted
+{
+ pPDC->PDC_TNPR = (unsigned int) address;
+ pPDC->PDC_TNCR = bytes;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_SetRx
+//* \brief Set the receive transfer descriptor
+//*----------------------------------------------------------------------------
+static inline void AT91F_PDC_SetRx (
+ AT91PS_PDC pPDC, // \arg pointer to a PDC controller
+ unsigned char *address,// \arg address to the next bloc to be received
+ unsigned int bytes) // \arg number of bytes to be received
+{
+ pPDC->PDC_RPR = (unsigned int) address;
+ pPDC->PDC_RCR = bytes;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_SetTx
+//* \brief Set the transmit transfer descriptor
+//*----------------------------------------------------------------------------
+static inline void AT91F_PDC_SetTx (
+ AT91PS_PDC pPDC, // \arg pointer to a PDC controller
+ const unsigned char *address,// \arg address to the next bloc to be transmitted
+ unsigned int bytes) // \arg number of bytes to be transmitted
+{
+ pPDC->PDC_TPR = (unsigned int) address;
+ pPDC->PDC_TCR = bytes;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_EnableTx
+//* \brief Enable transmit
+//*----------------------------------------------------------------------------
+static inline void AT91F_PDC_EnableTx (
+ AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
+{
+ pPDC->PDC_PTCR = AT91C_PDC_TXTEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_EnableRx
+//* \brief Enable receive
+//*----------------------------------------------------------------------------
+static inline void AT91F_PDC_EnableRx (
+ AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
+{
+ pPDC->PDC_PTCR = AT91C_PDC_RXTEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_DisableTx
+//* \brief Disable transmit
+//*----------------------------------------------------------------------------
+static inline void AT91F_PDC_DisableTx (
+ AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
+{
+ pPDC->PDC_PTCR = AT91C_PDC_TXTDIS;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_DisableRx
+//* \brief Disable receive
+//*----------------------------------------------------------------------------
+static inline void AT91F_PDC_DisableRx (
+ AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
+{
+ pPDC->PDC_PTCR = AT91C_PDC_RXTDIS;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_IsTxEmpty
+//* \brief Test if the current transfer descriptor has been sent
+//*----------------------------------------------------------------------------
+static inline int AT91F_PDC_IsTxEmpty ( // \return return 1 if transfer is complete
+ AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
+{
+ return !(pPDC->PDC_TCR);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_IsNextTxEmpty
+//* \brief Test if the next transfer descriptor has been moved to the current td
+//*----------------------------------------------------------------------------
+static inline int AT91F_PDC_IsNextTxEmpty ( // \return return 1 if transfer is complete
+ AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
+{
+ return !(pPDC->PDC_TNCR);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_IsRxEmpty
+//* \brief Test if the current transfer descriptor has been filled
+//*----------------------------------------------------------------------------
+static inline int AT91F_PDC_IsRxEmpty ( // \return return 1 if transfer is complete
+ AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
+{
+ return !(pPDC->PDC_RCR);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_IsNextRxEmpty
+//* \brief Test if the next transfer descriptor has been moved to the current td
+//*----------------------------------------------------------------------------
+static inline int AT91F_PDC_IsNextRxEmpty ( // \return return 1 if transfer is complete
+ AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
+{
+ return !(pPDC->PDC_RNCR);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_Open
+//* \brief Open PDC: disable TX and RX reset transfer descriptors, re-enable RX and TX
+//*----------------------------------------------------------------------------
+extern void AT91F_PDC_Open(AT91PS_PDC pPDC); // \arg pointer to a PDC controller
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_Close
+//* \brief Close PDC: disable TX and RX reset transfer descriptors
+//*----------------------------------------------------------------------------
+extern void AT91F_PDC_Close(AT91PS_PDC pPDC); // \arg pointer to a PDC controller
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_SendFrame
+//* \brief Close PDC: disable TX and RX reset transfer descriptors
+//*----------------------------------------------------------------------------
+extern unsigned int AT91F_PDC_SendFrame(
+ AT91PS_PDC pPDC,
+ const unsigned char *pBuffer,
+ unsigned int szBuffer,
+ const unsigned char *pNextBuffer,
+ unsigned int szNextBuffer);
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_ReceiveFrame
+//* \brief Close PDC: disable TX and RX reset transfer descriptors
+//*----------------------------------------------------------------------------
+extern unsigned int AT91F_PDC_ReceiveFrame (
+ AT91PS_PDC pPDC,
+ unsigned char *pBuffer,
+ unsigned int szBuffer,
+ unsigned char *pNextBuffer,
+ unsigned int szNextBuffer);
+
+/* *****************************************************************************
+ SOFTWARE API FOR DBGU
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_DBGU_InterruptEnable
+//* \brief Enable DBGU Interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_DBGU_InterruptEnable(
+ AT91PS_DBGU pDbgu, // \arg pointer to a DBGU controller
+ unsigned int flag) // \arg dbgu interrupt to be enabled
+{
+ pDbgu->DBGU_IER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_DBGU_InterruptDisable
+//* \brief Disable DBGU Interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_DBGU_InterruptDisable(
+ AT91PS_DBGU pDbgu, // \arg pointer to a DBGU controller
+ unsigned int flag) // \arg dbgu interrupt to be disabled
+{
+ pDbgu->DBGU_IDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_DBGU_GetInterruptMaskStatus
+//* \brief Return DBGU Interrupt Mask Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_DBGU_GetInterruptMaskStatus( // \return DBGU Interrupt Mask Status
+ AT91PS_DBGU pDbgu) // \arg pointer to a DBGU controller
+{
+ return pDbgu->DBGU_IMR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_DBGU_IsInterruptMasked
+//* \brief Test if DBGU Interrupt is Masked
+//*----------------------------------------------------------------------------
+static inline int AT91F_DBGU_IsInterruptMasked(
+ AT91PS_DBGU pDbgu, // \arg pointer to a DBGU controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_DBGU_GetInterruptMaskStatus(pDbgu) & flag);
+}
+
+/* *****************************************************************************
+ SOFTWARE API FOR PIO
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_CfgPeriph
+//* \brief Enable pins to be drived by peripheral
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_CfgPeriph(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int periphAEnable, // \arg PERIPH A to enable
+ unsigned int periphBEnable) // \arg PERIPH B to enable
+
+{
+ pPio->PIO_ASR = periphAEnable;
+ pPio->PIO_BSR = periphBEnable;
+ pPio->PIO_PDR = (periphAEnable | periphBEnable); // Set in Periph mode
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_CfgOutput
+//* \brief Enable PIO in output mode
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_CfgOutput(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int pioEnable) // \arg PIO to be enabled
+{
+ pPio->PIO_PER = pioEnable; // Set in PIO mode
+ pPio->PIO_OER = pioEnable; // Configure in Output
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_CfgInput
+//* \brief Enable PIO in input mode
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_CfgInput(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int inputEnable) // \arg PIO to be enabled
+{
+ // Disable output
+ pPio->PIO_ODR = inputEnable;
+ pPio->PIO_PER = inputEnable;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_CfgOpendrain
+//* \brief Configure PIO in open drain
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_CfgOpendrain(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int multiDrvEnable) // \arg pio to be configured in open drain
+{
+ // Configure the multi-drive option
+ pPio->PIO_MDDR = ~multiDrvEnable;
+ pPio->PIO_MDER = multiDrvEnable;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_CfgPullup
+//* \brief Enable pullup on PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_CfgPullup(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int pullupEnable) // \arg enable pullup on PIO
+{
+ // Connect or not Pullup
+ pPio->PIO_PPUDR = ~pullupEnable;
+ pPio->PIO_PPUER = pullupEnable;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_CfgDirectDrive
+//* \brief Enable direct drive on PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_CfgDirectDrive(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int directDrive) // \arg PIO to be configured with direct drive
+
+{
+ // Configure the Direct Drive
+ pPio->PIO_OWDR = ~directDrive;
+ pPio->PIO_OWER = directDrive;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_CfgInputFilter
+//* \brief Enable input filter on input PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_CfgInputFilter(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int inputFilter) // \arg PIO to be configured with input filter
+
+{
+ // Configure the Direct Drive
+ pPio->PIO_IFDR = ~inputFilter;
+ pPio->PIO_IFER = inputFilter;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_GetInput
+//* \brief Return PIO input value
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PIO_GetInput( // \return PIO input
+ AT91PS_PIO pPio) // \arg pointer to a PIO controller
+{
+ return pPio->PIO_PDSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_IsInputSet
+//* \brief Test if PIO is input flag is active
+//*----------------------------------------------------------------------------
+static inline int AT91F_PIO_IsInputSet(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PIO_GetInput(pPio) & flag);
+}
+
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_SetOutput
+//* \brief Set to 1 output PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_SetOutput(
+ const AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ const unsigned int flag) // \arg output to be set
+{
+ pPio->PIO_SODR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_ClearOutput
+//* \brief Set to 0 output PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_ClearOutput(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg output to be cleared
+{
+ pPio->PIO_CODR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_ForceOutput
+//* \brief Force output when Direct drive option is enabled
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_ForceOutput(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg output to be forced
+{
+ pPio->PIO_ODSR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_Enable
+//* \brief Enable PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_Enable(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio to be enabled
+{
+ pPio->PIO_PER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_Disable
+//* \brief Disable PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_Disable(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio to be disabled
+{
+ pPio->PIO_PDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_GetStatus
+//* \brief Return PIO Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PIO_GetStatus( // \return PIO Status
+ AT91PS_PIO pPio) // \arg pointer to a PIO controller
+{
+ return pPio->PIO_PSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_IsSet
+//* \brief Test if PIO is Set
+//*----------------------------------------------------------------------------
+static inline int AT91F_PIO_IsSet(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PIO_GetStatus(pPio) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_OutputEnable
+//* \brief Output Enable PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_OutputEnable(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio output to be enabled
+{
+ pPio->PIO_OER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_OutputDisable
+//* \brief Output Enable PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_OutputDisable(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio output to be disabled
+{
+ pPio->PIO_ODR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_GetOutputStatus
+//* \brief Return PIO Output Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PIO_GetOutputStatus( // \return PIO Output Status
+ AT91PS_PIO pPio) // \arg pointer to a PIO controller
+{
+ return pPio->PIO_OSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_IsOuputSet
+//* \brief Test if PIO Output is Set
+//*----------------------------------------------------------------------------
+static inline int AT91F_PIO_IsOutputSet(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PIO_GetOutputStatus(pPio) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_InputFilterEnable
+//* \brief Input Filter Enable PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_InputFilterEnable(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio input filter to be enabled
+{
+ pPio->PIO_IFER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_InputFilterDisable
+//* \brief Input Filter Disable PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_InputFilterDisable(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio input filter to be disabled
+{
+ pPio->PIO_IFDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_GetInputFilterStatus
+//* \brief Return PIO Input Filter Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PIO_GetInputFilterStatus( // \return PIO Input Filter Status
+ AT91PS_PIO pPio) // \arg pointer to a PIO controller
+{
+ return pPio->PIO_IFSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_IsInputFilterSet
+//* \brief Test if PIO Input filter is Set
+//*----------------------------------------------------------------------------
+static inline int AT91F_PIO_IsInputFilterSet(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PIO_GetInputFilterStatus(pPio) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_GetOutputDataStatus
+//* \brief Return PIO Output Data Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PIO_GetOutputDataStatus( // \return PIO Output Data Status
+ AT91PS_PIO pPio) // \arg pointer to a PIO controller
+{
+ return pPio->PIO_ODSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_InterruptEnable
+//* \brief Enable PIO Interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_InterruptEnable(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio interrupt to be enabled
+{
+ pPio->PIO_IER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_InterruptDisable
+//* \brief Disable PIO Interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_InterruptDisable(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio interrupt to be disabled
+{
+ pPio->PIO_IDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_GetInterruptMaskStatus
+//* \brief Return PIO Interrupt Mask Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PIO_GetInterruptMaskStatus( // \return PIO Interrupt Mask Status
+ AT91PS_PIO pPio) // \arg pointer to a PIO controller
+{
+ return pPio->PIO_IMR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_GetInterruptStatus
+//* \brief Return PIO Interrupt Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PIO_GetInterruptStatus( // \return PIO Interrupt Status
+ AT91PS_PIO pPio) // \arg pointer to a PIO controller
+{
+ return pPio->PIO_ISR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_IsInterruptMasked
+//* \brief Test if PIO Interrupt is Masked
+//*----------------------------------------------------------------------------
+static inline int AT91F_PIO_IsInterruptMasked(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PIO_GetInterruptMaskStatus(pPio) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_IsInterruptSet
+//* \brief Test if PIO Interrupt is Set
+//*----------------------------------------------------------------------------
+static inline int AT91F_PIO_IsInterruptSet(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PIO_GetInterruptStatus(pPio) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_MultiDriverEnable
+//* \brief Multi Driver Enable PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_MultiDriverEnable(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio to be enabled
+{
+ pPio->PIO_MDER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_MultiDriverDisable
+//* \brief Multi Driver Disable PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_MultiDriverDisable(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio to be disabled
+{
+ pPio->PIO_MDDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_GetMultiDriverStatus
+//* \brief Return PIO Multi Driver Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PIO_GetMultiDriverStatus( // \return PIO Multi Driver Status
+ AT91PS_PIO pPio) // \arg pointer to a PIO controller
+{
+ return pPio->PIO_MDSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_IsMultiDriverSet
+//* \brief Test if PIO MultiDriver is Set
+//*----------------------------------------------------------------------------
+static inline int AT91F_PIO_IsMultiDriverSet(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PIO_GetMultiDriverStatus(pPio) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_A_RegisterSelection
+//* \brief PIO A Register Selection
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_A_RegisterSelection(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio A register selection
+{
+ pPio->PIO_ASR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_B_RegisterSelection
+//* \brief PIO B Register Selection
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_B_RegisterSelection(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio B register selection
+{
+ pPio->PIO_BSR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_Get_AB_RegisterStatus
+//* \brief Return PIO Interrupt Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PIO_Get_AB_RegisterStatus( // \return PIO AB Register Status
+ AT91PS_PIO pPio) // \arg pointer to a PIO controller
+{
+ return pPio->PIO_ABSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_IsAB_RegisterSet
+//* \brief Test if PIO AB Register is Set
+//*----------------------------------------------------------------------------
+static inline int AT91F_PIO_IsAB_RegisterSet(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PIO_Get_AB_RegisterStatus(pPio) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_OutputWriteEnable
+//* \brief Output Write Enable PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_OutputWriteEnable(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio output write to be enabled
+{
+ pPio->PIO_OWER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_OutputWriteDisable
+//* \brief Output Write Disable PIO
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIO_OutputWriteDisable(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg pio output write to be disabled
+{
+ pPio->PIO_OWDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_GetOutputWriteStatus
+//* \brief Return PIO Output Write Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PIO_GetOutputWriteStatus( // \return PIO Output Write Status
+ AT91PS_PIO pPio) // \arg pointer to a PIO controller
+{
+ return pPio->PIO_OWSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_IsOutputWriteSet
+//* \brief Test if PIO OutputWrite is Set
+//*----------------------------------------------------------------------------
+static inline int AT91F_PIO_IsOutputWriteSet(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PIO_GetOutputWriteStatus(pPio) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_GetCfgPullup
+//* \brief Return PIO Configuration Pullup
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PIO_GetCfgPullup( // \return PIO Configuration Pullup
+ AT91PS_PIO pPio) // \arg pointer to a PIO controller
+{
+ return pPio->PIO_PPUSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_IsOutputDataStatusSet
+//* \brief Test if PIO Output Data Status is Set
+//*----------------------------------------------------------------------------
+static inline int AT91F_PIO_IsOutputDataStatusSet(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PIO_GetOutputDataStatus(pPio) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIO_IsCfgPullupStatusSet
+//* \brief Test if PIO Configuration Pullup Status is Set
+//*----------------------------------------------------------------------------
+static inline int AT91F_PIO_IsCfgPullupStatusSet(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (~AT91F_PIO_GetCfgPullup(pPio) & flag);
+}
+
+/* *****************************************************************************
+ SOFTWARE API FOR PMC
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_CfgSysClkEnableReg
+//* \brief Configure the System Clock Enable Register of the PMC controller
+//*----------------------------------------------------------------------------
+static inline void AT91F_PMC_CfgSysClkEnableReg (
+ AT91PS_PMC pPMC, // \arg pointer to PMC controller
+ unsigned int mode)
+{
+ //* Write to the SCER register
+ pPMC->PMC_SCER = mode;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_CfgSysClkDisableReg
+//* \brief Configure the System Clock Disable Register of the PMC controller
+//*----------------------------------------------------------------------------
+static inline void AT91F_PMC_CfgSysClkDisableReg (
+ AT91PS_PMC pPMC, // \arg pointer to PMC controller
+ unsigned int mode)
+{
+ //* Write to the SCDR register
+ pPMC->PMC_SCDR = mode;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_GetSysClkStatusReg
+//* \brief Return the System Clock Status Register of the PMC controller
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PMC_GetSysClkStatusReg (
+ AT91PS_PMC pPMC // pointer to a CAN controller
+ )
+{
+ return pPMC->PMC_SCSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_EnablePeriphClock
+//* \brief Enable peripheral clock
+//*----------------------------------------------------------------------------
+static inline void AT91F_PMC_EnablePeriphClock (
+ AT91PS_PMC pPMC, // \arg pointer to PMC controller
+ unsigned int periphIds) // \arg IDs of peripherals to enable
+{
+ pPMC->PMC_PCER = periphIds;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_DisablePeriphClock
+//* \brief Disable peripheral clock
+//*----------------------------------------------------------------------------
+static inline void AT91F_PMC_DisablePeriphClock (
+ AT91PS_PMC pPMC, // \arg pointer to PMC controller
+ unsigned int periphIds) // \arg IDs of peripherals to enable
+{
+ pPMC->PMC_PCDR = periphIds;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_GetPeriphClock
+//* \brief Get peripheral clock status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PMC_GetPeriphClock (
+ AT91PS_PMC pPMC) // \arg pointer to PMC controller
+{
+ return pPMC->PMC_PCSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_CKGR_CfgMainOscillatorReg
+//* \brief Cfg the main oscillator
+//*----------------------------------------------------------------------------
+static inline void AT91F_CKGR_CfgMainOscillatorReg (
+ AT91PS_CKGR pCKGR, // \arg pointer to CKGR controller
+ unsigned int mode)
+{
+ pCKGR->CKGR_MOR = mode;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_CKGR_GetMainOscillatorReg
+//* \brief Cfg the main oscillator
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_CKGR_GetMainOscillatorReg (
+ AT91PS_CKGR pCKGR) // \arg pointer to CKGR controller
+{
+ return pCKGR->CKGR_MOR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_CKGR_EnableMainOscillator
+//* \brief Enable the main oscillator
+//*----------------------------------------------------------------------------
+static inline void AT91F_CKGR_EnableMainOscillator(
+ AT91PS_CKGR pCKGR) // \arg pointer to CKGR controller
+{
+ pCKGR->CKGR_MOR |= AT91C_CKGR_MOSCEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_CKGR_DisableMainOscillator
+//* \brief Disable the main oscillator
+//*----------------------------------------------------------------------------
+static inline void AT91F_CKGR_DisableMainOscillator (
+ AT91PS_CKGR pCKGR) // \arg pointer to CKGR controller
+{
+ pCKGR->CKGR_MOR &= ~AT91C_CKGR_MOSCEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_CKGR_CfgMainOscStartUpTime
+//* \brief Cfg MOR Register according to the main osc startup time
+//*----------------------------------------------------------------------------
+static inline void AT91F_CKGR_CfgMainOscStartUpTime (
+ AT91PS_CKGR pCKGR, // \arg pointer to CKGR controller
+ unsigned int startup_time, // \arg main osc startup time in microsecond (us)
+ unsigned int slowClock) // \arg slowClock in Hz
+{
+ pCKGR->CKGR_MOR &= ~AT91C_CKGR_OSCOUNT;
+ pCKGR->CKGR_MOR |= ((slowClock * startup_time)/(8*1000000)) << 8;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_CKGR_GetMainClockFreqReg
+//* \brief Cfg the main oscillator
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_CKGR_GetMainClockFreqReg (
+ AT91PS_CKGR pCKGR) // \arg pointer to CKGR controller
+{
+ return pCKGR->CKGR_MCFR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_CKGR_GetMainClock
+//* \brief Return Main clock in Hz
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_CKGR_GetMainClock (
+ AT91PS_CKGR pCKGR, // \arg pointer to CKGR controller
+ unsigned int slowClock) // \arg slowClock in Hz
+{
+ return ((pCKGR->CKGR_MCFR & AT91C_CKGR_MAINF) * slowClock) >> 4;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_CfgMCKReg
+//* \brief Cfg Master Clock Register
+//*----------------------------------------------------------------------------
+static inline void AT91F_PMC_CfgMCKReg (
+ AT91PS_PMC pPMC, // \arg pointer to PMC controller
+ unsigned int mode)
+{
+ pPMC->PMC_MCKR = mode;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_GetMCKReg
+//* \brief Return Master Clock Register
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PMC_GetMCKReg(
+ AT91PS_PMC pPMC) // \arg pointer to PMC controller
+{
+ return pPMC->PMC_MCKR;
+}
+
+//*------------------------------------------------------------------------------
+//* \fn AT91F_PMC_GetMasterClock
+//* \brief Return master clock in Hz which correponds to processor clock for ARM7
+//*------------------------------------------------------------------------------
+extern unsigned int AT91F_PMC_GetMasterClock (
+ AT91PS_PMC pPMC, // \arg pointer to PMC controller
+ AT91PS_CKGR pCKGR, // \arg pointer to CKGR controller
+ unsigned int slowClock); // \arg slowClock in Hz
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_EnablePCK
+//* \brief Enable peripheral clock
+//*----------------------------------------------------------------------------
+static inline void AT91F_PMC_EnablePCK (
+ AT91PS_PMC pPMC, // \arg pointer to PMC controller
+ unsigned int pck, // \arg Peripheral clock identifier 0 .. 7
+ unsigned int mode)
+{
+ pPMC->PMC_PCKR[pck] = mode;
+ pPMC->PMC_SCER = (1 << pck) << 8;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_DisablePCK
+//* \brief Enable peripheral clock
+//*----------------------------------------------------------------------------
+static inline void AT91F_PMC_DisablePCK (
+ AT91PS_PMC pPMC, // \arg pointer to PMC controller
+ unsigned int pck) // \arg Peripheral clock identifier 0 .. 7
+{
+ pPMC->PMC_SCDR = (1 << pck) << 8;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_EnableIt
+//* \brief Enable PMC interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_PMC_EnableIt (
+ AT91PS_PMC pPMC, // pointer to a PMC controller
+ unsigned int flag) // IT to be enabled
+{
+ //* Write to the IER register
+ pPMC->PMC_IER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_DisableIt
+//* \brief Disable PMC interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_PMC_DisableIt (
+ AT91PS_PMC pPMC, // pointer to a PMC controller
+ unsigned int flag) // IT to be disabled
+{
+ //* Write to the IDR register
+ pPMC->PMC_IDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_GetStatus
+//* \brief Return PMC Interrupt Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PMC_GetStatus( // \return PMC Interrupt Status
+ AT91PS_PMC pPMC) // pointer to a PMC controller
+{
+ return pPMC->PMC_SR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_GetInterruptMaskStatus
+//* \brief Return PMC Interrupt Mask Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PMC_GetInterruptMaskStatus( // \return PMC Interrupt Mask Status
+ AT91PS_PMC pPMC) // pointer to a PMC controller
+{
+ return pPMC->PMC_IMR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_IsInterruptMasked
+//* \brief Test if PMC Interrupt is Masked
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PMC_IsInterruptMasked(
+ AT91PS_PMC pPMC, // \arg pointer to a PMC controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PMC_GetInterruptMaskStatus(pPMC) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_IsStatusSet
+//* \brief Test if PMC Status is Set
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PMC_IsStatusSet(
+ AT91PS_PMC pPMC, // \arg pointer to a PMC controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PMC_GetStatus(pPMC) & flag);
+}
+
+// ----------------------------------------------------------------------------
+// \fn AT91F_CKGR_CfgPLLReg
+// \brief Cfg the PLL Register
+// ----------------------------------------------------------------------------
+static inline void AT91F_CKGR_CfgPLLReg (
+ AT91PS_CKGR pCKGR, // \arg pointer to CKGR controller
+ unsigned int mode)
+{
+ pCKGR->CKGR_PLLR = mode;
+}
+
+// ----------------------------------------------------------------------------
+// \fn AT91F_CKGR_GetPLLReg
+// \brief Get the PLL Register
+// ----------------------------------------------------------------------------
+static inline unsigned int AT91F_CKGR_GetPLLReg (
+ AT91PS_CKGR pCKGR) // \arg pointer to CKGR controller
+{
+ return pCKGR->CKGR_PLLR;
+}
+
+
+
+/* *****************************************************************************
+ SOFTWARE API FOR RSTC
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_RSTSoftReset
+//* \brief Start Software Reset
+//*----------------------------------------------------------------------------
+static inline void AT91F_RSTSoftReset(
+ AT91PS_RSTC pRSTC,
+ unsigned int reset)
+{
+ pRSTC->RSTC_RCR = (0xA5000000 | reset);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_RSTSetMode
+//* \brief Set Reset Mode
+//*----------------------------------------------------------------------------
+static inline void AT91F_RSTSetMode(
+ AT91PS_RSTC pRSTC,
+ unsigned int mode)
+{
+ pRSTC->RSTC_RMR = (0xA5000000 | mode);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_RSTGetMode
+//* \brief Get Reset Mode
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_RSTGetMode(
+ AT91PS_RSTC pRSTC)
+{
+ return (pRSTC->RSTC_RMR);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_RSTGetStatus
+//* \brief Get Reset Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_RSTGetStatus(
+ AT91PS_RSTC pRSTC)
+{
+ return (pRSTC->RSTC_RSR);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_RSTIsSoftRstActive
+//* \brief Return !=0 if software reset is still not completed
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_RSTIsSoftRstActive(
+ AT91PS_RSTC pRSTC)
+{
+ return ((pRSTC->RSTC_RSR) & AT91C_RSTC_SRCMP);
+}
+/* *****************************************************************************
+ SOFTWARE API FOR RTTC
+ ***************************************************************************** */
+//*--------------------------------------------------------------------------------------
+//* \fn AT91F_SetRTT_TimeBase()
+//* \brief Set the RTT prescaler according to the TimeBase in ms
+//*--------------------------------------------------------------------------------------
+static inline unsigned int AT91F_RTTSetTimeBase(
+ AT91PS_RTTC pRTTC,
+ unsigned int ms)
+{
+ if (ms > 2000)
+ return 1; // AT91C_TIME_OUT_OF_RANGE
+ pRTTC->RTTC_RTMR &= ~0xFFFF;
+ pRTTC->RTTC_RTMR |= (((ms << 15) /1000) & 0xFFFF);
+ return 0;
+}
+
+//*--------------------------------------------------------------------------------------
+//* \fn AT91F_RTTSetPrescaler()
+//* \brief Set the new prescaler value
+//*--------------------------------------------------------------------------------------
+static inline unsigned int AT91F_RTTSetPrescaler(
+ AT91PS_RTTC pRTTC,
+ unsigned int rtpres)
+{
+ pRTTC->RTTC_RTMR &= ~0xFFFF;
+ pRTTC->RTTC_RTMR |= (rtpres & 0xFFFF);
+ return (pRTTC->RTTC_RTMR);
+}
+
+//*--------------------------------------------------------------------------------------
+//* \fn AT91F_RTTRestart()
+//* \brief Restart the RTT prescaler
+//*--------------------------------------------------------------------------------------
+static inline void AT91F_RTTRestart(
+ AT91PS_RTTC pRTTC)
+{
+ pRTTC->RTTC_RTMR |= AT91C_RTTC_RTTRST;
+}
+
+
+//*--------------------------------------------------------------------------------------
+//* \fn AT91F_RTT_SetAlarmINT()
+//* \brief Enable RTT Alarm Interrupt
+//*--------------------------------------------------------------------------------------
+static inline void AT91F_RTTSetAlarmINT(
+ AT91PS_RTTC pRTTC)
+{
+ pRTTC->RTTC_RTMR |= AT91C_RTTC_ALMIEN;
+}
+
+//*--------------------------------------------------------------------------------------
+//* \fn AT91F_RTT_ClearAlarmINT()
+//* \brief Disable RTT Alarm Interrupt
+//*--------------------------------------------------------------------------------------
+static inline void AT91F_RTTClearAlarmINT(
+ AT91PS_RTTC pRTTC)
+{
+ pRTTC->RTTC_RTMR &= ~AT91C_RTTC_ALMIEN;
+}
+
+//*--------------------------------------------------------------------------------------
+//* \fn AT91F_RTT_SetRttIncINT()
+//* \brief Enable RTT INC Interrupt
+//*--------------------------------------------------------------------------------------
+static inline void AT91F_RTTSetRttIncINT(
+ AT91PS_RTTC pRTTC)
+{
+ pRTTC->RTTC_RTMR |= AT91C_RTTC_RTTINCIEN;
+}
+
+//*--------------------------------------------------------------------------------------
+//* \fn AT91F_RTT_ClearRttIncINT()
+//* \brief Disable RTT INC Interrupt
+//*--------------------------------------------------------------------------------------
+static inline void AT91F_RTTClearRttIncINT(
+ AT91PS_RTTC pRTTC)
+{
+ pRTTC->RTTC_RTMR &= ~AT91C_RTTC_RTTINCIEN;
+}
+
+//*--------------------------------------------------------------------------------------
+//* \fn AT91F_RTT_SetAlarmValue()
+//* \brief Set RTT Alarm Value
+//*--------------------------------------------------------------------------------------
+static inline void AT91F_RTTSetAlarmValue(
+ AT91PS_RTTC pRTTC, unsigned int alarm)
+{
+ pRTTC->RTTC_RTAR = alarm;
+}
+
+//*--------------------------------------------------------------------------------------
+//* \fn AT91F_RTT_GetAlarmValue()
+//* \brief Get RTT Alarm Value
+//*--------------------------------------------------------------------------------------
+static inline unsigned int AT91F_RTTGetAlarmValue(
+ AT91PS_RTTC pRTTC)
+{
+ return(pRTTC->RTTC_RTAR);
+}
+
+//*--------------------------------------------------------------------------------------
+//* \fn AT91F_RTTGetStatus()
+//* \brief Read the RTT status
+//*--------------------------------------------------------------------------------------
+static inline unsigned int AT91F_RTTGetStatus(
+ AT91PS_RTTC pRTTC)
+{
+ return(pRTTC->RTTC_RTSR);
+}
+
+//*--------------------------------------------------------------------------------------
+//* \fn AT91F_RTT_ReadValue()
+//* \brief Read the RTT value
+//*--------------------------------------------------------------------------------------
+extern unsigned int AT91F_RTTReadValue(AT91PS_RTTC pRTTC);
+
+/* *****************************************************************************
+ SOFTWARE API FOR PITC
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PITInit
+//* \brief System timer init : period in ‘second, system clock freq in MHz
+//*----------------------------------------------------------------------------
+static inline void AT91F_PITInit(
+ AT91PS_PITC pPITC,
+ unsigned int period,
+ unsigned int pit_frequency)
+{
+ pPITC->PITC_PIMR = period? (period * pit_frequency + 8) >> 4 : 0; // +8 to avoid %10 and /10
+ pPITC->PITC_PIMR |= AT91C_PITC_PITEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PITSetPIV
+//* \brief Set the PIT Periodic Interval Value
+//*----------------------------------------------------------------------------
+static inline void AT91F_PITSetPIV(
+ AT91PS_PITC pPITC,
+ unsigned int piv)
+{
+ pPITC->PITC_PIMR = piv | (pPITC->PITC_PIMR & (AT91C_PITC_PITEN | AT91C_PITC_PITIEN));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PITEnableInt
+//* \brief Enable PIT periodic interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_PITEnableInt(
+ AT91PS_PITC pPITC)
+{
+ pPITC->PITC_PIMR |= AT91C_PITC_PITIEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PITDisableInt
+//* \brief Disable PIT periodic interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_PITDisableInt(
+ AT91PS_PITC pPITC)
+{
+ pPITC->PITC_PIMR &= ~AT91C_PITC_PITIEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PITGetMode
+//* \brief Read PIT mode register
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PITGetMode(
+ AT91PS_PITC pPITC)
+{
+ return(pPITC->PITC_PIMR);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PITGetStatus
+//* \brief Read PIT status register
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PITGetStatus(
+ AT91PS_PITC pPITC)
+{
+ return(pPITC->PITC_PISR);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PITGetPIIR
+//* \brief Read PIT CPIV and PICNT without ressetting the counters
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PITGetPIIR(
+ AT91PS_PITC pPITC)
+{
+ return(pPITC->PITC_PIIR);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PITGetPIVR
+//* \brief Read System timer CPIV and PICNT without ressetting the counters
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PITGetPIVR(
+ AT91PS_PITC pPITC)
+{
+ return(pPITC->PITC_PIVR);
+}
+/* *****************************************************************************
+ SOFTWARE API FOR WDTC
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_WDTSetMode
+//* \brief Set Watchdog Mode Register
+//*----------------------------------------------------------------------------
+static inline void AT91F_WDTSetMode(
+ AT91PS_WDTC pWDTC,
+ unsigned int Mode)
+{
+ pWDTC->WDTC_WDMR = Mode;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_WDTRestart
+//* \brief Restart Watchdog
+//*----------------------------------------------------------------------------
+static inline void AT91F_WDTRestart(
+ AT91PS_WDTC pWDTC)
+{
+ pWDTC->WDTC_WDCR = 0xA5000001;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_WDTSGettatus
+//* \brief Get Watchdog Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_WDTSGettatus(
+ AT91PS_WDTC pWDTC)
+{
+ return(pWDTC->WDTC_WDSR & 0x3);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_WDTGetPeriod
+//* \brief Translate ms into Watchdog Compatible value
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_WDTGetPeriod(unsigned int ms)
+{
+ if ((ms < 4) || (ms > 16000))
+ return 0;
+ return((ms << 8) / 1000);
+}
+/* *****************************************************************************
+ SOFTWARE API FOR VREG
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_VREG_Enable_LowPowerMode
+//* \brief Enable VREG Low Power Mode
+//*----------------------------------------------------------------------------
+static inline void AT91F_VREG_Enable_LowPowerMode(
+ AT91PS_VREG pVREG)
+{
+ pVREG->VREG_MR |= AT91C_VREG_PSTDBY;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_VREG_Disable_LowPowerMode
+//* \brief Disable VREG Low Power Mode
+//*----------------------------------------------------------------------------
+static inline void AT91F_VREG_Disable_LowPowerMode(
+ AT91PS_VREG pVREG)
+{
+ pVREG->VREG_MR &= ~AT91C_VREG_PSTDBY;
+}/* *****************************************************************************
+ SOFTWARE API FOR MC
+ ***************************************************************************** */
+
+#define AT91C_MC_CORRECT_KEY ((unsigned int) 0x5A << 24) // (MC) Correct Protect Key
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_MC_Remap
+//* \brief Make Remap
+//*----------------------------------------------------------------------------
+static inline void AT91F_MC_Remap (void) //
+{
+ AT91PS_MC pMC = (AT91PS_MC) AT91C_BASE_MC;
+
+ pMC->MC_RCR = AT91C_MC_RCB;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_MC_EFC_CfgModeReg
+//* \brief Configure the EFC Mode Register of the MC controller
+//*----------------------------------------------------------------------------
+static inline void AT91F_MC_EFC_CfgModeReg (
+ AT91PS_MC pMC, // pointer to a MC controller
+ unsigned int mode) // mode register
+{
+ // Write to the FMR register
+ pMC->MC_FMR = mode;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_MC_EFC_GetModeReg
+//* \brief Return MC EFC Mode Regsiter
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_MC_EFC_GetModeReg(
+ AT91PS_MC pMC) // pointer to a MC controller
+{
+ return pMC->MC_FMR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_MC_EFC_ComputeFMCN
+//* \brief Return MC EFC Mode Regsiter
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_MC_EFC_ComputeFMCN(
+ int master_clock) // master clock in Hz
+{
+ return (master_clock/1000000 +2);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_MC_EFC_PerformCmd
+//* \brief Perform EFC Command
+//*----------------------------------------------------------------------------
+static inline void AT91F_MC_EFC_PerformCmd (
+ AT91PS_MC pMC, // pointer to a MC controller
+ unsigned int transfer_cmd)
+{
+ pMC->MC_FCR = transfer_cmd;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_MC_EFC_GetStatus
+//* \brief Return MC EFC Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_MC_EFC_GetStatus(
+ AT91PS_MC pMC) // pointer to a MC controller
+{
+ return pMC->MC_FSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_MC_EFC_IsInterruptMasked
+//* \brief Test if EFC MC Interrupt is Masked
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_MC_EFC_IsInterruptMasked(
+ AT91PS_MC pMC, // \arg pointer to a MC controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_MC_EFC_GetModeReg(pMC) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_MC_EFC_IsInterruptSet
+//* \brief Test if EFC MC Interrupt is Set
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_MC_EFC_IsInterruptSet(
+ AT91PS_MC pMC, // \arg pointer to a MC controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_MC_EFC_GetStatus(pMC) & flag);
+}
+
+/* *****************************************************************************
+ SOFTWARE API FOR SPI
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_CfgCs
+//* \brief Configure SPI chip select register
+//*----------------------------------------------------------------------------
+static inline void AT91F_SPI_CfgCs (
+ AT91PS_SPI pSPI, // pointer to a SPI controller
+ int cs, // SPI cs number (0 to 3)
+ int val) // chip select register
+{
+ //* Write to the CSR register
+ *(pSPI->SPI_CSR + cs) = val;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_EnableIt
+//* \brief Enable SPI interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_SPI_EnableIt (
+ AT91PS_SPI pSPI, // pointer to a SPI controller
+ unsigned int flag) // IT to be enabled
+{
+ //* Write to the IER register
+ pSPI->SPI_IER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_DisableIt
+//* \brief Disable SPI interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_SPI_DisableIt (
+ AT91PS_SPI pSPI, // pointer to a SPI controller
+ unsigned int flag) // IT to be disabled
+{
+ //* Write to the IDR register
+ pSPI->SPI_IDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_Reset
+//* \brief Reset the SPI controller
+//*----------------------------------------------------------------------------
+static inline void AT91F_SPI_Reset (
+ AT91PS_SPI pSPI // pointer to a SPI controller
+ )
+{
+ //* Write to the CR register
+ pSPI->SPI_CR = AT91C_SPI_SWRST;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_Enable
+//* \brief Enable the SPI controller
+//*----------------------------------------------------------------------------
+static inline void AT91F_SPI_Enable (
+ AT91PS_SPI pSPI // pointer to a SPI controller
+ )
+{
+ //* Write to the CR register
+ pSPI->SPI_CR = AT91C_SPI_SPIEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_Disable
+//* \brief Disable the SPI controller
+//*----------------------------------------------------------------------------
+static inline void AT91F_SPI_Disable (
+ AT91PS_SPI pSPI // pointer to a SPI controller
+ )
+{
+ //* Write to the CR register
+ pSPI->SPI_CR = AT91C_SPI_SPIDIS;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_CfgMode
+//* \brief Enable the SPI controller
+//*----------------------------------------------------------------------------
+static inline void AT91F_SPI_CfgMode (
+ AT91PS_SPI pSPI, // pointer to a SPI controller
+ int mode) // mode register
+{
+ //* Write to the MR register
+ pSPI->SPI_MR = mode;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_CfgPCS
+//* \brief Switch to the correct PCS of SPI Mode Register : Fixed Peripheral Selected
+//*----------------------------------------------------------------------------
+static inline void AT91F_SPI_CfgPCS (
+ AT91PS_SPI pSPI, // pointer to a SPI controller
+ char PCS_Device) // PCS of the Device
+{
+ //* Write to the MR register
+ pSPI->SPI_MR &= 0xFFF0FFFF;
+ pSPI->SPI_MR |= ( (PCS_Device<<16) & AT91C_SPI_PCS );
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_ReceiveFrame
+//* \brief Return 2 if PDC has been initialized with Buffer and Next Buffer, 1 if PDC has been initializaed with Next Buffer, 0 if PDC is busy
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_SPI_ReceiveFrame (
+ AT91PS_SPI pSPI,
+ unsigned char *pBuffer,
+ unsigned int szBuffer,
+ unsigned char *pNextBuffer,
+ unsigned int szNextBuffer )
+{
+ return AT91F_PDC_ReceiveFrame(
+ (AT91PS_PDC) &(pSPI->SPI_RPR),
+ pBuffer,
+ szBuffer,
+ pNextBuffer,
+ szNextBuffer);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_SendFrame
+//* \brief Return 2 if PDC has been initialized with Buffer and Next Buffer, 1 if PDC has been initializaed with Next Buffer, 0 if PDC is bSPIy
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_SPI_SendFrame(
+ AT91PS_SPI pSPI,
+ const unsigned char *pBuffer,
+ unsigned int szBuffer,
+ const unsigned char *pNextBuffer,
+ unsigned int szNextBuffer )
+{
+ return AT91F_PDC_SendFrame(
+ (AT91PS_PDC) &(pSPI->SPI_RPR),
+ pBuffer,
+ szBuffer,
+ pNextBuffer,
+ szNextBuffer);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_Close
+//* \brief Close SPI: disable IT disable transfert, close PDC
+//*----------------------------------------------------------------------------
+extern void AT91F_SPI_Close(AT91PS_SPI pSPI); // \arg pointer to a SPI controller
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_PutChar
+//* \brief Send a character,does not check if ready to send
+//*----------------------------------------------------------------------------
+static inline void AT91F_SPI_PutChar (
+ AT91PS_SPI pSPI,
+ unsigned int character,
+ unsigned int cs_number )
+{
+ unsigned int value_for_cs;
+ value_for_cs = (~(1 << cs_number)) & 0xF; //Place a zero among a 4 ONEs number
+ pSPI->SPI_TDR = (character & 0xFFFF) | (value_for_cs << 16);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_GetChar
+//* \brief Receive a character,does not check if a character is available
+//*----------------------------------------------------------------------------
+static inline int AT91F_SPI_GetChar (
+ const AT91PS_SPI pSPI)
+{
+ return((pSPI->SPI_RDR) & 0xFFFF);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_GetInterruptMaskStatus
+//* \brief Return SPI Interrupt Mask Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_SPI_GetInterruptMaskStatus( // \return SPI Interrupt Mask Status
+ AT91PS_SPI pSpi) // \arg pointer to a SPI controller
+{
+ return pSpi->SPI_IMR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_IsInterruptMasked
+//* \brief Test if SPI Interrupt is Masked
+//*----------------------------------------------------------------------------
+static inline int AT91F_SPI_IsInterruptMasked(
+ AT91PS_SPI pSpi, // \arg pointer to a SPI controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_SPI_GetInterruptMaskStatus(pSpi) & flag);
+}
+
+/* *****************************************************************************
+ SOFTWARE API FOR ADC
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_EnableIt
+//* \brief Enable ADC interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_ADC_EnableIt (
+ AT91PS_ADC pADC, // pointer to a ADC controller
+ unsigned int flag) // IT to be enabled
+{
+ //* Write to the IER register
+ pADC->ADC_IER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_DisableIt
+//* \brief Disable ADC interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_ADC_DisableIt (
+ AT91PS_ADC pADC, // pointer to a ADC controller
+ unsigned int flag) // IT to be disabled
+{
+ //* Write to the IDR register
+ pADC->ADC_IDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetStatus
+//* \brief Return ADC Interrupt Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetStatus( // \return ADC Interrupt Status
+ AT91PS_ADC pADC) // pointer to a ADC controller
+{
+ return pADC->ADC_SR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetInterruptMaskStatus
+//* \brief Return ADC Interrupt Mask Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetInterruptMaskStatus( // \return ADC Interrupt Mask Status
+ AT91PS_ADC pADC) // pointer to a ADC controller
+{
+ return pADC->ADC_IMR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_IsInterruptMasked
+//* \brief Test if ADC Interrupt is Masked
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_IsInterruptMasked(
+ AT91PS_ADC pADC, // \arg pointer to a ADC controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_ADC_GetInterruptMaskStatus(pADC) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_IsStatusSet
+//* \brief Test if ADC Status is Set
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_IsStatusSet(
+ AT91PS_ADC pADC, // \arg pointer to a ADC controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_ADC_GetStatus(pADC) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_CfgModeReg
+//* \brief Configure the Mode Register of the ADC controller
+//*----------------------------------------------------------------------------
+static inline void AT91F_ADC_CfgModeReg (
+ AT91PS_ADC pADC, // pointer to a ADC controller
+ unsigned int mode) // mode register
+{
+ //* Write to the MR register
+ pADC->ADC_MR = mode;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetModeReg
+//* \brief Return the Mode Register of the ADC controller value
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetModeReg (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ return pADC->ADC_MR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_CfgTimings
+//* \brief Configure the different necessary timings of the ADC controller
+//*----------------------------------------------------------------------------
+extern void AT91F_ADC_CfgTimings (
+ AT91PS_ADC pADC, // pointer to a ADC controller
+ unsigned int mck_clock, // in MHz
+ unsigned int adc_clock, // in MHz
+ unsigned int startup_time, // in us
+ unsigned int sample_and_hold_time); // in ns
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_EnableChannel
+//* \brief Return ADC Timer Register Value
+//*----------------------------------------------------------------------------
+static inline void AT91F_ADC_EnableChannel (
+ AT91PS_ADC pADC, // pointer to a ADC controller
+ unsigned int channel) // mode register
+{
+ //* Write to the CHER register
+ pADC->ADC_CHER = channel;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_DisableChannel
+//* \brief Return ADC Timer Register Value
+//*----------------------------------------------------------------------------
+static inline void AT91F_ADC_DisableChannel (
+ AT91PS_ADC pADC, // pointer to a ADC controller
+ unsigned int channel) // mode register
+{
+ //* Write to the CHDR register
+ pADC->ADC_CHDR = channel;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetChannelStatus
+//* \brief Return ADC Timer Register Value
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetChannelStatus (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ return pADC->ADC_CHSR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_StartConversion
+//* \brief Software request for a analog to digital conversion
+//*----------------------------------------------------------------------------
+static inline void AT91F_ADC_StartConversion (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ pADC->ADC_CR = AT91C_ADC_START;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_SoftReset
+//* \brief Software reset
+//*----------------------------------------------------------------------------
+static inline void AT91F_ADC_SoftReset (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ pADC->ADC_CR = AT91C_ADC_SWRST;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetLastConvertedData
+//* \brief Return the Last Converted Data
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetLastConvertedData (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ return pADC->ADC_LCDR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetConvertedDataCH0
+//* \brief Return the Channel 0 Converted Data
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetConvertedDataCH0 (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ return pADC->ADC_CDR0;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetConvertedDataCH1
+//* \brief Return the Channel 1 Converted Data
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetConvertedDataCH1 (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ return pADC->ADC_CDR1;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetConvertedDataCH2
+//* \brief Return the Channel 2 Converted Data
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetConvertedDataCH2 (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ return pADC->ADC_CDR2;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetConvertedDataCH3
+//* \brief Return the Channel 3 Converted Data
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetConvertedDataCH3 (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ return pADC->ADC_CDR3;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetConvertedDataCH4
+//* \brief Return the Channel 4 Converted Data
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetConvertedDataCH4 (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ return pADC->ADC_CDR4;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetConvertedDataCH5
+//* \brief Return the Channel 5 Converted Data
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetConvertedDataCH5 (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ return pADC->ADC_CDR5;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetConvertedDataCH6
+//* \brief Return the Channel 6 Converted Data
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetConvertedDataCH6 (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ return pADC->ADC_CDR6;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_GetConvertedDataCH7
+//* \brief Return the Channel 7 Converted Data
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_ADC_GetConvertedDataCH7 (
+ AT91PS_ADC pADC // pointer to a ADC controller
+ )
+{
+ return pADC->ADC_CDR7;
+}
+
+/* *****************************************************************************
+ SOFTWARE API FOR SSC
+ ***************************************************************************** */
+//* Define the standard I2S mode configuration
+
+//* Configuration to set in the SSC Transmit Clock Mode Register
+//* Parameters : nb_bit_by_slot : 8, 16 or 32 bits
+//* nb_slot_by_frame : number of channels
+#define AT91C_I2S_ASY_MASTER_TX_SETTING(nb_bit_by_slot, nb_slot_by_frame)( +\
+ AT91C_SSC_CKS_DIV +\
+ AT91C_SSC_CKO_CONTINOUS +\
+ AT91C_SSC_CKG_NONE +\
+ AT91C_SSC_START_FALL_RF +\
+ AT91C_SSC_STTOUT +\
+ ((1<<16) & AT91C_SSC_STTDLY) +\
+ ((((nb_bit_by_slot*nb_slot_by_frame)/2)-1) <<24))
+
+
+//* Configuration to set in the SSC Transmit Frame Mode Register
+//* Parameters : nb_bit_by_slot : 8, 16 or 32 bits
+//* nb_slot_by_frame : number of channels
+#define AT91C_I2S_ASY_TX_FRAME_SETTING(nb_bit_by_slot, nb_slot_by_frame)( +\
+ (nb_bit_by_slot-1) +\
+ AT91C_SSC_MSBF +\
+ (((nb_slot_by_frame-1)<<8) & AT91C_SSC_DATNB) +\
+ (((nb_bit_by_slot-1)<<16) & AT91C_SSC_FSLEN) +\
+ AT91C_SSC_FSOS_NEGATIVE)
+
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_SetBaudrate
+//* \brief Set the baudrate according to the CPU clock
+//*----------------------------------------------------------------------------
+extern void AT91F_SSC_SetBaudrate (
+ AT91PS_SSC pSSC, // \arg pointer to a SSC controller
+ unsigned int mainClock, // \arg peripheral clock
+ unsigned int speed); // \arg SSC baudrate
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_Configure
+//* \brief Configure SSC
+//*----------------------------------------------------------------------------
+extern void AT91F_SSC_Configure (
+ AT91PS_SSC pSSC, // \arg pointer to a SSC controller
+ unsigned int syst_clock, // \arg System Clock Frequency
+ unsigned int baud_rate, // \arg Expected Baud Rate Frequency
+ unsigned int clock_rx, // \arg Receiver Clock Parameters
+ unsigned int mode_rx, // \arg mode Register to be programmed
+ unsigned int clock_tx, // \arg Transmitter Clock Parameters
+ unsigned int mode_tx); // \arg mode Register to be programmed
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_EnableRx
+//* \brief Enable receiving datas
+//*----------------------------------------------------------------------------
+static inline void AT91F_SSC_EnableRx (
+ AT91PS_SSC pSSC) // \arg pointer to a SSC controller
+{
+ //* Enable receiver
+ pSSC->SSC_CR = AT91C_SSC_RXEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_DisableRx
+//* \brief Disable receiving datas
+//*----------------------------------------------------------------------------
+static inline void AT91F_SSC_DisableRx (
+ AT91PS_SSC pSSC) // \arg pointer to a SSC controller
+{
+ //* Disable receiver
+ pSSC->SSC_CR = AT91C_SSC_RXDIS;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_EnableTx
+//* \brief Enable sending datas
+//*----------------------------------------------------------------------------
+static inline void AT91F_SSC_EnableTx (
+ AT91PS_SSC pSSC) // \arg pointer to a SSC controller
+{
+ //* Enable transmitter
+ pSSC->SSC_CR = AT91C_SSC_TXEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_DisableTx
+//* \brief Disable sending datas
+//*----------------------------------------------------------------------------
+static inline void AT91F_SSC_DisableTx (
+ AT91PS_SSC pSSC) // \arg pointer to a SSC controller
+{
+ //* Disable transmitter
+ pSSC->SSC_CR = AT91C_SSC_TXDIS;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_EnableIt
+//* \brief Enable SSC IT
+//*----------------------------------------------------------------------------
+static inline void AT91F_SSC_EnableIt (
+ AT91PS_SSC pSSC, // \arg pointer to a SSC controller
+ unsigned int flag) // \arg IT to be enabled
+{
+ //* Write to the IER register
+ pSSC->SSC_IER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_DisableIt
+//* \brief Disable SSC IT
+//*----------------------------------------------------------------------------
+static inline void AT91F_SSC_DisableIt (
+ AT91PS_SSC pSSC, // \arg pointer to a SSC controller
+ unsigned int flag) // \arg IT to be disabled
+{
+ //* Write to the IDR register
+ pSSC->SSC_IDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_ReceiveFrame
+//* \brief Return 2 if PDC has been initialized with Buffer and Next Buffer, 1 if PDC has been initialized with Next Buffer, 0 if PDC is busy
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_SSC_ReceiveFrame (
+ AT91PS_SSC pSSC,
+ unsigned char *pBuffer,
+ unsigned int szBuffer,
+ unsigned char *pNextBuffer,
+ unsigned int szNextBuffer )
+{
+ return AT91F_PDC_ReceiveFrame(
+ (AT91PS_PDC) &(pSSC->SSC_RPR),
+ pBuffer,
+ szBuffer,
+ pNextBuffer,
+ szNextBuffer);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_SendFrame
+//* \brief Return 2 if PDC has been initialized with Buffer and Next Buffer, 1 if PDC has been initialized with Next Buffer, 0 if PDC is busy
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_SSC_SendFrame(
+ AT91PS_SSC pSSC,
+ const unsigned char *pBuffer,
+ unsigned int szBuffer,
+ const unsigned char *pNextBuffer,
+ unsigned int szNextBuffer )
+{
+ return AT91F_PDC_SendFrame(
+ (AT91PS_PDC) &(pSSC->SSC_RPR),
+ pBuffer,
+ szBuffer,
+ pNextBuffer,
+ szNextBuffer);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_GetInterruptMaskStatus
+//* \brief Return SSC Interrupt Mask Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_SSC_GetInterruptMaskStatus( // \return SSC Interrupt Mask Status
+ AT91PS_SSC pSsc) // \arg pointer to a SSC controller
+{
+ return pSsc->SSC_IMR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_IsInterruptMasked
+//* \brief Test if SSC Interrupt is Masked
+//*----------------------------------------------------------------------------
+static inline int AT91F_SSC_IsInterruptMasked(
+ AT91PS_SSC pSsc, // \arg pointer to a SSC controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_SSC_GetInterruptMaskStatus(pSsc) & flag);
+}
+
+/* *****************************************************************************
+ SOFTWARE API FOR USART
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_Baudrate
+//* \brief Calculate the baudrate
+//* Standard Asynchronous Mode : 8 bits , 1 stop , no parity
+#define AT91C_US_ASYNC_MODE ( AT91C_US_USMODE_NORMAL + \
+ AT91C_US_NBSTOP_1_BIT + \
+ AT91C_US_PAR_NONE + \
+ AT91C_US_CHRL_8_BITS + \
+ AT91C_US_CLKS_CLOCK )
+
+//* Standard External Asynchronous Mode : 8 bits , 1 stop , no parity
+#define AT91C_US_ASYNC_SCK_MODE ( AT91C_US_USMODE_NORMAL + \
+ AT91C_US_NBSTOP_1_BIT + \
+ AT91C_US_PAR_NONE + \
+ AT91C_US_CHRL_8_BITS + \
+ AT91C_US_CLKS_EXT )
+
+//* Standard Synchronous Mode : 8 bits , 1 stop , no parity
+#define AT91C_US_SYNC_MODE ( AT91C_US_SYNC + \
+ AT91C_US_USMODE_NORMAL + \
+ AT91C_US_NBSTOP_1_BIT + \
+ AT91C_US_PAR_NONE + \
+ AT91C_US_CHRL_8_BITS + \
+ AT91C_US_CLKS_CLOCK )
+
+//* SCK used Label
+#define AT91C_US_SCK_USED (AT91C_US_CKLO | AT91C_US_CLKS_EXT)
+
+//* Standard ISO T=0 Mode : 8 bits , 1 stop , parity
+#define AT91C_US_ISO_READER_MODE ( AT91C_US_USMODE_ISO7816_0 + \
+ AT91C_US_CLKS_CLOCK +\
+ AT91C_US_NBSTOP_1_BIT + \
+ AT91C_US_PAR_EVEN + \
+ AT91C_US_CHRL_8_BITS + \
+ AT91C_US_CKLO +\
+ AT91C_US_OVER)
+
+//* Standard IRDA mode
+#define AT91C_US_ASYNC_IRDA_MODE ( AT91C_US_USMODE_IRDA + \
+ AT91C_US_NBSTOP_1_BIT + \
+ AT91C_US_PAR_NONE + \
+ AT91C_US_CHRL_8_BITS + \
+ AT91C_US_CLKS_CLOCK )
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_Baudrate
+//* \brief Caluculate baud_value according to the main clock and the baud rate
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_US_Baudrate (
+ const unsigned int main_clock, // \arg peripheral clock
+ const unsigned int baud_rate) // \arg UART baudrate
+{
+ unsigned int baud_value = ((main_clock*10)/(baud_rate * 16));
+ if ((baud_value % 10) >= 5)
+ baud_value = (baud_value / 10) + 1;
+ else
+ baud_value /= 10;
+ return baud_value;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_SetBaudrate
+//* \brief Set the baudrate according to the CPU clock
+//*----------------------------------------------------------------------------
+static inline void AT91F_US_SetBaudrate (
+ AT91PS_USART pUSART, // \arg pointer to a USART controller
+ unsigned int mainClock, // \arg peripheral clock
+ unsigned int speed) // \arg UART baudrate
+{
+ //* Define the baud rate divisor register
+ pUSART->US_BRGR = AT91F_US_Baudrate(mainClock, speed);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_SetTimeguard
+//* \brief Set USART timeguard
+//*----------------------------------------------------------------------------
+static inline void AT91F_US_SetTimeguard (
+ AT91PS_USART pUSART, // \arg pointer to a USART controller
+ unsigned int timeguard) // \arg timeguard value
+{
+ //* Write the Timeguard Register
+ pUSART->US_TTGR = timeguard ;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_EnableIt
+//* \brief Enable USART IT
+//*----------------------------------------------------------------------------
+static inline void AT91F_US_EnableIt (
+ AT91PS_USART pUSART, // \arg pointer to a USART controller
+ unsigned int flag) // \arg IT to be enabled
+{
+ //* Write to the IER register
+ pUSART->US_IER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_DisableIt
+//* \brief Disable USART IT
+//*----------------------------------------------------------------------------
+static inline void AT91F_US_DisableIt (
+ AT91PS_USART pUSART, // \arg pointer to a USART controller
+ unsigned int flag) // \arg IT to be disabled
+{
+ //* Write to the IER register
+ pUSART->US_IDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_Configure
+//* \brief Configure USART
+//*----------------------------------------------------------------------------
+extern void AT91F_US_Configure (
+ AT91PS_USART pUSART, // \arg pointer to a USART controller
+ unsigned int mainClock, // \arg peripheral clock
+ unsigned int mode , // \arg mode Register to be programmed
+ unsigned int baudRate , // \arg baudrate to be programmed
+ unsigned int timeguard ); // \arg timeguard to be programmed
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_EnableRx
+//* \brief Enable receiving characters
+//*----------------------------------------------------------------------------
+static inline void AT91F_US_EnableRx (
+ AT91PS_USART pUSART) // \arg pointer to a USART controller
+{
+ //* Enable receiver
+ pUSART->US_CR = AT91C_US_RXEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_EnableTx
+//* \brief Enable sending characters
+//*----------------------------------------------------------------------------
+static inline void AT91F_US_EnableTx (
+ AT91PS_USART pUSART) // \arg pointer to a USART controller
+{
+ //* Enable transmitter
+ pUSART->US_CR = AT91C_US_TXEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_ResetRx
+//* \brief Reset Receiver and re-enable it
+//*----------------------------------------------------------------------------
+static inline void AT91F_US_ResetRx (
+ AT91PS_USART pUSART) // \arg pointer to a USART controller
+{
+ //* Reset receiver
+ pUSART->US_CR = AT91C_US_RSTRX;
+ //* Re-Enable receiver
+ pUSART->US_CR = AT91C_US_RXEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_ResetTx
+//* \brief Reset Transmitter and re-enable it
+//*----------------------------------------------------------------------------
+static inline void AT91F_US_ResetTx (
+ AT91PS_USART pUSART) // \arg pointer to a USART controller
+{
+ //* Reset transmitter
+ pUSART->US_CR = AT91C_US_RSTTX;
+ //* Enable transmitter
+ pUSART->US_CR = AT91C_US_TXEN;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_DisableRx
+//* \brief Disable Receiver
+//*----------------------------------------------------------------------------
+static inline void AT91F_US_DisableRx (
+ AT91PS_USART pUSART) // \arg pointer to a USART controller
+{
+ //* Disable receiver
+ pUSART->US_CR = AT91C_US_RXDIS;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_DisableTx
+//* \brief Disable Transmitter
+//*----------------------------------------------------------------------------
+static inline void AT91F_US_DisableTx (
+ AT91PS_USART pUSART) // \arg pointer to a USART controller
+{
+ //* Disable transmitter
+ pUSART->US_CR = AT91C_US_TXDIS;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_Close
+//* \brief Close USART: disable IT disable receiver and transmitter, close PDC
+//*----------------------------------------------------------------------------
+extern void AT91F_US_Close(AT91PS_USART pUSART); // \arg pointer to a USART controller
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_TxReady
+//* \brief Return 1 if a character can be written in US_THR
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_US_TxReady (
+ AT91PS_USART pUSART ) // \arg pointer to a USART controller
+{
+ return (pUSART->US_CSR & AT91C_US_TXRDY);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_RxReady
+//* \brief Return 1 if a character can be read in US_RHR
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_US_RxReady (
+ AT91PS_USART pUSART ) // \arg pointer to a USART controller
+{
+ return (pUSART->US_CSR & AT91C_US_RXRDY);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_Error
+//* \brief Return the error flag
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_US_Error (
+ AT91PS_USART pUSART ) // \arg pointer to a USART controller
+{
+ return (pUSART->US_CSR &
+ (AT91C_US_OVRE | // Overrun error
+ AT91C_US_FRAME | // Framing error
+ AT91C_US_PARE)); // Parity error
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_PutChar
+//* \brief Send a character,does not check if ready to send
+//*----------------------------------------------------------------------------
+static inline void AT91F_US_PutChar (
+ AT91PS_USART pUSART,
+ int character )
+{
+ pUSART->US_THR = (character & 0x1FF);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_GetChar
+//* \brief Receive a character,does not check if a character is available
+//*----------------------------------------------------------------------------
+static inline int AT91F_US_GetChar (
+ const AT91PS_USART pUSART)
+{
+ return((pUSART->US_RHR) & 0x1FF);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_SendFrame
+//* \brief Return 2 if PDC has been initialized with Buffer and Next Buffer, 1 if PDC has been initializaed with Next Buffer, 0 if PDC is busy
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_US_SendFrame(
+ AT91PS_USART pUSART,
+ const unsigned char *pBuffer,
+ unsigned int szBuffer,
+ const unsigned char *pNextBuffer,
+ unsigned int szNextBuffer )
+{
+ return AT91F_PDC_SendFrame(
+ (AT91PS_PDC) &(pUSART->US_RPR),
+ pBuffer,
+ szBuffer,
+ pNextBuffer,
+ szNextBuffer);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_ReceiveFrame
+//* \brief Return 2 if PDC has been initialized with Buffer and Next Buffer, 1 if PDC has been initializaed with Next Buffer, 0 if PDC is busy
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_US_ReceiveFrame (
+ AT91PS_USART pUSART,
+ unsigned char *pBuffer,
+ unsigned int szBuffer,
+ unsigned char *pNextBuffer,
+ unsigned int szNextBuffer )
+{
+ return AT91F_PDC_ReceiveFrame(
+ (AT91PS_PDC) &(pUSART->US_RPR),
+ pBuffer,
+ szBuffer,
+ pNextBuffer,
+ szNextBuffer);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_SetIrdaFilter
+//* \brief Set the value of IrDa filter tregister
+//*----------------------------------------------------------------------------
+static inline void AT91F_US_SetIrdaFilter (
+ AT91PS_USART pUSART,
+ unsigned char value
+)
+{
+ pUSART->US_IF = value;
+}
+
+/* *****************************************************************************
+ SOFTWARE API FOR TWI
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TWI_EnableIt
+//* \brief Enable TWI IT
+//*----------------------------------------------------------------------------
+static inline void AT91F_TWI_EnableIt (
+ AT91PS_TWI pTWI, // \arg pointer to a TWI controller
+ unsigned int flag) // \arg IT to be enabled
+{
+ //* Write to the IER register
+ pTWI->TWI_IER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TWI_DisableIt
+//* \brief Disable TWI IT
+//*----------------------------------------------------------------------------
+static inline void AT91F_TWI_DisableIt (
+ AT91PS_TWI pTWI, // \arg pointer to a TWI controller
+ unsigned int flag) // \arg IT to be disabled
+{
+ //* Write to the IDR register
+ pTWI->TWI_IDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TWI_Configure
+//* \brief Configure TWI in master mode
+//*----------------------------------------------------------------------------
+static inline void AT91F_TWI_Configure ( AT91PS_TWI pTWI ) // \arg pointer to a TWI controller
+{
+ //* Disable interrupts
+ pTWI->TWI_IDR = (unsigned int) -1;
+
+ //* Reset peripheral
+ pTWI->TWI_CR = AT91C_TWI_SWRST;
+
+ //* Set Master mode
+ pTWI->TWI_CR = AT91C_TWI_MSEN;
+
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TWI_GetInterruptMaskStatus
+//* \brief Return TWI Interrupt Mask Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_TWI_GetInterruptMaskStatus( // \return TWI Interrupt Mask Status
+ AT91PS_TWI pTwi) // \arg pointer to a TWI controller
+{
+ return pTwi->TWI_IMR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TWI_IsInterruptMasked
+//* \brief Test if TWI Interrupt is Masked
+//*----------------------------------------------------------------------------
+static inline int AT91F_TWI_IsInterruptMasked(
+ AT91PS_TWI pTwi, // \arg pointer to a TWI controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_TWI_GetInterruptMaskStatus(pTwi) & flag);
+}
+
+/* *****************************************************************************
+ SOFTWARE API FOR TC
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TC_InterruptEnable
+//* \brief Enable TC Interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_TC_InterruptEnable(
+ AT91PS_TC pTc, // \arg pointer to a TC controller
+ unsigned int flag) // \arg TC interrupt to be enabled
+{
+ pTc->TC_IER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TC_InterruptDisable
+//* \brief Disable TC Interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_TC_InterruptDisable(
+ AT91PS_TC pTc, // \arg pointer to a TC controller
+ unsigned int flag) // \arg TC interrupt to be disabled
+{
+ pTc->TC_IDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TC_GetInterruptMaskStatus
+//* \brief Return TC Interrupt Mask Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_TC_GetInterruptMaskStatus( // \return TC Interrupt Mask Status
+ AT91PS_TC pTc) // \arg pointer to a TC controller
+{
+ return pTc->TC_IMR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TC_IsInterruptMasked
+//* \brief Test if TC Interrupt is Masked
+//*----------------------------------------------------------------------------
+static inline int AT91F_TC_IsInterruptMasked(
+ AT91PS_TC pTc, // \arg pointer to a TC controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_TC_GetInterruptMaskStatus(pTc) & flag);
+}
+
+/* *****************************************************************************
+ SOFTWARE API FOR PWMC
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWM_GetStatus
+//* \brief Return PWM Interrupt Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PWMC_GetStatus( // \return PWM Interrupt Status
+ AT91PS_PWMC pPWM) // pointer to a PWM controller
+{
+ return pPWM->PWMC_SR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWM_InterruptEnable
+//* \brief Enable PWM Interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_PWMC_InterruptEnable(
+ AT91PS_PWMC pPwm, // \arg pointer to a PWM controller
+ unsigned int flag) // \arg PWM interrupt to be enabled
+{
+ pPwm->PWMC_IER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWM_InterruptDisable
+//* \brief Disable PWM Interrupt
+//*----------------------------------------------------------------------------
+static inline void AT91F_PWMC_InterruptDisable(
+ AT91PS_PWMC pPwm, // \arg pointer to a PWM controller
+ unsigned int flag) // \arg PWM interrupt to be disabled
+{
+ pPwm->PWMC_IDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWM_GetInterruptMaskStatus
+//* \brief Return PWM Interrupt Mask Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PWMC_GetInterruptMaskStatus( // \return PWM Interrupt Mask Status
+ AT91PS_PWMC pPwm) // \arg pointer to a PWM controller
+{
+ return pPwm->PWMC_IMR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWM_IsInterruptMasked
+//* \brief Test if PWM Interrupt is Masked
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PWMC_IsInterruptMasked(
+ AT91PS_PWMC pPWM, // \arg pointer to a PWM controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PWMC_GetInterruptMaskStatus(pPWM) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWM_IsStatusSet
+//* \brief Test if PWM Interrupt is Set
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_PWMC_IsStatusSet(
+ AT91PS_PWMC pPWM, // \arg pointer to a PWM controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_PWMC_GetStatus(pPWM) & flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWM_CfgChannel
+//* \brief Test if PWM Interrupt is Set
+//*----------------------------------------------------------------------------
+static inline void AT91F_PWMC_CfgChannel(
+ AT91PS_PWMC pPWM, // \arg pointer to a PWM controller
+ unsigned int channelId, // \arg PWM channel ID
+ unsigned int mode, // \arg PWM mode
+ unsigned int period, // \arg PWM period
+ unsigned int duty) // \arg PWM duty cycle
+{
+ pPWM->PWMC_CH[channelId].PWMC_CMR = mode;
+ pPWM->PWMC_CH[channelId].PWMC_CDTYR = duty;
+ pPWM->PWMC_CH[channelId].PWMC_CPRDR = period;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWM_StartChannel
+//* \brief Enable channel
+//*----------------------------------------------------------------------------
+static inline void AT91F_PWMC_StartChannel(
+ AT91PS_PWMC pPWM, // \arg pointer to a PWM controller
+ unsigned int flag) // \arg Channels IDs to be enabled
+{
+ pPWM->PWMC_ENA = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWM_StopChannel
+//* \brief Disable channel
+//*----------------------------------------------------------------------------
+static inline void AT91F_PWMC_StopChannel(
+ AT91PS_PWMC pPWM, // \arg pointer to a PWM controller
+ unsigned int flag) // \arg Channels IDs to be enabled
+{
+ pPWM->PWMC_DIS = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWM_UpdateChannel
+//* \brief Update Period or Duty Cycle
+//*----------------------------------------------------------------------------
+static inline void AT91F_PWMC_UpdateChannel(
+ AT91PS_PWMC pPWM, // \arg pointer to a PWM controller
+ unsigned int channelId, // \arg PWM channel ID
+ unsigned int update) // \arg Channels IDs to be enabled
+{
+ pPWM->PWMC_CH[channelId].PWMC_CUPDR = update;
+}
+
+/* *****************************************************************************
+ SOFTWARE API FOR UDP
+ ***************************************************************************** */
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_EnableIt
+//* \brief Enable UDP IT
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_EnableIt (
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned int flag) // \arg IT to be enabled
+{
+ //* Write to the IER register
+ pUDP->UDP_IER = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_DisableIt
+//* \brief Disable UDP IT
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_DisableIt (
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned int flag) // \arg IT to be disabled
+{
+ //* Write to the IDR register
+ pUDP->UDP_IDR = flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_SetAddress
+//* \brief Set UDP functional address
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_SetAddress (
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned char address) // \arg new UDP address
+{
+ pUDP->UDP_FADDR = (AT91C_UDP_FEN | address);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_EnableEp
+//* \brief Enable Endpoint
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_EnableEp (
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned char endpoint) // \arg endpoint number
+{
+ pUDP->UDP_CSR[endpoint] |= AT91C_UDP_EPEDS;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_DisableEp
+//* \brief Enable Endpoint
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_DisableEp (
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned char endpoint) // \arg endpoint number
+{
+ pUDP->UDP_CSR[endpoint] &= ~AT91C_UDP_EPEDS;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_SetState
+//* \brief Set UDP Device state
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_SetState (
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned int flag) // \arg new UDP address
+{
+ pUDP->UDP_GLBSTATE &= ~(AT91C_UDP_FADDEN | AT91C_UDP_CONFG);
+ pUDP->UDP_GLBSTATE |= flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_GetState
+//* \brief return UDP Device state
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_UDP_GetState ( // \return the UDP device state
+ AT91PS_UDP pUDP) // \arg pointer to a UDP controller
+{
+ return (pUDP->UDP_GLBSTATE & (AT91C_UDP_FADDEN | AT91C_UDP_CONFG));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_ResetEp
+//* \brief Reset UDP endpoint
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_ResetEp ( // \return the UDP device state
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned int flag) // \arg Endpoints to be reset
+{
+ pUDP->UDP_RSTEP = flag;
+ pUDP->UDP_RSTEP = 0;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_EpStall
+//* \brief Endpoint will STALL requests
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_EpStall(
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned char endpoint) // \arg endpoint number
+{
+ pUDP->UDP_CSR[endpoint] |= AT91C_UDP_FORCESTALL;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_EpWrite
+//* \brief Write value in the DPR
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_EpWrite(
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned char endpoint, // \arg endpoint number
+ unsigned char value) // \arg value to be written in the DPR
+{
+ pUDP->UDP_FDR[endpoint] = value;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_EpRead
+//* \brief Return value from the DPR
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_UDP_EpRead(
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned char endpoint) // \arg endpoint number
+{
+ return pUDP->UDP_FDR[endpoint];
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_EpEndOfWr
+//* \brief Notify the UDP that values in DPR are ready to be sent
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_EpEndOfWr(
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned char endpoint) // \arg endpoint number
+{
+ pUDP->UDP_CSR[endpoint] |= AT91C_UDP_TXPKTRDY;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_EpClear
+//* \brief Clear flag in the endpoint CSR register
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_EpClear(
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned char endpoint, // \arg endpoint number
+ unsigned int flag) // \arg flag to be cleared
+{
+ pUDP->UDP_CSR[endpoint] &= ~(flag);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_EpSet
+//* \brief Set flag in the endpoint CSR register
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_EpSet(
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned char endpoint, // \arg endpoint number
+ unsigned int flag) // \arg flag to be cleared
+{
+ pUDP->UDP_CSR[endpoint] |= flag;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_EpStatus
+//* \brief Return the endpoint CSR register
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_UDP_EpStatus(
+ AT91PS_UDP pUDP, // \arg pointer to a UDP controller
+ unsigned char endpoint) // \arg endpoint number
+{
+ return pUDP->UDP_CSR[endpoint];
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_GetInterruptMaskStatus
+//* \brief Return UDP Interrupt Mask Status
+//*----------------------------------------------------------------------------
+static inline unsigned int AT91F_UDP_GetInterruptMaskStatus(
+ AT91PS_UDP pUdp) // \arg pointer to a UDP controller
+{
+ return pUdp->UDP_IMR;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_IsInterruptMasked
+//* \brief Test if UDP Interrupt is Masked
+//*----------------------------------------------------------------------------
+static inline int AT91F_UDP_IsInterruptMasked(
+ AT91PS_UDP pUdp, // \arg pointer to a UDP controller
+ unsigned int flag) // \arg flag to be tested
+{
+ return (AT91F_UDP_GetInterruptMaskStatus(pUdp) & flag);
+}
+
+// ----------------------------------------------------------------------------
+// \fn AT91F_UDP_InterruptStatusRegister
+// \brief Return the Interrupt Status Register
+// ----------------------------------------------------------------------------
+static inline unsigned int AT91F_UDP_InterruptStatusRegister(
+ AT91PS_UDP pUDP ) // \arg pointer to a UDP controller
+{
+ return pUDP->UDP_ISR;
+}
+
+// ----------------------------------------------------------------------------
+// \fn AT91F_UDP_InterruptClearRegister
+// \brief Clear Interrupt Register
+// ----------------------------------------------------------------------------
+static inline void AT91F_UDP_InterruptClearRegister (
+ AT91PS_UDP pUDP, // \arg pointer to UDP controller
+ unsigned int flag) // \arg IT to be cleat
+{
+ pUDP->UDP_ICR = flag;
+}
+
+// ----------------------------------------------------------------------------
+// \fn AT91F_UDP_EnableTransceiver
+// \brief Enable transceiver
+// ----------------------------------------------------------------------------
+static inline void AT91F_UDP_EnableTransceiver(
+ AT91PS_UDP pUDP ) // \arg pointer to a UDP controller
+{
+ pUDP->UDP_TXVC &= ~AT91C_UDP_TXVDIS;
+}
+
+// ----------------------------------------------------------------------------
+// \fn AT91F_UDP_DisableTransceiver
+// \brief Disable transceiver
+// ----------------------------------------------------------------------------
+static inline void AT91F_UDP_DisableTransceiver(
+ AT91PS_UDP pUDP ) // \arg pointer to a UDP controller
+{
+ pUDP->UDP_TXVC = AT91C_UDP_TXVDIS;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_DBGU_CfgPMC
+//* \brief Enable Peripheral clock in PMC for DBGU
+//*----------------------------------------------------------------------------
+static inline void AT91F_DBGU_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_SYS));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_DBGU_CfgPIO
+//* \brief Configure PIO controllers to drive DBGU signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_DBGU_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ ((unsigned int) AT91C_PA9_DRXD ) |
+ ((unsigned int) AT91C_PA10_DTXD ), // Peripheral A
+ 0); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_CfgPMC
+//* \brief Enable Peripheral clock in PMC for PMC
+//*----------------------------------------------------------------------------
+static inline void AT91F_PMC_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_SYS));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PMC_CfgPIO
+//* \brief Configure PIO controllers to drive PMC signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_PMC_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ 0, // Peripheral A
+ ((unsigned int) AT91C_PA6_PCK0 ) |
+ ((unsigned int) AT91C_PA18_PCK2 ) |
+ ((unsigned int) AT91C_PA31_PCK2 ) |
+ ((unsigned int) AT91C_PA21_PCK1 ) |
+ ((unsigned int) AT91C_PA17_PCK1 )); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_VREG_CfgPMC
+//* \brief Enable Peripheral clock in PMC for VREG
+//*----------------------------------------------------------------------------
+static inline void AT91F_VREG_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_SYS));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_RSTC_CfgPMC
+//* \brief Enable Peripheral clock in PMC for RSTC
+//*----------------------------------------------------------------------------
+static inline void AT91F_RSTC_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_SYS));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_CfgPMC
+//* \brief Enable Peripheral clock in PMC for SSC
+//*----------------------------------------------------------------------------
+static inline void AT91F_SSC_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_SSC));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_CfgPIO
+//* \brief Configure PIO controllers to drive SSC signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_SSC_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ ((unsigned int) AT91C_PA19_RK ) |
+ ((unsigned int) AT91C_PA16_TK ) |
+ ((unsigned int) AT91C_PA15_TF ) |
+ ((unsigned int) AT91C_PA18_RD ) |
+ ((unsigned int) AT91C_PA20_RF ) |
+ ((unsigned int) AT91C_PA17_TD ), // Peripheral A
+ 0); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_WDTC_CfgPMC
+//* \brief Enable Peripheral clock in PMC for WDTC
+//*----------------------------------------------------------------------------
+static inline void AT91F_WDTC_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_SYS));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US1_CfgPMC
+//* \brief Enable Peripheral clock in PMC for US1
+//*----------------------------------------------------------------------------
+static inline void AT91F_US1_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_US1));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US1_CfgPIO
+//* \brief Configure PIO controllers to drive US1 signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_US1_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ ((unsigned int) AT91C_PA29_RI1 ) |
+ ((unsigned int) AT91C_PA26_DCD1 ) |
+ ((unsigned int) AT91C_PA28_DSR1 ) |
+ ((unsigned int) AT91C_PA27_DTR1 ) |
+ ((unsigned int) AT91C_PA23_SCK1 ) |
+ ((unsigned int) AT91C_PA24_RTS1 ) |
+ ((unsigned int) AT91C_PA22_TXD1 ) |
+ ((unsigned int) AT91C_PA21_RXD1 ) |
+ ((unsigned int) AT91C_PA25_CTS1 ), // Peripheral A
+ 0); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US0_CfgPMC
+//* \brief Enable Peripheral clock in PMC for US0
+//*----------------------------------------------------------------------------
+static inline void AT91F_US0_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_US0));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US0_CfgPIO
+//* \brief Configure PIO controllers to drive US0 signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_US0_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ ((unsigned int) AT91C_PA5_RXD0 ) |
+ ((unsigned int) AT91C_PA8_CTS0 ) |
+ ((unsigned int) AT91C_PA7_RTS0 ) |
+ ((unsigned int) AT91C_PA6_TXD0 ), // Peripheral A
+ ((unsigned int) AT91C_PA2_SCK0 )); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_CfgPMC
+//* \brief Enable Peripheral clock in PMC for SPI
+//*----------------------------------------------------------------------------
+static inline void AT91F_SPI_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_SPI));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_CfgPIO
+//* \brief Configure PIO controllers to drive SPI signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_SPI_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ ((unsigned int) AT91C_PA13_MOSI ) |
+ ((unsigned int) AT91C_PA31_NPCS1 ) |
+ ((unsigned int) AT91C_PA14_SPCK ) |
+ ((unsigned int) AT91C_PA11_NPCS0 ) |
+ ((unsigned int) AT91C_PA12_MISO ), // Peripheral A
+ ((unsigned int) AT91C_PA9_NPCS1 ) |
+ ((unsigned int) AT91C_PA22_NPCS3 ) |
+ ((unsigned int) AT91C_PA3_NPCS3 ) |
+ ((unsigned int) AT91C_PA5_NPCS3 ) |
+ ((unsigned int) AT91C_PA10_NPCS2 ) |
+ ((unsigned int) AT91C_PA30_NPCS2 )); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PITC_CfgPMC
+//* \brief Enable Peripheral clock in PMC for PITC
+//*----------------------------------------------------------------------------
+static inline void AT91F_PITC_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_SYS));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_CfgPMC
+//* \brief Enable Peripheral clock in PMC for AIC
+//*----------------------------------------------------------------------------
+static inline void AT91F_AIC_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_FIQ) |
+ ((unsigned int) 1 << AT91C_ID_IRQ0) |
+ ((unsigned int) 1 << AT91C_ID_IRQ1));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_CfgPIO
+//* \brief Configure PIO controllers to drive AIC signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_AIC_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ ((unsigned int) AT91C_PA30_IRQ1 ), // Peripheral A
+ ((unsigned int) AT91C_PA20_IRQ0 ) |
+ ((unsigned int) AT91C_PA19_FIQ )); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TWI_CfgPMC
+//* \brief Enable Peripheral clock in PMC for TWI
+//*----------------------------------------------------------------------------
+static inline void AT91F_TWI_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_TWI));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TWI_CfgPIO
+//* \brief Configure PIO controllers to drive TWI signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_TWI_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ ((unsigned int) AT91C_PA4_TWCK ) |
+ ((unsigned int) AT91C_PA3_TWD ), // Peripheral A
+ 0); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWMC_CH3_CfgPIO
+//* \brief Configure PIO controllers to drive PWMC_CH3 signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_PWMC_CH3_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ 0, // Peripheral A
+ ((unsigned int) AT91C_PA7_PWM3 ) |
+ ((unsigned int) AT91C_PA14_PWM3 )); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWMC_CH2_CfgPIO
+//* \brief Configure PIO controllers to drive PWMC_CH2 signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_PWMC_CH2_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ ((unsigned int) AT91C_PA2_PWM2 ), // Peripheral A
+ ((unsigned int) AT91C_PA13_PWM2 ) |
+ ((unsigned int) AT91C_PA25_PWM2 )); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWMC_CH1_CfgPIO
+//* \brief Configure PIO controllers to drive PWMC_CH1 signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_PWMC_CH1_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ ((unsigned int) AT91C_PA1_PWM1 ), // Peripheral A
+ ((unsigned int) AT91C_PA24_PWM1 ) |
+ ((unsigned int) AT91C_PA12_PWM1 )); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWMC_CH0_CfgPIO
+//* \brief Configure PIO controllers to drive PWMC_CH0 signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_PWMC_CH0_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ ((unsigned int) AT91C_PA0_PWM0 ), // Peripheral A
+ ((unsigned int) AT91C_PA23_PWM0 ) |
+ ((unsigned int) AT91C_PA11_PWM0 )); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_CfgPMC
+//* \brief Enable Peripheral clock in PMC for ADC
+//*----------------------------------------------------------------------------
+static inline void AT91F_ADC_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_ADC));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_CfgPIO
+//* \brief Configure PIO controllers to drive ADC signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_ADC_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ 0, // Peripheral A
+ ((unsigned int) AT91C_PA8_ADTRG )); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_RTTC_CfgPMC
+//* \brief Enable Peripheral clock in PMC for RTTC
+//*----------------------------------------------------------------------------
+static inline void AT91F_RTTC_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_SYS));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_UDP_CfgPMC
+//* \brief Enable Peripheral clock in PMC for UDP
+//*----------------------------------------------------------------------------
+static inline void AT91F_UDP_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_UDP));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TC0_CfgPMC
+//* \brief Enable Peripheral clock in PMC for TC0
+//*----------------------------------------------------------------------------
+static inline void AT91F_TC0_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_TC0));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TC0_CfgPIO
+//* \brief Configure PIO controllers to drive TC0 signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_TC0_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ 0, // Peripheral A
+ ((unsigned int) AT91C_PA0_TIOA0 ) |
+ ((unsigned int) AT91C_PA4_TCLK0 ) |
+ ((unsigned int) AT91C_PA1_TIOB0 )); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TC1_CfgPMC
+//* \brief Enable Peripheral clock in PMC for TC1
+//*----------------------------------------------------------------------------
+static inline void AT91F_TC1_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_TC1));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TC1_CfgPIO
+//* \brief Configure PIO controllers to drive TC1 signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_TC1_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ 0, // Peripheral A
+ ((unsigned int) AT91C_PA15_TIOA1 ) |
+ ((unsigned int) AT91C_PA28_TCLK1 ) |
+ ((unsigned int) AT91C_PA16_TIOB1 )); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TC2_CfgPMC
+//* \brief Enable Peripheral clock in PMC for TC2
+//*----------------------------------------------------------------------------
+static inline void AT91F_TC2_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_TC2));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_TC2_CfgPIO
+//* \brief Configure PIO controllers to drive TC2 signals
+//*----------------------------------------------------------------------------
+static inline void AT91F_TC2_CfgPIO (void)
+{
+ // Configure PIO controllers to periph mode
+ AT91F_PIO_CfgPeriph(
+ AT91C_BASE_PIOA, // PIO controller base address
+ 0, // Peripheral A
+ ((unsigned int) AT91C_PA27_TIOB2 ) |
+ ((unsigned int) AT91C_PA26_TIOA2 ) |
+ ((unsigned int) AT91C_PA29_TCLK2 )); // Peripheral B
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_MC_CfgPMC
+//* \brief Enable Peripheral clock in PMC for MC
+//*----------------------------------------------------------------------------
+static inline void AT91F_MC_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_SYS));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PIOA_CfgPMC
+//* \brief Enable Peripheral clock in PMC for PIOA
+//*----------------------------------------------------------------------------
+static inline void AT91F_PIOA_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_PIOA));
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PWMC_CfgPMC
+//* \brief Enable Peripheral clock in PMC for PWMC
+//*----------------------------------------------------------------------------
+static inline void AT91F_PWMC_CfgPMC (void)
+{
+ AT91F_PMC_EnablePeriphClock(
+ AT91C_BASE_PMC, // PIO controller base address
+ ((unsigned int) 1 << AT91C_ID_PWMC));
+}
+
+#define __ramfunc __attribute__ ((long_call, section (".fastrun")))
+
+#endif // lib_AT91SAM7S64_H
diff --git a/firmware/include/librfid/rfid.h b/firmware/include/librfid/rfid.h
new file mode 100644
index 0000000..308f46e
--- /dev/null
+++ b/firmware/include/librfid/rfid.h
@@ -0,0 +1,24 @@
+#ifndef _RFID_H
+#define _RFID_H
+
+#include <os/dbgu.h>
+
+#define rfid_hexdump hexdump
+
+enum rfid_frametype {
+ RFID_14443A_FRAME_REGULAR,
+ RFID_14443B_FRAME_REGULAR,
+ RFID_MIFARE_FRAME,
+};
+
+struct rfid_asic_handle {
+};
+
+struct rfid_asic {
+};
+
+#define RAH NULL
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#endif
diff --git a/firmware/include/librfid/rfid_layer2.h b/firmware/include/librfid/rfid_layer2.h
new file mode 100644
index 0000000..3dd54a2
--- /dev/null
+++ b/firmware/include/librfid/rfid_layer2.h
@@ -0,0 +1,76 @@
+#ifndef _RFID_LAYER2_H
+#define _RFID_LAYER2_H
+
+#include <sys/types.h>
+#include <librfid/rfid.h>
+
+struct rfid_layer2_handle;
+struct rfid_reader_handle;
+
+enum rfid_layer2_id {
+ RFID_LAYER2_NONE,
+ RFID_LAYER2_ISO14443A,
+ RFID_LAYER2_ISO14443B,
+ RFID_LAYER2_ISO15693,
+};
+
+struct rfid_layer2_handle *rfid_layer2_init(struct rfid_reader_handle *rh,
+ unsigned int id);
+int rfid_layer2_open(struct rfid_layer2_handle *l2h);
+int rfid_layer2_transceive(struct rfid_layer2_handle *l2h,
+ enum rfid_frametype frametype,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ u_int64_t timeout, unsigned int flags);
+int rfid_layer2_close(struct rfid_layer2_handle *l2h);
+int rfid_layer2_fini(struct rfid_layer2_handle *l2h);
+int rfid_layer2_getopt(struct rfid_layer2_handle *ph, int optname,
+ void *optval, unsigned int *optlen);
+int rfid_layer2_setopt(struct rfid_layer2_handle *ph, int optname,
+ const void *optval, unsigned int optlen);
+
+#ifdef __LIBRFID__
+
+#include <librfid/rfid_layer2_iso14443a.h>
+#include <librfid/rfid_layer2_iso14443b.h>
+#include <librfid/rfid_layer2_iso15693.h>
+
+struct rfid_layer2 {
+ unsigned int id;
+ char *name;
+
+ struct {
+ struct rfid_layer2_handle *(*init)(struct rfid_reader_handle *h);
+ int (*open)(struct rfid_layer2_handle *h);
+ int (*transceive)(struct rfid_layer2_handle *h,
+ enum rfid_frametype frametype,
+ const unsigned char *tx_buf,
+ unsigned int tx_len, unsigned char *rx_buf,
+ unsigned int *rx_len, u_int64_t timeout,
+ unsigned int flags);
+ int (*close)(struct rfid_layer2_handle *h);
+ int (*fini)(struct rfid_layer2_handle *h);
+ int (*getopt)(struct rfid_layer2_handle *h,
+ int optname, void *optval, unsigned int *optlen);
+ int (*setopt)(struct rfid_layer2_handle *h,
+ int optname, const void *optval,
+ unsigned int optlen);
+ } fn;
+ struct rfid_layer2 *next;
+};
+
+struct rfid_layer2_handle {
+ struct rfid_reader_handle *rh;
+ unsigned char uid[10]; /* triple size 14443a id is 10 bytes */
+ unsigned int uid_len;
+ union {
+ struct iso14443a_handle iso14443a;
+ struct iso14443b_handle iso14443b;
+ struct iso15693_handle iso15693;
+ } priv;
+ struct rfid_layer2 *l2;
+};
+
+#endif /* __LIBRFID__ */
+
+#endif
diff --git a/firmware/include/librfid/rfid_layer2_iso14443a.h b/firmware/include/librfid/rfid_layer2_iso14443a.h
new file mode 100644
index 0000000..e1ecd36
--- /dev/null
+++ b/firmware/include/librfid/rfid_layer2_iso14443a.h
@@ -0,0 +1,87 @@
+#ifndef _RFID_ISO14443A_H
+#define _RFID_ISO14443A_H
+
+
+enum rfid_14443a_opt {
+ RFID_OPT_14443A_SPEED_RX = 0x00000001,
+ RFID_OPT_14443A_SPEED_TX = 0x00000002,
+};
+
+enum rfid_14443_opt_speed {
+ RFID_14443A_SPEED_106K = 0x01,
+ RFID_14443A_SPEED_212K = 0x02,
+ RFID_14443A_SPEED_424K = 0x04,
+ RFID_14443A_SPEED_848K = 0x08,
+};
+
+#include <sys/types.h>
+
+/* protocol definitions */
+
+/* ISO 14443-3, Chapter 6.3.1 */
+enum iso14443a_sf_cmd {
+ ISO14443A_SF_CMD_REQA = 0x26,
+ ISO14443A_SF_CMD_WUPA = 0x52,
+ ISO14443A_SF_CMD_OPT_TIMESLOT = 0x35, /* Annex C */
+ /* 40 to 4f and 78 to 7f: proprietary */
+};
+
+struct iso14443a_atqa {
+ u_int8_t bf_anticol:5,
+ rfu1:1,
+ uid_size:2;
+ u_int8_t proprietary:4,
+ rfu2:4;
+} __attribute__ ((packed));
+
+#define ISO14443A_HLTA 0x5000
+
+/* ISO 14443-3, Chapter 6.3.2 */
+struct iso14443a_anticol_cmd {
+ unsigned char sel_code;
+ unsigned char nvb;
+ unsigned char uid_bits[5];
+} __attribute__ ((packed));
+
+enum iso14443a_anticol_sel_code {
+ ISO14443A_AC_SEL_CODE_CL1 = 0x93,
+ ISO14443A_AC_SEL_CODE_CL2 = 0x95,
+ ISO14443A_AC_SEL_CODE_CL3 = 0x97,
+};
+
+#define ISO14443A_BITOFCOL_NONE 0xffffffff
+
+struct iso14443a_handle {
+ unsigned int state;
+ unsigned int level;
+ unsigned int tcl_capable;
+};
+
+enum iso14443a_level {
+ ISO14443A_LEVEL_NONE,
+ ISO14443A_LEVEL_CL1,
+ ISO14443A_LEVEL_CL2,
+ ISO14443A_LEVEL_CL3,
+};
+
+enum iso14443a_state {
+ ISO14443A_STATE_ERROR,
+ ISO14443A_STATE_NONE,
+ ISO14443A_STATE_REQA_SENT,
+ ISO14443A_STATE_ATQA_RCVD,
+ ISO14443A_STATE_NO_BITFRAME_ANTICOL,
+ ISO14443A_STATE_ANTICOL_RUNNING,
+ ISO14443A_STATE_SELECTED,
+};
+
+/* Section 6.1.2 values in usec, rounded up to next usec */
+#define ISO14443A_FDT_ANTICOL_LAST1 92 /* 1236 / fc = 91.15 usec */
+#define ISO14443A_FDT_ANTICOL_LAST0 87 /* 1172 / fc = 86.43 usec */
+
+#define ISO14443_CARRIER_FREQ 13560000
+#define ISO14443A_FDT_OTHER_LAST1(n) (((n*128+84)*1000000)/ISO14443_CARRIER_FREQ)
+
+#include <librfid/rfid_layer2.h>
+struct rfid_layer2 rfid_layer2_iso14443a;
+
+#endif /* _ISO14443A_H */
diff --git a/firmware/include/librfid/rfid_layer2_iso14443b.h b/firmware/include/librfid/rfid_layer2_iso14443b.h
new file mode 100644
index 0000000..037c117
--- /dev/null
+++ b/firmware/include/librfid/rfid_layer2_iso14443b.h
@@ -0,0 +1,85 @@
+#ifndef _RFID_LAYER2_ISO14443B_H
+#define _RFID_LAYER2_ISO14443B_H
+
+#ifdef __LIBRFID__
+
+struct iso14443b_atqb {
+ unsigned char fifty;
+ unsigned char pupi[4];
+ unsigned char app_data[4];
+ struct {
+ unsigned char bit_rate_capability;
+ unsigned char protocol_type:4,
+ max_frame_size:4;
+ unsigned char fo:2,
+ adc:2,
+ fwi:4;
+ } protocol_info;
+} __attribute__((packed));
+
+struct iso14443b_attrib_hdr {
+ unsigned char one_d;
+ unsigned char identifier[4];
+ struct {
+ unsigned char rfu:2,
+ sof:1,
+ eof:1,
+ min_tr1:2,
+ min_tr0:2;
+ } param1;
+ struct {
+ unsigned char fsdi:4,
+ spd_out:2,
+ spd_in:2;
+ } param2;
+ struct {
+ unsigned char protocol_type:4,
+ rfu:4;
+ } param3;
+ struct {
+ unsigned char cid:4,
+ rfu:4;
+ } param4;
+} __attribute__((packed));
+
+struct iso14443b_handle {
+ unsigned int tcl_capable; /* do we support T=CL */
+
+ unsigned int cid; /* Card ID */
+
+ unsigned int fsc; /* max. frame size card */
+ unsigned int fsd; /* max. frame size reader */
+
+ unsigned int fwt; /* frame waiting time (in usec) */
+
+ unsigned int mbl; /* maximum buffer length */
+
+ unsigned int tr0; /* pcd-eof to picc-subcarrier-on */
+ unsigned int tr1; /* picc-subcarrier-on to picc-sof */
+
+ unsigned int flags;
+ unsigned int state;
+};
+
+enum {
+ ISO14443B_CID_SUPPORTED = 0x01,
+ ISO14443B_NAD_SUPPORTED = 0x02,
+};
+
+enum {
+ ISO14443B_STATE_ERROR,
+ ISO14443B_STATE_NONE,
+ ISO14443B_STATE_REQB_SENT,
+ ISO14443B_STATE_ATQB_RCVD,
+ ISO14443B_STATE_ATTRIB_SENT,
+ ISO14443B_STATE_SELECTED,
+ ISO14443B_STATE_HLTB_SENT,
+ ISO14443B_STATE_HALTED,
+};
+
+#include <librfid/rfid_layer2.h>
+struct rfid_layer2 rfid_layer2_iso14443b;
+
+#endif /* __LIBRFID__ */
+
+#endif
diff --git a/firmware/include/librfid/rfid_layer2_iso15693.h b/firmware/include/librfid/rfid_layer2_iso15693.h
new file mode 100644
index 0000000..d91b4ec
--- /dev/null
+++ b/firmware/include/librfid/rfid_layer2_iso15693.h
@@ -0,0 +1,55 @@
+#ifndef _RFID_ISO15693_H
+#define _RFID_ISO15693_H
+
+#include <sys/types.h>
+
+/*
+07h = TagIt
+04h = I.CODE
+05h = Infineon
+02h = ST
+*/
+
+/* protocol definitions */
+
+struct iso15693_handle;
+
+struct iso15693_transport {
+ unsigned char *name;
+
+ struct {
+ int (*init)(struct iso15693_handle *handle);
+ int (*fini)(struct iso15693_handle *handle);
+
+#if 0
+ int (*transceive_sf)(struct iso14443a_handle *handle,
+ unsigned char cmd,
+ struct iso14443a_atqa *atqa);
+ int (*transceive_acf)(struct iso14443a_handle *handle,
+ struct iso14443a_anticol_cmd *acf,
+ unsigned int *bit_of_col);
+#endif
+ int (*transceive)(struct iso15693_handle *handle,
+ const unsigned char *tx_buf,
+ unsigned int tx_len,
+ unsigned char *rx_buf,
+ unsigned int *rx_len);
+ } fn;
+
+ union {
+ } priv;
+};
+
+struct iso15693_handle {
+ unsigned int state;
+};
+
+enum iso15693_state {
+ ISO15693_STATE_ERROR,
+ ISO15693_STATE_NONE,
+};
+
+#include <librfid/rfid_layer2.h>
+extern struct rfid_layer2 rfid_layer2_iso15693;
+
+#endif /* _ISO15693_H */
diff --git a/firmware/include/librfid/rfid_protocol_mifare_classic.h b/firmware/include/librfid/rfid_protocol_mifare_classic.h
new file mode 100644
index 0000000..e6b2400
--- /dev/null
+++ b/firmware/include/librfid/rfid_protocol_mifare_classic.h
@@ -0,0 +1,28 @@
+#ifndef _MIFARE_CLASSIC_H
+
+#define MIFARE_CL_KEYA_DEFAULT "\xa0\xa1\xa2\xa3\xa4\xa5"
+#define MIFARE_CL_KEYB_DEFAULT "\xb0\xb1\xb2\xb3\xb4\xb5"
+
+#define MIFARE_CL_KEYA_DEFAULT_INFINEON "\xff\xff\xff\xff\xff\xff"
+#define MIFARE_CL_KEYB_DEFAULT_INFINEON MIFARE_CL_KEYA_DEFAULT_INFINEON
+
+#define MIFARE_CL_PAGE_MAX 0xff
+
+#define RFID_CMD_MIFARE_AUTH1A 0x60
+#define RFID_CMD_MIFARE_AUTH1B 0x61
+
+#ifdef __LIBRFID__
+
+extern struct rfid_protocol rfid_protocol_mfcl;
+
+
+#define MIFARE_CL_CMD_WRITE16 0xA0
+#define MIFARE_CL_CMD_READ 0x30
+
+#define MIFARE_CL_RESP_ACK 0x0a
+#define MIFARE_CL_RESP_NAK 0x00
+
+
+#endif /* __LIBRFID__ */
+
+#endif /* _MIFARE_CLASSIC_H */
diff --git a/firmware/include/openpcd.h b/firmware/include/openpcd.h
new file mode 100644
index 0000000..e6ccebe
--- /dev/null
+++ b/firmware/include/openpcd.h
@@ -0,0 +1,85 @@
+#ifndef _OPENPCD_PROTO_H
+#define _OPENPCD_PROTO_H
+
+/* This header file describes the USB protocol of the OpenPCD RFID reader */
+
+#include <sys/types.h>
+
+struct openpcd_hdr {
+ u_int8_t cmd; /* command. high nibble: class, low nibble: cmd */
+ u_int8_t flags;
+ u_int8_t reg; /* register */
+ u_int8_t val; /* value (in case of write *) */
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+#define OPENPC_FLAG_RESPOND 0x01 /* Response requested */
+
+enum openpcd_cmd_class {
+ /* PCD (reader) side */
+ OPENPCD_CMD_CLS_RC632 = 0x1,
+ OPENPCD_CMD_CLS_LED = 0x2,
+ OPENPCD_CMD_CLS_SSC = 0x3,
+ OPENPCD_CMD_CLS_PWM = 0x4,
+ OPENPCD_CMD_CLS_ADC = 0x5,
+ /* PICC (transponder) side */
+ OPENPCD_CMD_CLS_PICC = 0xe,
+
+ OPENPCD_CMD_CLS_USBTEST = 0xf,
+};
+
+#define OPENPCD_REG_MAX 0x3f
+
+#define OPENPCD_CMD_CLS(x) (x >> 4)
+#define OPENPCD_CMD(x) (x & 0xf)
+
+#define OPENPCD_CLS2CMD(x) (x << 4)
+
+/* CMD_CLS_RC632 */
+#define OPENPCD_CMD_WRITE_REG (0x1|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_RC632))
+#define OPENPCD_CMD_WRITE_FIFO (0x2|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_RC632))
+#define OPENPCD_CMD_WRITE_VFIFO (0x3|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_RC632))
+#define OPENPCD_CMD_REG_BITS_CLEAR (0x4|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_RC632))
+#define OPENPCD_CMD_REG_BITS_SET (0x5|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_RC632))
+#define OPENPCD_CMD_READ_REG (0x6|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_RC632))
+#define OPENPCD_CMD_READ_FIFO (0x7|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_RC632))
+#define OPENPCD_CMD_READ_VFIFO (0x8|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_RC632))
+#define OPENPCD_CMD_DUMP_REGS (0x9|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_RC632))
+#define OPENPCD_CMD_IRQ (0xa|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_RC632))
+
+/* CMD_CLS_LED */
+#define OPENPCD_CMD_SET_LED (0x1|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_LED))
+
+/* CMD_CLS_SSC */
+#define OPENPCD_CMD_SSC_READ (0x1|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_SSC))
+#define OPENPCD_CMD_SSC_WRITE (0x2|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_SSC))
+
+/* CMD_CLS_PWM */
+#define OPENPCD_CMD_PWM_ENABLE (0x1|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_PWM))
+#define OPENPCD_CMD_PWM_DUTY_SET (0x2|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_PWM))
+#define OPENPCD_CMD_PWM_DUTY_GET (0x3|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_PWM))
+#define OPENPCD_CMD_PWM_FREQ_SET (0x4|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_PWM))
+#define OPENPCD_CMD_PWM_FREQ_GET (0x5|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_PWM))
+
+/* CMD_CLS_PICC */
+#define OPENPCD_CMD_PICC_REG_WRITE (0x1|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_PICC))
+#define OPENPCD_CMD_PICC_REG_READ (0x2|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_PICC))
+
+/* CMD_CLS_ADC */
+#define OPENPCD_CMD_ADC_READ (0x1|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_ADC))
+
+/* CMD_CLS_USBTEST */
+#define OPENPCD_CMD_USBTEST_IN (0x1|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_USBTEST))
+#define OPENPCD_CMD_USBTEST_OUT (0x2|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_USBTEST))
+
+/* FIXME */
+#define OPENPCD_CMD_PIO_IRQ (0x3|OPENPCD_CLS2CMD(OPENPCD_CMD_CLS_USBTEST))
+
+
+#define OPENPCD_VENDOR_ID 0x2342
+#define OPENPCD_PRODUCT_ID 0x0001
+#define OPENPCD_OUT_EP 0x01
+#define OPENPCD_IN_EP 0x82
+#define OPENPCD_IRQ_EP 0x83
+
+#endif
diff --git a/firmware/include/openpicc.h b/firmware/include/openpicc.h
new file mode 100644
index 0000000..2a9f1bc
--- /dev/null
+++ b/firmware/include/openpicc.h
@@ -0,0 +1,31 @@
+#ifndef _OPENPICC_H
+#define _OPENPICC_H
+
+/* OpenPICC Register definition
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ */
+
+enum openpicc_register {
+ OPICC_REG_MODE, /* operational mode */
+ OPICC_REG_ISO14443A_FDT_0, /* FDT (after 0) in carrier cycles */
+ OPICC_REG_ISO14443A_FDT_1, /* FDT (after 1) in carrier cycles */
+ OPICC_REG_BITCLK_PHASE_CORR, /* signed 8bit phase correction */
+ OPICC_REG_SPEED_RX,
+ OPICC_REG_SPEED_TX,
+ OPICC_REG_UID_PUPI, /* UID (14443A) / PUPI (14443B) */
+};
+
+enum openpicc_reg_mode {
+ OPICC_MODE_14443A,
+ OPICC_MODE_14443B,
+ OPICC_MODE_LOWLEVEL, /* low-level bit-transceive mode TBD */
+};
+
+enum openpicc_reg_speed {
+ OPICC_SPEED_14443_106K,
+ OPICC_SPEED_14443_212K,
+ OPICC_SPEED_14443_424K,
+ OPICC_SPEED_14443_848K,
+};
+
+#endif /* _OPENPICC_H */
diff --git a/firmware/include/usb_ch9.h b/firmware/include/usb_ch9.h
new file mode 100644
index 0000000..82edf61
--- /dev/null
+++ b/firmware/include/usb_ch9.h
@@ -0,0 +1,550 @@
+/*
+ * This file holds USB constants and structures that are needed for USB
+ * device APIs. These are used by the USB device model, which is defined
+ * in chapter 9 of the USB 2.0 specification. Linux has several APIs in C
+ * that need these:
+ *
+ * - the master/host side Linux-USB kernel driver API;
+ * - the "usbfs" user space API; and
+ * - the Linux "gadget" slave/device/peripheral side driver API.
+ *
+ * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems
+ * act either as a USB master/host or as a USB slave/device. That means
+ * the master and slave side APIs benefit from working well together.
+ *
+ * There's also "Wireless USB", using low power short range radios for
+ * peripheral interconnection but otherwise building on the USB framework.
+ */
+
+#ifndef __LINUX_USB_CH9_H
+#define __LINUX_USB_CH9_H
+
+#include <sys/types.h>
+
+/*-------------------------------------------------------------------------*/
+
+/* CONTROL REQUEST SUPPORT */
+
+/*
+ * USB directions
+ *
+ * This bit flag is used in endpoint descriptors' bEndpointAddress field.
+ * It's also one of three fields in control requests bRequestType.
+ */
+#define USB_DIR_OUT 0 /* to device */
+#define USB_DIR_IN 0x80 /* to host */
+
+/*
+ * USB types, the second of three bRequestType fields
+ */
+#define USB_TYPE_MASK (0x03 << 5)
+#define USB_TYPE_STANDARD (0x00 << 5)
+#define USB_TYPE_CLASS (0x01 << 5)
+#define USB_TYPE_VENDOR (0x02 << 5)
+#define USB_TYPE_RESERVED (0x03 << 5)
+
+/*
+ * USB recipients, the third of three bRequestType fields
+ */
+#define USB_RECIP_MASK 0x1f
+#define USB_RECIP_DEVICE 0x00
+#define USB_RECIP_INTERFACE 0x01
+#define USB_RECIP_ENDPOINT 0x02
+#define USB_RECIP_OTHER 0x03
+
+/*
+ * Standard requests, for the bRequest field of a SETUP packet.
+ *
+ * These are qualified by the bRequestType field, so that for example
+ * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
+ * by a GET_STATUS request.
+ */
+#define USB_REQ_GET_STATUS 0x00
+#define USB_REQ_CLEAR_FEATURE 0x01
+#define USB_REQ_SET_FEATURE 0x03
+#define USB_REQ_SET_ADDRESS 0x05
+#define USB_REQ_GET_DESCRIPTOR 0x06
+#define USB_REQ_SET_DESCRIPTOR 0x07
+#define USB_REQ_GET_CONFIGURATION 0x08
+#define USB_REQ_SET_CONFIGURATION 0x09
+#define USB_REQ_GET_INTERFACE 0x0A
+#define USB_REQ_SET_INTERFACE 0x0B
+#define USB_REQ_SYNCH_FRAME 0x0C
+
+#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */
+#define USB_REQ_GET_ENCRYPTION 0x0E
+#define USB_REQ_SET_HANDSHAKE 0x0F
+#define USB_REQ_GET_HANDSHAKE 0x10
+#define USB_REQ_SET_CONNECTION 0x11
+#define USB_REQ_SET_SECURITY_DATA 0x12
+#define USB_REQ_GET_SECURITY_DATA 0x13
+#define USB_REQ_SET_WUSB_DATA 0x14
+#define USB_REQ_LOOPBACK_DATA_WRITE 0x15
+#define USB_REQ_LOOPBACK_DATA_READ 0x16
+#define USB_REQ_SET_INTERFACE_DS 0x17
+
+/*
+ * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
+ * are read as a bit array returned by USB_REQ_GET_STATUS. (So there
+ * are at most sixteen features of each type.)
+ */
+#define USB_DEVICE_SELF_POWERED 0 /* (read only) */
+#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */
+#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */
+#define USB_DEVICE_BATTERY 2 /* (wireless) */
+#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */
+#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/
+#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */
+#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */
+#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */
+
+#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */
+
+
+/**
+ * struct usb_ctrlrequest - SETUP data for a USB device control request
+ * @bRequestType: matches the USB bmRequestType field
+ * @bRequest: matches the USB bRequest field
+ * @wValue: matches the USB wValue field (le16 byte order)
+ * @wIndex: matches the USB wIndex field (le16 byte order)
+ * @wLength: matches the USB wLength field (le16 byte order)
+ *
+ * This structure is used to send control requests to a USB device. It matches
+ * the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the
+ * USB spec for a fuller description of the different fields, and what they are
+ * used for.
+ *
+ * Note that the driver for any interface can issue control requests.
+ * For most devices, interfaces don't coordinate with each other, so
+ * such requests may be made at any time.
+ */
+struct usb_ctrlrequest {
+ u_int8_t bRequestType;
+ u_int8_t bRequest;
+ u_int16_t wValue;
+ u_int16_t wIndex;
+ u_int16_t wLength;
+} __attribute__ ((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
+ * (rarely) accepted by SET_DESCRIPTOR.
+ *
+ * Note that all multi-byte values here are encoded in little endian
+ * byte order "on the wire". But when exposed through Linux-USB APIs,
+ * they've been converted to cpu byte order.
+ */
+
+/*
+ * Descriptor types ... USB 2.0 spec table 9.5
+ */
+#define USB_DT_DEVICE 0x01
+#define USB_DT_CONFIG 0x02
+#define USB_DT_STRING 0x03
+#define USB_DT_INTERFACE 0x04
+#define USB_DT_ENDPOINT 0x05
+#define USB_DT_DEVICE_QUALIFIER 0x06
+#define USB_DT_OTHER_SPEED_CONFIG 0x07
+#define USB_DT_INTERFACE_POWER 0x08
+/* these are from a minor usb 2.0 revision (ECN) */
+#define USB_DT_OTG 0x09
+#define USB_DT_DEBUG 0x0a
+#define USB_DT_INTERFACE_ASSOCIATION 0x0b
+/* these are from the Wireless USB spec */
+#define USB_DT_SECURITY 0x0c
+#define USB_DT_KEY 0x0d
+#define USB_DT_ENCRYPTION_TYPE 0x0e
+#define USB_DT_BOS 0x0f
+#define USB_DT_DEVICE_CAPABILITY 0x10
+#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11
+
+/* conventional codes for class-specific descriptors */
+#define USB_DT_CS_DEVICE 0x21
+#define USB_DT_CS_CONFIG 0x22
+#define USB_DT_CS_STRING 0x23
+#define USB_DT_CS_INTERFACE 0x24
+#define USB_DT_CS_ENDPOINT 0x25
+
+/* All standard descriptors have these 2 fields at the beginning */
+struct usb_descriptor_header {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+} __attribute__ ((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEVICE: Device descriptor */
+struct usb_device_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int16_t bcdUSB;
+ u_int8_t bDeviceClass;
+ u_int8_t bDeviceSubClass;
+ u_int8_t bDeviceProtocol;
+ u_int8_t bMaxPacketSize0;
+ u_int16_t idVendor;
+ u_int16_t idProduct;
+ u_int16_t bcdDevice;
+ u_int8_t iManufacturer;
+ u_int8_t iProduct;
+ u_int8_t iSerialNumber;
+ u_int8_t bNumConfigurations;
+} __attribute__ ((packed));
+
+#define USB_DT_DEVICE_SIZE 18
+
+
+/*
+ * Device and/or Interface Class codes
+ * as found in bDeviceClass or bInterfaceClass
+ * and defined by www.usb.org documents
+ */
+#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
+#define USB_CLASS_AUDIO 1
+#define USB_CLASS_COMM 2
+#define USB_CLASS_HID 3
+#define USB_CLASS_PHYSICAL 5
+#define USB_CLASS_STILL_IMAGE 6
+#define USB_CLASS_PRINTER 7
+#define USB_CLASS_MASS_STORAGE 8
+#define USB_CLASS_HUB 9
+#define USB_CLASS_CDC_DATA 0x0a
+#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
+#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
+#define USB_CLASS_VIDEO 0x0e
+#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
+#define USB_CLASS_APP_SPEC 0xfe
+#define USB_CLASS_VENDOR_SPEC 0xff
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_CONFIG: Configuration descriptor information.
+ *
+ * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
+ * descriptor type is different. Highspeed-capable devices can look
+ * different depending on what speed they're currently running. Only
+ * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
+ * descriptors.
+ */
+struct usb_config_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int16_t wTotalLength;
+ u_int8_t bNumInterfaces;
+ u_int8_t bConfigurationValue;
+ u_int8_t iConfiguration;
+ u_int8_t bmAttributes;
+ u_int8_t bMaxPower;
+} __attribute__ ((packed));
+
+#define USB_DT_CONFIG_SIZE 9
+
+/* from config descriptor bmAttributes */
+#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */
+#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */
+#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */
+#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_STRING: String descriptor */
+struct usb_string_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int16_t wData[1]; /* UTF-16LE encoded */
+} __attribute__ ((packed));
+
+/* note that "string" zero is special, it holds language codes that
+ * the device supports, not Unicode characters.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_INTERFACE: Interface descriptor */
+struct usb_interface_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int8_t bInterfaceNumber;
+ u_int8_t bAlternateSetting;
+ u_int8_t bNumEndpoints;
+ u_int8_t bInterfaceClass;
+ u_int8_t bInterfaceSubClass;
+ u_int8_t bInterfaceProtocol;
+ u_int8_t iInterface;
+} __attribute__ ((packed));
+
+#define USB_DT_INTERFACE_SIZE 9
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_ENDPOINT: Endpoint descriptor */
+struct usb_endpoint_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int8_t bEndpointAddress;
+ u_int8_t bmAttributes;
+ u_int16_t wMaxPacketSize;
+ u_int8_t bInterval;
+} __attribute__ ((packed));
+
+#define USB_DT_ENDPOINT_SIZE 7
+#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
+
+
+/*
+ * Endpoints
+ */
+#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
+#define USB_ENDPOINT_DIR_MASK 0x80
+
+#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
+#define USB_ENDPOINT_XFER_CONTROL 0
+#define USB_ENDPOINT_XFER_ISOC 1
+#define USB_ENDPOINT_XFER_BULK 2
+#define USB_ENDPOINT_XFER_INT 3
+#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
+struct usb_qualifier_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int16_t bcdUSB;
+ u_int8_t bDeviceClass;
+ u_int8_t bDeviceSubClass;
+ u_int8_t bDeviceProtocol;
+ u_int8_t bMaxPacketSize0;
+ u_int8_t bNumConfigurations;
+ u_int8_t bRESERVED;
+} __attribute__ ((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_OTG (from OTG 1.0a supplement) */
+struct usb_otg_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int8_t bmAttributes; /* support for HNP, SRP, etc */
+} __attribute__ ((packed));
+
+/* from usb_otg_descriptor.bmAttributes */
+#define USB_OTG_SRP (1 << 0)
+#define USB_OTG_HNP (1 << 1) /* swap host/device roles */
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */
+struct usb_debug_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ /* bulk endpoints with 8 byte maxpacket */
+ u_int8_t bDebugInEndpoint;
+ u_int8_t bDebugOutEndpoint;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */
+struct usb_interface_assoc_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int8_t bFirstInterface;
+ u_int8_t bInterfaceCount;
+ u_int8_t bFunctionClass;
+ u_int8_t bFunctionSubClass;
+ u_int8_t bFunctionProtocol;
+ u_int8_t iFunction;
+} __attribute__ ((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_SECURITY: group of wireless security descriptors, including
+ * encryption types available for setting up a CC/association.
+ */
+struct usb_security_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int16_t wTotalLength;
+ u_int8_t bNumEncryptionTypes;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_KEY: used with {GET,SET}_SECURITY_DATA; only public keys
+ * may be retrieved.
+ */
+struct usb_key_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int8_t tTKID[3];
+ u_int8_t bReserved;
+ u_int8_t bKeyData[0];
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_ENCRYPTION_TYPE: bundled in DT_SECURITY groups */
+struct usb_encryption_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int8_t bEncryptionType;
+#define USB_ENC_TYPE_UNSECURE 0
+#define USB_ENC_TYPE_WIRED 1 /* non-wireless mode */
+#define USB_ENC_TYPE_CCM_1 2 /* aes128/cbc session */
+#define USB_ENC_TYPE_RSA_1 3 /* rsa3072/sha1 auth */
+ u_int8_t bEncryptionValue; /* use in SET_ENCRYPTION */
+ u_int8_t bAuthKeyIndex;
+};
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_BOS: group of wireless capabilities */
+struct usb_bos_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int16_t wTotalLength;
+ u_int8_t bNumDeviceCaps;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEVICE_CAPABILITY: grouped with BOS */
+struct usb_dev_cap_header {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+ u_int8_t bDevCapabilityType;
+};
+
+#define USB_CAP_TYPE_WIRELESS_USB 1
+
+struct usb_wireless_cap_descriptor { /* Ultra Wide Band */
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+ u_int8_t bDevCapabilityType;
+
+ u_int8_t bmAttributes;
+#define USB_WIRELESS_P2P_DRD (1 << 1)
+#define USB_WIRELESS_BEACON_MASK (3 << 2)
+#define USB_WIRELESS_BEACON_SELF (1 << 2)
+#define USB_WIRELESS_BEACON_DIRECTED (2 << 2)
+#define USB_WIRELESS_BEACON_NONE (3 << 2)
+ u_int16_t wPHYRates; /* bit rates, Mbps */
+#define USB_WIRELESS_PHY_53 (1 << 0) /* always set */
+#define USB_WIRELESS_PHY_80 (1 << 1)
+#define USB_WIRELESS_PHY_107 (1 << 2) /* always set */
+#define USB_WIRELESS_PHY_160 (1 << 3)
+#define USB_WIRELESS_PHY_200 (1 << 4) /* always set */
+#define USB_WIRELESS_PHY_320 (1 << 5)
+#define USB_WIRELESS_PHY_400 (1 << 6)
+#define USB_WIRELESS_PHY_480 (1 << 7)
+ u_int8_t bmTFITXPowerInfo; /* TFI power levels */
+ u_int8_t bmFFITXPowerInfo; /* FFI power levels */
+ u_int16_t bmBandGroup;
+ u_int8_t bReserved;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with
+ * each endpoint descriptor for a wireless device
+ */
+struct usb_wireless_ep_comp_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+
+ u_int8_t bMaxBurst;
+ u_int8_t bMaxSequence;
+ u_int16_t wMaxStreamDelay;
+ u_int16_t wOverTheAirPacketSize;
+ u_int8_t bOverTheAirInterval;
+ u_int8_t bmCompAttributes;
+#define USB_ENDPOINT_SWITCH_MASK 0x03 /* in bmCompAttributes */
+#define USB_ENDPOINT_SWITCH_NO 0
+#define USB_ENDPOINT_SWITCH_SWITCH 1
+#define USB_ENDPOINT_SWITCH_SCALE 2
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless
+ * host and a device for connection set up, mutual authentication, and
+ * exchanging short lived session keys. The handshake depends on a CC.
+ */
+struct usb_handshake {
+ u_int8_t bMessageNumber;
+ u_int8_t bStatus;
+ u_int8_t tTKID[3];
+ u_int8_t bReserved;
+ u_int8_t CDID[16];
+ u_int8_t nonce[16];
+ u_int8_t MIC[8];
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC).
+ * A CC may also be set up using non-wireless secure channels (including
+ * wired USB!), and some devices may support CCs with multiple hosts.
+ */
+struct usb_connection_context {
+ u_int8_t CHID[16]; /* persistent host id */
+ u_int8_t CDID[16]; /* device id (unique w/in host context) */
+ u_int8_t CK[16]; /* connection key */
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* USB 2.0 defines three speeds, here's how Linux identifies them */
+
+enum usb_device_speed {
+ USB_SPEED_UNKNOWN = 0, /* enumerating */
+ USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
+ USB_SPEED_HIGH, /* usb 2.0 */
+ USB_SPEED_VARIABLE, /* wireless (usb 2.5) */
+};
+
+enum usb_device_state {
+ /* NOTATTACHED isn't in the USB spec, and this state acts
+ * the same as ATTACHED ... but it's clearer this way.
+ */
+ USB_STATE_NOTATTACHED = 0,
+
+ /* chapter 9 and authentication (wireless) device states */
+ USB_STATE_ATTACHED,
+ USB_STATE_POWERED, /* wired */
+ USB_STATE_UNAUTHENTICATED, /* auth */
+ USB_STATE_RECONNECTING, /* auth */
+ USB_STATE_DEFAULT, /* limited function */
+ USB_STATE_ADDRESS,
+ USB_STATE_CONFIGURED, /* most functions */
+
+ USB_STATE_SUSPENDED
+
+ /* NOTE: there are actually four different SUSPENDED
+ * states, returning to POWERED, DEFAULT, ADDRESS, or
+ * CONFIGURED respectively when SOF tokens flow again.
+ */
+};
+
+#endif /* __LINUX_USB_CH9_H */
diff --git a/firmware/include/usb_dfu.h b/firmware/include/usb_dfu.h
new file mode 100644
index 0000000..5000edc
--- /dev/null
+++ b/firmware/include/usb_dfu.h
@@ -0,0 +1,81 @@
+#ifndef _USB_DFU_H
+#define _USB_DFU_H
+/* USB Device Firmware Update Implementation for OpenPCD
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * Protocol definitions for USB DFU
+ *
+ * This ought to be compliant to the USB DFU Spec 1.0 as available from
+ * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
+ *
+ */
+
+#include <sys/types.h>
+
+#define USB_DT_DFU 0x21
+
+struct usb_dfu_func_descriptor {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+ u_int8_t bmAttributes;
+#define USB_DFU_CAN_DOWNLOAD (1 << 0)
+#define USB_DFU_CAN_UPLOAD (1 << 1)
+#define USB_DFU_MANIFEST_TOL (1 << 2)
+#define USB_DFU_WILL_DETACH (1 << 3)
+ u_int16_t wDetachTimeOut;
+ u_int16_t wTransferSize;
+ u_int16_t bcdDFUVersion;
+} __attribute__ ((packed));
+
+#define USB_DT_DFU_SIZE 9
+
+#define USB_TYPE_DFU (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
+
+/* DFU class-specific requests (Section 3, DFU Rev 1.1) */
+#define USB_REQ_DFU_DETACH 0x00
+#define USB_REQ_DFU_DNLOAD 0x01
+#define USB_REQ_DFU_UPLOAD 0x02
+#define USB_REQ_DFU_GETSTATUS 0x03
+#define USB_REQ_DFU_CLRSTATUS 0x04
+#define USB_REQ_DFU_GETSTATE 0x05
+#define USB_REQ_DFU_ABORT 0x06
+
+struct dfu_status {
+ u_int8_t bStatus;
+ u_int8_t bwPollTimeout[3];
+ u_int8_t bState;
+ u_int8_t iString;
+} __attribute__((packed));
+
+#define DFU_STATUS_OK 0x00
+#define DFU_STATUS_errTARGET 0x01
+#define DFU_STATUS_errFILE 0x02
+#define DFU_STATUS_errWRITE 0x03
+#define DFU_STATUS_errERASE 0x04
+#define DFU_STATUS_errCHECK_ERASED 0x05
+#define DFU_STATUS_errPROG 0x06
+#define DFU_STATUS_errVERIFY 0x07
+#define DFU_STATUS_errADDRESS 0x08
+#define DFU_STATUS_errNOTDONE 0x09
+#define DFU_STATUS_errFIRMWARE 0x0a
+#define DFU_STATUS_errVENDOR 0x0b
+#define DFU_STATUS_errUSBR 0x0c
+#define DFU_STATUS_errPOR 0x0d
+#define DFU_STATUS_errUNKNOWN 0x0e
+#define DFU_STATUS_errSTALLEDPKT 0x0f
+
+enum dfu_state {
+ DFU_STATE_appIDLE = 0,
+ DFU_STATE_appDETACH = 1,
+ DFU_STATE_dfuIDLE = 2,
+ DFU_STATE_dfuDNLOAD_SYNC = 3,
+ DFU_STATE_dfuDNBUSY = 4,
+ DFU_STATE_dfuDNLOAD_IDLE = 5,
+ DFU_STATE_dfuMANIFEST_SYNC = 6,
+ DFU_STATE_dfuMANIFEST = 7,
+ DFU_STATE_dfuMANIFEST_WAIT_RST = 8,
+ DFU_STATE_dfuUPLOAD_IDLE = 9,
+ DFU_STATE_dfuERROR = 10,
+};
+
+#endif /* _USB_DFU_H */
diff --git a/firmware/lib/bitops.h b/firmware/lib/bitops.h
new file mode 100644
index 0000000..428c9a6
--- /dev/null
+++ b/firmware/lib/bitops.h
@@ -0,0 +1,33 @@
+ .macro bitop, instr
+ and r2, r0, #7
+ mov r3, #1
+ mov r3, r3, lsl r2
+ save_and_disable_irqs ip
+ ldrb r2, [r1, r0, lsr #3]
+ \instr r2, r2, r3
+ strb r2, [r1, r0, lsr #3]
+ restore_irqs ip
+ mov pc, lr
+ .endm
+
+/**
+ * testop - implement a test_and_xxx_bit operation.
+ * @instr: operational instruction
+ * @store: store instruction
+ *
+ * Note: we can trivially conditionalise the store instruction
+ * to avoid dirting the data cache.
+ */
+ .macro testop, instr, store
+ add r1, r1, r0, lsr #3
+ and r3, r0, #7
+ mov r0, #1
+ save_and_disable_irqs ip
+ ldrb r2, [r1]
+ tst r2, r0, lsl r3
+ \instr r2, r2, r0, lsl r3
+ \store r2, [r1]
+ restore_irqs ip
+ moveq r0, #0
+ mov pc, lr
+ .endm
diff --git a/firmware/lib/changebit.S b/firmware/lib/changebit.S
new file mode 100644
index 0000000..7c709fb
--- /dev/null
+++ b/firmware/lib/changebit.S
@@ -0,0 +1,21 @@
+/*
+ * linux/arch/arm/lib/changebit.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/linkage.h>
+#include <asm/assembler.h>
+#include "bitops.h"
+ .text
+
+/* Purpose : Function to change a bit
+ * Prototype: int change_bit(int bit, void *addr)
+ */
+ENTRY(_change_bit_be)
+ eor r0, r0, #0x18 @ big endian byte ordering
+ENTRY(_change_bit_le)
+ bitop eor
diff --git a/firmware/lib/clearbit.S b/firmware/lib/clearbit.S
new file mode 100644
index 0000000..cb48f7a
--- /dev/null
+++ b/firmware/lib/clearbit.S
@@ -0,0 +1,22 @@
+/*
+ * linux/arch/arm/lib/clearbit.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/linkage.h>
+#include <asm/assembler.h>
+#include "bitops.h"
+ .text
+
+/*
+ * Purpose : Function to clear a bit
+ * Prototype: int clear_bit(int bit, void *addr)
+ */
+ENTRY(_clear_bit_be)
+ eor r0, r0, #0x18 @ big endian byte ordering
+ENTRY(_clear_bit_le)
+ bitop bic
diff --git a/firmware/lib/copy_template.S b/firmware/lib/copy_template.S
new file mode 100644
index 0000000..cab355c
--- /dev/null
+++ b/firmware/lib/copy_template.S
@@ -0,0 +1,255 @@
+/*
+ * linux/arch/arm/lib/copy_template.s
+ *
+ * Code template for optimized memory copy functions
+ *
+ * Author: Nicolas Pitre
+ * Created: Sep 28, 2005
+ * Copyright: MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * This can be used to enable code to cacheline align the source pointer.
+ * Experiments on tested architectures (StrongARM and XScale) didn't show
+ * this a worthwhile thing to do. That might be different in the future.
+ */
+//#define CALGN(code...) code
+#define CALGN(code...)
+
+/*
+ * Theory of operation
+ * -------------------
+ *
+ * This file provides the core code for a forward memory copy used in
+ * the implementation of memcopy(), copy_to_user() and copy_from_user().
+ *
+ * The including file must define the following accessor macros
+ * according to the need of the given function:
+ *
+ * ldr1w ptr reg abort
+ *
+ * This loads one word from 'ptr', stores it in 'reg' and increments
+ * 'ptr' to the next word. The 'abort' argument is used for fixup tables.
+ *
+ * ldr4w ptr reg1 reg2 reg3 reg4 abort
+ * ldr8w ptr, reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+ *
+ * This loads four or eight words starting from 'ptr', stores them
+ * in provided registers and increments 'ptr' past those words.
+ * The'abort' argument is used for fixup tables.
+ *
+ * ldr1b ptr reg cond abort
+ *
+ * Similar to ldr1w, but it loads a byte and increments 'ptr' one byte.
+ * It also must apply the condition code if provided, otherwise the
+ * "al" condition is assumed by default.
+ *
+ * str1w ptr reg abort
+ * str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+ * str1b ptr reg cond abort
+ *
+ * Same as their ldr* counterparts, but data is stored to 'ptr' location
+ * rather than being loaded.
+ *
+ * enter reg1 reg2
+ *
+ * Preserve the provided registers on the stack plus any additional
+ * data as needed by the implementation including this code. Called
+ * upon code entry.
+ *
+ * exit reg1 reg2
+ *
+ * Restore registers with the values previously saved with the
+ * 'preserv' macro. Called upon code termination.
+ */
+
+
+ enter r4, lr
+
+ subs r2, r2, #4
+ blt 8f
+ ands ip, r0, #3
+ PLD( pld [r1, #0] )
+ bne 9f
+ ands ip, r1, #3
+ bne 10f
+
+1: subs r2, r2, #(28)
+ stmfd sp!, {r5 - r8}
+ blt 5f
+
+ CALGN( ands ip, r1, #31 )
+ CALGN( rsb r3, ip, #32 )
+ CALGN( sbcnes r4, r3, r2 ) @ C is always set here
+ CALGN( bcs 2f )
+ CALGN( adr r4, 6f )
+ CALGN( subs r2, r2, r3 ) @ C gets set
+ CALGN( add pc, r4, ip )
+
+ PLD( pld [r1, #0] )
+2: PLD( subs r2, r2, #96 )
+ PLD( pld [r1, #28] )
+ PLD( blt 4f )
+ PLD( pld [r1, #60] )
+ PLD( pld [r1, #92] )
+
+3: PLD( pld [r1, #124] )
+4: ldr8w r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
+ subs r2, r2, #32
+ str8w r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
+ bge 3b
+ PLD( cmn r2, #96 )
+ PLD( bge 4b )
+
+5: ands ip, r2, #28
+ rsb ip, ip, #32
+ addne pc, pc, ip @ C is always clear here
+ b 7f
+6: nop
+ ldr1w r1, r3, abort=20f
+ ldr1w r1, r4, abort=20f
+ ldr1w r1, r5, abort=20f
+ ldr1w r1, r6, abort=20f
+ ldr1w r1, r7, abort=20f
+ ldr1w r1, r8, abort=20f
+ ldr1w r1, lr, abort=20f
+
+ add pc, pc, ip
+ nop
+ nop
+ str1w r0, r3, abort=20f
+ str1w r0, r4, abort=20f
+ str1w r0, r5, abort=20f
+ str1w r0, r6, abort=20f
+ str1w r0, r7, abort=20f
+ str1w r0, r8, abort=20f
+ str1w r0, lr, abort=20f
+
+ CALGN( bcs 2b )
+
+7: ldmfd sp!, {r5 - r8}
+
+8: movs r2, r2, lsl #31
+ ldr1b r1, r3, ne, abort=21f
+ ldr1b r1, r4, cs, abort=21f
+ ldr1b r1, ip, cs, abort=21f
+ str1b r0, r3, ne, abort=21f
+ str1b r0, r4, cs, abort=21f
+ str1b r0, ip, cs, abort=21f
+
+ exit r4, pc
+
+9: rsb ip, ip, #4
+ cmp ip, #2
+ ldr1b r1, r3, gt, abort=21f
+ ldr1b r1, r4, ge, abort=21f
+ ldr1b r1, lr, abort=21f
+ str1b r0, r3, gt, abort=21f
+ str1b r0, r4, ge, abort=21f
+ subs r2, r2, ip
+ str1b r0, lr, abort=21f
+ blt 8b
+ ands ip, r1, #3
+ beq 1b
+
+10: bic r1, r1, #3
+ cmp ip, #2
+ ldr1w r1, lr, abort=21f
+ beq 17f
+ bgt 18f
+
+
+ .macro forward_copy_shift pull push
+
+ subs r2, r2, #28
+ blt 14f
+
+ CALGN( ands ip, r1, #31 )
+ CALGN( rsb ip, ip, #32 )
+ CALGN( sbcnes r4, ip, r2 ) @ C is always set here
+ CALGN( subcc r2, r2, ip )
+ CALGN( bcc 15f )
+
+11: stmfd sp!, {r5 - r9}
+
+ PLD( pld [r1, #0] )
+ PLD( subs r2, r2, #96 )
+ PLD( pld [r1, #28] )
+ PLD( blt 13f )
+ PLD( pld [r1, #60] )
+ PLD( pld [r1, #92] )
+
+12: PLD( pld [r1, #124] )
+13: ldr4w r1, r4, r5, r6, r7, abort=19f
+ mov r3, lr, pull #\pull
+ subs r2, r2, #32
+ ldr4w r1, r8, r9, ip, lr, abort=19f
+ orr r3, r3, r4, push #\push
+ mov r4, r4, pull #\pull
+ orr r4, r4, r5, push #\push
+ mov r5, r5, pull #\pull
+ orr r5, r5, r6, push #\push
+ mov r6, r6, pull #\pull
+ orr r6, r6, r7, push #\push
+ mov r7, r7, pull #\pull
+ orr r7, r7, r8, push #\push
+ mov r8, r8, pull #\pull
+ orr r8, r8, r9, push #\push
+ mov r9, r9, pull #\pull
+ orr r9, r9, ip, push #\push
+ mov ip, ip, pull #\pull
+ orr ip, ip, lr, push #\push
+ str8w r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f
+ bge 12b
+ PLD( cmn r2, #96 )
+ PLD( bge 13b )
+
+ ldmfd sp!, {r5 - r9}
+
+14: ands ip, r2, #28
+ beq 16f
+
+15: mov r3, lr, pull #\pull
+ ldr1w r1, lr, abort=21f
+ subs ip, ip, #4
+ orr r3, r3, lr, push #\push
+ str1w r0, r3, abort=21f
+ bgt 15b
+ CALGN( cmp r2, #0 )
+ CALGN( bge 11b )
+
+16: sub r1, r1, #(\push / 8)
+ b 8b
+
+ .endm
+
+
+ forward_copy_shift pull=8 push=24
+
+17: forward_copy_shift pull=16 push=16
+
+18: forward_copy_shift pull=24 push=8
+
+
+/*
+ * Abort preamble and completion macros.
+ * If a fixup handler is required then those macros must surround it.
+ * It is assumed that the fixup code will handle the private part of
+ * the exit macro.
+ */
+
+ .macro copy_abort_preamble
+19: ldmfd sp!, {r5 - r9}
+ b 21f
+20: ldmfd sp!, {r5 - r8}
+21:
+ .endm
+
+ .macro copy_abort_end
+ ldmfd sp!, {r4, pc}
+ .endm
+
diff --git a/firmware/lib/ctype.c b/firmware/lib/ctype.c
new file mode 100644
index 0000000..6ec51cc
--- /dev/null
+++ b/firmware/lib/ctype.c
@@ -0,0 +1,34 @@
+/*
+ * linux/lib/ctype.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include <asm/ctype.h>
+
+unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
+
diff --git a/firmware/lib/div64.S b/firmware/lib/div64.S
new file mode 100644
index 0000000..7eeef50
--- /dev/null
+++ b/firmware/lib/div64.S
@@ -0,0 +1,200 @@
+/*
+ * linux/arch/arm/lib/div64.S
+ *
+ * Optimized computation of 64-bit dividend / 32-bit divisor
+ *
+ * Author: Nicolas Pitre
+ * Created: Oct 5, 2003
+ * Copyright: Monta Vista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <asm/linkage.h>
+
+#ifdef __ARMEB__
+#define xh r0
+#define xl r1
+#define yh r2
+#define yl r3
+#else
+#define xl r0
+#define xh r1
+#define yl r2
+#define yh r3
+#endif
+
+/*
+ * __do_div64: perform a division with 64-bit dividend and 32-bit divisor.
+ *
+ * Note: Calling convention is totally non standard for optimal code.
+ * This is meant to be used by do_div() from include/asm/div64.h only.
+ *
+ * Input parameters:
+ * xh-xl = dividend (clobbered)
+ * r4 = divisor (preserved)
+ *
+ * Output values:
+ * yh-yl = result
+ * xh = remainder
+ *
+ * Clobbered regs: xl, ip
+ */
+
+ENTRY(__do_div64)
+
+ @ Test for easy paths first.
+ subs ip, r4, #1
+ bls 9f @ divisor is 0 or 1
+ tst ip, r4
+ beq 8f @ divisor is power of 2
+
+ @ See if we need to handle upper 32-bit result.
+ cmp xh, r4
+ mov yh, #0
+ blo 3f
+
+ @ Align divisor with upper part of dividend.
+ @ The aligned divisor is stored in yl preserving the original.
+ @ The bit position is stored in ip.
+
+#if __LINUX_ARM_ARCH__ >= 5
+
+ clz yl, r4
+ clz ip, xh
+ sub yl, yl, ip
+ mov ip, #1
+ mov ip, ip, lsl yl
+ mov yl, r4, lsl yl
+
+#else
+
+ mov yl, r4
+ mov ip, #1
+1: cmp yl, #0x80000000
+ cmpcc yl, xh
+ movcc yl, yl, lsl #1
+ movcc ip, ip, lsl #1
+ bcc 1b
+
+#endif
+
+ @ The division loop for needed upper bit positions.
+ @ Break out early if dividend reaches 0.
+2: cmp xh, yl
+ orrcs yh, yh, ip
+ subcss xh, xh, yl
+ movnes ip, ip, lsr #1
+ mov yl, yl, lsr #1
+ bne 2b
+
+ @ See if we need to handle lower 32-bit result.
+3: cmp xh, #0
+ mov yl, #0
+ cmpeq xl, r4
+ movlo xh, xl
+ movlo pc, lr
+
+ @ The division loop for lower bit positions.
+ @ Here we shift remainer bits leftwards rather than moving the
+ @ divisor for comparisons, considering the carry-out bit as well.
+ mov ip, #0x80000000
+4: movs xl, xl, lsl #1
+ adcs xh, xh, xh
+ beq 6f
+ cmpcc xh, r4
+5: orrcs yl, yl, ip
+ subcs xh, xh, r4
+ movs ip, ip, lsr #1
+ bne 4b
+ mov pc, lr
+
+ @ The top part of remainder became zero. If carry is set
+ @ (the 33th bit) this is a false positive so resume the loop.
+ @ Otherwise, if lower part is also null then we are done.
+6: bcs 5b
+ cmp xl, #0
+ moveq pc, lr
+
+ @ We still have remainer bits in the low part. Bring them up.
+
+#if __LINUX_ARM_ARCH__ >= 5
+
+ clz xh, xl @ we know xh is zero here so...
+ add xh, xh, #1
+ mov xl, xl, lsl xh
+ mov ip, ip, lsr xh
+
+#else
+
+7: movs xl, xl, lsl #1
+ mov ip, ip, lsr #1
+ bcc 7b
+
+#endif
+
+ @ Current remainder is now 1. It is worthless to compare with
+ @ divisor at this point since divisor can not be smaller than 3 here.
+ @ If possible, branch for another shift in the division loop.
+ @ If no bit position left then we are done.
+ movs ip, ip, lsr #1
+ mov xh, #1
+ bne 4b
+ mov pc, lr
+
+8: @ Division by a power of 2: determine what that divisor order is
+ @ then simply shift values around
+
+#if __LINUX_ARM_ARCH__ >= 5
+
+ clz ip, r4
+ rsb ip, ip, #31
+
+#else
+
+ mov yl, r4
+ cmp r4, #(1 << 16)
+ mov ip, #0
+ movhs yl, yl, lsr #16
+ movhs ip, #16
+
+ cmp yl, #(1 << 8)
+ movhs yl, yl, lsr #8
+ addhs ip, ip, #8
+
+ cmp yl, #(1 << 4)
+ movhs yl, yl, lsr #4
+ addhs ip, ip, #4
+
+ cmp yl, #(1 << 2)
+ addhi ip, ip, #3
+ addls ip, ip, yl, lsr #1
+
+#endif
+
+ mov yh, xh, lsr ip
+ mov yl, xl, lsr ip
+ rsb ip, ip, #32
+ orr yl, yl, xh, lsl ip
+ mov xh, xl, lsl ip
+ mov xh, xh, lsr ip
+ mov pc, lr
+
+ @ eq -> division by 1: obvious enough...
+9: moveq yl, xl
+ moveq yh, xh
+ moveq xh, #0
+ moveq pc, lr
+
+ @ Division by 0:
+ str lr, [sp, #-8]!
+ bl __div0
+
+ @ as wrong as it could be...
+ mov yl, #0
+ mov yh, #0
+ mov xh, #0
+ ldr pc, [sp], #8
+
diff --git a/firmware/lib/lib1funcs.S b/firmware/lib/lib1funcs.S
new file mode 100644
index 0000000..92a6c56
--- /dev/null
+++ b/firmware/lib/lib1funcs.S
@@ -0,0 +1,338 @@
+/*
+ * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
+ *
+ * Author: Nicolas Pitre <nico@cam.org>
+ * - contributed to gcc-3.4 on Sep 30, 2003
+ * - adapted for the Linux kernel on Oct 2, 2003
+ */
+
+/* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file. (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+#include <asm/linkage.h>
+#include <asm/assembler.h>
+
+
+.macro ARM_DIV_BODY dividend, divisor, result, curbit
+
+#if __LINUX_ARM_ARCH__ >= 5
+
+ clz \curbit, \divisor
+ clz \result, \dividend
+ sub \result, \curbit, \result
+ mov \curbit, #1
+ mov \divisor, \divisor, lsl \result
+ mov \curbit, \curbit, lsl \result
+ mov \result, #0
+
+#else
+
+ @ Initially shift the divisor left 3 bits if possible,
+ @ set curbit accordingly. This allows for curbit to be located
+ @ at the left end of each 4 bit nibbles in the division loop
+ @ to save one loop in most cases.
+ tst \divisor, #0xe0000000
+ moveq \divisor, \divisor, lsl #3
+ moveq \curbit, #8
+ movne \curbit, #1
+
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+1: cmp \divisor, #0x10000000
+ cmplo \divisor, \dividend
+ movlo \divisor, \divisor, lsl #4
+ movlo \curbit, \curbit, lsl #4
+ blo 1b
+
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+1: cmp \divisor, #0x80000000
+ cmplo \divisor, \dividend
+ movlo \divisor, \divisor, lsl #1
+ movlo \curbit, \curbit, lsl #1
+ blo 1b
+
+ mov \result, #0
+
+#endif
+
+ @ Division loop
+1: cmp \dividend, \divisor
+ subhs \dividend, \dividend, \divisor
+ orrhs \result, \result, \curbit
+ cmp \dividend, \divisor, lsr #1
+ subhs \dividend, \dividend, \divisor, lsr #1
+ orrhs \result, \result, \curbit, lsr #1
+ cmp \dividend, \divisor, lsr #2
+ subhs \dividend, \dividend, \divisor, lsr #2
+ orrhs \result, \result, \curbit, lsr #2
+ cmp \dividend, \divisor, lsr #3
+ subhs \dividend, \dividend, \divisor, lsr #3
+ orrhs \result, \result, \curbit, lsr #3
+ cmp \dividend, #0 @ Early termination?
+ movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
+ movne \divisor, \divisor, lsr #4
+ bne 1b
+
+.endm
+
+
+.macro ARM_DIV2_ORDER divisor, order
+
+#if __LINUX_ARM_ARCH__ >= 5
+
+ clz \order, \divisor
+ rsb \order, \order, #31
+
+#else
+
+ cmp \divisor, #(1 << 16)
+ movhs \divisor, \divisor, lsr #16
+ movhs \order, #16
+ movlo \order, #0
+
+ cmp \divisor, #(1 << 8)
+ movhs \divisor, \divisor, lsr #8
+ addhs \order, \order, #8
+
+ cmp \divisor, #(1 << 4)
+ movhs \divisor, \divisor, lsr #4
+ addhs \order, \order, #4
+
+ cmp \divisor, #(1 << 2)
+ addhi \order, \order, #3
+ addls \order, \order, \divisor, lsr #1
+
+#endif
+
+.endm
+
+
+.macro ARM_MOD_BODY dividend, divisor, order, spare
+
+#if __LINUX_ARM_ARCH__ >= 5
+
+ clz \order, \divisor
+ clz \spare, \dividend
+ sub \order, \order, \spare
+ mov \divisor, \divisor, lsl \order
+
+#else
+
+ mov \order, #0
+
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+1: cmp \divisor, #0x10000000
+ cmplo \divisor, \dividend
+ movlo \divisor, \divisor, lsl #4
+ addlo \order, \order, #4
+ blo 1b
+
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+1: cmp \divisor, #0x80000000
+ cmplo \divisor, \dividend
+ movlo \divisor, \divisor, lsl #1
+ addlo \order, \order, #1
+ blo 1b
+
+#endif
+
+ @ Perform all needed substractions to keep only the reminder.
+ @ Do comparisons in batch of 4 first.
+ subs \order, \order, #3 @ yes, 3 is intended here
+ blt 2f
+
+1: cmp \dividend, \divisor
+ subhs \dividend, \dividend, \divisor
+ cmp \dividend, \divisor, lsr #1
+ subhs \dividend, \dividend, \divisor, lsr #1
+ cmp \dividend, \divisor, lsr #2
+ subhs \dividend, \dividend, \divisor, lsr #2
+ cmp \dividend, \divisor, lsr #3
+ subhs \dividend, \dividend, \divisor, lsr #3
+ cmp \dividend, #1
+ mov \divisor, \divisor, lsr #4
+ subges \order, \order, #4
+ bge 1b
+
+ tst \order, #3
+ teqne \dividend, #0
+ beq 5f
+
+ @ Either 1, 2 or 3 comparison/substractions are left.
+2: cmn \order, #2
+ blt 4f
+ beq 3f
+ cmp \dividend, \divisor
+ subhs \dividend, \dividend, \divisor
+ mov \divisor, \divisor, lsr #1
+3: cmp \dividend, \divisor
+ subhs \dividend, \dividend, \divisor
+ mov \divisor, \divisor, lsr #1
+4: cmp \dividend, \divisor
+ subhs \dividend, \dividend, \divisor
+5:
+.endm
+
+
+ENTRY(__udivsi3)
+ENTRY(__aeabi_uidiv)
+
+ subs r2, r1, #1
+ moveq pc, lr
+ bcc Ldiv0
+ cmp r0, r1
+ bls 11f
+ tst r1, r2
+ beq 12f
+
+ ARM_DIV_BODY r0, r1, r2, r3
+
+ mov r0, r2
+ mov pc, lr
+
+11: moveq r0, #1
+ movne r0, #0
+ mov pc, lr
+
+12: ARM_DIV2_ORDER r1, r2
+
+ mov r0, r0, lsr r2
+ mov pc, lr
+
+
+ENTRY(__umodsi3)
+
+ subs r2, r1, #1 @ compare divisor with 1
+ bcc Ldiv0
+ cmpne r0, r1 @ compare dividend with divisor
+ moveq r0, #0
+ tsthi r1, r2 @ see if divisor is power of 2
+ andeq r0, r0, r2
+ movls pc, lr
+
+ ARM_MOD_BODY r0, r1, r2, r3
+
+ mov pc, lr
+
+
+ENTRY(__divsi3)
+ENTRY(__aeabi_idiv)
+
+ cmp r1, #0
+ eor ip, r0, r1 @ save the sign of the result.
+ beq Ldiv0
+ rsbmi r1, r1, #0 @ loops below use unsigned.
+ subs r2, r1, #1 @ division by 1 or -1 ?
+ beq 10f
+ movs r3, r0
+ rsbmi r3, r0, #0 @ positive dividend value
+ cmp r3, r1
+ bls 11f
+ tst r1, r2 @ divisor is power of 2 ?
+ beq 12f
+
+ ARM_DIV_BODY r3, r1, r0, r2
+
+ cmp ip, #0
+ rsbmi r0, r0, #0
+ mov pc, lr
+
+10: teq ip, r0 @ same sign ?
+ rsbmi r0, r0, #0
+ mov pc, lr
+
+11: movlo r0, #0
+ moveq r0, ip, asr #31
+ orreq r0, r0, #1
+ mov pc, lr
+
+12: ARM_DIV2_ORDER r1, r2
+
+ cmp ip, #0
+ mov r0, r3, lsr r2
+ rsbmi r0, r0, #0
+ mov pc, lr
+
+
+ENTRY(__modsi3)
+
+ cmp r1, #0
+ beq Ldiv0
+ rsbmi r1, r1, #0 @ loops below use unsigned.
+ movs ip, r0 @ preserve sign of dividend
+ rsbmi r0, r0, #0 @ if negative make positive
+ subs r2, r1, #1 @ compare divisor with 1
+ cmpne r0, r1 @ compare dividend with divisor
+ moveq r0, #0
+ tsthi r1, r2 @ see if divisor is power of 2
+ andeq r0, r0, r2
+ bls 10f
+
+ ARM_MOD_BODY r0, r1, r2, r3
+
+10: cmp ip, #0
+ rsbmi r0, r0, #0
+ mov pc, lr
+
+#ifdef CONFIG_AEABI
+
+ENTRY(__aeabi_uidivmod)
+
+ stmfd sp!, {r0, r1, ip, lr}
+ bl __aeabi_uidiv
+ ldmfd sp!, {r1, r2, ip, lr}
+ mul r3, r0, r2
+ sub r1, r1, r3
+ mov pc, lr
+
+ENTRY(__aeabi_idivmod)
+
+ stmfd sp!, {r0, r1, ip, lr}
+ bl __aeabi_idiv
+ ldmfd sp!, {r1, r2, ip, lr}
+ mul r3, r0, r2
+ sub r1, r1, r3
+ mov pc, lr
+
+#endif
+
+Ldiv0:
+
+ str lr, [sp, #-8]!
+ bl __div0
+ mov r0, #0 @ About as wrong as it could be.
+ ldr pc, [sp], #8
+
+ENTRY(__div0)
+ mov pc, lr
diff --git a/firmware/lib/lib_AT91SAM7.c b/firmware/lib/lib_AT91SAM7.c
new file mode 100644
index 0000000..950761f
--- /dev/null
+++ b/firmware/lib/lib_AT91SAM7.c
@@ -0,0 +1,405 @@
+//* ----------------------------------------------------------------------------
+//* ATMEL Microcontroller Software Support - ROUSSET -
+//* ----------------------------------------------------------------------------
+//* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+//* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+//* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+//* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+//* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+//* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+//* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+//* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+//* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//* ----------------------------------------------------------------------------
+//* File Name : lib_AT91SAM7S64.h
+//* Object : AT91SAM7S64 inlined functions
+//* Generated : AT91 SW Application Group 08/30/2005 (15:52:59)
+//*
+
+#include <sys/types.h>
+#include <include/AT91SAM7.h>
+#include <include/lib_AT91SAM7.h>
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_ConfigureIt
+//* \brief Interrupt Handler Initialization
+//*----------------------------------------------------------------------------
+unsigned int AT91F_AIC_ConfigureIt (
+ AT91PS_AIC pAic, // \arg pointer to the AIC registers
+ unsigned int irq_id, // \arg interrupt number to initialize
+ unsigned int priority, // \arg priority to give to the interrupt
+ unsigned int src_type, // \arg activation and sense of activation
+ void (*newHandler) () ) // \arg address of the interrupt handler
+{
+ unsigned int oldHandler;
+ unsigned int mask ;
+
+ oldHandler = pAic->AIC_SVR[irq_id];
+
+ mask = 0x1 << irq_id ;
+ //* Disable the interrupt on the interrupt controller
+ pAic->AIC_IDCR = mask ;
+ //* Save the interrupt handler routine pointer and the interrupt priority
+ pAic->AIC_SVR[irq_id] = (unsigned int) newHandler ;
+ //* Store the Source Mode Register
+ pAic->AIC_SMR[irq_id] = src_type | priority ;
+ //* Clear the interrupt on the interrupt controller
+ pAic->AIC_ICCR = mask ;
+
+ return oldHandler;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_SetExceptionVector
+//* \brief Configure vector handler
+//*----------------------------------------------------------------------------
+unsigned int AT91F_AIC_SetExceptionVector (
+ unsigned int *pVector, // \arg pointer to the AIC registers
+ void (*Handler) () ) // \arg Interrupt Handler
+{
+ unsigned int oldVector = *pVector;
+
+ if ((unsigned int) Handler == (unsigned int) AT91C_AIC_BRANCH_OPCODE)
+ *pVector = (unsigned int) AT91C_AIC_BRANCH_OPCODE;
+ else
+ *pVector = (((((unsigned int) Handler) - ((unsigned int) pVector) - 0x8) >> 2) & 0x00FFFFFF) | 0xEA000000;
+
+ return oldVector;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_AIC_Open
+//* \brief Set exception vectors and AIC registers to default values
+//*----------------------------------------------------------------------------
+void AT91F_AIC_Open(
+ AT91PS_AIC pAic, // \arg pointer to the AIC registers
+ void (*IrqHandler) (), // \arg Default IRQ vector exception
+ void (*FiqHandler) (), // \arg Default FIQ vector exception
+ void (*DefaultHandler) (), // \arg Default Handler set in ISR
+ void (*SpuriousHandler) (), // \arg Default Spurious Handler
+ unsigned int protectMode) // \arg Debug Control Register
+{
+ int i;
+
+ // Disable all interrupts and set IVR to the default handler
+ for (i = 0; i < 32; ++i) {
+ AT91F_AIC_DisableIt(pAic, i);
+ AT91F_AIC_ConfigureIt(pAic, i, AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, DefaultHandler);
+ }
+
+ // Set the IRQ exception vector
+ AT91F_AIC_SetExceptionVector((unsigned int *) 0x18, IrqHandler);
+ // Set the Fast Interrupt exception vector
+ AT91F_AIC_SetExceptionVector((unsigned int *) 0x1C, FiqHandler);
+
+ pAic->AIC_SPU = (unsigned int) SpuriousHandler;
+ pAic->AIC_DCR = protectMode;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_Open
+//* \brief Open PDC: disable TX and RX reset transfer descriptors, re-enable RX and TX
+//*----------------------------------------------------------------------------
+void AT91F_PDC_Open(AT91PS_PDC pPDC) // \arg pointer to a PDC controller
+{
+ //* Disable the RX and TX PDC transfer requests
+ AT91F_PDC_DisableRx(pPDC);
+ AT91F_PDC_DisableTx(pPDC);
+
+ //* Reset all Counter register Next buffer first
+ AT91F_PDC_SetNextTx(pPDC, NULL, 0);
+ AT91F_PDC_SetNextRx(pPDC, NULL, 0);
+ AT91F_PDC_SetTx(pPDC, NULL, 0);
+ AT91F_PDC_SetRx(pPDC, NULL, 0);
+
+ //* Enable the RX and TX PDC transfer requests
+ AT91F_PDC_EnableRx(pPDC);
+ AT91F_PDC_EnableTx(pPDC);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_Close
+//* \brief Close PDC: disable TX and RX reset transfer descriptors
+//*----------------------------------------------------------------------------
+void AT91F_PDC_Close(AT91PS_PDC pPDC) // \arg pointer to a PDC controller
+{
+ //* Disable the RX and TX PDC transfer requests
+ AT91F_PDC_DisableRx(pPDC);
+ AT91F_PDC_DisableTx(pPDC);
+
+ //* Reset all Counter register Next buffer first
+ AT91F_PDC_SetNextTx(pPDC, NULL, 0);
+ AT91F_PDC_SetNextRx(pPDC, NULL, 0);
+ AT91F_PDC_SetTx(pPDC, NULL, 0);
+ AT91F_PDC_SetRx(pPDC, NULL, 0);
+
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_SendFrame
+//* \brief Close PDC: disable TX and RX reset transfer descriptors
+//*----------------------------------------------------------------------------
+unsigned int AT91F_PDC_SendFrame(
+ AT91PS_PDC pPDC,
+ const unsigned char *pBuffer,
+ unsigned int szBuffer,
+ const unsigned char *pNextBuffer,
+ unsigned int szNextBuffer )
+{
+ if (AT91F_PDC_IsTxEmpty(pPDC)) {
+ //* Buffer and next buffer can be initialized
+ AT91F_PDC_SetTx(pPDC, pBuffer, szBuffer);
+ AT91F_PDC_SetNextTx(pPDC, pNextBuffer, szNextBuffer);
+ return 2;
+ }
+ else if (AT91F_PDC_IsNextTxEmpty(pPDC)) {
+ //* Only one buffer can be initialized
+ AT91F_PDC_SetNextTx(pPDC, pBuffer, szBuffer);
+ return 1;
+ }
+ else {
+ //* All buffer are in use...
+ return 0;
+ }
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_PDC_ReceiveFrame
+//* \brief Close PDC: disable TX and RX reset transfer descriptors
+//*----------------------------------------------------------------------------
+unsigned int AT91F_PDC_ReceiveFrame (
+ AT91PS_PDC pPDC,
+ unsigned char *pBuffer,
+ unsigned int szBuffer,
+ unsigned char *pNextBuffer,
+ unsigned int szNextBuffer )
+{
+ if (AT91F_PDC_IsRxEmpty(pPDC)) {
+ //* Buffer and next buffer can be initialized
+ AT91F_PDC_SetRx(pPDC, pBuffer, szBuffer);
+ AT91F_PDC_SetNextRx(pPDC, pNextBuffer, szNextBuffer);
+ return 2;
+ }
+ else if (AT91F_PDC_IsNextRxEmpty(pPDC)) {
+ //* Only one buffer can be initialized
+ AT91F_PDC_SetNextRx(pPDC, pBuffer, szBuffer);
+ return 1;
+ }
+ else {
+ //* All buffer are in use...
+ return 0;
+ }
+}
+
+//*------------------------------------------------------------------------------
+//* \fn AT91F_PMC_GetMasterClock
+//* \brief Return master clock in Hz which correponds to processor clock for ARM7
+//*------------------------------------------------------------------------------
+unsigned int AT91F_PMC_GetMasterClock (
+ AT91PS_PMC pPMC, // \arg pointer to PMC controller
+ AT91PS_CKGR pCKGR, // \arg pointer to CKGR controller
+ unsigned int slowClock) // \arg slowClock in Hz
+{
+ unsigned int reg = pPMC->PMC_MCKR;
+ unsigned int prescaler = (1 << ((reg & AT91C_PMC_PRES) >> 2));
+ unsigned int pllDivider, pllMultiplier;
+
+ switch (reg & AT91C_PMC_CSS) {
+ case AT91C_PMC_CSS_SLOW_CLK: // Slow clock selected
+ return slowClock / prescaler;
+ case AT91C_PMC_CSS_MAIN_CLK: // Main clock is selected
+ return AT91F_CKGR_GetMainClock(pCKGR, slowClock) / prescaler;
+ case AT91C_PMC_CSS_PLL_CLK: // PLLB clock is selected
+ reg = pCKGR->CKGR_PLLR;
+ pllDivider = (reg & AT91C_CKGR_DIV);
+ pllMultiplier = ((reg & AT91C_CKGR_MUL) >> 16) + 1;
+ return AT91F_CKGR_GetMainClock(pCKGR, slowClock) / pllDivider * pllMultiplier / prescaler;
+ }
+ return 0;
+}
+
+//*--------------------------------------------------------------------------------------
+//* \fn AT91F_RTT_ReadValue()
+//* \brief Read the RTT value
+//*--------------------------------------------------------------------------------------
+unsigned int AT91F_RTTReadValue(AT91PS_RTTC pRTTC)
+{
+ register volatile unsigned int val1,val2;
+ do
+ {
+ val1 = pRTTC->RTTC_RTVR;
+ val2 = pRTTC->RTTC_RTVR;
+ }
+ while(val1 != val2);
+ return(val1);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SPI_Close
+//* \brief Close SPI: disable IT disable transfert, close PDC
+//*----------------------------------------------------------------------------
+void AT91F_SPI_Close(AT91PS_SPI pSPI) // \arg pointer to a SPI controller
+{
+ //* Reset all the Chip Select register
+ pSPI->SPI_CSR[0] = 0 ;
+ pSPI->SPI_CSR[1] = 0 ;
+ pSPI->SPI_CSR[2] = 0 ;
+ pSPI->SPI_CSR[3] = 0 ;
+
+ //* Reset the SPI mode
+ pSPI->SPI_MR = 0 ;
+
+ //* Disable all interrupts
+ pSPI->SPI_IDR = 0xFFFFFFFF ;
+
+ //* Abort the Peripheral Data Transfers
+ AT91F_PDC_Close((AT91PS_PDC) &(pSPI->SPI_RPR));
+
+ //* Disable receiver and transmitter and stop any activity immediately
+ pSPI->SPI_CR = AT91C_SPI_SPIDIS;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_ADC_CfgTimings
+//* \brief Configure the different necessary timings of the ADC controller
+//*----------------------------------------------------------------------------
+void AT91F_ADC_CfgTimings (
+ AT91PS_ADC pADC, // pointer to a ADC controller
+ unsigned int mck_clock, // in MHz
+ unsigned int adc_clock, // in MHz
+ unsigned int startup_time, // in us
+ unsigned int sample_and_hold_time) // in ns
+{
+ unsigned int prescal,startup,shtim;
+
+ prescal = mck_clock/(2*adc_clock) - 1;
+ startup = adc_clock*startup_time/8 - 1;
+ shtim = adc_clock*sample_and_hold_time/1000 - 1;
+
+ //* Write to the MR register
+ pADC->ADC_MR = ( (prescal<<8) & AT91C_ADC_PRESCAL) | ( (startup<<16) & AT91C_ADC_STARTUP) | ( (shtim<<24) & AT91C_ADC_SHTIM);
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_SetBaudrate
+//* \brief Set the baudrate according to the CPU clock
+//*----------------------------------------------------------------------------
+void AT91F_SSC_SetBaudrate (
+ AT91PS_SSC pSSC, // \arg pointer to a SSC controller
+ unsigned int mainClock, // \arg peripheral clock
+ unsigned int speed) // \arg SSC baudrate
+{
+ unsigned int baud_value;
+ //* Define the baud rate divisor register
+ if (speed == 0)
+ baud_value = 0;
+ else
+ {
+ baud_value = (unsigned int) (mainClock * 10)/(2*speed);
+ if ((baud_value % 10) >= 5)
+ baud_value = (baud_value / 10) + 1;
+ else
+ baud_value /= 10;
+ }
+
+ pSSC->SSC_CMR = baud_value;
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_SSC_Configure
+//* \brief Configure SSC
+//*----------------------------------------------------------------------------
+void AT91F_SSC_Configure (
+ AT91PS_SSC pSSC, // \arg pointer to a SSC controller
+ unsigned int syst_clock, // \arg System Clock Frequency
+ unsigned int baud_rate, // \arg Expected Baud Rate Frequency
+ unsigned int clock_rx, // \arg Receiver Clock Parameters
+ unsigned int mode_rx, // \arg mode Register to be programmed
+ unsigned int clock_tx, // \arg Transmitter Clock Parameters
+ unsigned int mode_tx) // \arg mode Register to be programmed
+{
+ //* Disable interrupts
+ pSSC->SSC_IDR = (unsigned int) -1;
+
+ //* Reset receiver and transmitter
+ pSSC->SSC_CR = AT91C_SSC_SWRST | AT91C_SSC_RXDIS | AT91C_SSC_TXDIS ;
+
+ //* Define the Clock Mode Register
+ AT91F_SSC_SetBaudrate(pSSC, syst_clock, baud_rate);
+
+ //* Write the Receive Clock Mode Register
+ pSSC->SSC_RCMR = clock_rx;
+
+ //* Write the Transmit Clock Mode Register
+ pSSC->SSC_TCMR = clock_tx;
+
+ //* Write the Receive Frame Mode Register
+ pSSC->SSC_RFMR = mode_rx;
+
+ //* Write the Transmit Frame Mode Register
+ pSSC->SSC_TFMR = mode_tx;
+
+ //* Clear Transmit and Receive Counters
+ AT91F_PDC_Open((AT91PS_PDC) &(pSSC->SSC_RPR));
+
+
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_Configure
+//* \brief Configure USART
+//*----------------------------------------------------------------------------
+void AT91F_US_Configure (
+ AT91PS_USART pUSART, // \arg pointer to a USART controller
+ unsigned int mainClock, // \arg peripheral clock
+ unsigned int mode , // \arg mode Register to be programmed
+ unsigned int baudRate , // \arg baudrate to be programmed
+ unsigned int timeguard ) // \arg timeguard to be programmed
+{
+ //* Disable interrupts
+ pUSART->US_IDR = (unsigned int) -1;
+
+ //* Reset receiver and transmitter
+ pUSART->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS ;
+
+ //* Define the baud rate divisor register
+ AT91F_US_SetBaudrate(pUSART, mainClock, baudRate);
+
+ //* Write the Timeguard Register
+ AT91F_US_SetTimeguard(pUSART, timeguard);
+
+ //* Clear Transmit and Receive Counters
+ AT91F_PDC_Open((AT91PS_PDC) &(pUSART->US_RPR));
+
+ //* Define the USART mode
+ pUSART->US_MR = mode ;
+
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_Close
+//* \brief Close USART: disable IT disable receiver and transmitter, close PDC
+//*----------------------------------------------------------------------------
+void AT91F_US_Close(AT91PS_USART pUSART) // \arg pointer to a USART controller
+{
+ //* Reset the baud rate divisor register
+ pUSART->US_BRGR = 0 ;
+
+ //* Reset the USART mode
+ pUSART->US_MR = 0 ;
+
+ //* Reset the Timeguard Register
+ pUSART->US_TTGR = 0;
+
+ //* Disable all interrupts
+ pUSART->US_IDR = 0xFFFFFFFF ;
+
+ //* Abort the Peripheral Data Transfers
+ AT91F_PDC_Close((AT91PS_PDC) &(pUSART->US_RPR));
+
+ //* Disable receiver and transmitter and stop any activity immediately
+ pUSART->US_CR = AT91C_US_TXDIS | AT91C_US_RXDIS | AT91C_US_RSTTX | AT91C_US_RSTRX ;
+}
+
+
diff --git a/firmware/lib/memcpy.S b/firmware/lib/memcpy.S
new file mode 100644
index 0000000..2bbd569
--- /dev/null
+++ b/firmware/lib/memcpy.S
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/arm/lib/memcpy.S
+ *
+ * Author: Nicolas Pitre
+ * Created: Sep 28, 2005
+ * Copyright: MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <asm/linkage.h>
+#include <asm/assembler.h>
+
+ .macro ldr1w ptr reg abort
+ ldr \reg, [\ptr], #4
+ .endm
+
+ .macro ldr4w ptr reg1 reg2 reg3 reg4 abort
+ ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4}
+ .endm
+
+ .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+ ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
+ .endm
+
+ .macro ldr1b ptr reg cond=al abort
+ ldr\cond\()b \reg, [\ptr], #1
+ .endm
+
+ .macro str1w ptr reg abort
+ str \reg, [\ptr], #4
+ .endm
+
+ .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+ stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
+ .endm
+
+ .macro str1b ptr reg cond=al abort
+ str\cond\()b \reg, [\ptr], #1
+ .endm
+
+ .macro enter reg1 reg2
+ stmdb sp!, {r0, \reg1, \reg2}
+ .endm
+
+ .macro exit reg1 reg2
+ ldmfd sp!, {r0, \reg1, \reg2}
+ .endm
+
+ .text
+
+/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
+
+ENTRY(memcpy)
+
+#include "copy_template.S"
+
diff --git a/firmware/lib/memset.S b/firmware/lib/memset.S
new file mode 100644
index 0000000..04e254a
--- /dev/null
+++ b/firmware/lib/memset.S
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/arm/lib/memset.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ASM optimised string functions
+ */
+#include <asm/linkage.h>
+#include <asm/assembler.h>
+
+ .text
+ .align 5
+ .word 0
+
+1: subs r2, r2, #4 @ 1 do we have enough
+ blt 5f @ 1 bytes to align with?
+ cmp r3, #2 @ 1
+ strltb r1, [r0], #1 @ 1
+ strleb r1, [r0], #1 @ 1
+ strb r1, [r0], #1 @ 1
+ add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
+/*
+ * The pointer is now aligned and the length is adjusted. Try doing the
+ * memzero again.
+ */
+
+ENTRY(memset)
+ ands r3, r0, #3 @ 1 unaligned?
+ bne 1b @ 1
+/*
+ * we know that the pointer in r0 is aligned to a word boundary.
+ */
+ orr r1, r1, r1, lsl #8
+ orr r1, r1, r1, lsl #16
+ mov r3, r1
+ cmp r2, #16
+ blt 4f
+/*
+ * We need an extra register for this loop - save the return address and
+ * use the LR
+ */
+ str lr, [sp, #-4]!
+ mov ip, r1
+ mov lr, r1
+
+2: subs r2, r2, #64
+ stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time.
+ stmgeia r0!, {r1, r3, ip, lr}
+ stmgeia r0!, {r1, r3, ip, lr}
+ stmgeia r0!, {r1, r3, ip, lr}
+ bgt 2b
+ LOADREGS(eqfd, sp!, {pc}) @ Now <64 bytes to go.
+/*
+ * No need to correct the count; we're only testing bits from now on
+ */
+ tst r2, #32
+ stmneia r0!, {r1, r3, ip, lr}
+ stmneia r0!, {r1, r3, ip, lr}
+ tst r2, #16
+ stmneia r0!, {r1, r3, ip, lr}
+ ldr lr, [sp], #4
+
+4: tst r2, #8
+ stmneia r0!, {r1, r3}
+ tst r2, #4
+ strne r1, [r0], #4
+/*
+ * When we get here, we've got less than 4 bytes to zero. We
+ * may have an unaligned pointer as well.
+ */
+5: tst r2, #2
+ strneb r1, [r0], #1
+ strneb r1, [r0], #1
+ tst r2, #1
+ strneb r1, [r0], #1
+ RETINSTR(mov,pc,lr)
diff --git a/firmware/lib/setbit.S b/firmware/lib/setbit.S
new file mode 100644
index 0000000..9009bc1
--- /dev/null
+++ b/firmware/lib/setbit.S
@@ -0,0 +1,22 @@
+/*
+ * linux/arch/arm/lib/setbit.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/linkage.h>
+#include <asm/assembler.h>
+#include "bitops.h"
+ .text
+
+/*
+ * Purpose : Function to set a bit
+ * Prototype: int set_bit(int bit, void *addr)
+ */
+ENTRY(_set_bit_be)
+ eor r0, r0, #0x18 @ big endian byte ordering
+ENTRY(_set_bit_le)
+ bitop orr
diff --git a/firmware/lib/string.c b/firmware/lib/string.c
new file mode 100644
index 0000000..4158bca
--- /dev/null
+++ b/firmware/lib/string.c
@@ -0,0 +1,41 @@
+/*
+ * linux/lib/string.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/*
+ * stupid library routines.. The optimized versions should generally be found
+ * as inline code in <asm-xx/string.h>
+ *
+ * These are buggy as well..
+ *
+ * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
+ * - Added strsep() which will replace strtok() soon (because strsep() is
+ * reentrant and should be faster). Use only strsep() in new code, please.
+ *
+ * * Sat Feb 09 2002, Jason Thomas <jason@topic.com.au>,
+ * Matthew Hawkins <matt@mh.dropbear.id.au>
+ * - Kissed strtok() goodbye
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <asm/ctype.h>
+
+
+#ifndef __HAVE_ARCH_STRNLEN
+/**
+ * strnlen - Find the length of a length-limited string
+ * @s: The string to be sized
+ * @count: The maximum number of bytes to search
+ */
+size_t strnlen(const char *s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+#endif
diff --git a/firmware/lib/testchangebit.S b/firmware/lib/testchangebit.S
new file mode 100644
index 0000000..37c303e
--- /dev/null
+++ b/firmware/lib/testchangebit.S
@@ -0,0 +1,18 @@
+/*
+ * linux/arch/arm/lib/testchangebit.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/linkage.h>
+#include <asm/assembler.h>
+#include "bitops.h"
+ .text
+
+ENTRY(_test_and_change_bit_be)
+ eor r0, r0, #0x18 @ big endian byte ordering
+ENTRY(_test_and_change_bit_le)
+ testop eor, strb
diff --git a/firmware/lib/testclearbit.S b/firmware/lib/testclearbit.S
new file mode 100644
index 0000000..985c399
--- /dev/null
+++ b/firmware/lib/testclearbit.S
@@ -0,0 +1,18 @@
+/*
+ * linux/arch/arm/lib/testclearbit.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/linkage.h>
+#include <asm/assembler.h>
+#include "bitops.h"
+ .text
+
+ENTRY(_test_and_clear_bit_be)
+ eor r0, r0, #0x18 @ big endian byte ordering
+ENTRY(_test_and_clear_bit_le)
+ testop bicne, strneb
diff --git a/firmware/lib/testsetbit.S b/firmware/lib/testsetbit.S
new file mode 100644
index 0000000..4a8a164
--- /dev/null
+++ b/firmware/lib/testsetbit.S
@@ -0,0 +1,18 @@
+/*
+ * linux/arch/arm/lib/testsetbit.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/linkage.h>
+#include <asm/assembler.h>
+#include "bitops.h"
+ .text
+
+ENTRY(_test_and_set_bit_be)
+ eor r0, r0, #0x18 @ big endian byte ordering
+ENTRY(_test_and_set_bit_le)
+ testop orreq, streqb
diff --git a/firmware/lib/vsprintf.c b/firmware/lib/vsprintf.c
new file mode 100644
index 0000000..9eff70b
--- /dev/null
+++ b/firmware/lib/vsprintf.c
@@ -0,0 +1,830 @@
+/*
+ * linux/lib/vsprintf.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+/*
+ * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
+ * - changed to provide snprintf and vsnprintf functions
+ * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
+ * - scnprintf and vscnprintf
+ */
+
+#include <stdarg.h>
+#include <sys/types.h>
+#include <string.h>
+#include <asm/ctype.h>
+
+#include <asm/div64.h>
+
+/**
+ * simple_strtoul - convert a string to an unsigned long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+{
+ unsigned long result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ } else if (base == 16) {
+ if (cp[0] == '0' && toupper(cp[1]) == 'X')
+ cp += 2;
+ }
+ while (isxdigit(*cp) &&
+ (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+
+/**
+ * simple_strtol - convert a string to a signed long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long simple_strtol(const char *cp,char **endp,unsigned int base)
+{
+ if(*cp=='-')
+ return -simple_strtoul(cp+1,endp,base);
+ return simple_strtoul(cp,endp,base);
+}
+
+
+/**
+ * simple_strtoull - convert a string to an unsigned long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
+{
+ unsigned long long result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ } else if (base == 16) {
+ if (cp[0] == '0' && toupper(cp[1]) == 'X')
+ cp += 2;
+ }
+ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+ ? toupper(*cp) : *cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+
+/**
+ * simple_strtoll - convert a string to a signed long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long long simple_strtoll(const char *cp,char **endp,unsigned int base)
+{
+ if(*cp=='-')
+ return -simple_strtoull(cp+1,endp,base);
+ return simple_strtoull(cp,endp,base);
+}
+
+static int skip_atoi(const char **s)
+{
+ int i=0;
+
+ while (isdigit(**s))
+ i = i*10 + *((*s)++) - '0';
+ return i;
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIAL 32 /* 0x */
+#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+
+static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type)
+{
+ char c,sign,tmp[66];
+ const char *digits;
+ static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+ static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ int i;
+
+ digits = (type & LARGE) ? large_digits : small_digits;
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return NULL;
+ c = (type & ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & SIGN) {
+ if ((signed long long) num < 0) {
+ sign = '-';
+ num = - (signed long long) num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else while (num != 0)
+ tmp[i++] = digits[do_div(num,base)];
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT))) {
+ while(size-->0) {
+ if (buf <= end)
+ *buf = ' ';
+ ++buf;
+ }
+ }
+ if (sign) {
+ if (buf <= end)
+ *buf = sign;
+ ++buf;
+ }
+ if (type & SPECIAL) {
+ if (base==8) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ } else if (base==16) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ if (buf <= end)
+ *buf = digits[33];
+ ++buf;
+ }
+ }
+ if (!(type & LEFT)) {
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = c;
+ ++buf;
+ }
+ }
+ while (i < precision--) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ }
+ while (i-- > 0) {
+ if (buf <= end)
+ *buf = tmp[i];
+ ++buf;
+ }
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = ' ';
+ ++buf;
+ }
+ return buf;
+}
+
+/**
+ * vsnprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * The return value is the number of characters which would
+ * be generated for the given input, excluding the trailing
+ * '\0', as per ISO C99. If you want to have the exact
+ * number of characters written into @buf as return value
+ * (not including the trailing '\0'), use vscnprintf. If the
+ * return is greater than or equal to @size, the resulting
+ * string is truncated.
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want snprintf instead.
+ */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+ int len;
+ unsigned long long num;
+ int i, base;
+ char *str, *end, c;
+ const char *s;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* 'h', 'l', or 'L' for integer fields */
+ /* 'z' support added 23/7/1999 S.H. */
+ /* 'z' changed to 'Z' --davidm 1/25/99 */
+ /* 't' added for ptrdiff_t */
+
+ /* Reject out-of-range values early */
+ if ((int) size < 0) {
+ return 0;
+ }
+
+ str = buf;
+ end = buf + size - 1;
+
+ if (end < buf - 1) {
+ end = ((void *) -1);
+ size = end - buf + 1;
+ }
+
+ for (; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-': flags |= LEFT; goto repeat;
+ case '+': flags |= PLUS; goto repeat;
+ case ' ': flags |= SPACE; goto repeat;
+ case '#': flags |= SPECIAL; goto repeat;
+ case '0': flags |= ZEROPAD; goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (isdigit(*fmt))
+ field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (isdigit(*fmt))
+ precision = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+ *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
+ qualifier = *fmt;
+ ++fmt;
+ if (qualifier == 'l' && *fmt == 'l') {
+ qualifier = 'L';
+ ++fmt;
+ }
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT)) {
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ }
+ c = (unsigned char) va_arg(args, int);
+ if (str <= end)
+ *str = c;
+ ++str;
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+
+ len = strnlen(s, precision);
+
+ if (!(flags & LEFT)) {
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = *s;
+ ++str; ++s;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ continue;
+
+ case 'p':
+ if (field_width == -1) {
+ field_width = 2*sizeof(void *);
+ flags |= ZEROPAD;
+ }
+ str = number(str, end,
+ (unsigned long) va_arg(args, void *),
+ 16, field_width, precision, flags);
+ continue;
+
+
+ case 'n':
+ /* FIXME:
+ * What does C99 say about the overflow case here? */
+ if (qualifier == 'l') {
+ long * ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else if (qualifier == 'Z' || qualifier == 'z') {
+ size_t * ip = va_arg(args, size_t *);
+ *ip = (str - buf);
+ } else {
+ int * ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ continue;
+
+ case '%':
+ if (str <= end)
+ *str = '%';
+ ++str;
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'X':
+ flags |= LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ if (str <= end)
+ *str = '%';
+ ++str;
+ if (*fmt) {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ } else {
+ --fmt;
+ }
+ continue;
+ }
+ if (qualifier == 'L')
+ num = va_arg(args, long long);
+ else if (qualifier == 'l') {
+ num = va_arg(args, unsigned long);
+ if (flags & SIGN)
+ num = (signed long) num;
+ } else if (qualifier == 'Z' || qualifier == 'z') {
+ num = va_arg(args, size_t);
+ } else if (qualifier == 't') {
+ num = va_arg(args, ptrdiff_t);
+ } else if (qualifier == 'h') {
+ num = (unsigned short) va_arg(args, int);
+ if (flags & SIGN)
+ num = (signed short) num;
+ } else {
+ num = va_arg(args, unsigned int);
+ if (flags & SIGN)
+ num = (signed int) num;
+ }
+ str = number(str, end, num, base,
+ field_width, precision, flags);
+ }
+ if (str <= end)
+ *str = '\0';
+ else if (size > 0)
+ /* don't write out a null byte if the buf size is zero */
+ *end = '\0';
+ /* the trailing null byte doesn't count towards the total
+ * ++str;
+ */
+ return str-buf;
+}
+
+
+/**
+ * vscnprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * The return value is the number of characters which have been written into
+ * the @buf not including the trailing '\0'. If @size is <= 0 the function
+ * returns 0.
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want scnprintf instead.
+ */
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+ int i;
+
+ i=vsnprintf(buf,size,fmt,args);
+ return (i >= size) ? (size - 1) : i;
+}
+
+
+/**
+ * snprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ *
+ * The return value is the number of characters which would be
+ * generated for the given input, excluding the trailing null,
+ * as per ISO C99. If the return is greater than or equal to
+ * @size, the resulting string is truncated.
+ */
+int snprintf(char * buf, size_t size, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsnprintf(buf,size,fmt,args);
+ va_end(args);
+ return i;
+}
+
+
+/**
+ * scnprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ *
+ * The return value is the number of characters written into @buf not including
+ * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
+ * greater than or equal to @size, the resulting string is truncated.
+ */
+
+int scnprintf(char * buf, size_t size, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, size, fmt, args);
+ va_end(args);
+ return (i >= size) ? (size - 1) : i;
+}
+
+/**
+ * vsprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * The function returns the number of characters written
+ * into @buf. Use vsnprintf or vscnprintf in order to avoid
+ * buffer overflows.
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want sprintf instead.
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ return vsnprintf(buf, INT_MAX, fmt, args);
+}
+
+
+/**
+ * sprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ *
+ * The function returns the number of characters written
+ * into @buf. Use snprintf or scnprintf in order to avoid
+ * buffer overflows.
+ */
+int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsnprintf(buf, INT_MAX, fmt, args);
+ va_end(args);
+ return i;
+}
+
+
+/**
+ * vsscanf - Unformat a buffer into a list of arguments
+ * @buf: input buffer
+ * @fmt: format of buffer
+ * @args: arguments
+ */
+int vsscanf(const char * buf, const char * fmt, va_list args)
+{
+ const char *str = buf;
+ char *next;
+ char digit;
+ int num = 0;
+ int qualifier;
+ int base;
+ int field_width;
+ int is_sign = 0;
+
+ while(*fmt && *str) {
+ /* skip any white space in format */
+ /* white space in format matchs any amount of
+ * white space, including none, in the input.
+ */
+ if (isspace(*fmt)) {
+ while (isspace(*fmt))
+ ++fmt;
+ while (isspace(*str))
+ ++str;
+ }
+
+ /* anything that is not a conversion must match exactly */
+ if (*fmt != '%' && *fmt) {
+ if (*fmt++ != *str++)
+ break;
+ continue;
+ }
+
+ if (!*fmt)
+ break;
+ ++fmt;
+
+ /* skip this conversion.
+ * advance both strings to next white space
+ */
+ if (*fmt == '*') {
+ while (!isspace(*fmt) && *fmt)
+ fmt++;
+ while (!isspace(*str) && *str)
+ str++;
+ continue;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (isdigit(*fmt))
+ field_width = skip_atoi(&fmt);
+
+ /* get conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+ *fmt == 'Z' || *fmt == 'z') {
+ qualifier = *fmt++;
+ if (qualifier == *fmt) {
+ if (qualifier == 'h') {
+ qualifier = 'H';
+ fmt++;
+ } else if (qualifier == 'l') {
+ qualifier = 'L';
+ fmt++;
+ }
+ }
+ }
+ base = 10;
+ is_sign = 0;
+
+ if (!*fmt || !*str)
+ break;
+
+ switch(*fmt++) {
+ case 'c':
+ {
+ char *s = (char *) va_arg(args,char*);
+ if (field_width == -1)
+ field_width = 1;
+ do {
+ *s++ = *str++;
+ } while (--field_width > 0 && *str);
+ num++;
+ }
+ continue;
+ case 's':
+ {
+ char *s = (char *) va_arg(args, char *);
+ if(field_width == -1)
+ field_width = INT_MAX;
+ /* first, skip leading white space in buffer */
+ while (isspace(*str))
+ str++;
+
+ /* now copy until next white space */
+ while (*str && !isspace(*str) && field_width--) {
+ *s++ = *str++;
+ }
+ *s = '\0';
+ num++;
+ }
+ continue;
+ case 'n':
+ /* return number of characters read so far */
+ {
+ int *i = (int *)va_arg(args,int*);
+ *i = str - buf;
+ }
+ continue;
+ case 'o':
+ base = 8;
+ break;
+ case 'x':
+ case 'X':
+ base = 16;
+ break;
+ case 'i':
+ base = 0;
+ case 'd':
+ is_sign = 1;
+ case 'u':
+ break;
+ case '%':
+ /* looking for '%' in str */
+ if (*str++ != '%')
+ return num;
+ continue;
+ default:
+ /* invalid format; stop here */
+ return num;
+ }
+
+ /* have some sort of integer conversion.
+ * first, skip white space in buffer.
+ */
+ while (isspace(*str))
+ str++;
+
+ digit = *str;
+ if (is_sign && digit == '-')
+ digit = *(str + 1);
+
+ if (!digit
+ || (base == 16 && !isxdigit(digit))
+ || (base == 10 && !isdigit(digit))
+ || (base == 8 && (!isdigit(digit) || digit > '7'))
+ || (base == 0 && !isdigit(digit)))
+ break;
+
+ switch(qualifier) {
+ case 'H': /* that's 'hh' in format */
+ if (is_sign) {
+ signed char *s = (signed char *) va_arg(args,signed char *);
+ *s = (signed char) simple_strtol(str,&next,base);
+ } else {
+ unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
+ *s = (unsigned char) simple_strtoul(str, &next, base);
+ }
+ break;
+ case 'h':
+ if (is_sign) {
+ short *s = (short *) va_arg(args,short *);
+ *s = (short) simple_strtol(str,&next,base);
+ } else {
+ unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
+ *s = (unsigned short) simple_strtoul(str, &next, base);
+ }
+ break;
+ case 'l':
+ if (is_sign) {
+ long *l = (long *) va_arg(args,long *);
+ *l = simple_strtol(str,&next,base);
+ } else {
+ unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
+ *l = simple_strtoul(str,&next,base);
+ }
+ break;
+ case 'L':
+ if (is_sign) {
+ long long *l = (long long*) va_arg(args,long long *);
+ *l = simple_strtoll(str,&next,base);
+ } else {
+ unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
+ *l = simple_strtoull(str,&next,base);
+ }
+ break;
+ case 'Z':
+ case 'z':
+ {
+ size_t *s = (size_t*) va_arg(args,size_t*);
+ *s = (size_t) simple_strtoul(str,&next,base);
+ }
+ break;
+ default:
+ if (is_sign) {
+ int *i = (int *) va_arg(args, int*);
+ *i = (int) simple_strtol(str,&next,base);
+ } else {
+ unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
+ *i = (unsigned int) simple_strtoul(str,&next,base);
+ }
+ break;
+ }
+ num++;
+
+ if (!next)
+ break;
+ str = next;
+ }
+ return num;
+}
+
+
+/**
+ * sscanf - Unformat a buffer into a list of arguments
+ * @buf: input buffer
+ * @fmt: formatting of buffer
+ * @...: resulting arguments
+ */
+int sscanf(const char * buf, const char * fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args,fmt);
+ i = vsscanf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
diff --git a/firmware/link/AT91SAM7S256-RAM.ld b/firmware/link/AT91SAM7S256-RAM.ld
new file mode 100644
index 0000000..dc303dd
--- /dev/null
+++ b/firmware/link/AT91SAM7S256-RAM.ld
@@ -0,0 +1,131 @@
+/*---------------------------------------------------------------------------*/
+/*- ATMEL Microcontroller Software Support - ROUSSET - */
+/*---------------------------------------------------------------------------*/
+/* The software is delivered "AS IS" without warranty or condition of any */
+/* kind, either express, implied or statutory. This includes without */
+/* limitation any warranty or condition with respect to merchantability or */
+/* fitness for any particular purpose, or against the infringements of */
+/* intellectual property rights of others. */
+/*---------------------------------------------------------------------------*/
+/*- File source : GCC_RAM.ld */
+/*- Object : Linker Script File for RAM Workspace */
+/*- Compilation flag : None */
+/*- */
+/*- 1.0 11/Mar/05 JPP : Creation S256 */
+/*---------------------------------------------------------------------------*/
+
+/*
+ 24-02-2006 Ewout Boks. Adapted from AT91SAM7S64-RAM.ld script by M. Thomas.
+ - Changed the memory sections to model the AT91SAM7S256 .
+ - modified the region where the .text section is loaded to DATA
+ - tested succesfully with AT91SAM7 GPIO Example and PEEDI debugger
+ on AT91SAM7S-EK equipped with AT91SAM7S256
+*/
+
+/* Memory Definitions */
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00100000, LENGTH = 0x00040000
+ DATA (rw) : ORIGIN = 0x00200000, LENGTH = 0x00010000
+ STACK (rw) : ORIGIN = 0x00210000, LENGTH = 0x00000000
+}
+
+
+/* Section Definitions */
+
+SECTIONS
+{
+ /* first section is .text which is used for code */
+ . = 0x0000000;
+ .text : { *cstartup.o (.text) }>DATA =0
+ .text :
+ {
+ *(.text) /* remaining code */
+
+ *(.glue_7t) *(.glue_7)
+
+ } >DATA
+ . = ALIGN(4);
+
+ /* .rodata section which is used for read-only data (constants) */
+
+ .rodata :
+ {
+ *(.rodata)
+ } >DATA
+
+ . = ALIGN(4);
+
+ _etext = . ;
+ PROVIDE (etext = .);
+
+ /* .data section which is used for initialized data */
+
+ .data : AT (_etext)
+ {
+ _data = . ;
+ *(.data)
+ SORT(CONSTRUCTORS)
+ } >DATA
+ . = ALIGN(4);
+
+ _edata = . ;
+ PROVIDE (edata = .);
+
+ /* .bss section which is used for uninitialized data */
+
+ .bss :
+ {
+ __bss_start = . ;
+ __bss_start__ = . ;
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(4);
+ __bss_end__ = . ;
+ __bss_end__ = . ;
+ _end = .;
+ . = ALIGN(4);
+ .int_data :
+ {
+ *(.internal_ram_top)
+ }> STACK
+
+ PROVIDE (end = .);
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+}
diff --git a/firmware/link/AT91SAM7S256-ROM-dfu-fullimage.ld b/firmware/link/AT91SAM7S256-ROM-dfu-fullimage.ld
new file mode 100644
index 0000000..3932e64
--- /dev/null
+++ b/firmware/link/AT91SAM7S256-ROM-dfu-fullimage.ld
@@ -0,0 +1,152 @@
+/*---------------------------------------------------------------------------*/
+/*- ATMEL Microcontroller Software Support - ROUSSET - */
+/*---------------------------------------------------------------------------*/
+/* The software is delivered "AS IS" without warranty or condition of any */
+/* kind, either express, implied or statutory. This includes without */
+/* limitation any warranty or condition with respect to merchantability or */
+/* fitness for any particular purpose, or against the infringements of */
+/* intellectual property rights of others. */
+/*---------------------------------------------------------------------------*/
+/*- File source : GCC_FLASH.ld */
+/*- Object : Linker Script File for Flash Workspace */
+/*- Compilation flag : None */
+/*- */
+/*- 1.0 11/Mar/05 JPP : Creation S256 */
+/*---------------------------------------------------------------------------*/
+
+/*
+ 24-02-2006 Ewout Boks. Adapted from AT91SAM7S64-RAM.ld script by M. Thomas.
+ - Changed the memory sections to model the AT91SAM7S256 .
+ - tested succesfully with AT91SAM7 GPIO Example and PEEDI debugger
+ on AT91SAM7S-EK equipped with AT91SAM7S256
+ 20-08-2006 Harald Welte
+ - Add support for USB DFU handling
+ - Partition FLASH into two sections
+ idx 0x00000 ... 0x01fff: dfu loader
+ idx 0x02000 ... 0x020ff: dfu_api function pointers
+ idx 0x02100 ... 0x40000: application program
+*/
+
+/* Memory Definitions */
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00100000, LENGTH = 0x00040000
+ DATA (rw) : ORIGIN = 0x00200000, LENGTH = 0x00010000
+ STACK (rw) : ORIGIN = 0x00210000, LENGTH = 0x00000000
+}
+
+
+/* Section Definitions */
+
+SECTIONS
+{
+ . = 0x00000000;
+ /* first section is .text which is used for code */
+ .dfu.text 0x00100000: AT ( 0x00000000 ) {
+ src/start/Cstartup*.o (.text)
+ *(.dfu.func)
+ *(.dfu.struct)
+ . = ALIGN(4);
+ } >FLASH
+
+ _etext_dfu = . ;
+
+ .dfu.data 0x00200000: AT ( ADDR(.dfu.text) + SIZEOF(.dfu.text) - ADDR(.dfu.text) ) {
+ _data_dfu = . ;
+ *(.vectram)
+ src/os/dfu.o (.data)
+ . = ALIGN(4);
+ } >DATA
+
+ _edata_dfu = . ;
+
+ .dfu.functab 0x00102100: AT ( ADDR(.dfu.functab) - ADDR(.dfu.text) ) {
+ *(.dfu.functab)
+ . = ALIGN(4);
+ } >FLASH
+
+ .text 0x00102200: AT ( ADDR(.text) - ADDR(.dfu.text) ) {
+ *(.text) /* remaining code */
+ *(.glue_7t) *(.glue_7)
+ . = ALIGN(4);
+ } >FLASH
+
+
+ /* .rodata section which is used for read-only data (constants) */
+ .rodata : AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.dfu.text) ) {
+ *(.rodata*)
+ . = ALIGN(4);
+ } >FLASH
+
+ _etext = . ;
+ PROVIDE (etext = .);
+
+ /* .data section which is used for initialized data */
+ .data : AT ( ADDR(.rodata) + SIZEOF(.rodata) - ADDR(.dfu.text) ) {
+ _data = . ;
+ *(.data)
+ SORT(CONSTRUCTORS)
+ . = ALIGN(4);
+ *(.fastrun)
+ . = ALIGN(4);
+ } >DATA
+
+ _edata = . ;
+ PROVIDE (edata = .);
+
+ /* .bss section which is used for uninitialized data */
+ .bss : {
+ __bss_start = . ;
+ __bss_start__ = . ;
+ *(.bss)
+ *(COMMON)
+ } >DATA
+
+ . = ALIGN(4);
+ __bss_end__ = . ;
+ __bss_end__ = . ;
+ _end = . ;
+
+ . = ALIGN(4);
+ .int_data : {
+ *(.internal_ram_top)
+ } >STACK
+
+ PROVIDE (end = .);
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+}
diff --git a/firmware/link/AT91SAM7S256-ROM.ld b/firmware/link/AT91SAM7S256-ROM.ld
new file mode 100644
index 0000000..c83d63d
--- /dev/null
+++ b/firmware/link/AT91SAM7S256-ROM.ld
@@ -0,0 +1,134 @@
+/*---------------------------------------------------------------------------*/
+/*- ATMEL Microcontroller Software Support - ROUSSET - */
+/*---------------------------------------------------------------------------*/
+/* The software is delivered "AS IS" without warranty or condition of any */
+/* kind, either express, implied or statutory. This includes without */
+/* limitation any warranty or condition with respect to merchantability or */
+/* fitness for any particular purpose, or against the infringements of */
+/* intellectual property rights of others. */
+/*---------------------------------------------------------------------------*/
+/*- File source : GCC_FLASH.ld */
+/*- Object : Linker Script File for Flash Workspace */
+/*- Compilation flag : None */
+/*- */
+/*- 1.0 11/Mar/05 JPP : Creation S256 */
+/*---------------------------------------------------------------------------*/
+
+/*
+ 24-02-2006 Ewout Boks. Adapted from AT91SAM7S64-RAM.ld script by M. Thomas.
+ - Changed the memory sections to model the AT91SAM7S256 .
+ - tested succesfully with AT91SAM7 GPIO Example and PEEDI debugger
+ on AT91SAM7S-EK equipped with AT91SAM7S256
+*/
+
+/* Memory Definitions */
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00100000, LENGTH = 0x00040000
+ DATA (rw) : ORIGIN = 0x00200000, LENGTH = 0x00010000
+ STACK (rw) : ORIGIN = 0x00210000, LENGTH = 0x00000000
+}
+
+
+/* Section Definitions */
+
+SECTIONS
+{
+ /* first section is .text which is used for code */
+ . = 0x0000000;
+ .text : { *cstartup.o (.text) }>FLASH =0
+ .text :
+ {
+ *(.text) /* remaining code */
+
+ *(.glue_7t) *(.glue_7)
+
+ } >FLASH
+
+ . = ALIGN(4);
+
+ /* .rodata section which is used for read-only data (constants) */
+
+ .rodata :
+ {
+ *(.rodata)
+ } >FLASH
+
+ . = ALIGN(4);
+
+ _etext = . ;
+ PROVIDE (etext = .);
+
+ /* .data section which is used for initialized data */
+
+ .data : AT (_etext)
+ {
+ _data = . ;
+ KEEP(*(.vectram))
+ *(.data)
+ SORT(CONSTRUCTORS)
+ . = ALIGN(4);
+ *(.fastrun)
+ } >DATA
+ . = ALIGN(4);
+
+ _edata = . ;
+ PROVIDE (edata = .);
+
+ /* .bss section which is used for uninitialized data */
+
+ .bss :
+ {
+ __bss_start = . ;
+ __bss_start__ = . ;
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(4);
+ __bss_end__ = . ;
+ __bss_end__ = . ;
+ _end = .;
+ . = ALIGN(4);
+ .int_data :
+ {
+ *(.internal_ram_top)
+ }> STACK
+
+ PROVIDE (end = .);
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+}
diff --git a/firmware/link/AT91SAM7S64-RAM.ld b/firmware/link/AT91SAM7S64-RAM.ld
new file mode 100644
index 0000000..2b6ba81
--- /dev/null
+++ b/firmware/link/AT91SAM7S64-RAM.ld
@@ -0,0 +1,146 @@
+/*---------------------------------------------------------------------------*/
+/*- ATMEL Microcontroller Software Support - ROUSSET - */
+/*---------------------------------------------------------------------------*/
+/* The software is delivered "AS IS" without warranty or condition of any */
+/* kind, either express, implied or statutory. This includes without */
+/* limitation any warranty or condition with respect to merchantability or */
+/* fitness for any particular purpose, or against the infringements of */
+/* intellectual property rights of others. */
+/*---------------------------------------------------------------------------*/
+/*- File source : GCC_RAM.ld */
+/*- Object : Linker Script File for RAM Workspace */
+/*- Compilation flag : None */
+/*- */
+/*- 1.0 20/Oct/04 JPP : Creation */
+/*---------------------------------------------------------------------------*/
+
+
+/*
+//*** <<< Use Configuration Wizard in Context Menu >>> ***
+*/
+
+
+/*
+// <h> Memory Configuration
+// <h> Code (Read Only)
+// <o> Start <0x0-0xFFFFFFFF>
+// <o1> Size <0x0-0xFFFFFFFF>
+// </h>
+// <h> Data (Read/Write)
+// <o2> Start <0x0-0xFFFFFFFF>
+// <o3> Size <0x0-0xFFFFFFFF>
+// </h>
+// <h> Top of Stack (Read/Write)
+// <o4> STACK <0x0-0xFFFFFFFF>
+// </h>
+// </h>
+*/
+
+/* Memory Definitions */
+
+MEMORY
+{
+ CODE (rx) : ORIGIN = 0x00000000, LENGTH = 0x00003000
+ DATA (rw) : ORIGIN = 0x00003000, LENGTH = 0x00001000
+ STACK (rw) : ORIGIN = 0x00004000,LENGTH = 0x00000000
+}
+
+
+/* Section Definitions */
+
+SECTIONS
+{
+ /* first section is .text which is used for code */
+ . = 0x0000000;
+ .text : { *cstartup.o (.text) }>CODE =0
+ .text :
+ {
+ *(.text) /* remaining code */
+
+ *(.glue_7t) *(.glue_7)
+
+ } >CODE =0
+
+ . = ALIGN(4);
+
+ /* .rodata section which is used for read-only data (constants) */
+
+ .rodata :
+ {
+ *(.rodata)
+ } >CODE
+
+ . = ALIGN(4);
+
+ _etext = . ;
+ PROVIDE (etext = .);
+
+ /* .data section which is used for initialized data */
+
+ .data : AT (_etext)
+ {
+ _data = . ;
+ *(.data)
+ SORT(CONSTRUCTORS)
+ } >DATA
+ . = ALIGN(4);
+
+ _edata = . ;
+ PROVIDE (edata = .);
+
+ /* .bss section which is used for uninitialized data */
+
+ .bss :
+ {
+ __bss_start = . ;
+ __bss_start__ = . ;
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(4);
+ __bss_end__ = . ;
+ __bss_end__ = . ;
+ _end = .;
+ . = ALIGN(4);
+ .int_data :
+ {
+ *(.internal_ram_top)
+ }> STACK
+
+ PROVIDE (end = .);
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+}
diff --git a/firmware/link/AT91SAM7S64-ROM.ld b/firmware/link/AT91SAM7S64-ROM.ld
new file mode 100644
index 0000000..3289705
--- /dev/null
+++ b/firmware/link/AT91SAM7S64-ROM.ld
@@ -0,0 +1,151 @@
+/*---------------------------------------------------------------------------*/
+/*- ATMEL Microcontroller Software Support - ROUSSET - */
+/*---------------------------------------------------------------------------*/
+/* The software is delivered "AS IS" without warranty or condition of any */
+/* kind, either express, implied or statutory. This includes without */
+/* limitation any warranty or condition with respect to merchantability or */
+/* fitness for any particular purpose, or against the infringements of */
+/* intellectual property rights of others. */
+/*---------------------------------------------------------------------------*/
+/*- File source : GCC_FLASH.ld */
+/*- Object : Linker Script File for Flash Workspace */
+/*- Compilation flag : None */
+/*- */
+/*- 1.0 20/Oct/04 JPP : Creation */
+/*---------------------------------------------------------------------------*/
+
+/* slightly modified for the WinARM example - M.Thomas (not Atmel) */
+
+/*
+//*** <<< Use Configuration Wizard in Context Menu >>> ***
+*/
+
+
+/*
+// <h> Memory Configuration
+// <h> Code (Read Only)
+// <o> Start <0x0-0xFFFFFFFF>
+// <o1> Size <0x0-0xFFFFFFFF>
+// </h>
+// <h> Data (Read/Write)
+// <o2> Start <0x0-0xFFFFFFFF>
+// <o3> Size <0x0-0xFFFFFFFF>
+// </h>
+// <h> Top of Stack (Read/Write)
+// <o4> STACK <0x0-0xFFFFFFFF>
+// </h>
+// </h>
+*/
+
+/* Memory Definitions */
+
+/* mt change code origin from 0x00000000 */
+MEMORY
+{
+ CODE (rx) : ORIGIN = 0x00100000, LENGTH = 0x00010000
+ DATA (rw) : ORIGIN = 0x00200000, LENGTH = 0x00004000
+ STACK (rw) : ORIGIN = 0x00204000,LENGTH = 0x00000000
+}
+
+
+/* Section Definitions */
+
+SECTIONS
+{
+ /* first section is .text which is used for code */
+ . = 0x0000000;
+ .text : { *cstartup.o (.text) }>CODE =0
+ .text :
+ {
+ *(.text) /* remaining code */
+
+ *(.glue_7t) *(.glue_7)
+
+ } >CODE =0
+
+ . = ALIGN(4);
+
+ /* .rodata section which is used for read-only data (constants) */
+
+ .rodata :
+ {
+ *(.rodata)
+ } >CODE
+
+ . = ALIGN(4);
+
+ _etext = . ;
+ PROVIDE (etext = .);
+
+ /* .data section which is used for initialized data */
+
+ .data : AT (_etext)
+ {
+ _data = . ;
+ KEEP(*(.vectram))
+ *(.data)
+ SORT(CONSTRUCTORS)
+ . = ALIGN(4);
+ *(.fastrun)
+ } >DATA
+ . = ALIGN(4);
+
+ _edata = . ;
+ PROVIDE (edata = .);
+
+ /* .bss section which is used for uninitialized data */
+
+ .bss :
+ {
+ __bss_start = . ;
+ __bss_start__ = . ;
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(4);
+ __bss_end__ = . ;
+ __bss_end__ = . ;
+ _end = .;
+ . = ALIGN(4);
+ .int_data :
+ {
+ *(.internal_ram_top)
+ }> STACK
+
+ PROVIDE (end = .);
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+}
diff --git a/firmware/src/main_usb.c b/firmware/src/main_usb.c
new file mode 100644
index 0000000..abb6948
--- /dev/null
+++ b/firmware/src/main_usb.c
@@ -0,0 +1,48 @@
+/* main_usb - OpenPCD test firmware for benchmarking USB performance
+ * (C) 2006 by Harald Welte <laforge@gnumonks.org>
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <lib_AT91SAM7.h>
+#include "openpcd.h"
+#include "rc632.h"
+#include "dbgu.h"
+#include "led.h"
+#include "pwm.h"
+#include "tc.h"
+#include "ssc.h"
+#include "pcd_enumerate.h"
+#include "usb_handler.h"
+
+static void help(void)
+{
+}
+
+int _main_dbgu(char key)
+{
+ switch (key) {
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void _init_func(void)
+{
+ usbtest_init();
+}
+
+void _main_func(void)
+{
+ /* first we try to get rid of pending to-be-sent stuff */
+ //usb_out_process();
+
+ /* next we deal with incoming reqyests from USB EP1 (OUT) */
+ usb_in_process();
+
+ /* try unthrottling sources since we now are [more] likely to
+ * have empty request contexts */
+ udp_unthrottle();
+}
diff --git a/firmware/src/openpcd.h b/firmware/src/openpcd.h
new file mode 100644
index 0000000..3099373
--- /dev/null
+++ b/firmware/src/openpcd.h
@@ -0,0 +1,165 @@
+#ifndef _OPENPCD_H
+#define _OPENPCD_H
+
+#include <openpcd.h>
+
+#define Hz
+#define kHz *1000 Hz
+#define MHz *1000 kHz
+#define MCLK (48 MHz)
+
+
+#ifdef OLIMEX
+#define OPENPCD_PIO_LED2 AT91C_PIO_PA17
+#define OPENPCD_PIO_LED1 AT91C_PIO_PA18
+#define OPENPCD_PIO_UDP_CNX AT91C_PIO_PA24
+#define OPENPCD_PIO_UDP_PUP AT91C_PIO_PA16
+#else
+#if defined(PCD)
+#define OPENPCD_PIO_UDP_CNX AT91C_PIO_PA15
+#define OPENPCD_PIO_UDP_PUP AT91C_PIO_PA22
+#define OPENPCD_PIO_LED1 AT91C_PIO_PA25
+#define OPENPCD_PIO_LED2 AT91C_PIO_PA26
+#define PIO_BOOTLDR AT91C_PIO_PA27
+#elif defined(PICC)
+#define OPENPCD_PIO_UDP_CNX NO_UDP_CNX
+#define OPENPCD_PIO_UDP_PUP AT91C_PIO_PA22
+#define OPENPCD_PIO_LED1 AT91C_PIO_PA25
+#define OPENPCD_PIO_LED2 AT91C_PIO_PA12
+#define PIO_BOOTLDR AT91C_PIO_PA6
+#else
+#error "unknown PCB"
+#endif
+#endif
+
+#define OPENPCD_IRQ_RC632 AT91C_ID_IRQ1
+
+/* PIO A mapping for OpenPCD v0.2
+ *
+ * PA0 TIOA0 B O CARRIER_DIV_HELP
+ * PA1 TIOB1 B O CARRIER_DIV
+ * PA2 PA2 P I N/C
+ * PA3 TWD A I/O I2C
+ *
+ * PA4 TWCK A O I2C
+ * PA5 PA5 P O RFID_RESET
+ * PA6 PA6 P I N/C
+ * PA7 PA7 P I N/C
+ *
+ * PA8 PA8 P I N/C
+ * PA9 DRXD A I Debug
+ * PA10 DTXD A O Debug
+ * PA11 NPCS0 A O SPI Slave Select
+ *
+ * PA12 MISO A I SPi Master In
+ * PA13 MOSI A O SPI Maste Out
+ * PA14 SPCK A O SPI Clock
+ * PA15 P I N/C
+ *
+ * PA16 PA16 P O UDP_PUP (disabled)
+ * PA17 TD A O MFIN *
+ * PA18 RD A I MFOUT
+ * PA19 RK A I CARRIER_DIV
+ *
+ * PA20 PA20 P I AB_DETECT
+ * PA21 PA21 P I N/C
+ * PA22 PA22 P I UDP_PUP
+ * PA23 PWM0 B O MFIN *
+ *
+ * PA24 P I N/C
+ * PA25 PA25 P O LED1
+ * PA26 PA26 P O LED2
+ * PA27 PA27 P I BOOTLDR_SW
+ *
+ * PA28 TCLK1 B I PIO_CARRIER
+ * PA29 TCLK2 B I CARRIER_DIV_HELP
+ * PA30 IRQ1 A I RC632_IRQ
+ * PA31 PA31 P O TRIGGER
+ *
+ * => PIO_PSR = 0x8f7181e4 (= PIO_PER)
+ * => PIO_OSR = 0x86010020 (= PIO_OER)
+ * => PIO_ASR = 0x400e7e18
+ * => PIO_BSR = 0x30800003
+ *
+ * * MFIN connected to both SSC and PWM output !!!
+ */
+
+#define OPENPCD_PIO_CDIV_HELP_OUT AT91C_PA0_TIOA0
+#define OPENPCD_PIO_CDIV_HELP_IN AT91C_PA29_TCLK2
+#define OPENPCD_PIO_MFIN_PWM AT91C_PA23_PWM0
+#define OPENPCD_PIO_CARRIER_DIV_OUT AT91C_PA1_TIOB0
+#define OPENPCD_PIO_MFIN_SSC_TX AT91C_PA17_TD
+#define OPENPCD_PIO_MFOUT_SSC_RX AT91C_PA18_RD
+#define OPENPCD_PIO_SSP_CKIN AT91C_PA19_RK
+#define OPENPCD_PIO_RC632_RESET AT91C_PIO_PA5
+#define OPENPCD_PIO_TRIGGER AT91C_PIO_PA31
+#define OPENPCD_PIO_CARRIER_IN AT91C_PA28_TCLK1
+
+
+/* PIO Definition PICCSIM v0.3 (modified)
+ *
+ * PA0 TIOA0 B O CARRIER_DIV_HELP
+ * PA1 TIOB1 B O SSC_CLOCK
+ * PA2 PA2 P O LOAD1
+ * PA3 PA3 P O LOAD2
+ *
+ * PA4 PA4 P I PLL_LOCK
+ * PA5 PA5 P O nSLAVE_RESET
+ * PA6 PA6 P I BOOTLOADER_SW
+ * PA7 PA7 P I N/C
+ *
+ * PA8 PA8 P O SPI_SS2 (Comparator)
+ * PA9 DRXD A I Debug
+ * PA10 DTXD A O Debug
+ * PA11 NPCS0 A O SPI_SS1 (Gain)
+ *
+ * PA12 PA12 P O LED2 red
+ * PA13 MOSI A O SPI Master Out
+ * PA14 SPCK A O SPI Clock
+ * PA15 TF A I SSC Tx Frame
+ *
+ * PA16 PA16 P O UDP_PUP (old)
+ * PA17 TD A O SSC Tx Data (MOD) *
+ * PA18 RD A I SSC Rx Data (SSC_DATA)
+ * PA19 RK A I SSC Rx Clock (SSC_CLOCK)
+ *
+ * PA20 PA20 P I AB_DETECT
+ * PA21 PA21 P I N/C
+ * PA22 PA22 P I N/C
+ * PA23 PWM0 B O PWM Output (MOD) *
+ *
+ * PA24 PA24 P O PLL_INHIBIT
+ * PA25 PA25 P O LED1 green
+ * PA26 TIOA2 B O TC FDT output (-> SPI Tx Frame)
+ * PA27 TIOB2 B I DATA
+ *
+ * PA28 TCLK1 B I CARRIER
+ * PA29 TCLK2 B I CARRIER_DIV_HELP
+ * PA30 PA30 P I N/C
+ * PA31 PA31 P I N/C
+ *
+ */
+
+#define OPENPICC_PIO_LOAD1 AT91C_PIO_PA2
+#define OPENPICC_PIO_LOAD2 AT91C_PIO_PA3
+#define OPENPICC_PIO_nSLAVE_RESET AT91C_PIO_PA5
+#define OPENPICC_PIO_BOOTLDR AT91C_PIO_PA6
+#define OPENPICC_PIO_SS2_DT_THRESH AT91C_PIO_PA8
+#define OPENPICC_PIO_SS1_GAIN AT91C_PIO_PA11
+#define OPENPICC_PIO_PLL_LOCK AT91C_PIO_PA4
+
+#define OPENPICC_PIO_AB_DETECT AT91C_PIO_PA20
+#define OPENPICC_PIO_PLL_INHIBIT AT91C_PIO_PA24
+
+#define OPENPICC_ADC_FIELD_STRENGTH AT91C_ADC_CH4
+#define OPENPICC_ADC_PLL_DEM AT91C_ADC_CH5
+#define OPENPICC_ADC_AN1 AT91C_ADC_CH6
+#define OPENPICC_ADC_AN2 AT91C_ADC_CH7
+
+#define OPENPCD_IRQ_PRIO_SPI AT91C_AIC_PRIOR_HIGHEST
+#define OPENPCD_IRQ_PRIO_SSC (AT91C_AIC_PRIOR_HIGHEST-1)
+#define OPENPCD_IRQ_PRIO_UDP (AT91C_AIC_PRIOR_LOWEST+2)
+#define OPENPCD_IRQ_PRIO_PIT (AT91C_AIC_PRIOR_LOWEST+1)
+#define OPENPCD_IRQ_PRIO_RC632 AT91C_AIC_PRIOR_LOWEST
+
+#endif /* _OPENPCD_H */
diff --git a/firmware/src/os/dbgu.c b/firmware/src/os/dbgu.c
new file mode 100644
index 0000000..dc1a040
--- /dev/null
+++ b/firmware/src/os/dbgu.c
@@ -0,0 +1,303 @@
+/*----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support - ROUSSET -
+ *----------------------------------------------------------------------------
+ * The software is delivered "AS IS" without warranty or condition of any
+ * kind, either express, implied or statutory. This includes without
+ * limitation any warranty or condition with respect to merchantability or
+ * fitness for any particular purpose, or against the infringements of
+ * intellectual property rights of others.
+ *----------------------------------------------------------------------------
+ * File Name : Debug.c
+ * Object : Debug menu
+ * Creation : JPP 14/Sep/2004
+ * 1.1 29/Aug/05 JPP : Update AIC definion
+ *----------------------------------------------------------------------------*/
+
+// Include Standard files
+#include <board.h>
+#include <os/dbgu.h>
+#include "../openpcd.h"
+#include <os/led.h>
+#include <os/main.h>
+#include <asm/system.h>
+
+#define USART_SYS_LEVEL 4
+/*---------------------------- Global Variable ------------------------------*/
+//*--------------------------1--------------------------------------------------
+//* \fn AT91F_DBGU_Printk
+//* \brief This function is used to send a string through the DBGU channel
+//*----------------------------------------------------------------------------
+void AT91F_DBGU_Ready(void)
+{
+ while (!(AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXEMPTY)) ;
+}
+
+//*----------------------------------------------------------------------------
+//* Function Name : Send_reset
+//* Object : Acknoledeg AIC and send reset
+//*----------------------------------------------------------------------------
+static void Send_reset(void)
+{
+ void (*pfct) (void) = (void (*)(void))0x00000000;
+
+ // Acknoledge the interrupt
+ // Mark the End of Interrupt on the AIC
+ AT91C_BASE_AIC->AIC_EOICR = 0;
+ AT91F_DBGU_Ready();
+ // Jump in reset
+ pfct();
+}
+
+//*----------------------------------------------------------------------------
+//* Function Name : DBGU_irq_handler
+//* Object : C handler interrupt function called by the interrupts
+//* assembling routine
+//*----------------------------------------------------------------------------
+static void DBGU_irq_handler(void)
+{
+ static char value;
+
+ AT91F_DBGU_Get(&value);
+ switch (value) {
+ case '0': //* info
+ AT91F_DBGU_Frame("Clear Pull up\n\r");
+ // Set
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
+ break;
+ case '1': //* info
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
+ AT91F_DBGU_Printk("Set Pull up\n\r");
+ // Reset Application
+ Send_reset();
+ break;
+ case '2':
+ AT91F_DBGU_Printk("Toggling LED 1\n\r");
+ led_toggle(1);
+ break;
+ case '3':
+ AT91F_DBGU_Printk("Toggling LED 2\n\r");
+ led_toggle(2);
+ break;
+ default:
+ if (_main_dbgu(value) < 0)
+ AT91F_DBGU_Printk("\n\r");
+ break;
+ } // end switch
+}
+
+void dbgu_rb_init(void);
+//*----------------------------------------------------------------------------
+//* \fn AT91F_DBGU_Init
+//* \brief This function is used to send a string through the DBGU channel (Very low level debugging)
+//*----------------------------------------------------------------------------
+void AT91F_DBGU_Init(void)
+{
+ dbgu_rb_init();
+
+ //* Open PIO for DBGU
+ AT91F_DBGU_CfgPIO();
+ //* Enable Transmitter & receivier
+ ((AT91PS_USART) AT91C_BASE_DBGU)->US_CR =
+ AT91C_US_RSTTX | AT91C_US_RSTRX;
+
+ //* Configure DBGU
+ AT91F_US_Configure((AT91PS_USART) AT91C_BASE_DBGU, // DBGU base address
+ MCK, AT91C_US_ASYNC_MODE, // Mode Register to be programmed
+ AT91C_DBGU_BAUD, // Baudrate to be programmed
+ 0); // Timeguard to be programmed
+
+ //* Enable Transmitter & receivier
+ ((AT91PS_USART) AT91C_BASE_DBGU)->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;
+
+ //* Enable USART IT error and AT91C_US_ENDRX
+ AT91F_US_EnableIt((AT91PS_USART) AT91C_BASE_DBGU, AT91C_US_RXRDY);
+
+ //* open interrupt
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, USART_SYS_LEVEL,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
+ DBGU_irq_handler);
+ AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS);
+
+ AT91F_DBGU_Printk
+ ("\n\r-I- OpenPCD test mode\n\r 0) Set Pull-up 1) Clear Pull-up "
+ "2) Toggle LED1 3) Toggle LED2 4) Test RC632\n\r"
+ "5) Read RxWait 6) Write RxWait 7) Dump RC632 Regs\n\r");
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_DBGU_Printk
+//* \brief This function is used to send a string through the DBGU channel (Very low level debugging)
+//*----------------------------------------------------------------------------
+void AT91F_DBGU_Printk(char *buffer)
+{
+ while (*buffer != '\0') {
+ while (!AT91F_US_TxReady((AT91PS_USART) AT91C_BASE_DBGU)) ;
+ AT91F_US_PutChar((AT91PS_USART) AT91C_BASE_DBGU, *buffer++);
+ }
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_DBGU_Frame
+//* \brief This function is used to send a string through the DBGU channel
+//*----------------------------------------------------------------------------
+void AT91F_DBGU_Frame(char *buffer)
+{
+ unsigned char len;
+
+ for (len = 0; buffer[len] != '\0'; len++) {
+ }
+
+ AT91F_US_SendFrame((AT91PS_USART) AT91C_BASE_DBGU,
+ (unsigned char *)buffer, len, 0, 0);
+
+}
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_US_Get
+//* \brief Get a Char to USART
+//*----------------------------------------------------------------------------
+int AT91F_DBGU_Get(char *val)
+{
+ if ((AT91F_US_RxReady((AT91PS_USART) AT91C_BASE_DBGU)) == 0)
+ return (0);
+ else {
+ *val = AT91F_US_GetChar((AT91PS_USART) AT91C_BASE_DBGU);
+ return (-1);
+ }
+}
+
+// mthomas: function not used in this application. avoid
+// linking huge newlib code for sscanf.
+
+#ifdef DEBUG
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+const char *
+hexdump(const void *data, unsigned int len)
+{
+ static char string[256];
+ unsigned char *d = (unsigned char *) data;
+ unsigned int i, left;
+
+ string[0] = '\0';
+ left = sizeof(string);
+ for (i = 0; len--; i += 3) {
+ if (i >= sizeof(string) -4)
+ break;
+ snprintf(string+i, 4, " %02x", *d++);
+ }
+ return string;
+}
+
+struct dbgu {
+ char buf[4096];
+ char *next_inbyte;
+ char *next_outbyte;
+};
+static struct dbgu dbgu;
+
+void dbgu_rb_init(void)
+{
+ memset(dbgu.buf, 0, sizeof(dbgu.buf));
+ dbgu.next_inbyte = &dbgu.buf[0];
+ dbgu.next_outbyte = &dbgu.buf[0];
+}
+
+/* pull one char out of debug ring buffer */
+static int dbgu_rb_pull(char *ret)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ if (dbgu.next_outbyte == dbgu.next_inbyte) {
+ local_irq_restore(flags);
+ return -1;
+ }
+
+ *ret = *dbgu.next_outbyte;
+
+ dbgu.next_outbyte++;
+ if (dbgu.next_outbyte == &dbgu.buf[0]+sizeof(dbgu.buf)) {
+ //AT91F_DBGU_Printk("WRAP DURING PULL\r\n");
+ dbgu.next_outbyte = &dbgu.buf[0];
+ } else if (dbgu.next_outbyte > &dbgu.buf[0]+sizeof(dbgu.buf)) {
+ //AT91F_DBGU_Printk("OUTBYTE > END_OF_BUF!!\r\n");
+ dbgu.next_outbyte -= sizeof(dbgu.buf);
+ }
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static void __rb_flush(void)
+{
+ char ch;
+ while (dbgu_rb_pull(&ch) >= 0) {
+ while (!AT91F_US_TxReady((AT91PS_USART) AT91C_BASE_DBGU)) ;
+ AT91F_US_PutChar((AT91PS_USART) AT91C_BASE_DBGU, ch);
+ }
+}
+
+/* flush pending data from debug ring buffer to serial port */
+void dbgu_rb_flush(void)
+{
+ __rb_flush();
+}
+
+static void __dbgu_rb_append(char *data, int len)
+{
+ char *pos = dbgu.next_inbyte;
+
+ dbgu.next_inbyte += len;
+ if (dbgu.next_inbyte >= &dbgu.buf[0]+sizeof(dbgu.buf)) {
+ AT91F_DBGU_Printk("WRAP DURING APPEND\r\n");
+ dbgu.next_inbyte -= sizeof(dbgu.buf);
+ }
+
+ memcpy(pos, data, len);
+}
+
+void dbgu_rb_append(char *data, int len)
+{
+ unsigned long flags;
+ int bytes_left;
+ char *data_cur;
+
+ local_irq_save(flags);
+
+ bytes_left = &dbgu.buf[0]+sizeof(dbgu.buf)-dbgu.next_inbyte;
+ data_cur = data;
+
+ if (len > bytes_left) {
+ AT91F_DBGU_Printk("LEN > BYTES_LEFT\r\n");
+ __rb_flush();
+ __dbgu_rb_append(data_cur, bytes_left);
+ len -= bytes_left;
+ data_cur += bytes_left;
+ }
+ __dbgu_rb_append(data_cur, len);
+
+ local_irq_restore(flags);
+}
+
+static char dbg_buf[256];
+void debugp(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(dbg_buf, sizeof(dbg_buf)-1, format, ap);
+ va_end(ap);
+
+ dbg_buf[sizeof(dbg_buf)-1] = '\0';
+ //AT91F_DBGU_Frame(dbg_buf);
+ //AT91F_DBGU_Printk(dbg_buf);
+ dbgu_rb_append(dbg_buf, strlen(dbg_buf));
+}
+#else
+void dbgu_rb_flush(void) {}
+void dbgu_rb_init(void) {}
+#endif
diff --git a/firmware/src/os/dbgu.h b/firmware/src/os/dbgu.h
new file mode 100644
index 0000000..e29e351
--- /dev/null
+++ b/firmware/src/os/dbgu.h
@@ -0,0 +1,44 @@
+//*----------------------------------------------------------------------------
+//* ATMEL Microcontroller Software Support - ROUSSET -
+//*----------------------------------------------------------------------------
+//* The software is delivered "AS IS" without warranty or condition of any
+//* kind, either express, implied or statutory. This includes without
+//* limitation any warranty or condition with respect to merchantability or
+//* fitness for any particular purpose, or against the infringements of
+//* intellectual property rights of others.
+//*----------------------------------------------------------------------------
+//* File Name : Debug.h
+//* Object : Debug menu
+//* Creation : JPP 02/Sep/2004
+//*----------------------------------------------------------------------------
+
+#ifndef dbgu_h
+#define dbgu_h
+
+#define AT91C_DBGU_BAUD 115200
+
+//#define DEBUGP(x) AT91F_DBGU_Printk(x)
+
+//* ----------------------- External Function Prototype -----------------------
+
+extern const char *hexdump(const void *data, unsigned int len);
+void AT91F_DBGU_Init(void);
+void AT91F_DBGU_Printk( char *buffer);
+void AT91F_DBGU_Frame( char *buffer);
+int AT91F_DBGU_Get( char *val);
+void dbgu_rb_flush(void);
+#ifndef __WinARM__
+void AT91F_DBGU_scanf(char * type,unsigned int * val);
+#endif
+
+#ifdef DEBUG
+extern void debugp(const char *format, ...);
+#define DEBUGP(x, args ...) debugp(x, ## args)
+#else
+#define DEBUGP(x, args ...) do {} while(0)
+#endif
+
+#define DEBUGPCR(x, args ...) DEBUGP(x "\r\n", ## args)
+#define DEBUGPCRF(x, args ...) DEBUGPCR("%s(%d): " x, __FUNCTION__, __LINE__, ## args)
+
+#endif /* dbgu_h */
diff --git a/firmware/src/os/dfu.c b/firmware/src/os/dfu.c
new file mode 100644
index 0000000..f2bc0ca
--- /dev/null
+++ b/firmware/src/os/dfu.c
@@ -0,0 +1,681 @@
+/* USB Device Firmware Update Implementation for OpenPCD
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This ought to be compliant to the USB DFU Spec 1.0 as available from
+ * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
+ *
+ */
+
+#include <errno.h>
+#include <usb_ch9.h>
+#include <usb_dfu.h>
+#include <lib_AT91SAM7.h>
+
+#include <os/dfu.h>
+#include <os/pcd_enumerate.h>
+#include <os/req_ctx.h>
+#include "../openpcd.h"
+
+/* If debug is enabled, we need to access debug functions from flash
+ * and therefore have to omit flashing */
+//#define DEBUG_DFU
+
+#ifdef DEBUG_DFU
+#define DEBUGE DEBUGP
+#define DEBUGI DEBUGP
+#else
+#define DEBUGE(x, args ...) do { } while (0)
+#define DEBUGI(x, args ...) do { } while (0)
+#endif
+
+
+void __dfufunc udp_init(void)
+{
+ /* Set the PLL USB Divider */
+ AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1;
+
+ /* Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock */
+ AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
+
+ /* Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
+ * Set in PIO mode and Configure in Output */
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
+}
+
+/* Send Data through the control endpoint */
+static void __dfufunc udp_ep0_send_data(const char *pData, u_int32_t length)
+{
+ AT91PS_UDP pUdp = AT91C_BASE_UDP;
+ u_int32_t cpt = 0;
+ AT91_REG csr;
+
+ DEBUGE("send_data: %u bytes ", length);
+
+ do {
+ cpt = MIN(length, 8);
+ length -= cpt;
+
+ while (cpt--)
+ pUdp->UDP_FDR[0] = *pData++;
+
+ if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
+ pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
+ while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) ;
+ }
+
+ pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
+ do {
+ csr = pUdp->UDP_CSR[0];
+
+ /* Data IN stage has been stopped by a status OUT */
+ if (csr & AT91C_UDP_RX_DATA_BK0) {
+ pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
+ DEBUGE("stopped by status out ");
+ return;
+ }
+ } while (!(csr & AT91C_UDP_TXCOMP));
+
+ } while (length);
+
+ if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
+ pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
+ while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) ;
+ }
+}
+
+/* Send zero length packet through the control endpoint */
+static void __dfufunc udp_ep0_send_zlp(void)
+{
+ AT91PS_UDP pUdp = AT91C_BASE_UDP;
+ pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
+ while (!(pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP)) ;
+ pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
+ while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) ;
+}
+
+/* Stall the control endpoint */
+static void __dfufunc udp_ep0_send_stall(void)
+{
+ AT91PS_UDP pUdp = AT91C_BASE_UDP;
+ pUdp->UDP_CSR[0] |= AT91C_UDP_FORCESTALL;
+ while (!(pUdp->UDP_CSR[0] & AT91C_UDP_ISOERROR)) ;
+ pUdp->UDP_CSR[0] &= ~(AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);
+ while (pUdp->UDP_CSR[0] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR)) ;
+}
+
+
+static u_int8_t status;
+static u_int8_t *ptr;
+static u_int8_t dfu_state;
+
+static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len)
+{
+ volatile u_int32_t *p = (volatile u_int32_t *)ptr;
+
+ DEBUGE("download ");
+
+ if (len > AT91C_IFLASH_PAGE_SIZE) {
+ /* Too big */
+ dfu_state = DFU_STATE_dfuERROR;
+ status = DFU_STATUS_errADDRESS;
+ udp_ep0_send_stall();
+ return -EINVAL;
+ }
+ if (len & 0x3) {
+ dfu_state = DFU_STATE_dfuERROR;
+ status = DFU_STATUS_errADDRESS;
+ udp_ep0_send_stall();
+ return -EINVAL;
+ }
+ if (len == 0) {
+ dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
+ return 0;
+ }
+#if 0
+ for (i = 0; i < len/4; i++)
+ p[i] =
+#endif
+
+ /* FIXME: get data packet from FIFO, (erase+)write flash */
+#ifndef DEBUG_DFU
+
+#endif
+
+ return 0;
+}
+
+static __dfufunc int handle_upload(u_int16_t val, u_int16_t len)
+{
+ DEBUGE("upload ");
+ if (len > AT91C_IFLASH_PAGE_SIZE
+ || ptr > AT91C_IFLASH_SIZE) {
+ /* Too big */
+ dfu_state = DFU_STATE_dfuERROR;
+ status = DFU_STATUS_errADDRESS;
+ udp_ep0_send_stall();
+ return -EINVAL;
+ }
+
+ if (ptr + len > AT91C_IFLASH_SIZE)
+ len = AT91C_IFLASH_SIZE - (u_int32_t) ptr;
+
+ udp_ep0_send_data((char *)ptr, len);
+ ptr+= len;
+
+ return len;
+}
+
+static __dfufunc void handle_getstatus(void)
+{
+ struct dfu_status dstat;
+
+ DEBUGE("getstatus ");
+
+ /* send status response */
+ dstat.bStatus = status;
+ dstat.bState = dfu_state;
+ dstat.iString = 0;
+ udp_ep0_send_data((char *)&dstat, sizeof(dstat));
+}
+
+static void __dfufunc handle_getstate(void)
+{
+ u_int8_t u8 = dfu_state;
+ DEBUGE("getstate ");
+ udp_ep0_send_data((char *)&u8, sizeof(u8));
+}
+
+/* callback function for DFU requests */
+int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req,
+ u_int16_t val, u_int16_t len)
+{
+ int rc;
+
+ DEBUGE("old_state = %u ", dfu_state);
+
+ switch (dfu_state) {
+ case DFU_STATE_appIDLE:
+ if (req != USB_REQ_DFU_DETACH)
+ goto send_stall;
+ dfu_state = DFU_STATE_appDETACH;
+ goto send_zlp;
+ break;
+ case DFU_STATE_appDETACH:
+ switch (req) {
+ case USB_REQ_DFU_GETSTATUS:
+ handle_getstatus();
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate();
+ break;
+ default:
+ dfu_state = DFU_STATE_appIDLE;
+ goto send_stall;
+ break;
+ }
+ /* FIXME: implement timer to return to appIDLE */
+ break;
+ case DFU_STATE_dfuIDLE:
+ switch (req) {
+ case USB_REQ_DFU_DNLOAD:
+ if (len == 0) {
+ dfu_state = DFU_STATE_dfuERROR;
+ goto send_stall;
+ }
+ handle_dnload(val, len);
+ break;
+ case USB_REQ_DFU_UPLOAD:
+ ptr = 0;
+ dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
+ handle_upload(val, len);
+ break;
+ case USB_REQ_DFU_ABORT:
+ /* no zlp? */
+ goto send_zlp;
+ break;
+ case USB_REQ_DFU_GETSTATUS:
+ handle_getstatus();
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate();
+ break;
+ default:
+ dfu_state = DFU_STATE_dfuERROR;
+ goto send_stall;
+ break;
+ }
+ break;
+ case DFU_STATE_dfuDNLOAD_SYNC:
+ switch (req) {
+ case USB_REQ_DFU_GETSTATUS:
+ handle_getstatus();
+ /* FIXME: state transition depending on block completeness */
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate();
+ break;
+ default:
+ dfu_state = DFU_STATE_dfuERROR;
+ goto send_stall;
+ }
+ break;
+ case DFU_STATE_dfuDNBUSY:
+ dfu_state = DFU_STATE_dfuERROR;
+ goto send_stall;
+ break;
+ case DFU_STATE_dfuDNLOAD_IDLE:
+ switch (req) {
+ case USB_REQ_DFU_DNLOAD:
+ if (handle_dnload(val, len))
+ /* FIXME: state transition */
+ break;
+ case USB_REQ_DFU_ABORT:
+ dfu_state = DFU_STATE_dfuIDLE;
+ goto send_zlp;
+ break;
+ case USB_REQ_DFU_GETSTATUS:
+ handle_getstatus();
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate();
+ break;
+ default:
+ dfu_state = DFU_STATE_dfuERROR;
+ goto send_stall;
+ break;
+ }
+ break;
+ case DFU_STATE_dfuMANIFEST_SYNC:
+ switch (req) {
+ case USB_REQ_DFU_GETSTATUS:
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate();
+ break;
+ default:
+ dfu_state = DFU_STATE_dfuERROR;
+ goto send_stall;
+ break;
+ }
+ break;
+ case DFU_STATE_dfuMANIFEST:
+ dfu_state = DFU_STATE_dfuERROR;
+ goto send_stall;
+ break;
+ case DFU_STATE_dfuMANIFEST_WAIT_RST:
+ /* we should never go here */
+ break;
+ case DFU_STATE_dfuUPLOAD_IDLE:
+ switch (req) {
+ case USB_REQ_DFU_UPLOAD:
+ /* state transition if less data then requested */
+ rc = handle_upload(val, len);
+ if (rc >= 0 && rc < len)
+ dfu_state = DFU_STATE_dfuIDLE;
+ break;
+ case USB_REQ_DFU_ABORT:
+ dfu_state = DFU_STATE_dfuIDLE;
+ /* no zlp? */
+ goto send_zlp;
+ break;
+ case USB_REQ_DFU_GETSTATUS:
+ handle_getstatus();
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate();
+ break;
+ default:
+ dfu_state = DFU_STATE_dfuERROR;
+ goto send_stall;
+ break;
+ }
+ break;
+ case DFU_STATE_dfuERROR:
+ switch (req) {
+ case USB_REQ_DFU_GETSTATUS:
+ handle_getstatus();
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate();
+ break;
+ case USB_REQ_DFU_CLRSTATUS:
+ dfu_state = DFU_STATE_dfuIDLE;
+ /* no zlp? */
+ goto send_zlp;
+ break;
+ default:
+ dfu_state = DFU_STATE_dfuERROR;
+ goto send_stall;
+ break;
+ }
+ break;
+ }
+
+ DEBUGE("OK new_state = %u\r\n", dfu_state);
+ return 0;
+
+send_stall:
+ udp_ep0_send_stall();
+ DEBUGE("STALL new_state = %u\r\n", dfu_state);
+ return -EINVAL;
+
+send_zlp:
+ udp_ep0_send_zlp();
+ DEBUGE("ZLP new_state = %u\r\n", dfu_state);
+ return 0;
+}
+static u_int8_t cur_config;
+
+/* USB DFU Device descriptor in DFU mode */
+__dfustruct const struct usb_device_descriptor dfu_dev_descriptor = {
+ .bLength = USB_DT_DEVICE_SIZE,
+ .bDescriptorType = USB_DT_DEVICE,
+ .bcdUSB = 0x0100,
+ .bDeviceClass = 0x00,
+ .bDeviceSubClass = 0x00,
+ .bDeviceProtocol = 0x00,
+ .bMaxPacketSize0 = 8,
+ .idVendor = OPENPCD_VENDOR_ID,
+ .idProduct = OPENPCD_PRODUCT_ID,
+ .bcdDevice = 0x0000,
+ .iManufacturer = 0x00,
+ .iProduct = 0x00,
+ .iSerialNumber = 0x00,
+ .bNumConfigurations = 0x01,
+};
+
+/* USB DFU Config descriptor in DFU mode */
+__dfustruct const struct _dfu_desc dfu_cfg_descriptor = {
+ .ucfg = {
+ .bLength = USB_DT_CONFIG_SIZE,
+ .bDescriptorType = USB_DT_CONFIG,
+ .wTotalLength = USB_DT_CONFIG_SIZE +
+ 2* USB_DT_INTERFACE_SIZE +
+ USB_DT_DFU_SIZE,
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .iConfiguration = 0,
+ .bmAttributes = USB_CONFIG_ATT_ONE,
+ .bMaxPower = 100,
+ },
+ .uif[0] = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0x00,
+ .bAlternateSetting = 0x00,
+ .bNumEndpoints = 0x00,
+ .bInterfaceClass = 0xfe,
+ .bInterfaceSubClass = 0x01,
+ .bInterfaceProtocol = 0x02,
+ .iInterface = 0,
+ },
+ .uif[1] = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0x00,
+ .bAlternateSetting = 0x01,
+ .bNumEndpoints = 0x00,
+ .bInterfaceClass = 0xfe,
+ .bInterfaceSubClass = 0x01,
+ .bInterfaceProtocol = 0x02,
+ .iInterface = 0,
+ },
+
+ .func_dfu = DFU_FUNC_DESC,
+};
+
+
+/* minimal USB EP0 handler in DFU mode */
+static __dfufunc void dfu_udp_ep0_handler(void)
+{
+ AT91PS_UDP pUDP = AT91C_BASE_UDP;
+ u_int8_t bmRequestType, bRequest;
+ u_int16_t wValue, wIndex, wLength, wStatus;
+ u_int32_t csr = pUDP->UDP_CSR[0];
+
+ DEBUGE("CSR=0x%04x ", csr);
+
+ if (csr & AT91C_UDP_STALLSENT) {
+ DEBUGE("ACK_STALLSENT ");
+ pUDP->UDP_CSR[0] = ~AT91C_UDP_STALLSENT;
+ }
+
+ if (csr & AT91C_UDP_RX_DATA_BK0) {
+ DEBUGE("ACK_BANK0 ");
+ pUDP->UDP_CSR[0] &= ~AT91C_UDP_RX_DATA_BK0;
+ }
+
+ if (!(csr & AT91C_UDP_RXSETUP)) {
+ DEBUGE("no setup packet ");
+ return;
+ }
+
+ DEBUGE("len=%d ", csr >> 16);
+ if (csr >> 16 == 0) {
+ DEBUGE("empty packet ");
+ return;
+ }
+
+ bmRequestType = pUDP->UDP_FDR[0];
+ bRequest = pUDP->UDP_FDR[0];
+ wValue = (pUDP->UDP_FDR[0] & 0xFF);
+ wValue |= (pUDP->UDP_FDR[0] << 8);
+ wIndex = (pUDP->UDP_FDR[0] & 0xFF);
+ wIndex |= (pUDP->UDP_FDR[0] << 8);
+ wLength = (pUDP->UDP_FDR[0] & 0xFF);
+ wLength |= (pUDP->UDP_FDR[0] << 8);
+
+ DEBUGE("bmRequestType=0x%2x ", bmRequestType);
+
+ if (bmRequestType & 0x80) {
+ DEBUGE("DATA_IN=1 ");
+ pUDP->UDP_CSR[0] |= AT91C_UDP_DIR;
+ while (!(pUDP->UDP_CSR[0] & AT91C_UDP_DIR)) ;
+ }
+ pUDP->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;
+ while ((pUDP->UDP_CSR[0] & AT91C_UDP_RXSETUP)) ;
+
+ /* Handle supported standard device request Cf Table 9-3 in USB
+ * speciication Rev 1.1 */
+ switch ((bRequest << 8) | bmRequestType) {
+ case STD_GET_DESCRIPTOR:
+ DEBUGE("GET_DESCRIPTOR ");
+ if (wValue == 0x100) {
+ /* Return Device Descriptor */
+ udp_ep0_send_data((const char *)
+ &dfu_dev_descriptor,
+ MIN(sizeof(dfu_dev_descriptor),
+ wLength));
+ } else if (wValue == 0x200) {
+ /* Return Configuration Descriptor */
+ udp_ep0_send_data((const char *)
+ &dfu_cfg_descriptor,
+ MIN(sizeof(dfu_cfg_descriptor),
+ wLength));
+#if 0
+ } else if (wValue == 0x400) {
+ /* Return Interface descriptor */
+ if (wIndex != 0x01)
+ udp_ep0_send_stall();
+ udp_ep0_send_data((const char *)
+ &dfu_if_descriptor,
+ MIN(sizeof(dfu_if_descriptor),
+ wLength));
+#endif
+ } else
+ udp_ep0_send_stall();
+ break;
+ case STD_SET_ADDRESS:
+ DEBUGE("SET_ADDRESS ");
+ udp_ep0_send_zlp();
+ pUDP->UDP_FADDR = (AT91C_UDP_FEN | wValue);
+ pUDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
+ break;
+ case STD_SET_CONFIGURATION:
+ DEBUGE("SET_CONFIG ");
+ if (wValue)
+ DEBUGE("VALUE!=0 ");
+ cur_config = wValue;
+ udp_ep0_send_zlp();
+ pUDP->UDP_GLBSTATE =
+ (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
+ pUDP->UDP_CSR[1] =
+ (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) :
+ 0;
+ pUDP->UDP_CSR[2] =
+ (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
+ pUDP->UDP_CSR[3] =
+ (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
+ pUDP->UDP_IER = (AT91C_UDP_EPINT0|AT91C_UDP_EPINT1|
+ AT91C_UDP_EPINT2|AT91C_UDP_EPINT3);
+ break;
+ case STD_GET_CONFIGURATION:
+ DEBUGE("GET_CONFIG ");
+ udp_ep0_send_data((char *)&(cur_config),
+ sizeof(cur_config));
+ break;
+ case STD_GET_STATUS_ZERO:
+ DEBUGE("GET_STATUS_ZERO ");
+ wStatus = 0;
+ udp_ep0_send_data((char *)&wStatus, sizeof(wStatus));
+ break;
+ case STD_GET_STATUS_INTERFACE:
+ DEBUGE("GET_STATUS_INTERFACE ");
+ wStatus = 0;
+ udp_ep0_send_data((char *)&wStatus, sizeof(wStatus));
+ break;
+ case STD_GET_STATUS_ENDPOINT:
+ DEBUGE("GET_STATUS_ENDPOINT(EPidx=%u) ", wIndex&0x0f);
+ wStatus = 0;
+ wIndex &= 0x0F;
+ if ((pUDP->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex == 0)) {
+ wStatus =
+ (pUDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
+ udp_ep0_send_data((char *)&wStatus,
+ sizeof(wStatus));
+ } else if ((pUDP->UDP_GLBSTATE & AT91C_UDP_FADDEN)
+ && (wIndex == 0)) {
+ wStatus =
+ (pUDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
+ udp_ep0_send_data((char *)&wStatus,
+ sizeof(wStatus));
+ } else
+ udp_ep0_send_stall();
+ break;
+ case STD_SET_FEATURE_ZERO:
+ DEBUGE("SET_FEATURE_ZERO ");
+ udp_ep0_send_stall();
+ break;
+ case STD_SET_FEATURE_INTERFACE:
+ DEBUGE("SET_FEATURE_INTERFACE ");
+ udp_ep0_send_zlp();
+ break;
+ case STD_SET_FEATURE_ENDPOINT:
+ DEBUGE("SET_FEATURE_ENDPOINT ");
+ udp_ep0_send_stall();
+ break;
+ case STD_CLEAR_FEATURE_ZERO:
+ DEBUGE("CLEAR_FEATURE_ZERO ");
+ udp_ep0_send_stall();
+ break;
+ case STD_CLEAR_FEATURE_INTERFACE:
+ DEBUGE("CLEAR_FEATURE_INTERFACE ");
+ udp_ep0_send_zlp();
+ break;
+ case STD_CLEAR_FEATURE_ENDPOINT:
+ DEBUGE("CLEAR_FEATURE_ENDPOINT(EPidx=%u) ", wIndex & 0x0f);
+ udp_ep0_send_stall();
+ break;
+ case STD_SET_INTERFACE:
+ DEBUGE("SET INTERFACE ");
+ udp_ep0_send_stall();
+ break;
+ default:
+ DEBUGE("DEFAULT(req=0x%02x, type=0x%02x) ", bRequest, bmRequestType);
+ if ((bmRequestType & 0x3f) == USB_TYPE_DFU) {
+ dfu_ep0_handler(bmRequestType, bRequest, wValue, wLength);
+ } else
+ udp_ep0_send_stall();
+ break;
+ }
+}
+
+/* minimal USB IRQ handler in DFU mode */
+static __dfufunc void dfu_udp_irq(void)
+{
+ AT91PS_UDP pUDP = AT91C_BASE_UDP;
+ AT91_REG isr = pUDP->UDP_ISR;
+
+ if (isr & AT91C_UDP_ENDBUSRES) {
+ pUDP->UDP_IER = AT91C_UDP_EPINT0;
+ /* reset all endpoints */
+ pUDP->UDP_RSTEP = (unsigned int)-1;
+ pUDP->UDP_RSTEP = 0;
+ /* Enable the function */
+ pUDP->UDP_FADDR = AT91C_UDP_FEN;
+ /* Configure endpoint 0 */
+ pUDP->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
+ cur_config = 0;
+ }
+
+ if (isr & AT91C_UDP_EPINT0)
+ dfu_udp_ep0_handler();
+
+ /* clear all interrupts */
+ pUDP->UDP_ICR = isr;
+
+ AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_UDP);
+}
+
+/* this is only called once before DFU mode, no __dfufunc required */
+static void dfu_switch(void)
+{
+ AT91PS_AIC pAic = AT91C_BASE_AIC;
+
+ DEBUGE("Switching to DFU mode ");
+
+ pAic->AIC_SVR[AT91C_ID_UDP] = (unsigned int) &dfu_udp_irq;
+ dfu_state = DFU_STATE_dfuIDLE;
+}
+
+void __dfufunc dfu_main(void)
+{
+ udp_init();
+
+ /* This implements
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_UDP,
+ OPENPCD_IRQ_PRIO_UDP,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, dfu_udp_irq);
+ */
+ AT91PS_AIC pAic = AT91C_BASE_AIC;
+ pAic->AIC_IDCR = 1 << AT91C_ID_UDP;
+ pAic->AIC_SVR[AT91C_ID_UDP] = (unsigned int) &dfu_udp_irq;
+ pAic->AIC_SMR[AT91C_ID_UDP] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL |
+ OPENPCD_IRQ_PRIO_UDP;
+ pAic->AIC_ICCR = 1 << AT91C_ID_UDP;
+
+ AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_UDP);
+
+ /* End-of-Bus-Reset is always enabled */
+
+ /* Clear for set the Pull up resistor */
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
+
+ /* do nothing, since all of DFU is interrupt driven */
+ while (1) ;
+}
+
+const struct dfuapi __dfufunctab dfu_api = {
+ .ep0_send_data = &udp_ep0_send_data,
+ .ep0_send_zlp = &udp_ep0_send_zlp,
+ .ep0_send_stall = &udp_ep0_send_stall,
+ .dfu_ep0_handler = &dfu_ep0_handler,
+ .dfu_switch = &dfu_switch,
+ .dfu_state = &dfu_state,
+ .dfu_dev_descriptor = &dfu_dev_descriptor,
+ .dfu_cfg_descriptor = &dfu_cfg_descriptor,
+};
+
+/* just for testing */
+int foo = 12345;
diff --git a/firmware/src/os/dfu.h b/firmware/src/os/dfu.h
new file mode 100644
index 0000000..8786044
--- /dev/null
+++ b/firmware/src/os/dfu.h
@@ -0,0 +1,80 @@
+#ifndef _DFU_H
+#define _DFU_H
+
+/* USB Device Firmware Update Implementation for OpenPCD
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This ought to be compliant to the USB DFU Spec 1.0 as available from
+ * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
+ *
+ */
+
+#include <sys/types.h>
+#include <usb_ch9.h>
+#include <usb_dfu.h>
+
+#include "dbgu.h"
+
+/* USB DFU functional descriptor */
+#define DFU_FUNC_DESC { \
+ .bLength = USB_DT_DFU_SIZE, \
+ .bDescriptorType = USB_DT_DFU, \
+ .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD, \
+ .wDetachTimeOut = 0xff00, \
+ .wTransferSize = AT91C_IFLASH_PAGE_SIZE, \
+ .bcdDFUVersion = 0x0100, \
+}
+
+/* USB Interface descriptor in Runtime mode */
+#define DFU_RT_IF_DESC { \
+ .bLength = USB_DT_INTERFACE_SIZE, \
+ .bDescriptorType = USB_DT_INTERFACE, \
+ .bInterfaceNumber = 0x01, \
+ .bAlternateSetting = 0x00, \
+ .bNumEndpoints = 0x00, \
+ .bInterfaceClass = 0xfe, \
+ .bInterfaceSubClass = 0x01, \
+ .bInterfaceProtocol = 0x01, \
+ .iInterface = 1, \
+}
+
+#define __dfufunc __attribute__ ((long_call, section (".dfu.func")))
+#define __dfustruct __attribute__ ((section (".dfu.struct"))) const
+#define __dfufunctab __attribute__ ((section (".dfu.functab")))
+
+#if 0
+extern void __dfufunc udp_ep0_send_data(const char *data, u_int32_t length);
+extern void __dfufunc udp_ep0_send_zlp(void);
+extern void __dfufunc udp_ep0_send_stall(void);
+extern __dfustruct struct usb_device_descriptor dfu_dev_descriptor;
+extern __dfustruct struct _dfu_desc dfu_cfg_descriptor;
+extern void dfu_switch(void);
+extern int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req,
+ u_int16_t val, u_int16_t len);
+extern static u_int8_t dfu_state;
+struct udp_pcd;
+#endif
+
+
+extern void __dfufunc udp_init(void);
+
+struct _dfu_desc {
+ struct usb_config_descriptor ucfg;
+ struct usb_interface_descriptor uif[2];
+ struct usb_dfu_func_descriptor func_dfu;
+};
+
+struct dfuapi {
+ void (*ep0_send_data)(const char *data, u_int32_t len);
+ void (*ep0_send_zlp)(void);
+ void (*ep0_send_stall)(void);
+ int (*dfu_ep0_handler)(u_int8_t req_type, u_int8_t req,
+ u_int16_t val, u_int16_t len);
+ void (*dfu_switch)(void);
+ u_int8_t *dfu_state;
+ const struct usb_device_descriptor *dfu_dev_descriptor;
+ const struct _dfu_desc *dfu_cfg_descriptor;
+};
+
+
+#endif /* _DFU_H */
diff --git a/firmware/src/os/fifo.c b/firmware/src/os/fifo.c
new file mode 100644
index 0000000..b0ec152
--- /dev/null
+++ b/firmware/src/os/fifo.c
@@ -0,0 +1,108 @@
+/* Implementation of a virtual FIFO */
+
+#include "fifo.h"
+
+#include <errno.h>
+#include <string.h>
+
+#define FIFO_IRQ_LO 0x01
+#define FIFO_IRQ_HI 0x02
+#define FIFO_IRQ_OFLOW 0x04
+
+/* returns number of data bytes present in the fifo */
+int fifo_available(struct fifo *fifo)
+{
+ if (fifo->producer > fifo->consumer)
+ return fifo->producer - fifo->consumer;
+ else
+ return (fifo->size - fifo->consumer) + fifo->producer;
+}
+
+void fifo_check_water(struct fifo *fifo)
+{
+ int avail = fifo_available(fifo);
+
+ if (avail <= fifo->watermark)
+ fifo->irq |= FIFO_IRQ_LO;
+ else
+ fifo->irq &= FIFO_IRQ_LO;
+
+ if (fifo->size - avail >= fifo->watermark)
+ fifo->irq |= FIFO_IRQ_HI;
+ else
+ fifo->irq &= FIFO_IRQ_HI;
+}
+
+void fifo_check_raise_int(struct fifo *fifo)
+{
+ if (fifo->irq & fifo->irq_en)
+ fifo->callback(fifo, fifo->irq, fifo->cb_data);
+}
+
+
+u_int16_t fifo_data_put(struct fifo *fifo, u_int16_t len, u_int8_t *data)
+{
+ if (len > fifo_available(fifo)) {
+ len = fifo_available(fifo);
+ fifo->irq |= FIFO_IRQ_OFLOW;
+ }
+
+ if (len + fifo->producer <= fifo->size) {
+ /* easy case */
+ memcpy(&fifo->data[fifo->producer], data, len);
+ fifo->producer += len;
+ } else {
+ /* difficult: wrap around */
+ u_int16_t chunk_len;
+
+ chunk_len = fifo->size - fifo->producer;
+ memcpy(&fifo->data[fifo->producer], data, chunk_len);
+
+ memcpy(&fifo->data[0], data + chunk_len, len - chunk_len);
+ fifo->producer = len - chunk_len;
+ }
+
+ fifo_check_water(fifo);
+
+ return len;
+}
+
+
+u_int16_t fifo_data_get(struct fifo *fifo, u_int16_t len, u_int8_t *data)
+{
+ u_int16_t avail = fifo_available(fifo);
+
+ if (avail < len)
+ len = avail;
+
+ if (fifo->producer > fifo->consumer) {
+ /* easy case */
+ memcpy(data, &fifo->data[fifo->consumer], len);
+ } else {
+ /* difficult case: wrap */
+ u_int16_t chunk_len = fifo->size - fifo->consumer;
+ memcpy(data, &fifo->data[fifo->consumer], chunk_len);
+ memcpy(data+chunk_len, &fifo->data[0], len - chunk_len);
+ }
+
+ fifo_check_water(fifo);
+
+ return len;
+}
+
+int fifo_init(struct fifo *fifo, u_int16_t size,
+ void (*cb)(struct fifo *fifo, u_int8_t event, void *data), void *cb_data)
+{
+ if (size > sizeof(fifo->data))
+ return -EINVAL;
+
+ memset(fifo->data, 0, sizeof(fifo->data));
+ fifo->size = size;
+ fifo->producer = fifo->consumer = 0;
+ fifo->watermark = 0;
+ fifo->callback = cb;
+ fifo->cb_data = cb_data;
+
+ return 0;
+}
+
diff --git a/firmware/src/os/fifo.h b/firmware/src/os/fifo.h
new file mode 100644
index 0000000..d91c6c2
--- /dev/null
+++ b/firmware/src/os/fifo.h
@@ -0,0 +1,28 @@
+#ifndef _FIFO_H
+#define _FIFO_H
+
+#include <sys/types.h>
+
+#define FIFO_SIZE 1024
+
+struct fifo {
+ u_int16_t size; /* actual FIFO size, can be smaller than 'data' */
+ u_int16_t producer; /* index of producer */
+ u_int16_t consumer; /* index of consumer */
+ u_int16_t watermark;
+ u_int8_t irq;
+ u_int8_t irq_en;
+ u_int8_t status;
+ void (*callback)(struct fifo *fifo, u_int8_t event, void *data);
+ void *cb_data;
+ u_int8_t data[FIFO_SIZE];
+};
+
+
+extern int fifo_init(struct fifo *fifo, u_int16_t size,
+ void (*callback)(struct fifo *fifo, u_int8_t event, void *data), void *cb_data);
+extern u_int16_t fifo_data_get(struct fifo *fifo, u_int16_t len, u_int8_t *data);
+extern u_int16_t fifo_data_put(struct fifo *fifo, u_int16_t len, u_int8_t *data);
+extern int fifo_available(struct fifo *fifo);
+
+#endif
diff --git a/firmware/src/os/flash.c b/firmware/src/os/flash.c
new file mode 100644
index 0000000..2aaf760
--- /dev/null
+++ b/firmware/src/os/flash.c
@@ -0,0 +1,45 @@
+
+
+#define EFCS_CMD_WRITE_PAGE 0x01
+#define EFCS_CMD_SET_LOCK_BIT 0x02
+#define EFCS_CMD_WRITE_PAGE_LOCK 0x03
+#define EFCS_CMD_CLEAR_LOCK 0x04
+#define EFCS_CMD_ERASE_ALL 0x08
+#define EFCS_CMD_SET_NVM_BIT 0x0b
+#define EFCS_CMD_CLEAR_NVM_BIT 0x0d
+#define EFCS_CMD_SET_SECURITY_BIT 0x0f
+
+
+int unlock_page(u_int16_t page)
+{
+ AT91C_MC_FCMD_UNLOCK | AT91C_MC_CORRECT_KEY |
+
+}
+
+int flash_sector(unsigned int sector, const u_int8_t *data, unsigned int len)
+{
+ volatile u_int32_t *p = (volatile u_int32_t *)0;
+ u_int32_t *src32 = (u_int32_t *)data;
+ int i;
+
+ /* hand-code memcpy because we need to make sure only 32bit accesses
+ * are used */
+ for (i = 0; i < len/4; i++)
+ p[i] = src32[i];
+
+ AT91F_MC_EFC_PerformCmd(pmc , AT91C_MC_FCMD_START_PROG|
+ AT91C_MC_CORRECT_KEY | );
+}
+
+
+void flash_init(void)
+{
+ unsigned int fmcn = AT91F_MC_EFC_ComputerFMCN(48000000);
+
+ AT91F_MC_EFC_CfgModeReg(ff, fmcn << 16 | AT91C_MC_FWS_3FWS |
+ AT91C_MC_FRDY | AT91C_MC_LOCKE |
+ AT91C_MC_PROGE);
+
+ AT91F_AIC_EnableIt();
+
+}
diff --git a/firmware/src/os/led.c b/firmware/src/os/led.c
new file mode 100644
index 0000000..8c34c6c
--- /dev/null
+++ b/firmware/src/os/led.c
@@ -0,0 +1,85 @@
+
+#include <sys/types.h>
+#include <errno.h>
+#include <lib_AT91SAM7.h>
+#include <openpcd.h>
+#include "../openpcd.h"
+#include <os/usb_handler.h>
+#include <os/req_ctx.h>
+#include <os/dbgu.h>
+
+static int led2port(int led)
+{
+ if (led == 1)
+ return OPENPCD_PIO_LED1;
+ else if (led == 2)
+ return OPENPCD_PIO_LED2;
+ else
+ return 0;
+}
+
+void led_switch(int led, int on)
+{
+ int port = led2port(led);
+
+ if (port == -1)
+ return;
+
+ if (on)
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, port);
+ else
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, port);
+}
+
+int led_get(int led)
+{
+ int port = led2port(led);
+
+ if (port == -1)
+ return -1;
+
+ return !(AT91F_PIO_GetOutputDataStatus(AT91C_BASE_PIOA) & port);
+}
+
+int led_toggle(int led)
+{
+ int on = led_get(led);
+ if (on == -1)
+ return -1;
+
+ if (on)
+ led_switch(led, 0);
+ else
+ led_switch(led, 1);
+
+ return !on;
+}
+
+static int led_usb_rx(struct req_ctx *rctx)
+{
+ struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0];
+ int ret = 1;
+
+ switch (poh->cmd) {
+ case OPENPCD_CMD_SET_LED:
+ DEBUGP("SET LED(%u,%u) ", poh->reg, poh->val);
+ led_switch(poh->reg, poh->val);
+ break;
+ default:
+ DEBUGP("UNKNOWN ");
+ ret = -EINVAL;
+ break;
+ }
+ req_ctx_put(rctx);
+ return 1;
+}
+
+void led_init(void)
+{
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1);
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2);
+ led_switch(1, 0);
+ led_switch(2, 0);
+
+ usb_hdlr_register(&led_usb_rx, OPENPCD_CMD_CLS_LED);
+}
diff --git a/firmware/src/os/led.h b/firmware/src/os/led.h
new file mode 100644
index 0000000..394107b
--- /dev/null
+++ b/firmware/src/os/led.h
@@ -0,0 +1,9 @@
+#ifndef _LED_H
+#define _LED_H
+
+extern void led_init(void);
+extern void led_switch(int led, int on);
+extern int led_get(int led);
+extern int led_toggle(int led);
+
+#endif
diff --git a/firmware/src/os/main.c b/firmware/src/os/main.c
new file mode 100644
index 0000000..4b7a7a2
--- /dev/null
+++ b/firmware/src/os/main.c
@@ -0,0 +1,47 @@
+#include <errno.h>
+#include <string.h>
+#include <include/lib_AT91SAM7.h>
+#include <os/dbgu.h>
+#include <os/led.h>
+#include <os/dfu.h>
+#include <os/main.h>
+#include <os/power.h>
+#include <os/pcd_enumerate.h>
+#include "../openpcd.h"
+
+int main(void)
+{
+ /* initialize LED and debug unit */
+ led_init();
+ AT91F_DBGU_Init();
+
+ AT91F_PIOA_CfgPMC();
+ /* call application specific init function */
+ _init_func();
+
+ /* initialize USB */
+ udp_init();
+ udp_open();
+
+ // Enable User Reset and set its minimal assertion to 960 us
+ AT91C_BASE_RSTC->RSTC_RMR =
+ AT91C_RSTC_URSTEN | (0x4 << 8) | (unsigned int)(0xA5 << 24);
+
+#ifdef DEBUG_CLOCK_PA6
+ AT91F_PMC_EnablePCK(AT91C_BASE_PMC, 0, AT91C_PMC_CSS_PLL_CLK);
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, AT91C_PA6_PCK0);
+#endif
+
+ /* switch on first led */
+ led_switch(2, 1);
+
+ DEBUGPCRF("entering main (idle) loop");
+ while (1) {
+ /* Call application specific main idle function */
+ _main_func();
+ dbgu_rb_flush();
+#ifdef CONFIG_IDLE
+ //cpu_idle();
+#endif
+ }
+}
diff --git a/firmware/src/os/main.h b/firmware/src/os/main.h
new file mode 100644
index 0000000..1adc8f6
--- /dev/null
+++ b/firmware/src/os/main.h
@@ -0,0 +1,8 @@
+#ifndef _MAIN_H
+#define _MAIN_H
+
+extern void _init_func(void);
+extern int _main_dbgu(char key);
+extern void _main_func(void);
+
+#endif
diff --git a/firmware/src/os/pcd_enumerate.c b/firmware/src/os/pcd_enumerate.c
new file mode 100644
index 0000000..cded8c8
--- /dev/null
+++ b/firmware/src/os/pcd_enumerate.c
@@ -0,0 +1,605 @@
+/* AT91SAM7 USB interface code for OpenPCD
+ *
+ * (C) 2006 by Harald Welte <laforge@gnumonks.org>
+ *
+ * based on existing AT91SAM7 UDP CDC ACM example code, licensed as followed:
+ *----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support - ROUSSET -
+ *----------------------------------------------------------------------------
+ * The software is delivered "AS IS" without warranty or condition of any
+ * kind, either express, implied or statutory. This includes without
+ * limitation any warranty or condition with respect to merchantability or
+ * fitness for any particular purpose, or against the infringements of
+ * intellectual property rights of others.
+ *----------------------------------------------------------------------------
+ */
+
+#include <errno.h>
+#include <usb_ch9.h>
+#include <sys/types.h>
+#include <asm/atomic.h>
+#include <lib_AT91SAM7.h>
+#include <openpcd.h>
+
+#include <os/pcd_enumerate.h>
+#include <os/req_ctx.h>
+#include <os/dfu.h>
+#include "../openpcd.h"
+#include <os/dbgu.h>
+
+#define DEBUG_UDP_IRQ
+#define DEBUG_UDP_EP0
+
+#define CONFIG_DFU
+
+#define AT91C_EP_OUT 1
+#define AT91C_EP_OUT_SIZE 0x40
+#define AT91C_EP_IN 2
+#define AT91C_EP_IN_SIZE 0x40
+#define AT91C_EP_INT 3
+
+#ifdef CONFIG_DFU
+#define DFU_API_LOCATION ((const struct dfuapi *) 0x00102100)
+static const struct dfuapi *dfu = DFU_API_LOCATION;
+#define udp_ep0_send_data dfu->ep0_send_data
+#define udp_ep0_send_zlp dfu->ep0_send_zlp
+#define udp_ep0_send_stall dfu->ep0_send_stall
+#else
+#error non-DFU builds currently not supported (yet) again
+#endif
+
+static struct udp_pcd upcd;
+
+const struct usb_device_descriptor dev_descriptor = {
+ .bLength = USB_DT_DEVICE_SIZE,
+ .bDescriptorType = USB_DT_DEVICE,
+ .bcdUSB = 0x0200,
+ .bDeviceClass = USB_CLASS_VENDOR_SPEC,
+ .bDeviceSubClass = 0xff,
+ .bDeviceProtocol = 0xff,
+ .bMaxPacketSize0 = 0x08,
+ .idVendor = OPENPCD_VENDOR_ID,
+ .idProduct = OPENPCD_PRODUCT_ID,
+ .bcdDevice = 0x0000,
+ .iManufacturer = 0x00,
+ .iProduct = 0x00,
+ .iSerialNumber = 0x00,
+ .bNumConfigurations = 0x01,
+};
+
+struct _desc {
+ struct usb_config_descriptor ucfg;
+ struct usb_interface_descriptor uif;
+ struct usb_endpoint_descriptor ep[3];
+#ifdef CONFIG_DFU
+ struct usb_interface_descriptor uif_dfu;
+ struct usb_dfu_func_descriptor func_dfu;
+#endif
+};
+
+const struct _desc cfg_descriptor = {
+ .ucfg = {
+ .bLength = USB_DT_CONFIG_SIZE,
+ .bDescriptorType = USB_DT_CONFIG,
+ .wTotalLength = USB_DT_CONFIG_SIZE +
+#ifdef CONFIG_DFU
+ 2 * USB_DT_INTERFACE_SIZE +
+ 3 * USB_DT_ENDPOINT_SIZE +
+ USB_DT_DFU_SIZE,
+ .bNumInterfaces = 2,
+#else
+ 1 * USB_DT_INTERFACE_SIZE +
+ 3 * USB_DT_ENDPOINT_SIZE,
+ .bNumInterfaces = 1,
+#endif
+ .bConfigurationValue = 1,
+ .iConfiguration = 0,
+ .bmAttributes = USB_CONFIG_ATT_ONE,
+ .bMaxPower = 100, /* 200mA */
+ },
+ .uif = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 3,
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0xff,
+ .iInterface = 0,
+ },
+ .ep= {
+ {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = OPENPCD_OUT_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = AT91C_EP_OUT_SIZE,
+ .bInterval = 0x00,
+ }, {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = OPENPCD_IN_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = AT91C_EP_IN_SIZE,
+ .bInterval = 0x00,
+ }, {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = OPENPCD_IRQ_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = AT91C_EP_IN_SIZE,
+ .bInterval = 0xff, /* FIXME */
+ },
+ },
+#ifdef CONFIG_DFU
+ .uif_dfu = DFU_RT_IF_DESC,
+ .func_dfu = DFU_FUNC_DESC,
+#endif
+};
+
+static const struct usb_string_descriptor string0 = {
+ .bLength = sizeof(string0),
+ .bDescriptorType = USB_DT_STRING,
+ .wData[0] = 0x0409, /* English */
+};
+
+
+static void udp_ep0_handler(void);
+
+void udp_unthrottle(void)
+{
+ AT91PS_UDP pUDP = upcd.pUdp;
+ pUDP->UDP_IER = AT91C_UDP_EPINT1;
+}
+
+int udp_refill_ep(int ep, struct req_ctx *rctx)
+{
+ u_int16_t i;
+ AT91PS_UDP pUDP = upcd.pUdp;
+
+ if (!upcd.cur_config)
+ return -ENXIO;
+
+ if (rctx->tx.tot_len > AT91C_EP_IN_SIZE) {
+ DEBUGPCRF("TOO LARGE!!!!!!!!!!!!!!!!!!!!!!!!!!! (%d > %d)",
+ rctx->tx.tot_len, AT91C_EP_IN_SIZE);
+ return -EINVAL;
+ }
+
+ if (atomic_read(&upcd.ep[ep].pkts_in_transit) == 2)
+ return -EBUSY;
+
+ /* fill FIFO/DPR */
+ for (i = 0; i < rctx->tx.tot_len; i++)
+ pUDP->UDP_FDR[ep] = rctx->tx.data[i];
+
+ if (atomic_inc_return(&upcd.ep[ep].pkts_in_transit) == 1) {
+ /* not been transmitting before, start transmit */
+ pUDP->UDP_CSR[ep] |= AT91C_UDP_TXPKTRDY;
+ }
+
+ /* return rctx to pool of free contexts */
+ req_ctx_put(rctx);
+
+ return 0;
+}
+
+#ifdef DEBUG_UDP_IRQ
+#define DEBUGI(x, args ...) DEBUGP(x, ## args)
+#else
+#define DEBUGI(x, args ...) do { } while (0)
+#endif
+
+static void udp_irq(void)
+{
+ u_int32_t csr;
+ AT91PS_UDP pUDP = upcd.pUdp;
+ AT91_REG isr = pUDP->UDP_ISR;
+
+ DEBUGI("udp_irq(imr=0x%04x, isr=0x%04x): ", pUDP->UDP_IMR, isr);
+
+ if (isr & AT91C_UDP_ENDBUSRES) {
+ DEBUGI("ENDBUSRES ");
+ pUDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
+ pUDP->UDP_IER = AT91C_UDP_EPINT0;
+ /* reset all endpoints */
+ pUDP->UDP_RSTEP = (unsigned int)-1;
+ pUDP->UDP_RSTEP = 0;
+ /* Enable the function */
+ pUDP->UDP_FADDR = AT91C_UDP_FEN;
+ /* Configure endpoint 0 */
+ pUDP->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
+ upcd.cur_config = 0;
+
+#ifdef CONFIG_DFU
+ if (*dfu->dfu_state == DFU_STATE_appDETACH) {
+ /* now we need to switch to DFU mode */
+ dfu->dfu_switch();
+ }
+#endif
+ }
+
+ if (isr & AT91C_UDP_EPINT0) {
+ DEBUGI("EP0INT(Control) ");
+ udp_ep0_handler();
+ }
+ if (isr & AT91C_UDP_EPINT1) {
+ u_int32_t cur_rcv_bank = upcd.cur_rcv_bank;
+ csr = pUDP->UDP_CSR[1];
+ DEBUGI("EP1INT(Out, CSR=0x%08x) ", csr);
+ if (cur_rcv_bank == AT91C_UDP_RX_DATA_BK1)
+ DEBUGI("cur_bank=1 ");
+ else if (cur_rcv_bank == AT91C_UDP_RX_DATA_BK0)
+ DEBUGI("cur_bank=0 ");
+ else
+ DEBUGI("cur_bank INVALID ");
+
+ if (csr & AT91C_UDP_RX_DATA_BK1)
+ DEBUGI("BANK1 ");
+ if (csr & AT91C_UDP_RX_DATA_BK0)
+ DEBUGI("BANK0 ");
+
+ if (csr & cur_rcv_bank) {
+ u_int16_t pkt_recv = 0;
+ u_int16_t pkt_size = csr >> 16;
+ struct req_ctx *rctx = req_ctx_find_get(RCTX_STATE_FREE,
+ RCTX_STATE_UDP_RCV_BUSY);
+
+ if (rctx) {
+ rctx->rx.tot_len = pkt_size;
+ while (pkt_size--)
+ rctx->rx.data[pkt_recv++] = pUDP->UDP_FDR[1];
+ pUDP->UDP_CSR[1] &= ~cur_rcv_bank;
+ if (cur_rcv_bank == AT91C_UDP_RX_DATA_BK0)
+ cur_rcv_bank = AT91C_UDP_RX_DATA_BK1;
+ else
+ cur_rcv_bank = AT91C_UDP_RX_DATA_BK0;
+ upcd.cur_rcv_bank = cur_rcv_bank;
+ req_ctx_set_state(rctx, RCTX_STATE_UDP_RCV_DONE);
+ DEBUGI("RCTX=%u ", req_ctx_num(rctx));
+ } else {
+ /* disable interrupts for now */
+ pUDP->UDP_IDR = AT91C_UDP_EPINT1;
+ DEBUGP("NO_RCTX_AVAIL! ");
+ }
+ }
+ }
+ if (isr & AT91C_UDP_EPINT2) {
+ csr = pUDP->UDP_CSR[2];
+ DEBUGI("EP2INT(In, CSR=0x%08x) ", csr);
+ if (csr & AT91C_UDP_TXCOMP) {
+ struct req_ctx *rctx;
+
+ DEBUGI("ACK_TX_COMP ");
+ /* acknowledge TX completion */
+ pUDP->UDP_CSR[2] &= ~AT91C_UDP_TXCOMP;
+ while (pUDP->UDP_CSR[2] & AT91C_UDP_TXCOMP) ;
+
+ /* if we already have another packet in DPR, send it */
+ if (atomic_dec_return(&upcd.ep[2].pkts_in_transit) == 1)
+ pUDP->UDP_CSR[2] |= AT91C_UDP_TXPKTRDY;
+
+ /* try to re-fill from pending rcts for EP2 */
+ rctx = req_ctx_find_get(RCTX_STATE_UDP_EP2_PENDING,
+ RCTX_STATE_UDP_EP2_BUSY);
+ if (rctx)
+ udp_refill_ep(2, rctx);
+ else
+ DEBUGI("NO_RCTX_pending ");
+ }
+ }
+ if (isr & AT91C_UDP_EPINT3) {
+ csr = pUDP->UDP_CSR[3];
+ DEBUGI("EP3INT(Interrupt, CSR=0x%08x) ", csr);
+ /* Transmit has completed, re-fill from pending rcts for EP3 */
+ }
+
+ if (isr & AT91C_UDP_RXSUSP) {
+ pUDP->UDP_ICR = AT91C_UDP_RXSUSP;
+ DEBUGI("RXSUSP ");
+ /* FIXME: implement suspend/resume */
+ }
+ if (isr & AT91C_UDP_RXRSM) {
+ pUDP->UDP_ICR = AT91C_UDP_RXRSM;
+ DEBUGI("RXRSM ");
+ /* FIXME: implement suspend/resume */
+ }
+ if (isr & AT91C_UDP_EXTRSM) {
+ pUDP->UDP_ICR = AT91C_UDP_EXTRSM;
+ DEBUGI("EXTRSM ");
+ /* FIXME: implement suspend/resume */
+ }
+ if (isr & AT91C_UDP_SOFINT) {
+ pUDP->UDP_ICR = AT91C_UDP_SOFINT;
+ DEBUGI("SOFINT ");
+ }
+ if (isr & AT91C_UDP_WAKEUP) {
+ pUDP->UDP_ICR = AT91C_UDP_WAKEUP;
+ DEBUGI("WAKEUP ");
+ /* FIXME: implement suspend/resume */
+ }
+
+ DEBUGI("END\r\n");
+ AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_UDP);
+}
+
+/* Open USB Device Port */
+void udp_open(void)
+{
+ DEBUGPCRF("entering");
+ upcd.pUdp = AT91C_BASE_UDP;
+ upcd.cur_config = 0;
+ upcd.cur_rcv_bank = AT91C_UDP_RX_DATA_BK0;
+
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_UDP,
+ OPENPCD_IRQ_PRIO_UDP,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, udp_irq);
+ AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_UDP);
+
+ /* End-of-Bus-Reset is always enabled */
+
+ /* Set the Pull up resistor */
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
+}
+
+void udp_reset(void)
+{
+ volatile int i;
+
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
+ for (i = 0; i < 0xffff; i++)
+ ;
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
+}
+
+#ifdef DEBUG_UDP_EP0
+#define DEBUGE(x, args ...) DEBUGP(x, ## args)
+#else
+#define DEBUGE(x, args ...) do { } while (0)
+#endif
+
+/* Handle requests on the USB Control Endpoint */
+static void udp_ep0_handler(void)
+{
+ AT91PS_UDP pUDP = upcd.pUdp;
+ u_int8_t bmRequestType, bRequest;
+ u_int16_t wValue, wIndex, wLength, wStatus;
+ u_int32_t csr = pUDP->UDP_CSR[0];
+
+ DEBUGE("CSR=0x%04x ", csr);
+
+ if (csr & AT91C_UDP_STALLSENT) {
+ DEBUGE("ACK_STALLSENT ");
+ pUDP->UDP_CSR[0] = ~AT91C_UDP_STALLSENT;
+ }
+
+ if (csr & AT91C_UDP_RX_DATA_BK0) {
+ DEBUGE("ACK_BANK0 ");
+ pUDP->UDP_CSR[0] &= ~AT91C_UDP_RX_DATA_BK0;
+ }
+
+ if (!(csr & AT91C_UDP_RXSETUP)) {
+ DEBUGE("no setup packet ");
+ return;
+ }
+
+ DEBUGE("len=%d ", csr >> 16);
+ if (csr >> 16 == 0) {
+ DEBUGE("empty packet ");
+ return;
+ }
+
+ bmRequestType = pUDP->UDP_FDR[0];
+ bRequest = pUDP->UDP_FDR[0];
+ wValue = (pUDP->UDP_FDR[0] & 0xFF);
+ wValue |= (pUDP->UDP_FDR[0] << 8);
+ wIndex = (pUDP->UDP_FDR[0] & 0xFF);
+ wIndex |= (pUDP->UDP_FDR[0] << 8);
+ wLength = (pUDP->UDP_FDR[0] & 0xFF);
+ wLength |= (pUDP->UDP_FDR[0] << 8);
+
+ DEBUGE("bmRequestType=0x%2x ", bmRequestType);
+
+ if (bmRequestType & 0x80) {
+ DEBUGE("DATA_IN=1 ");
+ pUDP->UDP_CSR[0] |= AT91C_UDP_DIR;
+ while (!(pUDP->UDP_CSR[0] & AT91C_UDP_DIR)) ;
+ }
+ pUDP->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;
+ while ((pUDP->UDP_CSR[0] & AT91C_UDP_RXSETUP)) ;
+
+ /* Handle supported standard device request Cf Table 9-3 in USB
+ * speciication Rev 1.1 */
+ switch ((bRequest << 8) | bmRequestType) {
+ case STD_GET_DESCRIPTOR:
+ DEBUGE("GET_DESCRIPTOR ");
+ if (wValue == 0x100) {
+ /* Return Device Descriptor */
+#ifdef CONFIG_DFU
+ if (*dfu->dfu_state != DFU_STATE_appIDLE)
+ udp_ep0_send_data((const char *)
+ dfu->dfu_dev_descriptor,
+ MIN(dfu->dfu_dev_descriptor->bLength,
+ wLength));
+ else
+#endif
+ udp_ep0_send_data((const char *) &dev_descriptor,
+ MIN(sizeof(dev_descriptor), wLength));
+ } else if (wValue == 0x200) {
+ /* Return Configuration Descriptor */
+#ifdef CONFIG_DFU
+ if (*dfu->dfu_state != DFU_STATE_appIDLE)
+ udp_ep0_send_data((const char *)
+ dfu->dfu_cfg_descriptor,
+ MIN(dfu->dfu_cfg_descriptor->ucfg.wTotalLength,
+ wLength));
+ else
+#endif
+ udp_ep0_send_data((const char *) &cfg_descriptor,
+ MIN(sizeof(cfg_descriptor), wLength));
+ } else if (wValue == 0x300) {
+ /* Return String descriptor */
+ switch (wIndex) {
+ case 0:
+ udp_ep0_send_data((const char *) &string0,
+ MIN(sizeof(string0), wLength));
+ break;
+ default:
+ /* FIXME: implement this */
+ udp_ep0_send_stall();
+ break;
+ }
+#if 0
+ } else if (wValue == 0x400) {
+ /* Return Interface descriptor */
+ if (wIndex != 0x01)
+ udp_ep0_send_stall();
+ udp_ep0_send_data((const char *)
+ &dfu_if_descriptor,
+ MIN(sizeof(dfu_if_descriptor),
+ wLength));
+#endif
+ } else
+ udp_ep0_send_stall();
+ break;
+ case STD_SET_ADDRESS:
+ DEBUGE("SET_ADDRESS ");
+ udp_ep0_send_zlp();
+ pUDP->UDP_FADDR = (AT91C_UDP_FEN | wValue);
+ pUDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
+ break;
+ case STD_SET_CONFIGURATION:
+ DEBUGE("SET_CONFIG ");
+ if (wValue)
+ DEBUGE("VALUE!=0 ");
+ upcd.cur_config = wValue;
+ udp_ep0_send_zlp();
+ pUDP->UDP_GLBSTATE =
+ (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
+ pUDP->UDP_CSR[1] =
+ (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) :
+ 0;
+ pUDP->UDP_CSR[2] =
+ (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
+ pUDP->UDP_CSR[3] =
+ (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
+ pUDP->UDP_IER = (AT91C_UDP_EPINT0|AT91C_UDP_EPINT1|
+ AT91C_UDP_EPINT2|AT91C_UDP_EPINT3);
+ break;
+ case STD_GET_CONFIGURATION:
+ DEBUGE("GET_CONFIG ");
+ udp_ep0_send_data((char *)&(upcd.cur_config),
+ sizeof(upcd.cur_config));
+ break;
+ case STD_GET_STATUS_ZERO:
+ DEBUGE("GET_STATUS_ZERO ");
+ wStatus = 0;
+ udp_ep0_send_data((char *)&wStatus, sizeof(wStatus));
+ break;
+ case STD_GET_STATUS_INTERFACE:
+ DEBUGE("GET_STATUS_INTERFACE ");
+ wStatus = 0;
+ udp_ep0_send_data((char *)&wStatus, sizeof(wStatus));
+ break;
+ case STD_GET_STATUS_ENDPOINT:
+ DEBUGE("GET_STATUS_ENDPOINT(EPidx=%u) ", wIndex&0x0f);
+ wStatus = 0;
+ wIndex &= 0x0F;
+ if ((pUDP->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= 3)) {
+ wStatus =
+ (pUDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
+ udp_ep0_send_data((char *)&wStatus,
+ sizeof(wStatus));
+ } else if ((pUDP->UDP_GLBSTATE & AT91C_UDP_FADDEN)
+ && (wIndex == 0)) {
+ wStatus =
+ (pUDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
+ udp_ep0_send_data((char *)&wStatus,
+ sizeof(wStatus));
+ } else
+ udp_ep0_send_stall();
+ break;
+ case STD_SET_FEATURE_ZERO:
+ DEBUGE("SET_FEATURE_ZERO ");
+ udp_ep0_send_stall();
+ break;
+ case STD_SET_FEATURE_INTERFACE:
+ DEBUGE("SET_FEATURE_INTERFACE ");
+ udp_ep0_send_zlp();
+ break;
+ case STD_SET_FEATURE_ENDPOINT:
+ DEBUGE("SET_FEATURE_ENDPOINT ");
+ udp_ep0_send_zlp();
+ wIndex &= 0x0F;
+ if ((wValue == 0) && wIndex && (wIndex <= 3)) {
+ pUDP->UDP_CSR[wIndex] = 0;
+ udp_ep0_send_zlp();
+ } else
+ udp_ep0_send_stall();
+ break;
+ case STD_CLEAR_FEATURE_ZERO:
+ DEBUGE("CLEAR_FEATURE_ZERO ");
+ udp_ep0_send_stall();
+ break;
+ case STD_CLEAR_FEATURE_INTERFACE:
+ DEBUGP("CLEAR_FEATURE_INTERFACE ");
+ udp_ep0_send_zlp();
+ break;
+ case STD_CLEAR_FEATURE_ENDPOINT:
+ DEBUGE("CLEAR_FEATURE_ENDPOINT(EPidx=%u) ", wIndex & 0x0f);
+ wIndex &= 0x0F;
+ if ((wValue == 0) && wIndex && (wIndex <= 3)) {
+ struct req_ctx *rctx;
+ if (wIndex == 1) {
+ pUDP->UDP_CSR[1] =
+ (AT91C_UDP_EPEDS |
+ AT91C_UDP_EPTYPE_BULK_OUT);
+ pUDP->UDP_RSTEP |= AT91C_UDP_EP1;
+ pUDP->UDP_RSTEP &= ~AT91C_UDP_EP1;
+ }
+ else if (wIndex == 2) {
+ pUDP->UDP_CSR[2] =
+ (AT91C_UDP_EPEDS |
+ AT91C_UDP_EPTYPE_BULK_IN);
+ pUDP->UDP_RSTEP |= AT91C_UDP_EP2;
+ pUDP->UDP_RSTEP &= ~AT91C_UDP_EP2;
+
+ /* free all currently transmitting contexts */
+ while (rctx = req_ctx_find_get(RCTX_STATE_UDP_EP2_BUSY,
+ RCTX_STATE_FREE)) {}
+ atomic_set(&upcd.ep[wIndex].pkts_in_transit, 0);
+ }
+ else if (wIndex == 3) {
+ pUDP->UDP_CSR[3] =
+ (AT91C_UDP_EPEDS |
+ AT91C_UDP_EPTYPE_INT_IN);
+ pUDP->UDP_RSTEP |= AT91C_UDP_EP3;
+ pUDP->UDP_RSTEP &= ~AT91C_UDP_EP3;
+
+ /* free all currently transmitting contexts */
+ while (rctx = req_ctx_find_get(RCTX_STATE_UDP_EP3_BUSY,
+ RCTX_STATE_FREE)) {}
+ atomic_set(&upcd.ep[wIndex].pkts_in_transit, 0);
+ }
+ udp_ep0_send_zlp();
+ } else
+ udp_ep0_send_stall();
+ break;
+ case STD_SET_INTERFACE:
+ DEBUGE("SET INTERFACE ");
+ udp_ep0_send_stall();
+ break;
+ default:
+ DEBUGE("DEFAULT(req=0x%02x, type=0x%02x) ", bRequest, bmRequestType);
+#ifdef CONFIG_DFU
+ if ((bmRequestType & 0x3f) == USB_TYPE_DFU) {
+ dfu->dfu_ep0_handler(bmRequestType, bRequest, wValue, wLength);
+ } else
+#endif
+ udp_ep0_send_stall();
+ break;
+ }
+}
+
diff --git a/firmware/src/os/pcd_enumerate.h b/firmware/src/os/pcd_enumerate.h
new file mode 100644
index 0000000..57ff88c
--- /dev/null
+++ b/firmware/src/os/pcd_enumerate.h
@@ -0,0 +1,56 @@
+#ifndef _OPCD_USB_H
+#define _OPCD_USB_H
+
+#include <lib_AT91SAM7.h>
+#include <sys/types.h>
+#include <asm/atomic.h>
+#include "openpcd.h"
+#include "dfu.h"
+
+struct req_ctx;
+
+extern void udp_open(void);
+extern int udp_refill_ep(int ep, struct req_ctx *rctx);
+extern void udp_unthrottle(void);
+extern void udp_reset(void);
+
+struct ep_ctx {
+ atomic_t pkts_in_transit;
+ void *ctx;
+};
+
+struct udp_pcd {
+ AT91PS_UDP pUdp;
+ unsigned char cur_config;
+ unsigned int cur_rcv_bank;
+ struct ep_ctx ep[4];
+};
+
+/* USB standard request code */
+
+#define STD_GET_STATUS_ZERO 0x0080
+#define STD_GET_STATUS_INTERFACE 0x0081
+#define STD_GET_STATUS_ENDPOINT 0x0082
+
+#define STD_CLEAR_FEATURE_ZERO 0x0100
+#define STD_CLEAR_FEATURE_INTERFACE 0x0101
+#define STD_CLEAR_FEATURE_ENDPOINT 0x0102
+
+#define STD_SET_FEATURE_ZERO 0x0300
+#define STD_SET_FEATURE_INTERFACE 0x0301
+#define STD_SET_FEATURE_ENDPOINT 0x0302
+
+#define STD_SET_ADDRESS 0x0500
+#define STD_GET_DESCRIPTOR 0x0680
+#define STD_SET_DESCRIPTOR 0x0700
+#define STD_GET_CONFIGURATION 0x0880
+#define STD_SET_CONFIGURATION 0x0900
+#define STD_GET_INTERFACE 0x0A81
+#define STD_SET_INTERFACE 0x0B01
+#define STD_SYNCH_FRAME 0x0C82
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+
+#endif
+
diff --git a/firmware/src/os/pio_irq.c b/firmware/src/os/pio_irq.c
new file mode 100644
index 0000000..8dae806
--- /dev/null
+++ b/firmware/src/os/pio_irq.c
@@ -0,0 +1,122 @@
+#include <errno.h>
+#include <sys/types.h>
+#include <lib_AT91SAM7.h>
+#include <os/pio_irq.h>
+#include <os/dbgu.h>
+#include <os/req_ctx.h>
+#include <openpcd.h>
+
+struct pioirq_state {
+ irq_handler_t *handlers[NR_PIO];
+ u_int32_t usbmask;
+ u_int32_t usb_throttled; /* atomic? */
+};
+
+static struct pioirq_state pirqs;
+
+static void pio_irq_demux(void)
+{
+ u_int32_t pio = AT91F_PIO_GetInterruptStatus(AT91C_BASE_PIOA);
+ u_int8_t send_usb = 0;
+ int i;
+
+ DEBUGPCRF("PIO_ISR_STATUS = 0x%08x", pio);
+
+ for (i = 0; i < NR_PIO; i++) {
+ if (pio & (1 << i) && pirqs.handlers[i])
+ pirqs.handlers[i](i);
+ if (pirqs.usbmask & (1 << i))
+ send_usb = 1;
+ }
+
+ if (send_usb && !pirqs.usb_throttled) {
+ struct req_ctx *irq_rctx;
+ irq_rctx = req_ctx_find_get(RCTX_STATE_FREE,
+ RCTX_STATE_PIOIRQ_BUSY);
+ if (!irq_rctx) {
+ /* we cannot disable the interrupt, since we have
+ * non-usb listeners */
+ pirqs.usb_throttled = 1;
+ } else {
+ struct openpcd_hdr *opcdh;
+ u_int32_t *regmask;
+ opcdh = (struct openpcd_hdr *) &irq_rctx->tx.data[0];
+ regmask = (u_int32_t *) (&irq_rctx->tx.data[0] + sizeof(*opcdh));
+ opcdh->cmd = OPENPCD_CMD_PIO_IRQ;
+ opcdh->reg = 0x00;
+ opcdh->flags = 0x00;
+ opcdh->val = 0x00;
+
+ irq_rctx->tx.tot_len = sizeof(*opcdh) + sizeof(u_int32_t);
+ req_ctx_set_state(irq_rctx, RCTX_STATE_UDP_EP3_PENDING);
+ }
+ }
+
+ AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_PIOA);
+}
+
+void pio_irq_enable(u_int32_t pio)
+{
+ AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA, pio);
+}
+
+void pio_irq_disable(u_int32_t pio)
+{
+ AT91F_PIO_InterruptDisable(AT91C_BASE_PIOA, pio);
+}
+
+int pio_irq_register(u_int32_t pio, irq_handler_t *handler)
+{
+ u_int8_t num = ffs(pio);
+
+ if (num == 0)
+ return -EINVAL;
+ num--;
+
+ if (pirqs.handlers[num])
+ return -EBUSY;
+
+ pio_irq_disable(pio);
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, pio);
+ pirqs.handlers[num] = handler;
+
+ return 0;
+}
+
+void pio_irq_unregister(u_int32_t pio)
+{
+ u_int8_t num = ffs(pio);
+
+ if (num == 0)
+ return;
+ num--;
+
+ pio_irq_disable(pio);
+ pirqs.handlers[num] = NULL;
+}
+
+static int pio_irq_usb_in(struct req_ctx *rctx)
+{
+ struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0];
+ struct openpcd_hdr *pih = (struct openpcd_hdr *) &rctx->tx.data[0];
+
+ switch (poh->cmd) {
+ case OPENPCD_CMD_PIO_IRQ:
+ pirqs.usbmask = poh->val;
+ break;
+ default:
+ DEBUGP("UNKNOWN ");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void pio_irq_init(void)
+{
+ AT91F_PIOA_CfgPMC();
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,
+ AT91C_AIC_PRIOR_LOWEST,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &pio_irq_demux);
+ AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_PIOA);
+}
diff --git a/firmware/src/os/pio_irq.h b/firmware/src/os/pio_irq.h
new file mode 100644
index 0000000..33f4656
--- /dev/null
+++ b/firmware/src/os/pio_irq.h
@@ -0,0 +1,13 @@
+#ifndef _PIO_IRQ_H
+#define _PIO_IRQ_H
+
+#define NR_PIO 32
+typedef void irq_handler_t(u_int32_t pio);
+
+extern void pio_irq_enable(u_int32_t pio);
+extern void pio_irq_disable(u_int32_t pio);
+extern int pio_irq_register(u_int32_t pio, irq_handler_t *func);
+extern void pio_irq_unregister(u_int32_t pio);
+extern void pio_irq_init(void);
+
+#endif
diff --git a/firmware/src/os/pit.c b/firmware/src/os/pit.c
new file mode 100644
index 0000000..409faef
--- /dev/null
+++ b/firmware/src/os/pit.c
@@ -0,0 +1,38 @@
+
+
+#include <errno.h>
+#include <sys/types.h>
+#include <lib_AT91SAM7.h>
+#include <AT91SAM7.h>
+#include "../openpcd.h"
+
+/* PIT runs at MCK/16 (= 3MHz) */
+#define PIV_MS(x) (x * 3000)
+
+static void pit_irq(void)
+{
+ /* FIXME: do something */
+}
+
+void pit_mdelay(u_int32_t ms)
+{
+ u_int32_t end;
+
+ end = (AT91F_PITGetPIIR(AT91C_BASE_PITC) + ms) % 20;
+
+ while (end < AT91F_PITGetPIIR(AT91C_BASE_PITC)) { }
+}
+
+void pit_init(void)
+{
+ AT91F_PITC_CfgPMC();
+
+ AT91F_PITInit(AT91C_BASE_PITC, 1000 /* uS */, 48 /* MHz */);
+
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS,
+ OPENPCD_IRQ_PRIO_PIT,
+ AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE,
+ &pit_irq);
+
+ //AT91F_PITEnableInt(AT91C_BASE_PITC);
+}
diff --git a/firmware/src/os/pit.h b/firmware/src/os/pit.h
new file mode 100644
index 0000000..92426e9
--- /dev/null
+++ b/firmware/src/os/pit.h
@@ -0,0 +1,7 @@
+#ifndef _PIT_H
+#define _PIT_H
+
+extern void pit_init(void);
+extern void pit_mdelay(u_int32_t ms);
+
+#endif
diff --git a/firmware/src/os/power.h b/firmware/src/os/power.h
new file mode 100644
index 0000000..bfc6989
--- /dev/null
+++ b/firmware/src/os/power.h
@@ -0,0 +1,8 @@
+#ifndef _POWER_H
+
+static inline void cpu_idle(void)
+{
+ AT91F_PMC_DisablePCK(AT91C_BASE_PMC, AT91C_PMC_PCK);
+}
+
+#endif
diff --git a/firmware/src/os/pwm.c b/firmware/src/os/pwm.c
new file mode 100644
index 0000000..e05699b
--- /dev/null
+++ b/firmware/src/os/pwm.c
@@ -0,0 +1,165 @@
+/* AT91SAM7 PWM routines for OpenPCD / OpenPICC
+ *
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ */
+
+#include <lib_AT91SAM7.h>
+#include <AT91SAM7.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <openpcd.h>
+#include <os/usb_handler.h>
+#include <os/pcd_enumerate.h>
+#include <os/req_ctx.h>
+#include <os/dbgu.h>
+#include "../openpcd.h"
+
+#define Hz
+#define kHz *1000 Hz
+#define MHz *1000 kHz
+#define MCLK (48 MHz)
+
+#if 1
+#define DEBUGPWM DEBUGPCRF
+#else
+#define DEBUGPWM(x, args...)
+#endif
+
+static AT91PS_PWMC pwm = AT91C_BASE_PWMC;
+
+/* find highest bit set. returns bit (32..1) or 0 in case no bit set */
+static int fhs(u_int32_t val)
+{
+ int i;
+
+ for (i = 32; i > 0; i--) {
+ if (val & (1 << (i-1)))
+ return i;
+ }
+
+ return 0;
+}
+
+/* set frequency of PWM signal to freq */
+int pwm_freq_set(int channel, u_int32_t freq)
+{
+ /* in order to get maximum resolution, the pre-scaler must be set to
+ * something like freq << 16. However, the mimimum pre-scaled frequency
+ * we can get is MCLK (48MHz), the minimum is MCLK/(1024*255) =
+ * 48MHz/261120 = 183Hz */
+ u_int32_t overall_div;
+ u_int32_t presc_total;
+ u_int8_t cpre = 0;
+ u_int16_t cprd;
+
+ if (freq > MCLK)
+ return -ERANGE;
+
+ overall_div = MCLK / freq;
+ DEBUGPCRF("mclk=%u, freq=%u, overall_div=%u", MCLK, freq, overall_div);
+
+ if (overall_div > 0x7fff) {
+ /* divisor is larger than half the maximum CPRD register, we
+ * have to configure prescalers */
+ presc_total = overall_div >> 15;
+
+ /* find highest 2^n fitting in prescaler (highest bit set) */
+ cpre = fhs(presc_total);
+ if (cpre > 0) {
+ /* subtract one, because of fhs semantics */
+ cpre--;
+ }
+ cprd = overall_div / (1 << cpre);
+ } else
+ cprd = overall_div;
+
+ DEBUGPCRF("cpre=%u, cprd=%u", cpre, cprd);
+ AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, channel,
+ cpre|AT91C_PWMC_CPOL, cprd, 1);
+
+ return 0;
+}
+
+void pwm_start(int channel)
+{
+ AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, (1 << channel));
+}
+
+void pwm_stop(int channel)
+{
+ AT91F_PWMC_StopChannel(AT91C_BASE_PWMC, (1 << channel));
+}
+
+void pwm_duty_set_percent(int channel, u_int16_t duty)
+{
+ u_int32_t tmp = pwm->PWMC_CH[channel].PWMC_CPRDR & 0xffff;
+
+ tmp = tmp << 16; /* extend value by 2^16 */
+ tmp = tmp / 100; /* tmp = 1 % of extended cprd */
+ tmp = duty * tmp; /* tmp = 'duty' % of extended cprd */
+ tmp = tmp >> 16; /* un-extend tmp (divide by 2^16) */
+
+ DEBUGPWM("Writing %u to Update register\n", tmp);
+ AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, channel, tmp);
+}
+
+static int pwm_usb_in(struct req_ctx *rctx)
+{
+ struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0];
+ /* struct openpcd_hdr *pih = (struct openpcd_hdr *) &rctx->tx.data[0]; */
+ u_int32_t *freq;
+
+ switch (poh->cmd) {
+ case OPENPCD_CMD_PWM_ENABLE:
+ if (poh->val)
+ pwm_start(0);
+ else
+ pwm_stop(0);
+ break;
+ case OPENPCD_CMD_PWM_DUTY_SET:
+ pwm_duty_set_percent(0, poh->val);
+ break;
+ case OPENPCD_CMD_PWM_DUTY_GET:
+ goto respond;
+ break;
+ case OPENPCD_CMD_PWM_FREQ_SET:
+ if (rctx->rx.tot_len < sizeof(*poh)+4)
+ break;
+ freq = (unsigned char *) poh + sizeof(*poh);
+ pwm_freq_set(0, *freq);
+ break;
+ case OPENPCD_CMD_PWM_FREQ_GET:
+ goto respond;
+ break;
+ default:
+ break;
+ }
+
+ req_ctx_put(rctx);
+ return 0;
+respond:
+ req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING);
+ udp_refill_ep(2, rctx);
+ return 1;
+}
+
+void pwm_init(void)
+{
+ /* IMPORTANT: Disable PA17 (SSC TD) output */
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, AT91C_PIO_PA17);
+
+ /* Set PA23 to Peripheral A (PWM0) */
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, OPENPCD_PIO_MFIN_PWM);
+
+ /* Enable Clock for PWM controller */
+ AT91F_PWMC_CfgPMC();
+
+ usb_hdlr_register(&pwm_usb_in, OPENPCD_CMD_CLS_PWM);
+}
+
+void pwm_fini(void)
+{
+ usb_hdlr_unregister(OPENPCD_CMD_CLS_PWM);
+ AT91F_PMC_DisablePeriphClock(AT91C_BASE_PMC, (1 << AT91C_ID_PWMC));
+}
diff --git a/firmware/src/os/pwm.h b/firmware/src/os/pwm.h
new file mode 100644
index 0000000..8836c32
--- /dev/null
+++ b/firmware/src/os/pwm.h
@@ -0,0 +1,11 @@
+#ifndef _PWM_H
+#define _PWM_H
+
+extern void pwm_freq_set(int channel, u_int32_t freq);
+extern void pwm_start(int channel);
+extern void pwm_stop(int channel);
+extern void pwm_duty_set_percent(int channel, u_int16_t duty);
+extern void pwm_init(void);
+extern void pwm_fini(void);
+
+#endif
diff --git a/firmware/src/os/req_ctx.c b/firmware/src/os/req_ctx.c
new file mode 100644
index 0000000..99d248b
--- /dev/null
+++ b/firmware/src/os/req_ctx.c
@@ -0,0 +1,50 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <asm/bitops.h>
+#include <os/dbgu.h>
+#include <os/req_ctx.h>
+
+#include "../openpcd.h"
+
+/* FIXME: locking, FIFO order processing */
+
+static struct req_ctx req_ctx[NUM_REQ_CTX];
+
+struct req_ctx *req_ctx_find_get(unsigned long old_state, unsigned long new_state)
+{
+ unsigned long flags;
+ u_int8_t i;
+
+ for (i = 0; i < NUM_REQ_CTX; i++) {
+ local_irq_save(flags);
+ if (req_ctx[i].state == old_state) {
+ req_ctx[i].state = new_state;
+ local_irq_restore(flags);
+ return &req_ctx[i];
+ }
+ local_irq_restore(flags);
+ }
+
+ return NULL;
+}
+
+u_int8_t req_ctx_num(struct req_ctx *ctx)
+{
+ return ((char *)ctx - (char *)&req_ctx[0])/sizeof(*ctx);
+}
+
+void req_ctx_set_state(struct req_ctx *ctx, unsigned long new_state)
+{
+ unsigned long flags;
+
+ /* FIXME: do we need this kind of locking, we're UP! */
+ local_irq_save(flags);
+ ctx->state = new_state;
+ local_irq_restore(flags);
+}
+
+void req_ctx_put(struct req_ctx *ctx)
+{
+ req_ctx_set_state(ctx, RCTX_STATE_FREE);
+}
diff --git a/firmware/src/os/req_ctx.h b/firmware/src/os/req_ctx.h
new file mode 100644
index 0000000..82a133f
--- /dev/null
+++ b/firmware/src/os/req_ctx.h
@@ -0,0 +1,49 @@
+#ifndef _REQ_CTX_H
+#define _REQ_CTX_H
+
+#define MAX_HDRSIZE sizeof(struct openpcd_hdr)
+#define MAX_REQSIZE (64-MAX_HDRSIZE)
+
+#define req_buf_payload(x) (x->data[x->hdr_len])
+#define req_buf_hdr(x) (x->data[0])
+
+#include <sys/types.h>
+
+struct req_buf {
+ u_int16_t hdr_len;
+ u_int16_t tot_len;
+ u_int8_t data[64];
+};
+
+struct req_ctx {
+ u_int16_t seq; /* request sequence number */
+ u_int16_t flags;
+ volatile u_int32_t state;
+ struct req_buf rx;
+ struct req_buf tx;
+};
+
+#define RCTX_STATE_FREE 0x00
+#define RCTX_STATE_UDP_RCV_BUSY 0x01
+#define RCTX_STATE_UDP_RCV_DONE 0x02
+#define RCTX_STATE_MAIN_PROCESSING 0x03
+#define RCTX_STATE_RC632IRQ_BUSY 0x04
+
+#define RCTX_STATE_UDP_EP2_PENDING 0x10
+#define RCTX_STATE_UDP_EP2_BUSY 0x11
+
+#define RCTX_STATE_UDP_EP3_PENDING 0x12
+#define RCTX_STATE_UDP_EP3_BUSY 0x13
+
+#define RCTX_STATE_SSC_RX_BUSY 0x20
+
+#define RCTX_STATE_PIOIRQ_BUSY 0x80
+
+#define NUM_REQ_CTX 8
+extern struct req_ctx *req_ctx_find_get(unsigned long old_state, unsigned long new_state);
+extern struct req_ctx *req_ctx_find_busy(void);
+extern void req_ctx_set_state(struct req_ctx *ctx, unsigned long new_state);
+extern void req_ctx_put(struct req_ctx *ctx);
+extern u_int8_t req_ctx_num(struct req_ctx *ctx);
+
+#endif /* _REQ_CTX_H */
diff --git a/firmware/src/os/syscalls.c b/firmware/src/os/syscalls.c
new file mode 100644
index 0000000..ed989f1
--- /dev/null
+++ b/firmware/src/os/syscalls.c
@@ -0,0 +1,169 @@
+/***********************************************************************/
+/* */
+/* SYSCALLS.C: System Calls */
+/* most of this is from newlib-lpc and a Keil-demo */
+/* */
+/* These are "reentrant functions" as needed by */
+/* the WinARM-newlib-config, see newlib-manual. */
+/* Collected and modified by Martin Thomas */
+/* */
+/***********************************************************************/
+
+
+#include <stdlib.h>
+#include <reent.h>
+#include <sys/stat.h>
+
+#include <board.h>
+
+static void my_putc(char c)
+{
+ while (!AT91F_US_TxReady((AT91PS_USART)AT91C_BASE_DBGU));
+ AT91F_US_PutChar((AT91PS_USART)AT91C_BASE_DBGU, c);
+}
+
+static int my_kbhit( void )
+{
+ if ((AT91F_US_RxReady((AT91PS_USART)AT91C_BASE_DBGU)) == 0) return 0;
+ else return 1;
+}
+
+static char my_getc( void )
+{
+ return AT91F_US_GetChar((AT91PS_USART)AT91C_BASE_DBGU);
+}
+
+_ssize_t _read_r(
+ struct _reent *r,
+ int file,
+ void *ptr,
+ size_t len)
+{
+ char c;
+ int i;
+ unsigned char *p;
+
+ p = (unsigned char*)ptr;
+
+ for (i = 0; i < len; i++) {
+ // c = uart0Getch();
+ // c = uart0GetchW();
+ while ( !my_kbhit() ) ;
+ c = (char) my_getc();
+ if (c == 0x0D) {
+ *p='\0';
+ break;
+ }
+ *p++ = c;
+ ////// uart0_putc(c);
+ }
+ return len - i;
+}
+
+
+_ssize_t _write_r (
+ struct _reent *r,
+ int file,
+ const void *ptr,
+ size_t len)
+{
+ int i;
+ const unsigned char *p;
+
+ p = (const unsigned char*) ptr;
+
+ for (i = 0; i < len; i++) {
+ if (*p == '\n' ) my_putc('\r');
+ my_putc(*p++);
+ }
+
+ return len;
+}
+
+
+int _close_r(
+ struct _reent *r,
+ int file)
+{
+ return 0;
+}
+
+
+_off_t _lseek_r(
+ struct _reent *r,
+ int file,
+ _off_t ptr,
+ int dir)
+{
+ return (_off_t)0; /* Always indicate we are at file beginning. */
+}
+
+
+int _fstat_r(
+ struct _reent *r,
+ int file,
+ struct stat *st)
+{
+ /* Always set as character device. */
+ st->st_mode = S_IFCHR;
+ /* assigned to strong type with implicit */
+ /* signed/unsigned conversion. Required by */
+ /* newlib. */
+
+ return 0;
+}
+
+
+int isatty(int file); /* avoid warning */
+
+int isatty(int file)
+{
+ return 1;
+}
+
+
+#if 0
+static void _exit (int n) {
+label: goto label; /* endless loop */
+}
+#endif
+
+
+/* "malloc clue function" from newlib-lpc/Keil-Demo/"generic" */
+
+/**** Locally used variables. ****/
+// mt: "cleaner": extern char* end;
+extern char end[]; /* end is set in the linker command */
+ /* file and is the end of statically */
+ /* allocated data (thus start of heap). */
+
+static char *heap_ptr; /* Points to current end of the heap. */
+
+/************************** _sbrk_r *************************************
+ * Support function. Adjusts end of heap to provide more memory to
+ * memory allocator. Simple and dumb with no sanity checks.
+
+ * struct _reent *r -- re-entrancy structure, used by newlib to
+ * support multiple threads of operation.
+ * ptrdiff_t nbytes -- number of bytes to add.
+ * Returns pointer to start of new heap area.
+ *
+ * Note: This implementation is not thread safe (despite taking a
+ * _reent structure as a parameter).
+ * Since _s_r is not used in the current implementation,
+ * the following messages must be suppressed.
+ */
+void * _sbrk_r(
+ struct _reent *_s_r,
+ ptrdiff_t nbytes)
+{
+ char *base; /* errno should be set to ENOMEM on error */
+
+ if (!heap_ptr) { /* Initialize if first time through. */
+ heap_ptr = end;
+ }
+ base = heap_ptr; /* Point to end of heap. */
+ heap_ptr += nbytes; /* Increase heap. */
+
+ return base; /* Return pointer to start of new heap area. */
+}
diff --git a/firmware/src/os/tc_cdiv.c b/firmware/src/os/tc_cdiv.c
new file mode 100644
index 0000000..6c4024c
--- /dev/null
+++ b/firmware/src/os/tc_cdiv.c
@@ -0,0 +1,92 @@
+/* OpenPC TC (Timer / Clock) support code
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This idea of this code is to feed the 13.56MHz carrier clock of RC632
+ * into TCLK1, which is routed to XC1. Then configure TC0 to divide this
+ * clock by a configurable divider.
+ *
+ */
+
+#include <lib_AT91SAM7.h>
+#include <AT91SAM7.h>
+#include <os/dbgu.h>
+
+#include "../openpcd.h"
+#include <os/tc_cdiv.h>
+
+static AT91PS_TCB tcb = AT91C_BASE_TCB;
+
+/* set carrier divider to a specific */
+void tc_cdiv_set_divider(u_int16_t div)
+{
+ tcb->TCB_TC0.TC_RC = div;
+
+ /* set to 50% duty cycle */
+ tcb->TCB_TC0.TC_RA = 1;
+ tcb->TCB_TC0.TC_RB = 1 + (div >> 1);
+}
+
+void tc_cdiv_phase_add(int16_t inc)
+{
+ tcb->TCB_TC0.TC_RA = (tcb->TCB_TC0.TC_RA + inc) % tcb->TCB_TC0.TC_RC;
+ tcb->TCB_TC0.TC_RB = (tcb->TCB_TC0.TC_RB + inc) % tcb->TCB_TC0.TC_RC;
+
+ /* FIXME: can this be done more elegantly? */
+ if (tcb->TCB_TC0.TC_RA == 0) {
+ tcb->TCB_TC0.TC_RA += 1;
+ tcb->TCB_TC0.TC_RB += 1;
+ }
+}
+
+void tc_cdiv_init(void)
+{
+ /* Cfg PA28(TCLK1), PA0(TIOA0), PA1(TIOB0), PA20(TCLK2) as Periph B */
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0,
+ OPENPCD_PIO_CARRIER_IN |
+ OPENPCD_PIO_CARRIER_DIV_OUT |
+ OPENPCD_PIO_CDIV_HELP_OUT |
+ OPENPCD_PIO_CDIV_HELP_IN);
+
+ AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC,
+ ((unsigned int) 1 << AT91C_ID_TC0));
+
+ /* Enable Clock for TC0 */
+ tcb->TCB_TC0.TC_CCR = AT91C_TC_CLKEN;
+
+ /* Connect TCLK1 to XC1, TCLK2 to XC2 */
+ tcb->TCB_BMR &= ~(AT91C_TCB_TC1XC1S | AT91C_TCB_TC2XC2S);
+ tcb->TCB_BMR |= (AT91C_TCB_TC1XC1S_TCLK1 | AT91C_TCB_TC2XC2S_TCLK2);
+
+ /* Clock XC1, Wave mode, Reset on RC comp
+ * TIOA0 on RA comp = set, * TIOA0 on RC comp = clear,
+ * TIOB0 on EEVT = set, TIOB0 on RB comp = clear,
+ * EEVT = XC2 (TIOA0) */
+ tcb->TCB_TC0.TC_CMR = AT91C_TC_CLKS_XC1 | AT91C_TC_WAVE |
+ AT91C_TC_WAVESEL_UP_AUTO |
+ AT91C_TC_ACPA_SET | AT91C_TC_ACPC_CLEAR |
+ AT91C_TC_BEEVT_SET | AT91C_TC_BCPB_CLEAR |
+ AT91C_TC_EEVT_XC2 | AT91C_TC_ETRGEDG_RISING;
+
+ tc_cdiv_set_divider(128);
+
+ /* Reset to start timers */
+ tcb->TCB_BCR = 1;
+}
+
+void tc_cdiv_print(void)
+{
+ DEBUGP("TCB_BMR=0x%08x ", tcb->TCB_BMR);
+ DEBUGP("TC0_CV=0x%08x ", tcb->TCB_TC0.TC_CV);
+ DEBUGP("TC0_CMR=0x%08x ", tcb->TCB_TC0.TC_CMR);
+ DEBUGPCR("TC0_SR=0x%08x", tcb->TCB_TC0.TC_SR);
+
+ DEBUGPCR("TC0_RA=0x%04x, TC0_RB=0x%04x, TC0_RC=0x%04x",
+ tcb->TCB_TC0.TC_RA, tcb->TCB_TC0.TC_RB, tcb->TCB_TC0.TC_RC);
+}
+
+void tc_cdiv_fini(void)
+{
+ tcb->TCB_TC0.TC_CCR = AT91C_TC_CLKDIS;
+ AT91F_PMC_DisablePeriphClock(AT91C_BASE_PMC,
+ ((unsigned int) 1 << AT91C_ID_TC0));
+}
diff --git a/firmware/src/os/tc_cdiv.h b/firmware/src/os/tc_cdiv.h
new file mode 100644
index 0000000..4f2bc02
--- /dev/null
+++ b/firmware/src/os/tc_cdiv.h
@@ -0,0 +1,26 @@
+#ifndef _TC_CDIV_H
+#define _TC_CDIV_H
+
+#include <sys/types.h>
+#include <lib_AT91SAM7.h>
+
+static AT91PS_TCB tcb;
+
+extern void tc_cdiv_phase_add(int16_t inc);
+extern void tc_cdiv_set_divider(u_int16_t div);
+
+static inline void tc_cdiv_phase_inc(void)
+{
+ tc_cdiv_phase_add(1);
+}
+
+static inline void tc_cdiv_phase_dec(void)
+{
+ tc_cdiv_phase_add(-1);
+}
+
+extern void tc_cdiv_print(void);
+extern void tc_cdiv_init(void);
+extern void tc_cdiv_fini(void);
+
+#endif
diff --git a/firmware/src/os/trigger.c b/firmware/src/os/trigger.c
new file mode 100644
index 0000000..b8cedf3
--- /dev/null
+++ b/firmware/src/os/trigger.c
@@ -0,0 +1,17 @@
+#include <lib_AT91SAM7.h>
+#include <os/trigger.h>
+#include "../openpcd.h"
+
+void trigger_init(void)
+{
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_TRIGGER);
+}
+
+void trigger_pulse(void)
+{
+ volatile int i;
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_TRIGGER);
+ for (i=0; i < 0xff; i++)
+ { }
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_TRIGGER);
+}
diff --git a/firmware/src/os/trigger.h b/firmware/src/os/trigger.h
new file mode 100644
index 0000000..597704b
--- /dev/null
+++ b/firmware/src/os/trigger.h
@@ -0,0 +1,7 @@
+#ifndef _TRIGGER_H
+#define _TRIGGER_H
+
+extern void trigger_init(void);
+extern void trigger_pulse(void);
+
+#endif
diff --git a/firmware/src/os/usb_benchmark.c b/firmware/src/os/usb_benchmark.c
new file mode 100644
index 0000000..3637bc3
--- /dev/null
+++ b/firmware/src/os/usb_benchmark.c
@@ -0,0 +1,57 @@
+#include <errno.h>
+#include <string.h>
+#include <lib_AT91SAM7.h>
+#include <os/led.h>
+#include <os/pcd_enumerate.h>
+#include <os/usb_handler.h>
+#include <os/req_ctx.h>
+#include "../openpcd.h"
+
+static struct req_ctx dummy_rctx;
+static struct req_ctx empty_rctx;
+
+static void usbtest_tx_transfer(unsigned int num_pkts)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_pkts; i++) {
+ /* send 16 packets of 64byte */
+ while (udp_refill_ep(2, &dummy_rctx) < 0)
+ ;
+ }
+ /* send one packet of 0 byte */
+ while (udp_refill_ep(2, &empty_rctx) < 0)
+ ;
+}
+
+static int usbtest_rx(struct req_ctx *rctx)
+{
+ struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0];
+ int i;
+
+ switch (poh->cmd) {
+ case OPENPCD_CMD_USBTEST_IN:
+ /* test bulk in pipe */
+ for (i = 0; i < poh->reg; i++) {
+ usbtest_tx_transfer(poh->val);
+ led_toggle(2);
+ }
+ break;
+ case OPENPCD_CMD_USBTEST_OUT:
+ /* test bulk out pipe */
+ break;
+ }
+
+ req_ctx_put(rctx);
+ return 1;
+}
+
+void usbtest_init(void)
+{
+ dummy_rctx.tx.tot_len = 64;
+ memset(dummy_rctx.tx.data, 0x23, 64);
+
+ empty_rctx.tx.tot_len = 0;
+
+ usb_hdlr_register(&usbtest_rx, OPENPCD_CMD_CLS_USBTEST);
+}
diff --git a/firmware/src/os/usb_handler.c b/firmware/src/os/usb_handler.c
new file mode 100644
index 0000000..274353c
--- /dev/null
+++ b/firmware/src/os/usb_handler.c
@@ -0,0 +1,88 @@
+/* OpenPCD USB handler - handle incoming USB requests on OUT pipe
+ * (C) 2006 by Harald Welte
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+
+#include <openpcd.h>
+
+#include <os/pcd_enumerate.h>
+#include <os/usb_handler.h>
+#include <os/req_ctx.h>
+#include <os/led.h>
+#include <os/dbgu.h>
+
+#include "../openpcd.h"
+
+static usb_cmd_fn *cmd_hdlrs[16];
+
+int usb_hdlr_register(usb_cmd_fn *hdlr, u_int8_t class)
+{
+ cmd_hdlrs[class] = hdlr;
+ return 0;
+}
+
+void usb_hdlr_unregister(u_int8_t class)
+{
+ cmd_hdlrs[class] = NULL;
+}
+
+static int usb_in(struct req_ctx *rctx)
+{
+ struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0];
+ struct openpcd_hdr *pih = (struct openpcd_hdr *) &rctx->tx.data[0];
+ usb_cmd_fn *hdlr;
+
+ DEBUGP("usb_in(cls=%d) ", OPENPCD_CMD_CLS(poh->cmd));
+
+ if (rctx->rx.tot_len < sizeof(*poh))
+ return -EINVAL;
+
+ memcpy(pih, poh, sizeof(*poh));
+ rctx->tx.tot_len = sizeof(*poh);
+
+ hdlr = cmd_hdlrs[OPENPCD_CMD_CLS(poh->cmd)];
+ if (hdlr)
+ return (hdlr)(rctx);
+ else
+ DEBUGPCR("no handler for this class\n");
+}
+
+/* Process all pending request contexts that want to Tx on either
+ * IN or INTERRUPT endpoint */
+void usb_out_process(void)
+{
+ struct req_ctx *rctx;
+
+ while (rctx = req_ctx_find_get(RCTX_STATE_UDP_EP3_PENDING,
+ RCTX_STATE_UDP_EP3_BUSY)) {
+ DEBUGPCRF("EP3_BUSY for ctx %u", req_ctx_num(rctx));
+ if (udp_refill_ep(3, rctx) < 0)
+ req_ctx_set_state(rctx, RCTX_STATE_UDP_EP3_PENDING);
+ }
+
+ while (rctx = req_ctx_find_get(RCTX_STATE_UDP_EP2_PENDING,
+ RCTX_STATE_UDP_EP2_BUSY)) {
+ DEBUGPCRF("EP2_BUSY for ctx %u", req_ctx_num(rctx));
+ if (udp_refill_ep(2, rctx) < 0)
+ req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING);
+ }
+}
+
+/* process incoming USB packets (OUT pipe) that have already been
+ * put into request contexts by the UDP IRQ handler */
+void usb_in_process(void)
+{
+ struct req_ctx *rctx;
+
+ while (rctx = req_ctx_find_get(RCTX_STATE_UDP_RCV_DONE,
+ RCTX_STATE_MAIN_PROCESSING)) {
+ DEBUGPCRF("found used ctx %u: len=%u",
+ req_ctx_num(rctx), rctx->rx.tot_len);
+ usb_in(rctx);
+ }
+ udp_unthrottle();
+}
+
diff --git a/firmware/src/os/usb_handler.h b/firmware/src/os/usb_handler.h
new file mode 100644
index 0000000..3efcc1f
--- /dev/null
+++ b/firmware/src/os/usb_handler.h
@@ -0,0 +1,17 @@
+#ifndef _USB_HANDLER_H
+#define _USB_HANDLER_H
+
+#include "openpcd.h"
+#include <os/req_ctx.h>
+
+#define MAX_PAYLOAD_LEN (64 - sizeof(struct openpcd_hdr))
+
+typedef int usb_cmd_fn(struct req_ctx *rctx);
+
+extern int usb_hdlr_register(usb_cmd_fn *hdlr, u_int8_t class);
+extern void usb_hdlr_unregister(u_int8_t class);
+
+extern void usb_in_process(void);
+extern void usb_out_process(void);
+
+#endif
diff --git a/firmware/src/os/wdt.c b/firmware/src/os/wdt.c
new file mode 100644
index 0000000..d8a2145
--- /dev/null
+++ b/firmware/src/os/wdt.c
@@ -0,0 +1,23 @@
+/* AT91SAM7 Watch Dog Timer code for OpenPCD / OpenPICC
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ */
+
+#define WDT_DEBUG
+
+void wdt_irq(void)
+{
+ DEBUGPCRF("================> WATCHDOG EXPIRED !!!!!");
+}
+
+void wdt_init(void)
+{
+#ifdef WDT_DEBUG
+ AT91F_WDTSetMode(AT91C_BASE_WDT, (0xfff << 16) |
+ AT91C_WDTC_WDDBGHLT | AT91C_WDTC_WDIDLEHLT |
+ AT91C_WDTC_WDFIEN);
+#else
+ AT91F_WDTSetMode(AT91C_BASE_WDT, (0xfff << 16) |
+ AT91C_WDTC_WDDBGHLT | AT91C_WDTC_WDIDLEHLT |
+ AT91C_WDTC_WDRSTEN);
+#endif
+}
diff --git a/firmware/src/pcd.h b/firmware/src/pcd.h
new file mode 100644
index 0000000..77c99b2
--- /dev/null
+++ b/firmware/src/pcd.h
@@ -0,0 +1,35 @@
+#ifndef _OPENPCD_H
+#define _OPENPCD_H
+/* pcd.h - OpenPCD USB protocol definitions
+ * (C) 2006 Harald Welte <laforge@gnumonks.org>
+ */
+
+#include <sys/types.h>
+
+struct opcd_cmd_hdr {
+ u_int8_t cmd;
+ u_int8_t arg1;
+ u_int16_t arg2;
+} __attribute__ ((packed));
+
+enum opcd_cmd {
+ OPCD_CMD_REG_READ = 0x01, /* Transparent Read of RC632 REG */
+ OPCD_CMD_REG_WRITE = 0x02, /* Transparent Write to RC632 REG */
+
+ OPCD_CMD_FIFO_READ = 0x03, /* Transparent Read fron RC632 FIFO */
+ OPCD_CMD_FIFO_WRITE = 0x04, /* Transparent Write to RC632 FIFO */
+
+ OPCD_CMD_VFIFO_READ = 0x05, /* Read bytes from virtual FIFO */
+ OPCD_CMD_VFIFO_WRITE = 0x06, /* Write bytes to virtual FIFO */
+ OPCD_CMD_VFIFO_MODE = 0x07, /* Set Virtual FIFO mode */
+
+ OPCD_CMD_REG_SETBIT = 0x08, /* Set a bit in RC632 Register */
+ OPCD_CMD_REG_CLRBIT = 0x09, /* Clear a bit in RC632 Register */
+};
+
+struct opcd_status_hdr {
+ u_int8_t cause, /* interrupt cause register RC632 */
+ u_int8_t prim_status, /* primary status register RC632 */
+} __attribute__ ((packed));
+
+#endif /* _OPENPCD_H */
diff --git a/firmware/src/pcd/main_analog.c b/firmware/src/pcd/main_analog.c
new file mode 100644
index 0000000..8ffa1d4
--- /dev/null
+++ b/firmware/src/pcd/main_analog.c
@@ -0,0 +1,85 @@
+/* main_reqa - OpenPCD firmware for generating an endless loop of
+ * ISO 14443-A REQA packets.
+ *
+ * If a response is received from the PICC, LED1 (Red) will be switched
+ * on. If no valid response has been received within the timeout of the
+ * receiver, LED1 (Red) will be switched off.
+ *
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <librfid/rfid_layer2_iso14443a.h>
+#include "rc632.h"
+#include <os/dbgu.h>
+#include <os/led.h>
+#include <os/trigger.h>
+#include <os/pcd_enumerate.h>
+#include <os/main.h>
+
+void _init_func(void)
+{
+ trigger_init();
+ rc632_init();
+ DEBUGPCRF("turning on RF");
+ rc632_turn_on_rf(RAH);
+ /* FIXME: do we need this? */
+ DEBUGPCRF("initializing 14443A operation");
+ rc632_iso14443a_init(RAH);
+ /* Switch to 848kBps (1subcp / bit) */
+ //rc632_clear_bits(RAH, RC632_REG_RX_CONTROL1, RC632_RXCTRL1_SUBCP_MASK);
+}
+
+int _main_dbgu(char key)
+{
+ static char ana_out_sel;
+ int ret = -EINVAL;
+
+ switch (key) {
+ case 'q':
+ ana_out_sel--;
+ ret = 1;
+ break;
+ case 'w':
+ ana_out_sel++;
+ ret = 1;
+ break;
+ case 'c':
+ rc632_turn_on_rf(RAH);
+ break;
+ case 'o':
+ rc632_turn_off_rf(RAH);
+ break;
+ }
+
+ if (ana_out_sel >= 0xd)
+ ana_out_sel = 0;
+
+ if (ret == 1) {
+ ana_out_sel &= 0x0f;
+ DEBUGPCR("switching to analog output mode 0x%x\n", ana_out_sel);
+ rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, ana_out_sel);
+ }
+
+ return ret;
+}
+
+void _main_func(void)
+{
+#if 1
+ struct iso14443a_atqa atqa;
+
+ memset(&atqa, 0, sizeof(atqa));
+
+ trigger_pulse();
+
+ if (rc632_iso14443a_transceive_sf(RAH, ISO14443A_SF_CMD_WUPA, &atqa) < 0) {
+ DEBUGPCRF("error during transceive_sf");
+ led_switch(1, 0);
+ } else {
+ DEBUGPCRF("received ATQA: %s\n", hexdump((char *)&atqa, sizeof(atqa)));
+ led_switch(1, 1);
+ }
+#endif
+ led_toggle(2);
+}
diff --git a/firmware/src/pcd/main_dumbreader.c b/firmware/src/pcd/main_dumbreader.c
new file mode 100644
index 0000000..1535e27
--- /dev/null
+++ b/firmware/src/pcd/main_dumbreader.c
@@ -0,0 +1,63 @@
+#include <errno.h>
+#include <include/lib_AT91SAM7.h>
+#include <include/openpcd.h>
+#include <os/dbgu.h>
+#include "rc632.h"
+#include <os/led.h>
+#include <os/pcd_enumerate.h>
+#include <os/usb_handler.h>
+#include "../openpcd.h"
+#include <os/main.h>
+
+void _init_func(void)
+{
+ rc632_init();
+ rc632_test(RAH);
+}
+
+int _main_dbgu(char key)
+{
+ unsigned char value;
+
+ switch (key) {
+ case '4':
+ AT91F_DBGU_Printk("Testing RC632 : ");
+ if (rc632_test(RAH) == 0)
+ AT91F_DBGU_Printk("SUCCESS!\n\r");
+ else
+ AT91F_DBGU_Printk("ERROR!\n\r");
+
+ break;
+ case '5':
+ rc632_reg_read(RAH, RC632_REG_RX_WAIT, &value);
+ DEBUGPCR("Reading RC632 Reg RxWait: 0x%02xr", value);
+
+ break;
+ case '6':
+ DEBUGPCR("Writing RC632 Reg RxWait: 0x55");
+ rc632_reg_write(RAH, RC632_REG_RX_WAIT, 0x55);
+ break;
+ case '7':
+ rc632_dump();
+ break;
+ case 'P':
+ rc632_power(1);
+ break;
+ case 'p':
+ rc632_power(0);
+ break;
+ }
+
+ return -EINVAL;
+}
+
+void _main_func(void)
+{
+ /* first we try to get rid of pending to-be-sent stuff */
+ usb_out_process();
+
+ /* next we deal with incoming reqyests from USB EP1 (OUT) */
+ usb_in_process();
+
+ rc632_unthrottle();
+}
diff --git a/firmware/src/pcd/main_pwm.c b/firmware/src/pcd/main_pwm.c
new file mode 100644
index 0000000..2f92d28
--- /dev/null
+++ b/firmware/src/pcd/main_pwm.c
@@ -0,0 +1,257 @@
+/* main_pwm - OpenPCD firmware for generating a PWM-modulated 13.56MHz
+ * carrier
+ *
+ * To use this, you need to connect PIOA P0 with MFIN of the reader.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <lib_AT91SAM7.h>
+#include "../openpcd.h"
+#include <pcd/rc632.h>
+#include <os/dbgu.h>
+#include <os/led.h>
+#include <os/pwm.h>
+#include <os/tc_cdiv.h>
+#include <os/pcd_enumerate.h>
+#include <os/usb_handler.h>
+
+#ifdef SSC
+#include <pcd/ssc.h>
+#endif
+
+static u_int8_t force_100ask = 1;
+static u_int8_t mod_conductance = 0x3f;
+static u_int8_t cw_conductance = 0x3f;
+static u_int16_t duty_percent = 22;
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+static u_int32_t pwm_freq[] = { 105937, 211875, 423750, 847500 };
+static u_int8_t pwm_freq_idx = 0;
+
+static void rc632_modulate_mfin()
+{
+ rc632_reg_write(RAH, RC632_REG_TX_CONTROL,
+ RC632_TXCTRL_MOD_SRC_MFIN|RC632_TXCTRL_TX2_INV|
+ RC632_TXCTRL_TX1_RF_EN|RC632_TXCTRL_TX2_RF_EN);
+}
+
+/* (77/40) ^ EXPcsCfgCW */
+/* 1, 1.925, 3.705625, 7.13332812 */
+
+#define COND_MANT(x) (x & 0x0f)
+#define COND_EXP(x) ((x & 0x30) >> 4)
+
+static const u_int16_t rsrel_expfact[] = { 1000, 1925, 3706, 7133 };
+
+static u_int32_t calc_conduct_rel(u_int8_t inp)
+{
+ u_int32_t cond_rel;
+
+ cond_rel = COND_MANT(inp) * rsrel_expfact[COND_EXP(inp)];
+ cond_rel = cond_rel / 1000;
+
+ return cond_rel;
+}
+
+static const u_int8_t rsrel_table[] = {
+ 0, 16, 32, 48, 1, 17, 2, 3, 33, 18, 4, 5, 19, 6, 7, 49, 34, 20,
+ 8, 9, 21, 10, 11, 35, 22, 12, 13, 23, 14, 50, 36, 15, 24, 25,
+ 37, 26, 27, 51, 38, 28, 29, 39, 30, 52, 31, 40, 41, 53, 42, 43,
+ 54, 44, 45, 55, 46, 47, 56, 57, 58, 59, 60, 61, 62, 63 };
+
+
+static const u_int16_t cdivs[] = { 128, 64, 32, 16 };
+static int cdiv_idx = 0;
+
+static void help(void)
+{
+ DEBUGPCR("o: decrease duty p: increase duty\r\n"
+ "k: stop pwm l: start pwn\r\n"
+ "n: decrease freq m: incresae freq\r\n"
+ "v: decrease mod_cond b: increase mod_cond\r\n"
+ "g: decrease cw_cond h: increase cw_cond");
+ DEBUGPCR("u: PA23 const 1 y: PA23 const 0\r\n"
+ "t: PA23 PWM0 f: toggle Force100ASK\r\n"
+ "{: decrease cdiv_idx }: increse cdiv idx");
+}
+
+void _init_func(void)
+{
+ DEBUGPCR("\r\n===> main_pwm <===\r\n");
+ help();
+
+ rc632_init();
+ DEBUGPCRF("turning on RF");
+ rc632_turn_on_rf(RAH);
+
+ /* switch PA17 (connected to MFIN on board) to input */
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, AT91C_PIO_PA17);
+
+ DEBUGPCRF("Initializing carrier divider");
+ tc_cdiv_init();
+
+ DEBUGPCRF("Initializing PWM");
+ pwm_init();
+ pwm_freq_set(0, 105937);
+ pwm_start(0);
+ pwm_duty_set_percent(0, 22); /* 22% of 9.43uS = 2.07uS */
+ rc632_modulate_mfin();
+
+#ifdef SSC
+ DEBUGPCRF("Initializing SSC RX");
+ ssc_rx_init();
+#endif
+}
+
+int _main_dbgu(char key)
+{
+ switch (key) {
+ case 'o':
+ if (duty_percent >= 1)
+ duty_percent--;
+ pwm_duty_set_percent(0, duty_percent);
+ break;
+ case 'p':
+ if (duty_percent <= 99)
+ duty_percent++;
+ pwm_duty_set_percent(0, duty_percent);
+ break;
+ case 'k':
+ pwm_stop(0);
+ break;
+ case 'l':
+ pwm_start(0);
+ break;
+ case 'n':
+ if (pwm_freq_idx > 0) {
+ pwm_freq_idx--;
+ pwm_stop(0);
+ pwm_freq_set(0, pwm_freq[pwm_freq_idx]);
+ pwm_start(0);
+ pwm_duty_set_percent(0, 22); /* 22% of 9.43uS = 2.07uS */
+ }
+ break;
+ case 'm':
+ if (pwm_freq_idx < ARRAY_SIZE(pwm_freq)-1) {
+ pwm_freq_idx++;
+ pwm_stop(0);
+ pwm_freq_set(0, pwm_freq[pwm_freq_idx]);
+ pwm_start(0);
+ pwm_duty_set_percent(0, 22); /* 22% of 9.43uS = 2.07uS */
+ }
+ break;
+ case 'u':
+ DEBUGPCRF("PA23 output high");
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, AT91C_PIO_PA23);
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, AT91C_PIO_PA23);
+ break;
+ case 'y':
+ DEBUGPCRF("PA23 output low");
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, AT91C_PIO_PA23);
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, AT91C_PIO_PA23);
+ return 0;
+ break;
+ case 't':
+ DEBUGPCRF("PA23 PeriphA (PWM)");
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, AT91C_PA23_PWM0);
+ return 0;
+ break;
+ case 'f':
+ DEBUGPCRF("%sabling Force100ASK", force_100ask ? "Dis":"En");
+ if (force_100ask) {
+ force_100ask = 0;
+ rc632_clear_bits(RAH, RC632_REG_TX_CONTROL,
+ RC632_TXCTRL_FORCE_100_ASK);
+ } else {
+ force_100ask = 1;
+ rc632_set_bits(RAH, RC632_REG_TX_CONTROL,
+ RC632_TXCTRL_FORCE_100_ASK);
+ }
+ return 0;
+ break;
+ case 'v':
+ if (mod_conductance > 0) {
+ mod_conductance--;
+ rc632_reg_write(RAH, RC632_REG_MOD_CONDUCTANCE,
+ rsrel_table[mod_conductance]);
+ }
+ break;
+ case 'b':
+ if (mod_conductance < 0x3f) {
+ mod_conductance++;
+ rc632_reg_write(RAH, RC632_REG_MOD_CONDUCTANCE,
+ rsrel_table[mod_conductance]);
+ }
+ break;
+ case 'g':
+ if (cw_conductance > 0) {
+ cw_conductance--;
+ rc632_reg_write(RAH, RC632_REG_CW_CONDUCTANCE,
+ rsrel_table[cw_conductance]);
+ }
+ break;
+ case 'h':
+ if (cw_conductance < 0x3f) {
+ cw_conductance++;
+ rc632_reg_write(RAH, RC632_REG_CW_CONDUCTANCE,
+ rsrel_table[cw_conductance]);
+ }
+ break;
+ case '?':
+ help();
+ return 0;
+ break;
+ case '<':
+ tc_cdiv_phase_inc();
+ break;
+ case '>':
+ tc_cdiv_phase_dec();
+ break;
+ case '{':
+ if (cdiv_idx > 0)
+ cdiv_idx--;
+ tc_cdiv_set_divider(cdivs[cdiv_idx]);
+ break;
+ case '}':
+ if (cdiv_idx < ARRAY_SIZE(cdivs)-1)
+ cdiv_idx++;
+ tc_cdiv_set_divider(cdivs[cdiv_idx]);
+ break;
+#ifdef SSC
+ case 's':
+ ssc_rx_start();
+ break;
+ case 'S':
+ ssc_rx_stop();
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+
+ DEBUGPCR("pwm_freq=%u, duty_percent=%u, mod_cond=%u, cw_cond=%u tc_cdiv=%u",
+ pwm_freq[pwm_freq_idx], duty_percent, mod_conductance, cw_conductance,
+ cdivs[cdiv_idx]);
+
+ return 0;
+}
+
+
+void _main_func(void)
+{
+ /* first we try to get rid of pending to-be-sent stuff */
+ usb_out_process();
+
+ /* next we deal with incoming reqyests from USB EP1 (OUT) */
+ usb_in_process();
+
+ /* try unthrottling sources since we now are [more] likely to
+ * have empty request contexts */
+ rc632_unthrottle();
+#ifdef SSC
+ ssc_rx_unthrottle();
+#endif
+
+ led_toggle(2);
+}
diff --git a/firmware/src/pcd/main_reqa.c b/firmware/src/pcd/main_reqa.c
new file mode 100644
index 0000000..e28fdff
--- /dev/null
+++ b/firmware/src/pcd/main_reqa.c
@@ -0,0 +1,265 @@
+/* main_reqa - OpenPCD firmware for generating an endless loop of
+ * ISO 14443-A REQA packets. Alternatively we can send WUPA, or
+ * perform a full ISO14443A anti-collision loop.
+ *
+ * If a response is received from the PICC, LED1 (Red) will be switched
+ * on. If no valid response has been received within the timeout of the
+ * receiver, LED1 (Red) will be switched off.
+ *
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <lib_AT91SAM7.h>
+#include <librfid/rfid_layer2_iso14443a.h>
+#include "rc632.h"
+#include <os/dbgu.h>
+#include <os/led.h>
+#include <os/pcd_enumerate.h>
+#include <os/trigger.h>
+
+#include "../openpcd.h"
+
+#ifdef WITH_TC
+#include "tc.h"
+#endif
+
+void _init_func(void)
+{
+ trigger_init();
+ DEBUGPCRF("enabling RC632");
+ rc632_init();
+#ifdef WITH_TC
+ DEBUGPCRF("enabling TC");
+ tc_cdiv_init();
+#endif
+ DEBUGPCRF("turning on RF");
+ rc632_turn_on_rf(RAH);
+ DEBUGPCRF("initializing 14443A operation");
+ rc632_iso14443a_init(RAH);
+}
+
+#define MODE_REQA 0x01
+#define MODE_WUPA 0x02
+#define MODE_ANTICOL 0x03
+#define MODE_14443A 0x04
+
+static volatile int mode = MODE_REQA;
+
+static const char frame_14443a[] = { 0x00, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
+
+static void reg_inc(u_int8_t reg)
+{
+ u_int8_t val;
+ rc632_reg_read(RAH, reg, &val);
+ rc632_reg_write(RAH, reg, val++);
+ DEBUGPCRF("reg 0x%02x = 0x%02x", reg, val);
+}
+
+static void reg_dec(u_int8_t reg)
+{
+ u_int8_t val;
+ rc632_reg_read(RAH, reg, &val);
+ rc632_reg_write(RAH, reg, val--);
+ DEBUGPCRF("reg 0x%02x = 0x%02x", reg, val);
+}
+
+static u_int8_t ana_out_sel;
+static u_int8_t mfout_sel;
+static u_int8_t speed_idx;
+
+static void help(void)
+{
+ DEBUGPCR("r: REQA w: WUPA a: ANTICOL\r\n"
+ "A: 14443A +: inc speed -: dec speed\r\n"
+ "y: inc cw cond x: dec cond c: inc mod cond");
+ DEBUGPCR("v: dec mod cond o: dec ana_out p: dec ana_out\r\n"
+ "h: trigger high l: trigger low u: dec MFOUT mode");
+ DEBUGPCR("i: inc MFOUT md <: dec cdiv ph >: inc cdiv phase\r\n"
+ "{: dev cdiv }: inc cdiv");
+}
+
+static u_int16_t cdivs[] = { 128, 64, 32, 16 };
+
+int _main_dbgu(char key)
+{
+ int ret = 0;
+ static int cdiv_idx = 0;
+
+ switch (key) {
+ case '?':
+ help();
+ break;
+ case 'r':
+ mode = MODE_REQA;
+ break;
+ case 'w':
+ mode = MODE_WUPA;
+ break;
+ case 'A':
+ mode = MODE_14443A;
+ break;
+ case 'a':
+ mode = MODE_ANTICOL;
+ break;
+ /* Those below don't work as long as
+ * iso14443a_init() is called before
+ * every cycle */
+ case 'y':
+ reg_inc(RC632_REG_CW_CONDUCTANCE);
+ break;
+ case 'x':
+ reg_dec(RC632_REG_CW_CONDUCTANCE);
+ break;
+ case 'c':
+ reg_inc(RC632_REG_MOD_CONDUCTANCE);
+ break;
+ case 'v':
+ reg_dec(RC632_REG_MOD_CONDUCTANCE);
+ break;
+ case 'o':
+ if (ana_out_sel > 0) {
+ ana_out_sel--;
+ DEBUGPCR("switching to analog output mode 0x%x\n", ana_out_sel);
+ rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, ana_out_sel);
+ }
+ ret = 1;
+ break;
+ case 'p':
+ if (ana_out_sel < 0xc) {
+ ana_out_sel++;
+ DEBUGPCR("switching to analog output mode 0x%x\n", ana_out_sel);
+ rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, ana_out_sel);
+ }
+ ret = 1;
+ break;
+ case 'u':
+ if (mfout_sel > 0) {
+ mfout_sel--;
+ DEBUGPCR("switching to MFOUT mode 0x%x\n", mfout_sel);
+ rc632_reg_write(RAH, RC632_REG_MFOUT_SELECT, mfout_sel);
+ }
+ ret = 1;
+ break;
+ case 'i':
+ if (mfout_sel < 5) {
+ mfout_sel++;
+ DEBUGPCR("switching to MFOUT mode 0x%x\n", mfout_sel);
+ rc632_reg_write(RAH, RC632_REG_MFOUT_SELECT, mfout_sel);
+ }
+ ret = 1;
+ break;
+ case 'h':
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_TRIGGER);
+ break;
+ case 'l':
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_TRIGGER);
+ break;
+#ifdef WITH_TC
+ case '<':
+ tc_cdiv_phase_inc();
+ break;
+ case '>':
+ tc_cdiv_phase_dec();
+ break;
+ case '{':
+ if (cdiv_idx > 0)
+ cdiv_idx--;
+ tc_cdiv_set_divider(cdivs[cdiv_idx]);
+ break;
+ case '}':
+ if (cdiv_idx < ARRAY_SIZE(cdivs)-1)
+ cdiv_idx++;
+ tc_cdiv_set_divider(cdivs[cdiv_idx]);
+ break;
+#endif
+ case '-':
+ if (speed_idx > 0)
+ speed_idx--;
+ break;
+ case '+':
+ if (speed_idx < 3)
+ speed_idx++;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+void _main_func(void)
+{
+ int status;
+ struct iso14443a_atqa atqa;
+ struct rfid_layer2_handle l2h;
+ volatile int i;
+
+ memset(&atqa, 0, sizeof(atqa));
+
+ /* fake layer2 handle initialization */
+ memset(&l2h, 0, sizeof(l2h));
+ l2h.l2 = &rfid_layer2_iso14443a;
+ l2h.priv.iso14443a.state = ISO14443A_STATE_NONE;
+ l2h.priv.iso14443a.level = ISO14443A_LEVEL_NONE;
+
+ /* FIXME: why does this only work every second attempt without reset or
+ * power-cycle? */
+ rc632_turn_off_rf();
+ //rc632_reset();
+ rc632_turn_on_rf();
+
+ rc632_iso14443a_init(RAH);
+ rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, ana_out_sel);
+ rc632_reg_write(RAH, RC632_REG_MFOUT_SELECT, mfout_sel);
+ for (i = 0; i < 0x3ffff; i++) {}
+ //rc632_dump();
+#ifdef WITH_TC
+ tc_cdiv_print();
+#endif
+
+ switch (mode) {
+ case MODE_REQA:
+ status = rc632_iso14443a_transceive_sf(RAH, ISO14443A_SF_CMD_REQA, &atqa);
+ if (status < 0)
+ DEBUGPCRF("error during transceive_sf REQA");
+ else
+ DEBUGPCRF("received ATQA: %s", hexdump((char *)&atqa, sizeof(atqa)));
+ break;
+ case MODE_WUPA:
+ status = rc632_iso14443a_transceive_sf(RAH, ISO14443A_SF_CMD_WUPA, &atqa);
+ if (status < 0)
+ DEBUGPCRF("error during transceive_sf WUPA");
+ else
+ DEBUGPCRF("received WUPA: %s", hexdump((char *)&atqa, sizeof(atqa)));
+ break;
+ case MODE_ANTICOL:
+ status = rfid_layer2_iso14443a.fn.open(&l2h);
+ if (status < 0)
+ DEBUGPCR("error during anticol");
+ else
+ DEBUGPCR("Anticol OK");
+ break;
+ case MODE_14443A:
+ {
+ char rx_buf[4];
+ int rx_len = sizeof(rx_buf);
+ rfid_layer2_iso14443a.fn.setopt(&l2h, RFID_OPT_14443A_SPEED_RX,
+ &speed_idx, sizeof(speed_idx));
+ rfid_layer2_iso14443a.fn.setopt(&l2h, RFID_OPT_14443A_SPEED_TX,
+ &speed_idx, sizeof(speed_idx));
+ rfid_layer2_iso14443a.fn.transceive(&l2h, RFID_14443A_FRAME_REGULAR,
+ &frame_14443a, sizeof(frame_14443a),
+ &rx_buf, &rx_len, 1, 0);
+ }
+ break;
+ }
+
+ if (status < 0)
+ led_switch(1, 0);
+ else
+ led_switch(1, 1);
+
+ led_toggle(2);
+
+}
diff --git a/firmware/src/pcd/rc632.c b/firmware/src/pcd/rc632.c
new file mode 100644
index 0000000..5d45955
--- /dev/null
+++ b/firmware/src/pcd/rc632.c
@@ -0,0 +1,624 @@
+/* Philips CL RC632 driver (via SPI) for OpenPCD firmware
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This is heavily based on the librfid RC632 driver. All primitive access
+ * functions such as rc632_{reg,fifo}_{read,write}() are API compatible to
+ * librfid in order to be able to leverage higher-level code from librfid
+ * to this OpenPCD firmware.
+ *
+ * */
+
+#include <string.h>
+#include <errno.h>
+#include <lib_AT91SAM7.h>
+#include <cl_rc632.h>
+#include <openpcd.h>
+#include "../openpcd.h"
+#include <os/fifo.h>
+#include <os/dbgu.h>
+#include <os/pcd_enumerate.h>
+#include <os/usb_handler.h>
+#include <os/req_ctx.h>
+#include "rc632.h"
+
+#define ALWAYS_RESPOND
+
+#define NOTHING do {} while(0)
+
+#if 0
+#define DEBUGPSPI DEBUGP
+#define DEBUGPSPIIRQ DEBUGP
+#else
+#define DEBUGPSPI(x, args ...) NOTHING
+#define DEBUGPSPIIRQ(x, args...) NOTHING
+#endif
+
+#if 0
+#define DEBUG632 DEBUGPCRF
+#else
+#define DEBUG632(x, args ...) NOTHING
+#endif
+
+
+/* SPI driver */
+
+#ifdef OLIMEX
+#define SPI_DEBUG_LOOPBACK
+#endif
+
+#define SPI_USES_DMA
+
+#define SPI_MAX_XFER_LEN 65
+
+static const AT91PS_SPI pSPI = AT91C_BASE_SPI;
+
+/* SPI irq handler */
+static void spi_irq(void)
+{
+ u_int32_t status = pSPI->SPI_SR;
+
+ DEBUGPSPIIRQ("spi_irq: 0x%08x ", status);
+
+ if (status & AT91C_SPI_OVRES)
+ DEBUGPSPIIRQ("Overrun ");
+ if (status & AT91C_SPI_MODF)
+ DEBUGPSPIIRQ("ModeFault ");
+ if (status & AT91C_SPI_ENDRX) {
+ pSPI->SPI_IDR = AT91C_SPI_ENDRX;
+ DEBUGPSPIIRQ("ENDRX ");
+ }
+ if (status & AT91C_SPI_ENDTX) {
+ pSPI->SPI_IDR = AT91C_SPI_ENDTX;
+ DEBUGPSPIIRQ("ENDTX ");
+ }
+
+ DEBUGPSPIIRQ("\r\n");
+
+ AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_SPI);
+}
+
+#ifdef SPI_USES_DMA
+static int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len,
+ u_int8_t *rx_data, u_int16_t *rx_len)
+{
+ //tx_len = *rx_len = 65;
+ DEBUGPSPI("DMA Xfer tx=%s\r\n", hexdump(tx_data, tx_len));
+ if (*rx_len < tx_len) {
+ DEBUGPCRF("rx_len=%u smaller tx_len=%u\n", *rx_len, tx_len);
+ return -1;
+ }
+ //AT91F_SPI_Disable(pSPI);
+
+ AT91F_SPI_ReceiveFrame(pSPI, rx_data, tx_len, NULL, 0);
+ AT91F_SPI_SendFrame(pSPI, tx_data, tx_len, NULL, 0);
+
+ AT91F_PDC_EnableRx(AT91C_BASE_PDC_SPI);
+ AT91F_PDC_EnableTx(AT91C_BASE_PDC_SPI);
+
+ pSPI->SPI_IER = AT91C_SPI_ENDTX|AT91C_SPI_ENDRX;
+ //pSPI->SPI_IDR = AT91C_SPI_ENDTX|AT91C_SPI_ENDRX;
+
+
+ while (! (pSPI->SPI_SR & AT91C_SPI_ENDRX)) ;
+
+ DEBUGPSPI("DMA Xfer finished rx=%s\r\n", hexdump(rx_data, tx_len));
+
+ *rx_len = tx_len;
+
+ return 0;
+}
+#else
+/* stupid polling transceiver routine */
+static int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len,
+ u_int8_t *rx_data, u_int16_t *rx_len)
+{
+ u_int16_t tx_cur = 0;
+ u_int16_t rx_len_max = 0;
+ u_int16_t rx_cnt = 0;
+
+ /* disable RC632 interrupt because it wants to do SPI transactions */
+ AT91F_AIC_DisableIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632);
+
+ DEBUGPSPI("spi_transceive: enter(tx_len=%u) ", tx_len);
+
+ if (rx_len) {
+ rx_len_max = *rx_len;
+ *rx_len = 0;
+ }
+
+ //AT91F_SPI_Enable(pSPI);
+ while (1) {
+ u_int32_t sr = pSPI->SPI_SR;
+ u_int8_t tmp;
+ if (sr & AT91C_SPI_RDRF) {
+ tmp = pSPI->SPI_RDR;
+ rx_cnt++;
+ if (rx_len && *rx_len < rx_len_max)
+ rx_data[(*rx_len)++] = tmp;
+ }
+ if (sr & AT91C_SPI_TDRE) {
+ if (tx_len > tx_cur)
+ pSPI->SPI_TDR = tx_data[tx_cur++];
+ }
+ if (tx_cur >= tx_len && rx_cnt >= tx_len)
+ break;
+ }
+ //AT91F_SPI_Disable(pSPI);
+ if (rx_data)
+ DEBUGPSPI("leave(%02x %02x)\r\n", rx_data[0], rx_data[1]);
+ else
+ DEBUGPSPI("leave()\r\n");
+
+ /* Re-enable RC632 interrupts */
+ AT91F_AIC_EnableIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632);
+
+ return 0;
+}
+#endif
+
+/* RC632 driver */
+
+/* static buffers used by RC632 access primitives below.
+ * Since we only have one */
+
+static u_int8_t spi_outbuf[SPI_MAX_XFER_LEN];
+static u_int8_t spi_inbuf[SPI_MAX_XFER_LEN];
+
+#define FIFO_ADDR (RC632_REG_FIFO_DATA << 1)
+
+struct rc632 {
+ u_int16_t flags;
+ struct fifo fifo;
+};
+#define RC632_F_FIFO_TX 0x0001
+static struct rc632 rc632;
+
+/* RC632 access primitives */
+
+int rc632_reg_write(struct rfid_asic_handle *hdl,
+ u_int8_t addr, u_int8_t data)
+{
+ u_int16_t rx_len = 2;
+
+ DEBUG632("[0x%02x] <= 0x%02x", addr, data);
+
+ addr = (addr << 1) & 0x7e;
+
+ spi_outbuf[0] = addr;
+ spi_outbuf[1] = data;
+
+ //spi_transceive(spi_outbuf, 2, NULL, NULL);
+ return spi_transceive(spi_outbuf, 2, spi_inbuf, &rx_len);
+}
+
+int rc632_fifo_write(struct rfid_asic_handle *hdl,
+ u_int8_t len, u_int8_t *data, u_int8_t flags)
+{
+ if (len > sizeof(spi_outbuf)-1)
+ len = sizeof(spi_outbuf)-1;
+
+ spi_outbuf[0] = FIFO_ADDR;
+ memcpy(&spi_outbuf[1], data, len);
+
+ DEBUG632("[FIFO] <= %s", hexdump(data, len));
+
+ return spi_transceive(spi_outbuf, len+1, NULL, NULL);
+}
+
+int rc632_reg_read(struct rfid_asic_handle *hdl,
+ u_int8_t addr, u_int8_t *val)
+{
+ u_int16_t rx_len = 2;
+
+ addr = (addr << 1) & 0x7e;
+
+ spi_outbuf[0] = addr | 0x80;
+ spi_outbuf[1] = 0x00;
+
+ spi_transceive(spi_outbuf, 2, spi_inbuf, &rx_len);
+ *val = spi_inbuf[1];
+
+ DEBUG632("[0x%02x] => 0x%02x", addr>>1, *val);
+
+ return 0;
+}
+
+int rc632_fifo_read(struct rfid_asic_handle *hdl,
+ u_int8_t max_len, u_int8_t *data)
+{
+ int ret;
+ u_int8_t fifo_length;
+ u_int8_t i;
+ u_int16_t rx_len;
+
+ ret = rc632_reg_read(hdl, RC632_REG_FIFO_LENGTH, &fifo_length);
+ if (ret < 0)
+ return ret;
+
+ rx_len = fifo_length+1;
+
+ if (max_len < fifo_length)
+ fifo_length = max_len;
+
+ for (i = 0; i < fifo_length; i++)
+ spi_outbuf[i] = FIFO_ADDR;
+
+ spi_outbuf[0] |= 0x80;
+ spi_outbuf[fifo_length] = 0x00;
+
+ spi_transceive(spi_outbuf, fifo_length+1, spi_inbuf, &rx_len);
+ memcpy(data, spi_inbuf+1, rx_len-1);
+
+ DEBUG632("[FIFO] => %s", hexdump(data, rx_len-1));
+
+ return 0;
+}
+
+int rc632_set_bits(struct rfid_asic_handle *hdl,
+ u_int8_t reg, u_int8_t bits)
+{
+ u_int8_t val;
+ int ret;
+
+ ret = rc632_reg_read(hdl, reg, &val);
+ if (ret < 0)
+ return ret;
+
+ val |= bits;
+
+ return rc632_reg_write(hdl, reg, val);
+}
+
+int rc632_clear_bits(struct rfid_asic_handle *hdl,
+ u_int8_t reg, u_int8_t bits)
+{
+ u_int8_t val;
+ int ret;
+
+ ret = rc632_reg_read(hdl, reg, &val);
+ if (ret < 0)
+ return ret;
+
+ val &= ~bits;
+
+ return rc632_reg_write(hdl, reg, val);
+}
+
+/* RC632 interrupt handling */
+
+static void rc632_irq(void)
+{
+ struct req_ctx *irq_rctx;
+ struct openpcd_hdr *irq_opcdh;
+ u_int8_t cause;
+
+ /* CL RC632 has interrupted us */
+ rc632_reg_read(RAH, RC632_REG_INTERRUPT_RQ, &cause);
+
+ /* ACK all interrupts */
+ //rc632_reg_write(RAH, RC632_REG_INTERRUPT_RQ, cause);
+ rc632_reg_write(RAH, RC632_REG_INTERRUPT_RQ, RC632_INT_TIMER);
+ DEBUGP("rc632_irq: ");
+
+ if (cause & RC632_INT_LOALERT) {
+ /* FIFO is getting low, refill from virtual FIFO */
+ DEBUGP("FIFO_low ");
+ #if 0
+ if (!fifo_available(&rc632.fifo))
+ return;
+ #endif
+ /* FIXME */
+ }
+ if (cause & RC632_INT_HIALERT) {
+ /* FIFO is getting full, empty into virtual FIFO */
+ DEBUGP("FIFO_high ");
+ /* FIXME */
+ }
+ /* All interrupts below can be reported directly to the host */
+ if (cause & RC632_INT_TIMER)
+ DEBUGP("Timer ");
+ if (cause & RC632_INT_IDLE)
+ DEBUGP("Idle ");
+ if (cause & RC632_INT_RX)
+ DEBUGP("RxComplete ");
+ if (cause & RC632_INT_TX)
+ DEBUGP("TxComplete ");
+
+
+ irq_rctx = req_ctx_find_get(RCTX_STATE_FREE,
+ RCTX_STATE_RC632IRQ_BUSY);
+ if (!irq_rctx) {
+ DEBUGPCRF("NO RCTX!\n");
+ /* disable rc632 interrupt until RCTX is free */
+ AT91F_AIC_DisableIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632);
+ return;
+ }
+
+ irq_opcdh = (struct openpcd_hdr *) &irq_rctx->tx.data[0];
+
+ /* initialize static part of openpcd_hdr for USB IRQ reporting */
+ irq_opcdh->cmd = OPENPCD_CMD_IRQ;
+ irq_opcdh->flags = 0x00;
+ irq_opcdh->reg = 0x07;
+ irq_opcdh->val = cause;
+
+ req_ctx_set_state(irq_rctx, RCTX_STATE_UDP_EP3_PENDING);
+ DEBUGPCR("");
+}
+
+void rc632_unthrottle(void)
+{
+ AT91F_AIC_EnableIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632);
+}
+
+void rc632_power(u_int8_t up)
+{
+ DEBUGPCRF("powering %s RC632", up ? "up" : "down");
+ if (up)
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA,
+ OPENPCD_PIO_RC632_RESET);
+ else
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA,
+ OPENPCD_PIO_RC632_RESET);
+}
+
+void rc632_reset(void)
+{
+ volatile int i;
+
+ rc632_power(0);
+ for (i = 0; i < 0xffff; i++)
+ {}
+ rc632_power(1);
+
+ /* wait for startup phase to finish */
+ while (1) {
+ u_int8_t val;
+ rc632_reg_read(RAH, RC632_REG_COMMAND, &val);
+ if (val == 0x00)
+ break;
+ }
+
+ /* turn off register paging */
+ rc632_reg_write(RAH, RC632_REG_PAGE0, 0x00);
+}
+
+static int rc632_usb_in(struct req_ctx *rctx)
+{
+ struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0];
+ struct openpcd_hdr *pih = (struct openpcd_hdr *) &rctx->tx.data[0];
+ u_int16_t len = rctx->rx.tot_len-sizeof(*poh);
+
+ switch (poh->cmd) {
+ case OPENPCD_CMD_READ_REG:
+ rc632_reg_read(RAH, poh->reg, &pih->val);
+ DEBUGP("READ REG(0x%02x)=0x%02x ", poh->reg, pih->val);
+ goto respond;
+ break;
+ case OPENPCD_CMD_READ_FIFO:
+ {
+ u_int16_t req_len = poh->val, remain_len = req_len, pih_len;
+ if (req_len > MAX_PAYLOAD_LEN) {
+ pih_len = MAX_PAYLOAD_LEN;
+ remain_len -= pih_len;
+ rc632_fifo_read(RAH, pih_len, pih->data);
+ rctx->tx.tot_len += pih_len;
+ DEBUGP("READ FIFO(len=%u)=%s ", req_len,
+ hexdump(pih->data, pih_len));
+ req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING);
+ udp_refill_ep(2, rctx);
+
+ /* get and initialize second rctx */
+ rctx = req_ctx_find_get(RCTX_STATE_FREE,
+ RCTX_STATE_MAIN_PROCESSING);
+ if (!rctx) {
+ DEBUGPCRF("FATAL_NO_RCTX!!!\n");
+ break;
+ }
+ poh = (struct openpcd_hdr *) &rctx->rx.data[0];
+ pih = (struct openpcd_hdr *) &rctx->tx.data[0];
+ memcpy(pih, poh, sizeof(*poh));
+ rctx->tx.tot_len = sizeof(*poh);
+
+ pih_len = remain_len;
+ rc632_fifo_read(RAH, pih->val, pih->data);
+ rctx->tx.tot_len += pih_len;
+ DEBUGP("READ FIFO(len=%u)=%s ", pih_len,
+ hexdump(pih->data, pih_len));
+ /* don't set state of second rctx, main function
+ * body will do this after switch statement */
+ } else {
+ pih->val = poh->val;
+ rc632_fifo_read(RAH, poh->val, pih->data);
+ rctx->tx.tot_len += pih_len;
+ DEBUGP("READ FIFO(len=%u)=%s ", poh->val,
+ hexdump(pih->data, poh->val));
+ }
+ goto respond;
+ break;
+ }
+ case OPENPCD_CMD_WRITE_REG:
+ DEBUGP("WRITE_REG(0x%02x, 0x%02x) ", poh->reg, poh->val);
+ rc632_reg_write(RAH, poh->reg, poh->val);
+ break;
+ case OPENPCD_CMD_WRITE_FIFO:
+ DEBUGP("WRITE FIFO(len=%u): %s ", len,
+ hexdump(poh->data, len));
+ rc632_fifo_write(RAH, len, poh->data, 0);
+ break;
+ case OPENPCD_CMD_READ_VFIFO:
+ DEBUGP("READ VFIFO ");
+ DEBUGP("NOT IMPLEMENTED YET ");
+ goto respond;
+ break;
+ case OPENPCD_CMD_WRITE_VFIFO:
+ DEBUGP("WRITE VFIFO ");
+ DEBUGP("NOT IMPLEMENTED YET ");
+ break;
+ case OPENPCD_CMD_REG_BITS_CLEAR:
+ DEBUGP("CLEAR BITS ");
+ pih->val = rc632_clear_bits(RAH, poh->reg, poh->val);
+ break;
+ case OPENPCD_CMD_REG_BITS_SET:
+ DEBUGP("SET BITS ");
+ pih->val = rc632_set_bits(RAH, poh->reg, poh->val);
+ break;
+ case OPENPCD_CMD_DUMP_REGS:
+ DEBUGP("DUMP REGS ");
+ DEBUGP("NOT IMPLEMENTED YET ");
+ goto respond;
+ break;
+ default:
+ DEBUGP("UNKNOWN ");
+ return -EINVAL;
+ }
+
+#ifdef ALWAYS_RESPOND
+ goto respond;
+#endif
+
+ req_ctx_put(rctx);
+ DEBUGPCR("");
+ return 0;
+
+respond:
+ req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING);
+ /* FIXME: we could try to send this immediately */
+ udp_refill_ep(2, rctx);
+ DEBUGPCR("");
+
+ return 1;
+}
+
+void rc632_init(void)
+{
+ //fifo_init(&rc632.fifo, 256, NULL, &rc632);
+
+ DEBUGPCRF("entering");
+
+ AT91F_SPI_CfgPMC();
+
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA,
+ AT91C_PA11_NPCS0|AT91C_PA12_MISO|
+ AT91C_PA13_MOSI |AT91C_PA14_SPCK, 0);
+
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SPI,
+ OPENPCD_IRQ_PRIO_SPI,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &spi_irq);
+ AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SPI);
+
+ AT91F_SPI_EnableIt(pSPI, AT91C_SPI_MODF|AT91C_SPI_OVRES);
+#ifdef SPI_USES_DMA
+ AT91F_SPI_EnableIt(pSPI, AT91C_SPI_ENDRX|AT91C_SPI_ENDTX);
+#endif
+
+#ifdef SPI_DEBUG_LOOPBACK
+ AT91F_SPI_CfgMode(pSPI, AT91C_SPI_MSTR|AT91C_SPI_PS_FIXED|
+ AT91C_SPI_MODFDIS|AT91C_SPI_LLB);
+#else
+ AT91F_SPI_CfgMode(pSPI, AT91C_SPI_MSTR|AT91C_SPI_PS_FIXED|
+ AT91C_SPI_MODFDIS);
+#endif
+ /* CPOL = 0, NCPHA = 1, CSAAT = 0, BITS = 0000, SCBR = 10 (4.8MHz),
+ * DLYBS = 0, DLYBCT = 0 */
+#ifdef SPI_USES_DMA
+ AT91F_SPI_CfgCs(pSPI, 0, AT91C_SPI_BITS_8|AT91C_SPI_NCPHA|(10<<8));
+#else
+ /* 320 kHz in case of I/O based SPI */
+ AT91F_SPI_CfgCs(pSPI, 0, AT91C_SPI_BITS_8|AT91C_SPI_NCPHA|(0x7f<<8));
+#endif
+ AT91F_SPI_Enable(pSPI);
+
+ /* Register rc632_irq */
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632,
+ OPENPCD_IRQ_PRIO_RC632,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &rc632_irq);
+ AT91F_AIC_EnableIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632);
+
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_RC632_RESET);
+
+ rc632_reset();
+
+ /* configure IRQ pin */
+ rc632_reg_write(RAH, RC632_REG_IRQ_PIN_CONFIG,
+ RC632_IRQCFG_CMOS|RC632_IRQCFG_INV);
+ /* enable interrupts */
+ rc632_reg_write(RAH, RC632_REG_INTERRUPT_EN, RC632_INT_TIMER);
+
+ /* configure AUX to test signal four */
+ rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, 0x04);
+
+ usb_hdlr_register(&rc632_usb_in, OPENPCD_CMD_CLS_RC632);
+};
+
+#if 0
+void rc632_exit(void)
+{
+ usb_hdlr_unregister(OPENPCD_CMD_CLS_RC632);
+ AT91F_AIC_DisableIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632);
+ AT91F_AIC_DisableIt(AT91C_BASE_AIC, AT91C_ID_SPI);
+ AT91F_SPI_Disable(pSPI);
+}
+#endif
+
+#ifdef DEBUG
+static int rc632_reg_write_verify(struct rfid_asic_handle *hdl,
+ u_int8_t reg, u_int8_t val)
+{
+ u_int8_t tmp;
+
+ rc632_reg_write(hdl, reg, val);
+ rc632_reg_read(hdl, reg, &tmp);
+
+ DEBUGPCRF("reg=0x%02x, write=0x%02x, read=0x%02x ", reg, val, tmp);
+
+ return (val == tmp);
+}
+
+int rc632_dump(void)
+{
+ u_int8_t i;
+ u_int16_t rx_len = sizeof(spi_inbuf);
+
+ for (i = 0; i <= 0x3f; i++) {
+ u_int8_t reg = i;
+ if (reg == RC632_REG_FIFO_DATA)
+ reg = 0x3e;
+
+ spi_outbuf[i] = reg << 1;
+ spi_inbuf[i] = 0x00;
+ }
+
+ /* MSB of first byte of read spi transfer is high */
+ spi_outbuf[0] |= 0x80;
+
+ /* last byte of read spi transfer is 0x00 */
+ spi_outbuf[0x40] = 0x00;
+ spi_inbuf[0x40] = 0x00;
+
+ spi_transceive(spi_outbuf, 0x41, spi_inbuf, &rx_len);
+
+ for (i = 0; i < 0x3f; i++) {
+ if (i == RC632_REG_FIFO_DATA)
+ DEBUGPCR("REG 0x02 = NOT READ");
+ else
+ DEBUGPCR("REG 0x%02x = 0x%02x", i, spi_inbuf[i+1]);
+ }
+
+ return 0;
+}
+
+int rc632_test(struct rfid_asic_handle *hdl)
+{
+ if (rc632_reg_write_verify(hdl, RC632_REG_RX_WAIT, 0x55) != 1)
+ return -1;
+
+ if (rc632_reg_write_verify(hdl, RC632_REG_RX_WAIT, 0xAA) != 1)
+ return -1;
+
+ return 0;
+}
+#else /* DEBUG */
+int rc632_test(struct rfid_asic_handle *hdl) {}
+int rc632_dump(void) {}
+#endif /* DEBUG */
diff --git a/firmware/src/pcd/rc632.h b/firmware/src/pcd/rc632.h
new file mode 100644
index 0000000..1a4dc22
--- /dev/null
+++ b/firmware/src/pcd/rc632.h
@@ -0,0 +1,31 @@
+#ifndef _RC623_API_H
+#define _RC632_API_H
+
+#include <sys/types.h>
+#include <cl_rc632.h>
+#include <librfid/rfid.h>
+
+extern int rc632_reg_write(struct rfid_asic_handle *hdl,
+ u_int8_t addr, u_int8_t data);
+extern int rc632_fifo_write(struct rfid_asic_handle *hdl,
+ u_int8_t len, u_int8_t *data, u_int8_t flags);
+extern int rc632_reg_read(struct rfid_asic_handle *hdl,
+ u_int8_t addr, u_int8_t *val);
+extern int rc632_fifo_read(struct rfid_asic_handle *hdl,
+ u_int8_t max_len, u_int8_t *data);
+extern int rc632_clear_bits(struct rfid_asic_handle *hdl,
+ u_int8_t reg, u_int8_t bits);
+extern int rc632_set_bits(struct rfid_asic_handle *hdl,
+ u_int8_t reg, u_int8_t bits);
+
+extern void rc632_init(void);
+extern void rc632_exit(void);
+
+extern void rc632_unthrottle(void);
+
+#ifdef DEBUG
+extern int rc632_test(struct rfid_asic_handle *hdl);
+extern int rc632_dump(void);
+#endif
+
+#endif
diff --git a/firmware/src/pcd/rc632_highlevel.c b/firmware/src/pcd/rc632_highlevel.c
new file mode 100644
index 0000000..b1186ab
--- /dev/null
+++ b/firmware/src/pcd/rc632_highlevel.c
@@ -0,0 +1,1473 @@
+/* Generic Philips CL RC632 Routines
+ *
+ * (C) Harald Welte <laforge@gnumonks.org>
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+#include <cl_rc632.h>
+#include "rc632.h"
+#include <os/dbgu.h>
+#include <librfid/rfid_layer2_iso14443a.h>
+#include <librfid/rfid_protocol_mifare_classic.h>
+
+/* initially we use the same values as cm5121 */
+#define OPENPCD_CW_CONDUCTANCE 0x3f
+#define OPENPCD_MOD_CONDUCTANCE 0x3f
+#define OPENPCD_14443A_BITPHASE 0xa9
+#define OPENPCD_14443A_THRESHOLD 0xff
+#define OPENPCD_14443B_BITPHASE 0xad
+#define OPENPCD_14443B_THRESHOLD 0xff
+
+#define RC632_TMO_AUTH1 14000
+
+#define RC632_TIMEOUT_FUZZ_FACTOR 10
+
+#define USE_IRQ
+
+#define ENTER() DEBUGPCRF("entering")
+struct rfid_asic rc632;
+
+static int
+rc632_set_bit_mask(struct rfid_asic_handle *handle,
+ u_int8_t reg, u_int8_t mask, u_int8_t val)
+{
+ int ret;
+ u_int8_t tmp;
+
+ ret = rc632_reg_read(handle, reg, &tmp);
+ if (ret < 0)
+ return ret;
+
+ /* if bits are already like we want them, abort */
+ if ((tmp & mask) == val)
+ return 0;
+
+ return rc632_reg_write(handle, reg, (tmp & ~mask)|(val & mask));
+}
+
+int
+rc632_turn_on_rf(struct rfid_asic_handle *handle)
+{
+ ENTER();
+ return rc632_set_bits(handle, RC632_REG_TX_CONTROL, 0x03);
+}
+
+int
+rc632_turn_off_rf(struct rfid_asic_handle *handle)
+{
+ ENTER();
+ return rc632_clear_bits(handle, RC632_REG_TX_CONTROL, 0x03);
+}
+
+static int
+rc632_power_up(struct rfid_asic_handle *handle)
+{
+ ENTER();
+ return rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_POWERDOWN);
+}
+
+static int
+rc632_power_down(struct rfid_asic_handle *handle)
+{
+ return rc632_set_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_POWERDOWN);
+}
+
+/* calculate best 8bit prescaler and divisor for given usec timeout */
+static int best_prescaler(u_int64_t timeout, u_int8_t *prescaler,
+ u_int8_t *divisor)
+{
+ u_int8_t best_presc, best_divisor, i;
+ int64_t smallest_diff;
+
+ smallest_diff = 0x7fffffffffffffff;
+ best_presc = 0;
+
+ for (i = 0; i < 21; i++) {
+ u_int64_t clk, tmp_div, res;
+ int64_t diff;
+ clk = 13560000 / (1 << i);
+ tmp_div = (clk * timeout) / 1000000;
+ tmp_div++;
+
+ if (tmp_div > 0xff)
+ continue;
+
+ res = 1000000 / (clk / tmp_div);
+ diff = res - timeout;
+
+ if (diff < 0)
+ continue;
+
+ if (diff < smallest_diff) {
+ best_presc = i;
+ best_divisor = tmp_div;
+ smallest_diff = diff;
+ }
+ }
+
+ *prescaler = best_presc;
+ *divisor = best_divisor;
+
+ DEBUGPCRF("timeout %u usec, prescaler = %u, divisor = %u", timeout, best_presc, best_divisor);
+
+ return 0;
+}
+
+static int
+rc632_timer_set(struct rfid_asic_handle *handle,
+ u_int64_t timeout)
+{
+ int ret;
+ u_int8_t prescaler, divisor;
+
+ ret = best_prescaler(timeout*RC632_TIMEOUT_FUZZ_FACTOR,
+ &prescaler, &divisor);
+
+ ret = rc632_reg_write(handle, RC632_REG_TIMER_CLOCK,
+ prescaler & 0x1f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_TIMER_CONTROL,
+ RC632_TMR_START_TX_END|RC632_TMR_STOP_RX_BEGIN);
+
+ /* clear timer irq bit */
+ ret |= rc632_set_bits(handle, RC632_REG_INTERRUPT_RQ, RC632_INT_TIMER);
+
+#ifdef USE_IRQ_
+ /* enable interrupt for expired timer */
+ ret |= rc632_reg_write(handle, RC632_REG_INTERRUPT_EN,
+ RC632_INT_TIMER|RC632_INT_SET);
+#endif
+
+ ret |= rc632_reg_write(handle, RC632_REG_TIMER_RELOAD, divisor);
+
+ return ret;
+}
+
+/* Wait until RC632 is idle or TIMER IRQ has happened */
+static int rc632_wait_idle_timer(struct rfid_asic_handle *handle)
+{
+ int ret;
+ u_int8_t irq, cmd;
+
+ while (1) {
+ ret = rc632_reg_read(handle, RC632_REG_INTERRUPT_RQ, &irq);
+ if (ret < 0)
+ return ret;
+
+ /* FIXME: currently we're lazy: If we actually received
+ * something even after the timer expired, we accept it */
+ if (irq & RC632_INT_TIMER && !(irq & RC632_INT_RX)) {
+ u_int8_t foo;
+ rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &foo);
+ DEBUGPCRF("TIMER && !INT_RX, PRIM_STATUS=0x%02x", foo);
+ if (foo & 0x04) {
+ rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &foo);
+ DEBUGPCRF("ERROR_FLAG=0x%02x, returning timeout", foo);
+ }
+
+ return -ETIMEDOUT;
+ }
+
+ ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd);
+ if (ret < 0)
+ return ret;
+
+ if (cmd == 0 || irq & RC632_INT_RX)
+ return 0;
+
+ /* poll every millisecond */
+ /* FIXME usleep(1000);*/
+ }
+}
+
+/* Stupid RC632 implementations don't evaluate interrupts but poll the
+ * command register for "status idle" */
+static int
+rc632_wait_idle(struct rfid_asic_handle *handle, u_int64_t timeout)
+{
+ u_int8_t cmd = 0xff;
+ int ret, cycles = 0;
+#define USLEEP_PER_CYCLE 128
+
+ while (cmd != 0) {
+ ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd);
+ if (ret < 0)
+ return ret;
+
+ if (cmd == 0) {
+ /* FIXME: read second time ?? */
+ return 0;
+ }
+
+ {
+ u_int8_t foo;
+ rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &foo);
+ if (foo & 0x04)
+ rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &foo);
+ }
+
+ /* Abort after some timeout */
+ if (cycles > timeout*RC632_TIMEOUT_FUZZ_FACTOR/USLEEP_PER_CYCLE) {
+ return -ETIMEDOUT;
+ }
+
+ cycles++;
+ usleep(USLEEP_PER_CYCLE);
+ }
+
+ return 0;
+}
+
+static int
+rc632_transmit(struct rfid_asic_handle *handle,
+ const u_int8_t *buf,
+ u_int8_t len,
+ u_int64_t timeout)
+{
+ int ret, cur_len;
+ const u_int8_t *cur_buf = buf;
+
+ if (len > 64)
+ cur_len = 64;
+ else
+ cur_len = len;
+
+ do {
+ ret = rc632_fifo_write(handle, cur_len, cur_buf, 0x03);
+ if (ret < 0)
+ return ret;
+
+ if (cur_buf == buf) {
+ /* only start transmit first time */
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND,
+ RC632_CMD_TRANSMIT);
+ if (ret < 0)
+ return ret;
+ }
+
+ cur_buf += cur_len;
+ if (cur_buf < buf + len) {
+ cur_len = buf - cur_buf;
+ if (cur_len > 64)
+ cur_len = 64;
+ } else
+ cur_len = 0;
+
+ } while (cur_len);
+
+ return rc632_wait_idle(handle, timeout);
+}
+
+static int
+tcl_toggle_pcb(struct rfid_asic_handle *handle)
+{
+ // FIXME: toggle something between 0x0a and 0x0b
+ return 0;
+}
+
+static int
+rc632_transceive(struct rfid_asic_handle *handle,
+ const u_int8_t *tx_buf,
+ u_int8_t tx_len,
+ u_int8_t *rx_buf,
+ u_int8_t *rx_len,
+ u_int64_t timer,
+ unsigned int toggle)
+{
+ int ret, cur_tx_len;
+ const u_int8_t *cur_tx_buf = tx_buf;
+
+ DEBUGPCRF("tx_len=%u, rx_len=%u, timer=%llu", tx_len, *rx_len, timer);
+
+ if (tx_len > 64)
+ cur_tx_len = 64;
+ else
+ cur_tx_len = tx_len;
+
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND, 0x00);
+ /* clear all interrupts */
+ ret = rc632_reg_write(handle, RC632_REG_INTERRUPT_RQ, 0x7f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_timer_set(handle, timer);
+ if (ret < 0)
+ return ret;
+
+ do {
+ ret = rc632_fifo_write(handle, cur_tx_len, cur_tx_buf, 0x03);
+ if (ret < 0)
+ return ret;
+
+ if (cur_tx_buf == tx_buf) {
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND,
+ RC632_CMD_TRANSCEIVE);
+ if (ret < 0)
+ return ret;
+ }
+
+ cur_tx_buf += cur_tx_len;
+ if (cur_tx_buf < tx_buf + tx_len) {
+ u_int8_t fifo_fill;
+ ret = rc632_reg_read(handle, RC632_REG_FIFO_LENGTH,
+ &fifo_fill);
+ if (ret < 0)
+ return ret;
+
+ cur_tx_len = 64 - fifo_fill;
+ DEBUGPCRF("refilling tx fifo with %u bytes", cur_tx_len);
+ } else
+ cur_tx_len = 0;
+
+ } while (cur_tx_len);
+
+ if (toggle == 1)
+ tcl_toggle_pcb(handle);
+
+ ret = rc632_wait_idle_timer(handle);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_read(handle, RC632_REG_FIFO_LENGTH, rx_len);
+ if (ret < 0)
+ return ret;
+
+ DEBUGPCRF("rx_len = %u\n", *rx_len);
+
+ if (*rx_len == 0) {
+ u_int8_t tmp, tmp2;
+
+ rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &tmp);
+ rc632_reg_read(handle, RC632_REG_CHANNEL_REDUNDANCY, &tmp2);
+
+ DEBUGPCRF("rx_len == 0, error_flag=0x%02x, channel_red=0x%02x",
+ tmp, tmp2);
+
+ return -1;
+ }
+
+ return rc632_fifo_read(handle, *rx_len, rx_buf);
+}
+
+int
+rc632_read_eeprom(struct rfid_asic_handle *handle, u_int16_t addr, u_int8_t len,
+ u_int8_t *recvbuf)
+{
+ u_int8_t sndbuf[3];
+ u_int8_t err;
+ int ret;
+
+ sndbuf[0] = (addr & 0xff);
+ sndbuf[1] = addr >> 8;
+ sndbuf[2] = len;
+
+ ret = rc632_fifo_write(handle, 3, sndbuf, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_READ_E2);
+ if (ret < 0)
+ return ret;
+
+ /* usleep(20000); */
+
+ ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &err);
+ if (err & RC632_ERR_FLAG_ACCESS_ERR)
+ return -EPERM;
+
+ ret = rc632_reg_read(handle, RC632_REG_FIFO_DATA, &err);
+ if (err < len)
+ len = err;
+
+ ret = rc632_fifo_read(handle, len, recvbuf);
+ if (ret < 0)
+ return ret;
+
+ return len;
+}
+
+static int
+rc632_calc_crc16_from(struct rfid_asic_handle *handle)
+{
+ u_int8_t sndbuf[2] = { 0x01, 0x02 };
+ u_int8_t crc_lsb = 0x00 , crc_msb = 0x00;
+ int ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0x12);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0xe0);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_fifo_write(handle, sizeof(sndbuf), sndbuf, 3);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_CALC_CRC);
+ if (ret < 0)
+ return ret;
+
+ usleep(10000); // FIXME: no checking for cmd completion?
+
+ ret = rc632_reg_read(handle, RC632_REG_CRC_RESULT_LSB, &crc_lsb);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_read(handle, RC632_REG_CRC_RESULT_MSB, &crc_msb);
+ if (ret < 0)
+ return ret;
+
+ // FIXME: what to do with crc result?
+ return ret;
+}
+
+
+int
+rc632_register_dump(struct rfid_asic_handle *handle, u_int8_t *buf)
+{
+ int ret;
+ u_int8_t i;
+
+ for (i = 0; i <= 0x3f; i++) {
+ ret = rc632_reg_read(handle, i, &buf[i]);
+ // do we want error checks?
+ }
+ return 0;
+}
+
+
+#if 0
+static int
+rc632_init(struct rfid_asic_handle *ah)
+{
+ int ret;
+
+ /* switch off rf (make sure PICCs are reset at init time) */
+ ret = rc632_power_down(ah);
+ if (ret < 0)
+ return ret;
+
+ usleep(10000);
+
+ /* switch on rf */
+ ret = rc632_power_up(ah);
+ if (ret < 0)
+ return ret;
+
+ /* disable register paging */
+ ret = rc632_reg_write(ah, 0x00, 0x00);
+ if (ret < 0)
+ return ret;
+
+ /* set some sane default values */
+ ret = rc632_reg_write(ah, 0x11, 0x5b);
+ if (ret < 0)
+ return ret;
+
+ /* switch on rf */
+ ret = rc632_turn_on_rf(ah);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int
+rc632_fini(struct rfid_asic_handle *ah)
+{
+ int ret;
+
+ /* switch off rf */
+ ret = rc632_turn_off_rf(ah);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_power_down(ah);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+#endif
+
+
+/*
+ * Philips CL RC632 primitives for ISO 14443-A compliant PICC's
+ *
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ */
+
+int
+rc632_iso14443a_init(struct rfid_asic_handle *handle)
+{
+ int ret;
+
+ // FIXME: some fifo work (drain fifo?)
+
+ /* flush fifo (our way) */
+ ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01);
+
+ ret = rc632_reg_write(handle, RC632_REG_TX_CONTROL,
+ (RC632_TXCTRL_TX1_RF_EN |
+ RC632_TXCTRL_TX2_RF_EN |
+ RC632_TXCTRL_TX2_INV |
+ RC632_TXCTRL_FORCE_100_ASK |
+ RC632_TXCTRL_MOD_SRC_INT));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CW_CONDUCTANCE,
+ OPENPCD_CW_CONDUCTANCE);
+ if (ret < 0)
+ return ret;
+
+ /* Since FORCE_100_ASK is set (cf mc073930.pdf), this line may be left out? */
+ ret = rc632_reg_write(handle, RC632_REG_MOD_CONDUCTANCE,
+ OPENPCD_MOD_CONDUCTANCE);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CODER_CONTROL,
+ (RC632_CDRCTRL_TXCD_14443A |
+ RC632_CDRCTRL_RATE_106K));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, 0x13);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH_SOF, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_TYPE_B_FRAMING, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL1,
+ (RC632_RXCTRL1_GAIN_35DB |
+ RC632_RXCTRL1_ISO14443 |
+ RC632_RXCTRL1_SUBCP_8));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_DECODER_CONTROL,
+ (RC632_DECCTRL_MANCHESTER |
+ RC632_DECCTRL_RXFR_14443A));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_BIT_PHASE,
+ OPENPCD_14443A_BITPHASE);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD,
+ OPENPCD_14443A_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_BPSK_DEM_CONTROL, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL2,
+ (RC632_RXCTRL2_DECSRC_INT |
+ RC632_RXCTRL2_CLK_Q));
+ if (ret < 0)
+ return ret;
+
+ /* Omnikey proprietary driver has 0x03, but 0x06 is the default reset value ?!? */
+ ret = rc632_reg_write(handle, RC632_REG_RX_WAIT, 0x06);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0x63);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0x63);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int
+rc632_iso14443a_fini(struct iso14443a_handle *handle_14443)
+{
+
+#if 0
+ ret = rc632_turn_off_rf(handle);
+ if (ret < 0)
+ return ret;
+#endif
+
+
+ return 0;
+}
+
+
+/* issue a 14443-3 A PCD -> PICC command in a short frame, such as REQA, WUPA */
+int
+rc632_iso14443a_transceive_sf(struct rfid_asic_handle *handle,
+ u_int8_t cmd,
+ struct iso14443a_atqa *atqa)
+{
+ int ret;
+ u_int8_t tx_buf[1];
+ u_int8_t rx_len = 2;
+
+ DEBUGPCRF("");
+ memset(atqa, 0, sizeof(atqa));
+
+ tx_buf[0] = cmd;
+
+ /* transfer only 7 bits of last byte in frame */
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x07);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ if (ret < 0)
+ return ret;
+
+#if 0
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+#else
+ ret = rc632_clear_bits(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE);
+
+#endif
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transceive(handle, tx_buf, sizeof(tx_buf),
+ (u_int8_t *)atqa, &rx_len,
+ ISO14443A_FDT_ANTICOL_LAST1, 0);
+ if (ret < 0) {
+ DEBUGPCRF("error during rc632_transceive()");
+ return ret;
+ }
+
+ /* switch back to normal 8bit last byte */
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x00);
+ if (ret < 0)
+ return ret;
+
+ if (rx_len != 2) {
+ DEBUGPCRF("rx_len(%d) != 2", rx_len);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* transceive regular frame */
+int
+rc632_iso14443ab_transceive(struct rfid_asic_handle *handle,
+ unsigned int frametype,
+ const u_int8_t *tx_buf, unsigned int tx_len,
+ u_int8_t *rx_buf, unsigned int *rx_len,
+ u_int64_t timeout, unsigned int flags)
+{
+ int ret;
+ u_int8_t rxl = *rx_len & 0xff;
+ u_int8_t channel_red;
+
+ DEBUGPCRF("tx_len=%u, rx_len=%u", tx_len, *rx_len);
+
+ memset(rx_buf, 0, *rx_len);
+
+ switch (frametype) {
+ case RFID_14443A_FRAME_REGULAR:
+ case RFID_MIFARE_FRAME:
+ channel_red = RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE
+ |RC632_CR_PARITY_ENABLE|RC632_CR_PARITY_ODD;
+ break;
+ case RFID_14443B_FRAME_REGULAR:
+ channel_red = RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE
+ |RC632_CR_CRC3309;
+ break;
+#if 0
+ case RFID_MIFARE_FRAME:
+ channel_red = RC632_CR_PARITY_ENABLE|RC632_CR_PARITY_ODD;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ break;
+ }
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ channel_red);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transceive(handle, tx_buf, tx_len, rx_buf, &rxl, timeout, 0);
+ *rx_len = rxl;
+ if (ret < 0)
+ return ret;
+
+
+ return 0;
+}
+
+/* transceive anti collission bitframe */
+int
+rc632_iso14443a_transceive_acf(struct rfid_asic_handle *handle,
+ struct iso14443a_anticol_cmd *acf,
+ unsigned int *bit_of_col)
+{
+ int ret;
+ u_int8_t rx_buf[64];
+ u_int8_t rx_len = sizeof(rx_buf);
+ u_int8_t rx_align = 0, tx_last_bits, tx_bytes;
+ u_int8_t boc;
+ u_int8_t error_flag;
+ *bit_of_col = ISO14443A_BITOFCOL_NONE;
+ memset(rx_buf, 0, sizeof(rx_buf));
+
+ /* disable mifare cryto */
+ ret = rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ if (ret < 0)
+ return ret;
+
+ /* disable CRC summing */
+#if 0
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+#else
+ ret = rc632_clear_bits(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ RC632_CR_TX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE);
+#endif
+ if (ret < 0)
+ return ret;
+
+ tx_last_bits = acf->nvb & 0x0f; /* lower nibble indicates bits */
+ tx_bytes = acf->nvb >> 4;
+ if (tx_last_bits) {
+ tx_bytes++;
+ rx_align = (tx_last_bits+1) % 8;/* rx frame complements tx */
+ }
+
+ //rx_align = 8 - tx_last_bits;/* rx frame complements tx */
+
+ /* set RxAlign and TxLastBits*/
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING,
+ (rx_align << 4) | (tx_last_bits));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transceive(handle, (u_int8_t *)acf, tx_bytes,
+ rx_buf, &rx_len, 0x32, 0);
+ if (ret < 0)
+ return ret;
+
+ /* bitwise-OR the two halves of the split byte */
+ acf->uid_bits[tx_bytes-2] = (
+ (acf->uid_bits[tx_bytes-2] & (0xff >> (8-tx_last_bits)))
+ | rx_buf[0]);
+ /* copy the rest */
+ memcpy(&acf->uid_bits[tx_bytes+1-2], &rx_buf[1], rx_len-1);
+
+ /* determine whether there was a collission */
+ ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &error_flag);
+ if (ret < 0)
+ return ret;
+
+ if (error_flag & RC632_ERR_FLAG_COL_ERR) {
+ /* retrieve bit of collission */
+ ret = rc632_reg_read(handle, RC632_REG_COLL_POS, &boc);
+ if (ret < 0)
+ return ret;
+
+ /* bit of collission relative to start of part 1 of
+ * anticollision frame (!) */
+ *bit_of_col = 2*8 + boc;
+ }
+
+ return 0;
+}
+
+enum rc632_rate {
+ RC632_RATE_106 = 0x00,
+ RC632_RATE_212 = 0x01,
+ RC632_RATE_424 = 0x02,
+ RC632_RATE_848 = 0x03,
+};
+
+struct rx_config {
+ u_int8_t subc_pulses;
+ u_int8_t rx_coding;
+ u_int8_t rx_threshold;
+ u_int8_t bpsk_dem_ctrl;
+};
+
+struct tx_config {
+ u_int8_t rate;
+ u_int8_t mod_width;
+};
+
+static const struct rx_config rx_configs[] = {
+ {
+ .subc_pulses = RC632_RXCTRL1_SUBCP_8,
+ .rx_coding = RC632_DECCTRL_MANCHESTER,
+ .rx_threshold = 0x88,
+ .bpsk_dem_ctrl = 0x00,
+ },
+ {
+ .subc_pulses = RC632_RXCTRL1_SUBCP_4,
+ .rx_coding = RC632_DECCTRL_BPSK,
+ .rx_threshold = 0x50,
+ .bpsk_dem_ctrl = 0x0c,
+ },
+ {
+ .subc_pulses = RC632_RXCTRL1_SUBCP_2,
+ .rx_coding = RC632_DECCTRL_BPSK,
+ .rx_threshold = 0x50,
+ .bpsk_dem_ctrl = 0x0c,
+ },
+ {
+ .subc_pulses = RC632_RXCTRL1_SUBCP_1,
+ .rx_coding = RC632_DECCTRL_BPSK,
+ .rx_threshold = 0x50,
+ .bpsk_dem_ctrl = 0x0c,
+ },
+};
+
+static const struct tx_config tx_configs[] = {
+ {
+ .rate = RC632_CDRCTRL_RATE_106K,
+ .mod_width = 0x13,
+ },
+ {
+ .rate = RC632_CDRCTRL_RATE_212K,
+ .mod_width = 0x07,
+ },
+ {
+ .rate = RC632_CDRCTRL_RATE_424K,
+ .mod_width = 0x03,
+ },
+ {
+ .rate = RC632_CDRCTRL_RATE_848K,
+ .mod_width = 0x01,
+ },
+};
+
+int rc632_iso14443a_set_speed(struct rfid_asic_handle *handle,
+ unsigned int tx,
+ u_int8_t rate)
+{
+ int rc;
+ u_int8_t reg;
+
+
+ if (!tx) {
+ /* Rx */
+ if (rate > ARRAY_SIZE(rx_configs))
+ return -EINVAL;
+
+ rc = rc632_set_bit_mask(handle, RC632_REG_RX_CONTROL1,
+ RC632_RXCTRL1_SUBCP_MASK,
+ rx_configs[rate].subc_pulses);
+ if (rc < 0)
+ return rc;
+
+ rc = rc632_set_bit_mask(handle, RC632_REG_DECODER_CONTROL,
+ RC632_DECCTRL_BPSK,
+ rx_configs[rate].rx_coding);
+ if (rc < 0)
+ return rc;
+
+ rc = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD,
+ rx_configs[rate].rx_threshold);
+ if (rc < 0)
+ return rc;
+
+ if (rx_configs[rate].rx_coding == RC632_DECCTRL_BPSK) {
+ rc = rc632_reg_write(handle,
+ RC632_REG_BPSK_DEM_CONTROL,
+ rx_configs[rate].bpsk_dem_ctrl);
+ if (rc < 0)
+ return rc;
+ }
+ } else {
+ /* Tx */
+ if (rate > ARRAY_SIZE(tx_configs))
+ return -EINVAL;
+
+ rc = rc632_set_bit_mask(handle, RC632_REG_CODER_CONTROL,
+ RC632_CDRCTRL_RATE_MASK,
+ tx_configs[rate].rate);
+ if (rc < 0)
+ return rc;
+
+ rc = rc632_reg_write(handle, RC632_REG_MOD_WIDTH,
+ tx_configs[rate].mod_width);
+ if (rc < 0)
+ return rc;
+ }
+
+ return 0;
+}
+
+static int rc632_iso14443b_init(struct rfid_asic_handle *handle)
+{
+ int ret;
+
+ // FIXME: some FIFO work
+
+ /* flush fifo (our way) */
+ ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_TX_CONTROL,
+ (RC632_TXCTRL_TX1_RF_EN |
+ RC632_TXCTRL_TX2_RF_EN |
+ RC632_TXCTRL_TX2_INV |
+ RC632_TXCTRL_MOD_SRC_INT));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CW_CONDUCTANCE, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_CONDUCTANCE, 0x04);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CODER_CONTROL,
+ (RC632_CDRCTRL_TXCD_NRZ |
+ RC632_CDRCTRL_RATE_14443B));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, 0x13);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH_SOF, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_TYPE_B_FRAMING,
+ (RC632_TBFRAMING_SOF_11L_3H |
+ (6 << RC632_TBFRAMING_SPACE_SHIFT) |
+ RC632_TBFRAMING_EOF_11));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL1,
+ (RC632_RXCTRL1_GAIN_35DB |
+ RC632_RXCTRL1_ISO14443 |
+ RC632_RXCTRL1_SUBCP_8));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_DECODER_CONTROL,
+ (RC632_DECCTRL_BPSK |
+ RC632_DECCTRL_RXFR_14443B));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_BIT_PHASE,
+ OPENPCD_14443B_BITPHASE);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD,
+ OPENPCD_14443B_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_BPSK_DEM_CONTROL,
+ ((0x2 & RC632_BPSKD_TAUB_MASK)<<RC632_BPSKD_TAUB_SHIFT |
+ (0x3 & RC632_BPSKD_TAUD_MASK)<<RC632_BPSKD_TAUD_SHIFT |
+ RC632_BPSKD_FILTER_AMP_DETECT |
+ RC632_BPSKD_NO_RX_EOF |
+ RC632_BPSKD_NO_RX_EGT));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL2,
+ (RC632_RXCTRL2_AUTO_PD |
+ RC632_RXCTRL2_DECSRC_INT));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_WAIT, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_TX_CRC_ENABLE |
+ RC632_CR_RX_CRC_ENABLE |
+ RC632_CR_CRC3309));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0xff);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0xff);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int
+rc632_iso15693_init(struct rfid_asic_handle *h)
+{
+ int ret;
+
+ ret = rc632_reg_write(h, RC632_REG_TX_CONTROL,
+ (RC632_TXCTRL_MOD_SRC_INT |
+ RC632_TXCTRL_TX2_INV |
+ RC632_TXCTRL_TX2_RF_EN |
+ RC632_TXCTRL_TX1_RF_EN));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CW_CONDUCTANCE, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_MOD_CONDUCTANCE, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CODER_CONTROL,
+ (RC632_CDRCTRL_RATE_15693 |
+ 0x03)); /* FIXME */
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH_SOF, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_TYPE_B_FRAMING, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_RX_CONTROL1,
+ (RC632_RXCTRL1_SUBCP_16 |
+ RC632_RXCTRL1_ISO15693 |
+ RC632_RXCTRL1_GAIN_35DB));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_DECODER_CONTROL,
+ (RC632_DECCTRL_RXFR_15693 |
+ RC632_DECCTRL_RX_INVERT));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_BIT_PHASE, 0xe0);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_RX_THRESHOLD, 0xff);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_BPSK_DEM_CONTROL, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_RX_CONTROL2,
+ (RC632_RXCTRL2_AUTO_PD |
+ RC632_RXCTRL2_DECSRC_INT));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_CRC3309 |
+ RC632_CR_RX_CRC_ENABLE |
+ RC632_CR_TX_CRC_ENABLE));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_LSB, 0xff);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_MSB, 0xff);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int
+rc632_iso15693_icode_init(struct rfid_asic_handle *h)
+{
+ int ret;
+
+ ret = rc632_reg_write(h, RC632_REG_TX_CONTROL,
+ (RC632_TXCTRL_MOD_SRC_INT |
+ RC632_TXCTRL_TX2_INV |
+ RC632_TXCTRL_TX2_RF_EN |
+ RC632_TXCTRL_TX1_RF_EN));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CW_CONDUCTANCE, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_MOD_CONDUCTANCE, 0x02);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CODER_CONTROL, 0x2c);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH_SOF, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH_SOF, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_TYPE_B_FRAMING, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_RX_CONTROL1, 0x8b); /* FIXME */
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_DECODER_CONTROL, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_BIT_PHASE, 0x52);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_RX_THRESHOLD, 0x66);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_BPSK_DEM_CONTROL, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_RX_CONTROL2,
+ RC632_RXCTRL2_DECSRC_INT);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_RX_CRC_ENABLE |
+ RC632_CR_TX_CRC_ENABLE));
+ ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_LSB, 0xfe);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_MSB, 0xff);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int
+rc632_iso15693_icl_init(struct rfid_asic_handle *h)
+{
+ int ret;
+
+ /* ICL */
+
+ ret = rc632_reg_write(h, RC632_REG_TX_CONTROL,
+ (RC632_TXCTRL_MOD_SRC_INT |
+ RC632_TXCTRL_TX2_INV |
+ RC632_TXCTRL_TX2_RF_EN |
+ RC632_TXCTRL_TX1_RF_EN));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CW_CONDUCTANCE, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_MOD_CONDUCTANCE, 0x11);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CODER_CONTROL,
+ (RC632_CDRCTRL_RATE_15693 |
+ RC632_CDRCTRL_TXCD_ICODE_STD |
+ 0x03)); /* FIXME */
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH_SOF, 0x3f);
+ if (ret < 0)
+ return ret;
+ ret = rc632_reg_write(h, RC632_REG_RX_CONTROL1,
+ (RC632_RXCTRL1_SUBCP_16|
+ RC632_RXCTRL1_ISO15693|
+ RC632_RXCTRL1_GAIN_35DB));
+ if (ret < 0)
+ return ret;
+ ret = rc632_reg_write(h, RC632_REG_DECODER_CONTROL,
+ (RC632_DECCTRL_RX_INVERT|
+ RC632_DECCTRL_RXFR_15693));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_BIT_PHASE, 0xbd);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_RX_THRESHOLD, 0xff);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_BPSK_DEM_CONTROL, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_RX_CONTROL2,
+ RC632_RXCTRL2_DECSRC_INT);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CHANNEL_REDUNDANCY, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_LSB, 0x12);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_MSB, 0xe0);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+struct mifare_authcmd {
+ u_int8_t auth_cmd;
+ u_int8_t block_address;
+ u_int32_t serno; /* lsb 1 2 msb */
+} __attribute__ ((packed));
+
+
+#define RFID_MIFARE_KEY_LEN 6
+#define RFID_MIFARE_KEY_CODED_LEN 12
+
+/* Transform crypto1 key from generic 6byte into rc632 specific 12byte */
+static int
+rc632_mifare_transform_key(const u_int8_t *key6, u_int8_t *key12)
+{
+ int i;
+ u_int8_t ln;
+ u_int8_t hn;
+
+ for (i = 0; i < RFID_MIFARE_KEY_LEN; i++) {
+ ln = key6[i] & 0x0f;
+ hn = key6[i] >> 4;
+ key12[i * 2 + 1] = (~ln << 4) | ln;
+ key12[i * 2] = (~hn << 4) | hn;
+ }
+ return 0;
+}
+
+static int
+rc632_mifare_set_key(struct rfid_asic_handle *h, const u_int8_t *key)
+{
+ u_int8_t coded_key[RFID_MIFARE_KEY_CODED_LEN];
+ u_int8_t reg;
+ int ret;
+
+ ret = rc632_mifare_transform_key(key, coded_key);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_fifo_write(h, RFID_MIFARE_KEY_CODED_LEN, coded_key, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_LOAD_KEY);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_wait_idle(h, RC632_TMO_AUTH1);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_read(h, RC632_REG_ERROR_FLAG, &reg);
+ if (ret < 0)
+ return ret;
+
+ if (reg & RC632_ERR_FLAG_KEY_ERR)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int
+rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno,
+ u_int8_t block)
+{
+ int ret;
+ struct mifare_authcmd acmd;
+ u_int8_t reg;
+
+ if (cmd != RFID_CMD_MIFARE_AUTH1A && cmd != RFID_CMD_MIFARE_AUTH1B)
+ return -EINVAL;
+
+ /* Initialize acmd */
+ acmd.block_address = block & 0xff;
+ acmd.auth_cmd = cmd;
+ //acmd.serno = htonl(serno);
+ acmd.serno = serno;
+
+ /* Clear Rx CRC */
+ ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY,
+ RC632_CR_RX_CRC_ENABLE);
+ if (ret < 0)
+ return ret;
+
+ /* Send Authent1 Command */
+ ret = rc632_fifo_write(h, sizeof(acmd), (unsigned char *)&acmd, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_AUTHENT1);
+ if (ret < 0)
+ return ret;
+
+ /* Wait until transmitter is idle */
+ ret = rc632_wait_idle(h, RC632_TMO_AUTH1);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_read(h, RC632_REG_SECONDARY_STATUS, &reg);
+ if (ret < 0)
+ return ret;
+ if (reg & 0x07)
+ return -EIO;
+
+ /* Clear Tx CRC */
+ ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY,
+ RC632_CR_TX_CRC_ENABLE);
+ if (ret < 0)
+ return ret;
+
+ /* Send Authent2 Command */
+ ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_AUTHENT2);
+ if (ret < 0)
+ return ret;
+
+ /* Wait until transmitter is idle */
+ ret = rc632_wait_idle(h, RC632_TMO_AUTH1);
+ if (ret < 0)
+ return ret;
+
+ /* Check whether authentication was successful */
+ ret = rc632_reg_read(h, RC632_REG_CONTROL, &reg);
+ if (ret < 0)
+ return ret;
+
+ if (!(reg & RC632_CONTROL_CRYPTO1_ON))
+ return -EACCES;
+
+ return 0;
+
+}
+
+/* transceive regular frame */
+static int
+rc632_mifare_transceive(struct rfid_asic_handle *handle,
+ const u_int8_t *tx_buf, unsigned int tx_len,
+ u_int8_t *rx_buf, unsigned int *rx_len,
+ u_int64_t timeout, unsigned int flags)
+{
+ int ret;
+ u_int8_t rxl = *rx_len & 0xff;
+
+ DEBUGP("entered\n");
+ memset(rx_buf, 0, *rx_len);
+
+#if 1
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD |
+ RC632_CR_TX_CRC_ENABLE |
+ RC632_CR_RX_CRC_ENABLE));
+#else
+ ret = rc632_clear_bits(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE);
+#endif
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transceive(handle, tx_buf, tx_len, rx_buf, &rxl, 0x32, 0);
+ *rx_len = rxl;
+ if (ret < 0)
+ return ret;
+
+
+ return 0;
+}
+
diff --git a/firmware/src/pcd/rfid_layer2_iso14443a.c b/firmware/src/pcd/rfid_layer2_iso14443a.c
new file mode 100644
index 0000000..80d9d5f
--- /dev/null
+++ b/firmware/src/pcd/rfid_layer2_iso14443a.c
@@ -0,0 +1,319 @@
+/* ISO 14443-3 A anticollision implementation
+ *
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <librfid/rfid.h>
+#include <librfid/rfid_layer2.h>
+//#include <librfid/rfid_reader.h>
+#include <librfid/rfid_layer2_iso14443a.h>
+
+#define TIMEOUT 1236
+
+/* Transceive a 7-bit short frame */
+static int
+iso14443a_transceive_sf(struct rfid_layer2_handle *handle,
+ unsigned char cmd,
+ struct iso14443a_atqa *atqa)
+{
+ //struct rfid_reader *rdr = handle->rh->reader;
+ DEBUGPCRF("");
+
+ return rc632_iso14443a_transceive_sf(handle->rh, cmd, atqa);
+}
+
+/* Transmit an anticollission bit frame */
+static int
+iso14443a_transceive_acf(struct rfid_layer2_handle *handle,
+ struct iso14443a_anticol_cmd *acf,
+ unsigned int *bit_of_col)
+{
+ //struct rfid_reader *rdr = handle->rh->reader;
+ DEBUGPCRF("");
+
+ return rc632_iso14443a_transceive_acf(handle->rh, acf, bit_of_col);
+}
+
+/* Transmit a regular frame */
+static int
+iso14443a_transceive(struct rfid_layer2_handle *handle,
+ enum rfid_frametype frametype,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ u_int64_t timeout, unsigned int flags)
+{
+ DEBUGPCRF("tx_len=%u, rx_len=%u", tx_len, *rx_len);
+ return rc632_iso14443ab_transceive(handle->rh, frametype, tx_buf,
+ tx_len, rx_buf, rx_len, timeout, flags);
+}
+
+static int
+iso14443a_code_nvb_bits(unsigned char *nvb, unsigned int bits)
+{
+ unsigned int byte_count = bits / 8;
+ unsigned int bit_count = bits % 8;
+
+ if (byte_count < 2 || byte_count > 7)
+ return -1;
+
+ *nvb = ((byte_count & 0xf) << 4) | bit_count;
+
+ return 0;
+}
+
+/* first bit is '1', second bit '2' */
+static void
+set_bit_in_field(unsigned char *bitfield, unsigned int bit)
+{
+ unsigned int byte_count = bit / 8;
+ unsigned int bit_count = bit % 8;
+
+ DEBUGP("bitfield=%p, byte_count=%u, bit_count=%u\n",
+ bitfield, byte_count, bit_count);
+ DEBUGP("%p = 0x%02x\n", (bitfield+byte_count), *(bitfield+byte_count));
+ *(bitfield+byte_count) |= 1 << (bit_count-1);
+ DEBUGP("%p = 0x%02x\n", (bitfield+byte_count), *(bitfield+byte_count));
+}
+
+static int
+iso14443a_anticol(struct rfid_layer2_handle *handle)
+{
+ int ret;
+ unsigned int uid_size;
+ struct iso14443a_handle *h = &handle->priv.iso14443a;
+ struct iso14443a_atqa atqa;
+ struct iso14443a_anticol_cmd acf;
+ unsigned int bit_of_col;
+ unsigned char sak[3];
+ unsigned int rx_len = sizeof(sak);
+ char *aqptr = (char *) &atqa;
+
+ memset(handle->uid, 0, sizeof(handle->uid));
+ memset(sak, 0, sizeof(sak));
+ memset(&atqa, 0, sizeof(atqa));
+ memset(&acf, 0, sizeof(acf));
+
+ ret = iso14443a_transceive_sf(handle, ISO14443A_SF_CMD_REQA, &atqa);
+ if (ret < 0) {
+ h->state = ISO14443A_STATE_REQA_SENT;
+ DEBUGP("error during transceive_sf: %d\n", ret);
+ return ret;
+ }
+ h->state = ISO14443A_STATE_ATQA_RCVD;
+
+ DEBUGP("ATQA: 0x%02x 0x%02x\n", *aqptr, *(aqptr+1));
+
+ if (!atqa.bf_anticol) {
+ h->state = ISO14443A_STATE_NO_BITFRAME_ANTICOL;
+ DEBUGP("no bitframe anticollission bits set, aborting\n");
+ return -1;
+ }
+
+ if (atqa.uid_size == 2 || atqa.uid_size == 3)
+ uid_size = 3;
+ else if (atqa.uid_size == 1)
+ uid_size = 2;
+ else
+ uid_size = 1;
+
+ acf.sel_code = ISO14443A_AC_SEL_CODE_CL1;
+
+ h->state = ISO14443A_STATE_ANTICOL_RUNNING;
+ h->level = ISO14443A_LEVEL_CL1;
+
+cascade:
+ iso14443a_code_nvb_bits(&acf.nvb, 16);
+
+ ret = iso14443a_transceive_acf(handle, &acf, &bit_of_col);
+ if (ret < 0)
+ return ret;
+ DEBUGP("bit_of_col = %d\n", bit_of_col);
+
+ while (bit_of_col != ISO14443A_BITOFCOL_NONE) {
+ set_bit_in_field(&acf.uid_bits[0], bit_of_col-16);
+ iso14443a_code_nvb_bits(&acf.nvb, bit_of_col);
+ ret = iso14443a_transceive_acf(handle, &acf, &bit_of_col);
+ DEBUGP("bit_of_col = %d\n", bit_of_col);
+ if (ret < 0)
+ return ret;
+ }
+
+ iso14443a_code_nvb_bits(&acf.nvb, 7*8);
+ ret = iso14443a_transceive(handle, RFID_14443A_FRAME_REGULAR,
+ (unsigned char *)&acf, 7,
+ (unsigned char *) &sak, &rx_len,
+ TIMEOUT, 0);
+ if (ret < 0)
+ return ret;
+
+ if (sak[0] & 0x04) {
+ /* Cascade bit set, UID not complete */
+ switch (acf.sel_code) {
+ case ISO14443A_AC_SEL_CODE_CL1:
+ /* cascading from CL1 to CL2 */
+ if (acf.uid_bits[0] != 0x88) {
+ DEBUGP("Cascade bit set, but UID0 != 0x88\n");
+ return -1;
+ }
+ memcpy(&handle->uid[0], &acf.uid_bits[1], 3);
+ acf.sel_code = ISO14443A_AC_SEL_CODE_CL2;
+ h->level = ISO14443A_LEVEL_CL2;
+ break;
+ case ISO14443A_AC_SEL_CODE_CL2:
+ /* cascading from CL2 to CL3 */
+ memcpy(&handle->uid[3], &acf.uid_bits[1], 3);
+ acf.sel_code = ISO14443A_AC_SEL_CODE_CL3;
+ h->level = ISO14443A_LEVEL_CL3;
+ break;
+ default:
+ DEBUGP("cannot cascade any further than CL3\n");
+ h->state = ISO14443A_STATE_ERROR;
+ return -1;
+ break;
+ }
+ goto cascade;
+
+ } else {
+ switch (acf.sel_code) {
+ case ISO14443A_AC_SEL_CODE_CL1:
+ /* single size UID (4 bytes) */
+ memcpy(&handle->uid[0], &acf.uid_bits[0], 4);
+ break;
+ case ISO14443A_AC_SEL_CODE_CL2:
+ /* double size UID (7 bytes) */
+ memcpy(&handle->uid[3], &acf.uid_bits[0], 4);
+ break;
+ case ISO14443A_AC_SEL_CODE_CL3:
+ /* triple size UID (10 bytes) */
+ memcpy(&handle->uid[6], &acf.uid_bits[0], 4);
+ break;
+ }
+ }
+
+ h->level = ISO14443A_LEVEL_NONE;
+ h->state = ISO14443A_STATE_SELECTED;
+
+ {
+ if (uid_size == 1)
+ handle->uid_len = 4;
+ else if (uid_size == 2)
+ handle->uid_len = 7;
+ else
+ handle->uid_len = 10;
+
+ DEBUGP("UID %s\n", rfid_hexdump(handle->uid, handle->uid_len));
+ }
+
+ if (sak[0] & 0x20) {
+ DEBUGP("we have a T=CL compliant PICC\n");
+ h->tcl_capable = 1;
+ } else {
+ DEBUGP("we have a T!=CL PICC\n");
+ h->tcl_capable = 0;
+ }
+
+ return 0;
+}
+
+static int
+iso14443a_hlta(struct rfid_layer2_handle *handle)
+{
+ int ret;
+ unsigned char tx_buf[2] = { 0x50, 0x00 };
+ unsigned char rx_buf[10];
+ unsigned int rx_len = sizeof(rx_buf);
+
+ ret = iso14443a_transceive(handle, RFID_14443A_FRAME_REGULAR,
+ tx_buf, sizeof(tx_buf),
+ rx_buf, &rx_len, 1000 /* 1ms */, 0);
+ if (ret < 0) {
+ /* "error" case: we don't get somethng back from the card */
+ return 0;
+ }
+ return -1;
+}
+
+static int
+iso14443a_setopt(struct rfid_layer2_handle *handle, int optname,
+ const void *optval, unsigned int optlen)
+{
+ int ret = -EINVAL;
+ unsigned int speed;
+
+ switch (optname) {
+ case RFID_OPT_14443A_SPEED_RX:
+ speed = *(unsigned int *)optval;
+ ret = rc632_iso14443a_set_speed(handle->rh, 0, speed);
+ break;
+ case RFID_OPT_14443A_SPEED_TX:
+ speed = *(unsigned int *)optval;
+ ret = rc632_iso14443a_set_speed(handle->rh, 1, speed);
+ break;
+ };
+
+ return ret;
+}
+
+
+static struct rfid_layer2_handle *
+iso14443a_init(struct rfid_reader_handle *rh)
+{
+ int ret;
+ struct rfid_layer2_handle *h = malloc(sizeof(*h));
+ if (!h)
+ return NULL;
+
+ h->l2 = &rfid_layer2_iso14443a;
+ h->rh = rh;
+ h->priv.iso14443a.state = ISO14443A_STATE_NONE;
+ h->priv.iso14443a.level = ISO14443A_LEVEL_NONE;
+
+ ret = rc632_iso14443a_init(h->rh);
+ if (ret < 0) {
+ free(h);
+ return NULL;
+ }
+
+ return h;
+}
+
+static int
+iso14443a_fini(struct rfid_layer2_handle *handle)
+{
+ free(handle);
+ return 0;
+}
+
+struct rfid_layer2 rfid_layer2_iso14443a = {
+ .id = RFID_LAYER2_ISO14443A,
+ .name = "ISO 14443-3 A",
+ .fn = {
+ .init = &iso14443a_init,
+ .open = &iso14443a_anticol,
+ .transceive = &iso14443a_transceive,
+ .close = &iso14443a_hlta,
+ .fini = &iso14443a_fini,
+ .setopt = &iso14443a_setopt,
+ },
+};
diff --git a/firmware/src/picc/adc.c b/firmware/src/picc/adc.c
new file mode 100644
index 0000000..31b3469
--- /dev/null
+++ b/firmware/src/picc/adc.c
@@ -0,0 +1,145 @@
+/* AT91SAM7 ADC controller routines for OpenPCD / OpenPICC
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <AT91SAM7.h>
+#include <lib_AT91SAM7.h>
+#include <openpcd.h>
+
+#include <os/usb_handler.h>
+#include "../openpcd.h"
+#include <os/dbgu.h>
+
+#define OPENPICC_ADC_CH_FIELDSTR AT91C_ADC_CH4
+#define OPENPICC_ADC_CH_PLL_DEM AT91C_ADC_CH5
+
+#define DEBUG_ADC
+
+#ifdef DEBUG_ADC
+#define DEBUGADC DEBUGP
+#else
+#define DEBUGADC do { } while (0)
+#endif
+
+static const AT91PS_ADC adc = AT91C_BASE_ADC;
+
+enum adc_states {
+ ADC_NONE,
+ ADC_READ_CONTINUOUS,
+ ADC_READ_CONTINUOUS_USB,
+ ADC_READ_SINGLE,
+};
+
+struct adc_state {
+ enum adc_states state;
+ struct req_ctx *rctx;
+};
+
+static struct adc_state adc_state;
+
+static void adc_irq(void)
+{
+ u_int32_t sr = adc->ADC_SR;
+ struct req_ctx *rctx = adc_state.rctx;
+
+ DEBUGADC("adc_irq(SR=0x%08x, IMR=0x%08x, state=%u): ",
+ sr, adc->ADC_IMR, adc_state.state);
+
+ switch (adc_state.state) {
+ case ADC_NONE:
+ //break;
+ case ADC_READ_CONTINUOUS_USB:
+ if (sr & AT91C_ADC_EOC4)
+ DEBUGADC("CDR4=0x%4x ", adc->ADC_CDR4);
+ if (sr & AT91C_ADC_EOC5)
+ DEBUGADC("CDR5=0x%4x ", adc->ADC_CDR5);
+ if (sr & AT91C_ADC_ENDRX) {
+ /* rctx full, get rid of it */
+ DEBUGADC("sending rctx (val=%s) ",
+ hexdump(rctx->tx.data[4], 2));
+
+ req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING);
+ adc_state.state = ADC_NONE;
+ adc_state.rctx = NULL;
+
+ //AT91F_PDC_SetRx(AT91C_BASE_PDC_ADC, NULL, 0);
+
+ /* Disable EOC interrupts since we don't want to
+ * re-start conversion any further*/
+ AT91F_ADC_DisableIt(AT91C_BASE_ADC, AT91C_ADC_ENDRX);
+ //AT91C_ADC_EOC4|AT91C_ADC_EOC5|AT91C_ADC_ENDRX);
+ AT91F_PDC_DisableRx(AT91C_BASE_PDC_ADC);
+ DEBUGADC("disabled IT/RX ");
+ } else {
+ if (sr & (AT91C_ADC_EOC4|AT91C_ADC_EOC5)) {
+ /* re-start conversion, since we need more values */
+ AT91F_ADC_StartConversion(adc);
+ }
+ }
+ break;
+ }
+
+ AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_ADC);
+ DEBUGADC("cleeared ADC IRQ in AIC\r\n");
+}
+
+#if 0
+u_int16_t adc_read_fieldstr(void)
+{
+ return adc->ADC_CDR4;
+}
+
+u_int16_T adc_read_pll_dem(void)
+{
+ return adc
+}
+#endif
+
+static int adc_usb_in(struct req_ctx *rctx)
+{
+ struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0];
+ struct openpcd_hdr *pih = (struct openpcd_hdr *) &rctx->tx.data[0];
+
+ switch (poh->cmd) {
+ case OPENPCD_CMD_ADC_READ:
+ DEBUGADC("ADC_READ(chan=%u, len=%u) ", poh->reg, poh->val);
+ //channel = poh->reg;
+ if (adc_state.rctx) {
+ /* FIXME: do something */
+ req_ctx_put(rctx);
+ }
+
+ adc_state.state = ADC_READ_CONTINUOUS_USB;
+ adc_state.rctx = rctx;
+ memcpy(pih, poh, sizeof(*pih));
+ rctx->tx.tot_len = sizeof(*pih) + poh->val * 2;
+ AT91F_PDC_SetRx(AT91C_BASE_PDC_ADC, rctx->rx.data, poh->val);
+ AT91F_PDC_EnableRx(AT91C_BASE_PDC_ADC);
+ AT91F_ADC_EnableChannel(AT91C_BASE_ADC, OPENPICC_ADC_CH_FIELDSTR);
+ AT91F_ADC_EnableIt(AT91C_BASE_ADC, AT91C_ADC_ENDRX |
+ OPENPICC_ADC_CH_FIELDSTR);
+ AT91F_ADC_StartConversion(adc);
+ break;
+ }
+}
+
+int adc_init(void)
+{
+ AT91F_ADC_CfgPMC();
+ AT91F_ADC_CfgTimings(AT91C_BASE_ADC, 48 /*MHz*/, 5 /*MHz*/,
+ 20/*uSec*/, 700/*nSec*/);
+#if 0
+ AT91F_ADC_EnableChannel(AT91C_BASE_ADC, OPENPICC_ADC_CH_FIELDSTR |
+ OPENPICC_ADC_CH_PLL_DEM);
+#endif
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_ADC,
+ AT91C_AIC_PRIOR_LOWEST,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &adc_irq);
+ AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_ADC);
+
+ usb_hdlr_register(&adc_usb_in, OPENPCD_CMD_CLS_ADC);
+}
diff --git a/firmware/src/picc/decoder.c b/firmware/src/picc/decoder.c
new file mode 100644
index 0000000..9f9191a
--- /dev/null
+++ b/firmware/src/picc/decoder.c
@@ -0,0 +1,65 @@
+/* Decoder Core for OpenPCD / OpenPICC
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <picc/decoder.h>
+
+#include <os/dbgu.h>
+
+static struct decoder_algo *decoder_algo[DECODER_NUM_ALGOS];
+
+static int get_next_data(struct decoder_state *st, u_int8_t *data)
+{
+ u_int8_t parity_sample;
+ u_int32_t bytesample;
+
+ bytesample = st->algo->get_next_bytesample(st, &parity_sample);
+
+ return st->algo->decode_sample(bytesample, data);
+}
+
+/* iterate over sample buffer (size N bytes) and decode data */
+int decoder_decode(u_int8_t algo, const char *sample_buf,
+ int sample_buf_size, char *data_buf)
+{
+ int i, ret;
+ struct decoder_state st;
+
+ if (algo >= DECODER_NUM_ALGOS)
+ return -EINVAL;
+
+ st.buf = sample_buf;
+ st.buf32 = (u_int32_t *) st.buf;
+ st.bit_ofs = 0;
+ st.algo = decoder_algo[algo];
+
+ for (i = 0; i < (sample_buf_size*8)/st.algo->bits_per_sampled_char;
+ i++) {
+ ret = get_next_data(&st, &data_buf[i]);
+ if (ret < 0) {
+ DEBUGPCR("decoder error %d at data byte %u",
+ ret, i);
+ return ret;
+ }
+ }
+
+ return i+1;
+}
+
+int decoder_register(int algnum, struct decoder_algo *algo)
+{
+ if (algnum >= DECODER_NUM_ALGOS)
+ return -EINVAL;
+
+ decoder_algo[algnum] = algo;
+
+ return 0;
+}
+
+void decoder_init(void)
+{
+ decoder_register(DECODER_MILLER, &miller_decoder);
+ decoder_register(DECODER_NRZL, &nrzl_decoder);
+}
diff --git a/firmware/src/picc/decoder.h b/firmware/src/picc/decoder.h
new file mode 100644
index 0000000..aef0e20
--- /dev/null
+++ b/firmware/src/picc/decoder.h
@@ -0,0 +1,32 @@
+#ifndef _DECODER_H
+#define _DECODER_H
+
+struct decoder_state;
+
+struct decoder_algo {
+ u_int8_t oversampling_rate;
+ u_int8_t bits_per_sampled_char;
+ u_int32_t bytesample_mask;
+ int (*decode_sample)(const u_int32_t sample, u_int8_t data);
+ u_int32_t (*get_next_bytesample)(struct decoder_state *st, u_int8_t *parity_sample);
+};
+
+struct decoder_state {
+ struct decoder_algo *algo;
+ u_int8_t bit_ofs;
+ const char *buf;
+ const u_int32_t *buf32;
+};
+
+extern int decoder_register(int algnum, struct decoder_algo *algo);
+extern int decoder_decode(u_int8_t algo, const char *sample_buf,
+ int sample_buf_size, char *data_buf);
+
+#define DECODER_MILLER 0
+#define DECODER_NRZL 1
+#define DECODER_NUM_ALGOS 2
+
+static struct decoder_algo nrzl_decoder;
+static struct decoder_algo miller_decoder;
+
+#endif
diff --git a/firmware/src/picc/decoder_miller.c b/firmware/src/picc/decoder_miller.c
new file mode 100644
index 0000000..1394a17
--- /dev/null
+++ b/firmware/src/picc/decoder_miller.c
@@ -0,0 +1,112 @@
+/*
+ * ISO14443A modified Miller decoder
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * LSB First LSB hex
+ * Sequence X 0010 0100 0x4
+ * Sequence Y 0000 0000 0x0
+ * Sequence Z 1000 0001 0x1
+ *
+ * Logic 1 Sequence X
+ * Logic 0 Sequence Y with two exceptions:
+ * - if there are more contiguous 0, Z used from second one
+ * - if the first bit after SOF is 0, sequence Z used for all contig 0's
+ * SOF Sequence Z
+ * EOF Logic 0 followed by Sequence Y
+ *
+ * cmd hex bits symbols hex (quad-sampled)
+ *
+ * REQA 0x26 S 0110010 E Z ZXXYZXY ZY 0x10410441
+ * WUPA 0x52 S 0100101 E Z ZXYZXYX YY 0x04041041
+ *
+ * SOF is 'eaten' by SSC start condition (Compare 0). Remaining bits are
+ * mirrored, e.g. samples for LSB of first byte are & 0xf
+ *
+ */
+
+#include <sys/types.h>
+
+#include <os/dbgu.h>
+#include <picc/decoder.h>
+
+
+#define OVERSAMPLING_RATE 4
+
+/* definitions for four-times oversampling */
+#define SEQ_X 0x4
+#define SEQ_Y 0x0
+#define SEQ_Z 0x1
+
+/* decode a single sampled bit */
+static u_int8_t miller_decode_sampled_bit(u_int32_t sampled_bit)
+{
+ switch (sampled_bit) {
+ case SEQ_X:
+ return 1;
+ break;
+ case SEQ_Z:
+ case SEQ_Y:
+ return 0;
+ break;
+ default:
+ DEBUGP("unknown sequence sample `%x' ", sampled_bit);
+ return 2;
+ break;
+ }
+}
+
+/* decode a single 32bit data sample of an 8bit miller encoded word */
+static int miller_decode_sample(u_int32_t sample, u_int8_t *data)
+{
+ u_int8_t ret = 0;
+ unsigned int i;
+
+ for (i = 0; i < sizeof(sample)/OVERSAMPLING_RATE; i++) {
+ u_int8_t bit = miller_decode_sampled_bit(sample & 0xf);
+
+ if (bit == 1)
+ ret |= 1;
+ /* else do nothing since ret was initialized with 0 */
+
+ /* skip shifting in case of last data bit */
+ if (i == sizeof(sample)/OVERSAMPLING_RATE)
+ break;
+
+ sample = sample >> OVERSAMPLING_RATE;
+ ret = ret << 1;
+ }
+
+ *data = ret;
+
+ return ret;
+}
+
+static u_int32_t get_next_bytesample(struct decoder_state *ms,
+ u_int8_t *parity_sample)
+{
+ u_int32_t ret = 0;
+
+ /* get remaining bits from the current word */
+ ret = *(ms->buf32) >> ms->bit_ofs;
+ /* move to next word */
+ ms->buf32++;
+
+ /* if required, get remaining bits from next word */
+ if (ms->bit_ofs)
+ ret |= *(ms->buf32) << (32 - ms->bit_ofs);
+
+ *parity_sample = (*(ms->buf32) >> ms->bit_ofs & 0xf);
+
+ /* increment bit offset (modulo 32) */
+ ms->bit_ofs = (ms->bit_ofs + OVERSAMPLING_RATE) % 32;
+
+ return ret;
+}
+
+static struct decoder_algo miller_decoder = {
+ .oversampling_rate = OVERSAMPLING_RATE,
+ .bits_per_sampled_char = 9 * OVERSAMPLING_RATE,
+ .bytesample_mask = 0xffffffff,
+ .decode_sample = &miller_decode_sample,
+ .get_next_bytesample = &get_next_bytesample,
+};
diff --git a/firmware/src/picc/decoder_nrzl.c b/firmware/src/picc/decoder_nrzl.c
new file mode 100644
index 0000000..a1b79aa
--- /dev/null
+++ b/firmware/src/picc/decoder_nrzl.c
@@ -0,0 +1,91 @@
+/* ISO 14443 B Rx (PCD->PICC) implementation
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * speed(kbps) 106 212 424 848
+ * etu 128/fc 64/fc 32/fc 16/fc
+ * etu(usec) 9.4 4.7 2.35 1.18
+ *
+ * NRZ-L coding with logic level
+ *
+ * logic 1: carrier high field amplitude (no modulation)
+ * logic 0: carrier low field amplitude
+ *
+ * Character transmission format:
+ * start bit: logic 0
+ * data: eight bits, lsb first
+ * stop bit logic 1
+ *
+ * Frame Format:
+ *
+ * SOF char [EGT char, ...] EOF
+ *
+ * SOF: falling edge, 10..11 etu '0', rising edge in 1etu, 2..3etu '1'
+ * EGT: between 0 and 57uS
+ * EOF: falling edge, 10..11 etu '0', rising edge in 1etu
+ *
+ *
+ * Sampling
+ * - sample once per bit clock, exactly in the middle of it
+ * - synchronize CARRIER_DIV TC0 to first falling edge
+ * - Configure CARRIER_DIV RA compare (rising edge) to be at
+ * etu/2 carrier clocks.
+ * - problem: SOF 12..14etu length, therefore we cannot specify
+ * SOF as full start condition and then sample with 10bit
+ * frames :(
+ *
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <os/dbgu.h>
+#include <picc/decoder.h>
+
+/* currently this code will only work with oversampling_rate == 1 */
+#define OVERSAMPLING_RATE 1
+
+static u_int32_t get_next_bytesample(struct decoder_state *st,
+ u_int8_t *parity_sample)
+{
+ u_int32_t ret = 0;
+ u_int8_t bits_per_sampled_char = st->algo->bits_per_sampled_char;
+ u_int8_t bytesample_mask = st->algo->bytesample_mask;
+
+ /* FIXME: shift start and stop bit into parity_sample and just
+ * return plain 8-bit data word */
+
+ /* first part of 10-databit bytesample */
+ ret = (*(st->buf32) >> st->bit_ofs) & bytesample_mask;
+
+ if (st->bit_ofs > 32 - bits_per_sampled_char) {
+ /* second half of 10-databit bytesample */
+ st->buf32++;
+ ret |= (*(st->buf32) << (32 - st->bit_ofs));
+ }
+ st->bit_ofs = (st->bit_ofs + bits_per_sampled_char) % 32;
+
+ return ret & bytesample_mask;
+}
+
+static int nrzl_decode_sample(const u_int32_t sample, u_int8_t *data)
+{
+ *data = (sample >> 1) & 0xff;
+
+ if (!(sample & 0x01)) {
+ DEBUGPCRF("invalid start bit 0!");
+ return -EIO;
+ }
+ if (sample & 0x20) {
+ DEBUGPCRF("invalid stop bit 1!");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static struct decoder_algo nrzl_decoder = {
+ .oversampling_rate = OVERSAMPLING_RATE,
+ .bits_per_sampled_char = 10 * OVERSAMPLING_RATE,
+ .bytesample_mask = 0x3ff,
+ .decode_sample = &nrzl_decode_sample,
+ .get_next_bytesample = &get_next_bytesample,
+};
diff --git a/firmware/src/picc/iso14443a_manchester.c b/firmware/src/picc/iso14443a_manchester.c
new file mode 100644
index 0000000..aca832c
--- /dev/null
+++ b/firmware/src/picc/iso14443a_manchester.c
@@ -0,0 +1,106 @@
+/*
+ * ISO14443A Manchester encoder
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * Definitions for 106kBps, at sampling clock 1695kHz
+ *
+ * bit sample pattern for one bit cycle
+ * MSB first LSB first hex LSB first
+ * Sequence D 1010101000000000 0000000001010101 0x0055
+ * Sequence E 0000000010101010 0101010100000000 0x5500
+ * Sequence F 1010101010101010 0101010101010101 0x5555
+ *
+ * Logic 1 Sequence D
+ * Logic 0 Sequence E
+ * SOF Sequence D
+ * EOF Sequence F
+ *
+ * 212/424/848kBps: BPSK.
+ *
+ * SOF: 32 subcarrier clocks + bit '0'
+ *
+ * SOF: hex LSB first: 0x55555555 55555555 + bit '0'
+ *
+ * EOF: even parity of last byte (!)
+ *
+ */
+
+#define MANCHESTER_SEQ_D 0x0055
+#define MANCHESTER_SEQ_E 0x5500
+#define MANCHESTER_SEQ_F 0x5555
+
+static u_int32_t manchester_sample_size(u_int8_t frame_bytelen)
+{
+ /* 16 bits (2 bytes) per bit => 16 bytes samples per data byte,
+ * plus 16bit (2 bytes) parity per data byte
+ * plus 16bit (2 bytes) SOF plus 16bit (2 bytes) EOF */
+ return (frame_bytelen*18) + 2 + 2;
+
+ /* this results in a maximum samples-per-frame size of 4612 bytes
+ * for a 256byte frame */
+}
+
+struct manch_enc_state {
+ const char *data;
+ char *samples;
+ u_int16_t *samples16;
+};
+
+static void manchester_enc_byte(struct manch_enc_state *mencs, u_int8_t data)
+{
+ int i;
+ u_int8_t sum_1 = 0;
+
+ /* append 8 sample blobs, one for each bit */
+ for (i = 0; i < 8; i++) {
+ if (data & (1 << i)) {
+ *(mencs->samples16) = MANCHESTER_SEQ_D;
+ sum_1++;
+ } else {
+ *(mencs->samples16) = MANCHESTER_SEQ_E;
+ }
+ mencs->samples16++
+ }
+ /* append odd parity */
+ if (sum_1 & 0x01)
+ *(mencs->samples16) = MANCHESTER_SEQ_E;
+ else
+ *(mencs->samples16) = MANCHESTER_SEQ_D;
+ mencs->samples16++
+}
+
+int manchester_encode(char *sample_buf, u_int16_t sample_buf_len,
+ const char *data, u_int8_t data_len)
+{
+ int i, enc_size;
+ struct manch_enc_state mencs
+
+ enc_size = manchester_sample_size(data_len);
+
+ if (sample_buf_len < enc_size)
+ return -EINVAL;
+
+ /* SOF */
+ *(mencs.samples16++) = MANCHESTER_SEQ_D;
+
+ for (i = 0; i < data_len; i++)
+ manchester_enc_byte(mencs, data[i]);
+
+ /* EOF */
+ *(mencs.samples16++) = MANCHESTER_SEQ_F;
+
+ return enc_size;
+}
+
+#define BPSK_SPEED_212
+
+
+static u_int32_t bpsk_sample_size(u_int8_t frame_bytelen)
+
+int bpsk_encode(char *sample_buf, u_int16_t sample_buf_len,
+ const char *data, u_int8_t data_len)
+{
+ /* burst of 32 sub carrier cycles */
+ memset(sample_buf, 0x55, 8);
+
+}
diff --git a/firmware/src/picc/load_modulation.c b/firmware/src/picc/load_modulation.c
new file mode 100644
index 0000000..65c59d1
--- /dev/null
+++ b/firmware/src/picc/load_modulation.c
@@ -0,0 +1,29 @@
+#include <sys/types.h>
+#include <lib_AT91SAM7.h>
+
+#include "../openpcd.h"
+
+void load_mod_level(u_int8_t level)
+{
+ if (level > 3)
+ level = 3;
+
+ if (level & 0x1)
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD1);
+ else
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD1);
+
+ if (level & 0x2)
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD2);
+ else
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD2);
+}
+
+void load_mod_init(void)
+{
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD1);
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD2);
+
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD1);
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_LOAD2);
+}
diff --git a/firmware/src/picc/load_modulation.h b/firmware/src/picc/load_modulation.h
new file mode 100644
index 0000000..71f9d6f
--- /dev/null
+++ b/firmware/src/picc/load_modulation.h
@@ -0,0 +1,7 @@
+#ifndef _LOAD_MODULATION_H
+#define _LOAD_MODULATION_H
+
+extern void load_mod_level(u_int8_t level);
+extern void load_mod_init(void);
+
+#endif
diff --git a/firmware/src/picc/main_openpicc.c b/firmware/src/picc/main_openpicc.c
new file mode 100644
index 0000000..312194b
--- /dev/null
+++ b/firmware/src/picc/main_openpicc.c
@@ -0,0 +1,215 @@
+#include <errno.h>
+#include <include/lib_AT91SAM7.h>
+#include <include/openpcd.h>
+#include <os/dbgu.h>
+#include <os/led.h>
+#include <os/pcd_enumerate.h>
+#include <os/usb_handler.h>
+#include "../openpcd.h"
+#include <os/main.h>
+#include <os/pwm.h>
+#include <os/tc_cdiv.h>
+#include <os/pio_irq.h>
+#include <picc/poti.h>
+#include <picc/pll.h>
+#include <picc/ssc_picc.h>
+#include <picc/load_modulation.h>
+
+static const u_int16_t cdivs[] = { 128, 64, 32, 16 };
+static u_int8_t cdiv_idx = 0;
+
+static u_int16_t duty_percent = 22;
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+static u_int32_t pwm_freq[] = { 105937, 211875, 423750, 847500 };
+static u_int8_t pwm_freq_idx = 0;
+
+static u_int8_t load_mod = 0;
+
+void _init_func(void)
+{
+ pio_irq_init();
+ pll_init();
+ poti_init();
+ load_mod_init();
+ tc_cdiv_init();
+ //tc_fdt_init();
+ pwm_init();
+ adc_init();
+ ssc_rx_init();
+ // ssc_tx_init();
+
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPICC_PIO_BOOTLDR);
+}
+
+static void help(void)
+{
+ DEBUGPCR("q: poti decrease q: poti increase\r\n"
+ "e: poti retransmit P: PLL inhibit toggle");
+ DEBUGPCR("o: decrease duty p: increase duty\r\n"
+ "k: stop pwm l: start pwn\r\n"
+ "n: decrease freq m: incresae freq");
+ DEBUGPCR("u: PA23 const 1 y: PA23 const 0\r\n"
+ "t: PA23 PWM0 L: display PLL LOCK\r\n"
+ "{: decrease cdiv_idx }: increse cdiv idx\r\n"
+ "<: decrease cdiv_phase >: increase cdiv_phase");
+ DEBUGPCR("v: decrease load_mod b: increase load_mod\r\n"
+ "B: read button S: toggle nSLAVE_RESET\r\n"
+ "a: SSC stop s: SSC start\r\n"
+ "d: SSC mode select");
+}
+
+int _main_dbgu(char key)
+{
+ static u_int8_t poti = 64;
+ static u_int8_t pll_inh = 1;
+ static u_int8_t ssc_mode = 1;
+
+ DEBUGPCRF("main_dbgu");
+
+ switch (key) {
+ case 'q':
+ if (poti > 0)
+ poti--;
+ poti_comp_carr(poti);
+ DEBUGPCRF("Poti: %u", poti);
+ break;
+ case 'w':
+ if (poti < 127)
+ poti++;
+ poti_comp_carr(poti);
+ DEBUGPCRF("Poti: %u", poti);
+ break;
+ case 'e':
+ poti_comp_carr(poti);
+ DEBUGPCRF("Poti: %u", poti);
+ break;
+ case 'P':
+ pll_inh++;
+ pll_inh &= 0x01;
+ pll_inhibit(pll_inh);
+ DEBUGPCRF("PLL Inhibit: %u", pll_inh);
+ break;
+ case 'L':
+ DEBUGPCRF("PLL Lock: %u", pll_is_locked());
+ break;
+ case 'o':
+ if (duty_percent >= 1)
+ duty_percent--;
+ pwm_duty_set_percent(0, duty_percent);
+ break;
+ case 'p':
+ if (duty_percent <= 99)
+ duty_percent++;
+ pwm_duty_set_percent(0, duty_percent);
+ break;
+ case 'k':
+ pwm_stop(0);
+ break;
+ case 'l':
+ pwm_start(0);
+ break;
+ case 'n':
+ if (pwm_freq_idx > 0) {
+ pwm_freq_idx--;
+ pwm_stop(0);
+ pwm_freq_set(0, pwm_freq[pwm_freq_idx]);
+ pwm_start(0);
+ pwm_duty_set_percent(0, 22); /* 22% of 9.43uS = 2.07uS */
+ }
+ break;
+ case 'm':
+ if (pwm_freq_idx < ARRAY_SIZE(pwm_freq)-1) {
+ pwm_freq_idx++;
+ pwm_stop(0);
+ pwm_freq_set(0, pwm_freq[pwm_freq_idx]);
+ pwm_start(0);
+ pwm_duty_set_percent(0, 22); /* 22% of 9.43uS = 2.07uS */
+ }
+ break;
+ case 'u':
+ DEBUGPCRF("PA23 output high");
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, AT91C_PIO_PA23);
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, AT91C_PIO_PA23);
+ break;
+ case 'y':
+ DEBUGPCRF("PA23 output low");
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, AT91C_PIO_PA23);
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, AT91C_PIO_PA23);
+ break;
+ case 't':
+ DEBUGPCRF("PA23 PeriphA (PWM)");
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, AT91C_PA23_PWM0);
+ break;
+ case '?':
+ help();
+ break;
+ case '<':
+ tc_cdiv_phase_inc();
+ break;
+ case '>':
+ tc_cdiv_phase_dec();
+ break;
+ case '{':
+ if (cdiv_idx > 0)
+ cdiv_idx--;
+ tc_cdiv_set_divider(cdivs[cdiv_idx]);
+ break;
+ case '}':
+ if (cdiv_idx < ARRAY_SIZE(cdivs)-1)
+ cdiv_idx++;
+ tc_cdiv_set_divider(cdivs[cdiv_idx]);
+ break;
+ case 'v':
+ if (load_mod > 0)
+ load_mod--;
+ load_mod_level(load_mod);
+ DEBUGPCR("load_mod: %u\n", load_mod);
+ break;
+ case 'b':
+ if (load_mod < 3)
+ load_mod++;
+ load_mod_level(load_mod);
+ DEBUGPCR("load_mod: %u\n", load_mod);
+ break;
+ case 'B':
+ DEBUGPCRF("Button status: %u\n",
+ AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, AT91F_PIO_IsInputSet));
+ break;
+ case 'S':
+ if (AT91F_PIO_IsOutputSet(AT91C_BASE_PIOA, OPENPICC_PIO_nSLAVE_RESET)) {
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_nSLAVE_RESET);
+ DEBUGPCRF("nSLAVE_RESET == LOW");
+ } else {
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPICC_PIO_nSLAVE_RESET);
+ DEBUGPCRF("nSLAVE_RESET == HIGH");
+ }
+ break;
+ case 'a':
+ DEBUGPCRF("SSC RX STOP");
+ ssc_rx_stop();
+ break;
+ case 's':
+ DEBUGPCRF("SSC RX START");
+ ssc_rx_start();
+ break;
+ case 'd':
+ ssc_rx_mode_set(++ssc_mode);
+ DEBUGPCRF("SSC MODE %u", ssc_mode);
+ break;
+ }
+
+ tc_cdiv_print();
+
+ return -EINVAL;
+}
+
+void _main_func(void)
+{
+ /* first we try to get rid of pending to-be-sent stuff */
+ usb_out_process();
+
+ /* next we deal with incoming reqyests from USB EP1 (OUT) */
+ usb_in_process();
+
+ ssc_rx_unthrottle();
+}
diff --git a/firmware/src/picc/piccsim.h b/firmware/src/picc/piccsim.h
new file mode 100644
index 0000000..3cf6514
--- /dev/null
+++ b/firmware/src/picc/piccsim.h
@@ -0,0 +1,23 @@
+
+#include <librfid/rfid_layer2_iso14443a.h>
+
+struct piccsim_state {
+ enum rfid_layer2_id l2prot;
+ unsigned char uid[10];
+ u_int8_t uid_len;
+ union {
+ struct {
+ enum iso14443a_state state;
+ enum iso14443a_level level;
+ u_int32_t flags;
+ } iso14443a;
+ struct {
+ } iso14443b;
+ } l2;
+
+ union {
+ u_int32_t flags;
+ } proto;
+}
+
+#define PICCSIM_PROT_F_AUTO_WTX 0x01
diff --git a/firmware/src/picc/pll.c b/firmware/src/picc/pll.c
new file mode 100644
index 0000000..bed08ef
--- /dev/null
+++ b/firmware/src/picc/pll.c
@@ -0,0 +1,40 @@
+
+#include <sys/types.h>
+#include <lib_AT91SAM7.h>
+#include <os/pio_irq.h>
+#include <os/dbgu.h>
+#include "../openpcd.h"
+
+void pll_inhibit(int inhibit)
+{
+ if (inhibit)
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPICC_PIO_PLL_INHIBIT);
+ else
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_PLL_INHIBIT);
+}
+
+int pll_is_locked(void)
+{
+ return AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, OPENPICC_PIO_PLL_LOCK);
+}
+
+static void pll_lock_change_cb(u_int32_t pio)
+{
+ DEBUGPCRF("PLL LOCK: %d", pll_is_locked());
+#if 1
+ if (pll_is_locked())
+ led_switch(1, 1);
+ else
+ led_switch(1, 0);
+#endif
+}
+
+void pll_init(void)
+{
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPICC_PIO_PLL_INHIBIT);
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPICC_PIO_PLL_LOCK);
+ pll_inhibit(0);
+
+ pio_irq_register(OPENPICC_PIO_PLL_LOCK, &pll_lock_change_cb);
+ pio_irq_enable(OPENPICC_PIO_PLL_LOCK);
+}
diff --git a/firmware/src/picc/pll.h b/firmware/src/picc/pll.h
new file mode 100644
index 0000000..fc00105
--- /dev/null
+++ b/firmware/src/picc/pll.h
@@ -0,0 +1,8 @@
+#ifndef _PLL_H
+#define _PLL_H
+
+extern int pll_is_locked(void);
+extern void pll_inhibit(int inhibit);
+extern void pll_init(void);
+
+#endif
diff --git a/firmware/src/picc/poti.c b/firmware/src/picc/poti.c
new file mode 100644
index 0000000..2cc8e5c
--- /dev/null
+++ b/firmware/src/picc/poti.c
@@ -0,0 +1,58 @@
+/* SPI Potentiometer AD 7367 Driver for OpenPICC
+ * (C) by Harald Welte <hwelte@hmw-consulting.de>
+ */
+
+#include <sys/types.h>
+#include <lib_AT91SAM7.h>
+#include "../openpcd.h"
+
+static const AT91PS_SPI spi = AT91C_BASE_SPI;
+
+void poti_comp_carr(u_int8_t position)
+{
+ volatile int i;
+
+ while (!(spi->SPI_SR & AT91C_SPI_TDRE)) { }
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_SS2_DT_THRESH);
+ //for (i = 0; i < 0xff; i++) { }
+ /* shift one left, since it is a seven-bit value written as 8 bit xfer */
+ spi->SPI_TDR = position & 0x7f;
+ while (!(spi->SPI_SR & AT91C_SPI_TDRE)) { }
+ for (i = 0; i < 0xff; i++) { }
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPICC_PIO_SS2_DT_THRESH);
+}
+
+void poti_reset(void)
+{
+ volatile int i;
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_nSLAVE_RESET);
+ for (i = 0; i < 0xff; i++) { }
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPICC_PIO_nSLAVE_RESET);
+}
+
+void poti_init(void)
+{
+ AT91F_SPI_CfgPMC();
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA,
+ AT91C_PA13_MOSI | AT91C_PA14_SPCK, 0);
+
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPICC_PIO_SS2_DT_THRESH);
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPICC_PIO_SS2_DT_THRESH);
+
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPICC_PIO_nSLAVE_RESET);
+ poti_reset();
+
+#if 0
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SPI,
+ OPENPCD_IRQ_PRIO_SPI,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &spi_irq);
+ AT91G_AIC_EnableIt(AT9C_BASE_AIC, AT91C_ID_SPI);
+#endif
+ AT91F_SPI_CfgMode(spi, AT91C_SPI_MSTR |
+ AT91C_SPI_PS_FIXED | AT91C_SPI_MODFDIS);
+ /* CPOL = 0, NCPHA = 1, CSAAT = 0, BITS = 0000, SCBR = 13 (3.69MHz),
+ * DLYBS = 6 (125nS), DLYBCT = 0 */
+ AT91F_SPI_CfgCs(spi, 0, AT91C_SPI_BITS_8 | AT91C_SPI_NCPHA |
+ (13 << 8) | (6 << 16));
+ AT91F_SPI_Enable(spi);
+}
diff --git a/firmware/src/picc/poti.h b/firmware/src/picc/poti.h
new file mode 100644
index 0000000..92ec00d
--- /dev/null
+++ b/firmware/src/picc/poti.h
@@ -0,0 +1,7 @@
+#ifndef _POTI_H
+#define _POTI_H
+
+extern void poti_comp_carr(u_int8_t position);
+extern void poti_init(void);
+
+#endif
diff --git a/firmware/src/picc/ssc_picc.c b/firmware/src/picc/ssc_picc.c
new file mode 100644
index 0000000..fac2c62
--- /dev/null
+++ b/firmware/src/picc/ssc_picc.c
@@ -0,0 +1,384 @@
+/* AT91SAM7 SSC controller routines for OpenPCD
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * We use SSC for both TX and RX side.
+ *
+ * RX side is interconnected with demodulated carrier
+ *
+ * TX side is interconnected with load modulation circuitry
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <AT91SAM7.h>
+#include <lib_AT91SAM7.h>
+#include <openpcd.h>
+
+#include <os/usb_handler.h>
+#include <os/dbgu.h>
+#include "../openpcd.h"
+
+/* definitions for four-times oversampling */
+#define REQA 0x10410441
+#define WUPA 0x04041041
+
+static const AT91PS_SSC ssc = AT91C_BASE_SSC;
+static AT91PS_PDC rx_pdc;
+
+enum ssc_mode {
+ SSC_MODE_NONE,
+ SSC_MODE_14443A_SHORT,
+ SSC_MODE_14443A_STANDARD,
+ SSC_MODE_14443B,
+ SSC_MODE_EDGE_ONE_SHOT,
+};
+
+struct ssc_state {
+ struct req_ctx *rx_ctx[2];
+ enum ssc_mode mode;
+};
+static struct ssc_state ssc_state;
+
+/* This is for four-times oversampling */
+#define ISO14443A_SOF_SAMPLE 0x08
+#define ISO14443A_SOF_LEN 4
+
+void ssc_rx_mode_set(enum ssc_mode ssc_mode)
+{
+ u_int8_t data_len, num_data, sync_len;
+ u_int32_t start_cond;
+
+ /* disable Rx */
+ ssc->SSC_CR = AT91C_SSC_RXDIS;
+
+ /* disable all Rx related interrupt sources */
+ AT91F_SSC_DisableIt(ssc, AT91C_SSC_RXRDY |
+ AT91C_SSC_OVRUN | AT91C_SSC_ENDRX |
+ AT91C_SSC_RXBUFF | AT91C_SSC_RXSYN |
+ AT91C_SSC_CP0 | AT91C_SSC_CP1);
+
+ switch (ssc_mode) {
+ case SSC_MODE_14443A_SHORT:
+ start_cond = AT91C_SSC_START_0;
+ sync_len = ISO14443A_SOF_LEN;
+ ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE;
+ data_len = 32;
+ num_data = 1;
+ break;
+ case SSC_MODE_14443A_STANDARD:
+ start_cond = AT91C_SSC_START_0;
+ sync_len = ISO14443A_SOF_LEN;
+ ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE;
+ data_len = 1;
+ num_data = 1; /* FIXME */
+ break;
+ case SSC_MODE_14443B:
+ /* start sampling at first falling data edge */
+ //start_cond =
+ break;
+ case SSC_MODE_EDGE_ONE_SHOT:
+ //start_cond = AT91C_SSC_START_EDGE_RF;
+ start_cond = AT91C_SSC_START_CONTINOUS;
+ sync_len = 0;
+ data_len = 8;
+ num_data = 50;
+ break;
+ default:
+ return;
+ }
+ ssc->SSC_RFMR = (data_len-1) & 0x1f |
+ (((num_data-1) & 0x0f) << 8) |
+ (((sync_len-1) & 0x0f) << 16);
+ ssc->SSC_RCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE | start_cond;
+
+ AT91F_PDC_EnableRx(rx_pdc);
+ /* Enable RX interrupts */
+ AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN |
+ AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF);
+
+ ssc_state.mode = ssc_mode;
+
+}
+
+static void ssc_tx_mode_set(enum ssc_mode ssc_mode)
+{
+ u_int8_t data_len, num_data, sync_len;
+ u_int32_t start_cond;
+
+ /* disable Tx */
+ ssc->SSC_CR = AT91C_SSC_TXDIS;
+
+ /* disable all Tx related interrupt sources */
+ ssc->SSC_IDR = AT91C_SSC_TXRDY | AT91C_SSC_TXEMPTY | AT91C_SSC_ENDTX |
+ AT91C_SSC_TXBUFE | AT91C_SSC_TXSYN;
+
+ switch (ssc_mode) {
+ case SSC_MODE_14443A_SHORT:
+ start_cond = AT91C_SSC_START_RISE_RF;
+ sync_len = ISO14443A_SOF_LEN;
+ data_len = 32;
+ num_data = 1;
+ break;
+ case SSC_MODE_14443A_STANDARD:
+ start_cond = AT91C_SSC_START_0;
+ sync_len = ISO14443A_SOF_LEN;
+ ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE;
+ data_len = 1;
+ num_data = 1; /* FIXME */
+ break;
+ }
+ ssc->SSC_TFMR = (data_len-1) & 0x1f |
+ (((num_data-1) & 0x0f) << 8) |
+ (((sync_len-1) & 0x0f) << 16);
+ ssc->SSC_TCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE | start_cond;
+
+#if 0
+ /* Enable RX interrupts */
+ AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN |
+ AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF);
+ AT91F_PDC_EnableRx(rx_pdc);
+
+ ssc_state.mode = ssc_mode;
+#endif
+}
+
+
+
+
+static struct openpcd_hdr opcd_ssc_hdr = {
+ .cmd = OPENPCD_CMD_SSC_READ,
+};
+
+static inline void init_opcdhdr(struct req_ctx *rctx)
+{
+ memcpy(&rctx->tx.data[0], &opcd_ssc_hdr, sizeof(opcd_ssc_hdr));
+ rctx->tx.tot_len = MAX_HDRSIZE + MAX_REQSIZE -1;
+}
+
+#ifdef DEBUG_SSC_REFILL
+#define DEBUGR(x, args ...) DEBUGPCRF(x, ## args)
+#else
+#define DEBUGR(x, args ...)
+#endif
+
+static char dmabuf1[512];
+static char dmabuf2[512];
+
+/* Try to refill RX dma descriptors. Return values:
+ * 0) no dma descriptors empty
+ * 1) filled next/secondary descriptor
+ * 2) filled both primary and secondary descriptor
+ * -1) no free request contexts to use
+ * -2) only one free request context, but two free descriptors
+ */
+static int8_t ssc_rx_refill(void)
+{
+#if 1
+ struct req_ctx *rctx;
+
+ rctx = req_ctx_find_get(RCTX_STATE_FREE, RCTX_STATE_SSC_RX_BUSY);
+ if (!rctx) {
+ DEBUGPCRF("no rctx for refill!");
+ return -1;
+ }
+ init_opcdhdr(rctx);
+
+ if (AT91F_PDC_IsRxEmpty(rx_pdc)) {
+ DEBUGR("filling primary SSC RX dma ctx");
+ AT91F_PDC_SetRx(rx_pdc, &rctx->rx.data[MAX_HDRSIZE],
+ (sizeof(rctx->rx.data)-MAX_HDRSIZE)>>2);
+ ssc_state.rx_ctx[0] = rctx;
+
+ /* If primary is empty, secondary must be empty, too */
+ rctx = req_ctx_find_get(RCTX_STATE_FREE,
+ RCTX_STATE_SSC_RX_BUSY);
+ if (!rctx) {
+ DEBUGPCRF("no rctx for secondary refill!");
+ return -2;
+ }
+ init_opcdhdr(rctx);
+ }
+
+ if (AT91F_PDC_IsNextRxEmpty(rx_pdc)) {
+ DEBUGR("filling secondary SSC RX dma ctx");
+ AT91F_PDC_SetNextRx(rx_pdc, &rctx->rx.data[MAX_HDRSIZE],
+ (sizeof(rctx->rx.data)-MAX_HDRSIZE)>2);
+ ssc_state.rx_ctx[1] = rctx;
+ return 2;
+ } else {
+ /* we were unable to fill*/
+ DEBUGPCRF("prim/secnd DMA busy, can't refill");
+ req_ctx_put(rctx);
+ return 0;
+ }
+#else
+ if (AT91F_PDC_IsRxEmpty(rx_pdc))
+ AT91F_PDC_SetRx(rx_pdc, dmabuf1, sizeof(dmabuf1)>>2);
+
+ if (AT91F_PDC_IsNextRxEmpty(rx_pdc))
+ AT91F_PDC_SetNextRx(rx_pdc, dmabuf2, sizeof(dmabuf2)>>2);
+ else
+ DEBUGPCRF("prim/secnd DMA busy, can't refill");
+#endif
+}
+
+#define ISO14443A_FDT_SHORT_1 1236
+#define ISO14443A_FDT_SHORT_0 1172
+
+static void ssc_irq(void)
+{
+ u_int32_t ssc_sr = ssc->SSC_SR;
+ DEBUGP("ssc_sr=0x%08x, mode=%u: ", ssc_sr, ssc_state.mode);
+
+ if (ssc_sr & AT91C_SSC_OVRUN)
+ DEBUGP("RX OVERRUN ");
+
+ switch (ssc_state.mode) {
+ case SSC_MODE_14443A_SHORT:
+ if (ssc_sr & AT91C_SSC_RXSYN)
+ DEBUGP("RXSYN ");
+ if (ssc_sr & AT91C_SSC_RXRDY) {
+ u_int32_t sample = ssc->SSC_RHR;
+ DEBUGP("RXRDY=0x%08x ", sample);
+ /* Try to set FDT compare register ASAP */
+ if (sample == REQA) {
+ tc_fdt_set(ISO14443A_FDT_SHORT_0);
+ /* FIXME: prepare and configure ATQA response */
+ } else if (sample == WUPA) {
+ tc_fdt_set(ISO14443A_FDT_SHORT_1);
+ /* FIXME: prepare and configure ATQA response */
+ } else
+ DEBUGP("<== unknown ");
+ }
+ break;
+
+ case SSC_MODE_14443A_STANDARD:
+ case SSC_MODE_EDGE_ONE_SHOT:
+
+ if (ssc_sr & (AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF)) {
+#if 1
+ /* Mark primary RCTX as ready to send for usb */
+ req_ctx_set_state(ssc_state.rx_ctx[0],
+ RCTX_STATE_UDP_EP2_PENDING);
+ /* second buffer gets propagated to primary */
+ ssc_state.rx_ctx[0] = ssc_state.rx_ctx[1];
+ ssc_state.rx_ctx[1] = NULL;
+#endif
+
+ if (ssc_sr & AT91C_SSC_RXBUFF) {
+ DEBUGP("RXBUFF, shouldn't happen! ");
+#if 0
+ req_ctx_set_state(ssc_state.rx_ctx[0],
+ RCTX_STATE_UDP_EP2_PENDING);
+#endif
+ }
+ if (ssc_rx_refill() == -1)
+ AT91F_AIC_DisableIt(ssc, AT91C_SSC_ENDRX |
+ AT91C_SSC_RXBUFF |
+ AT91C_SSC_OVRUN);
+ }
+ break;
+ }
+ DEBUGPCR("");
+ AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_SSC);
+}
+
+
+void ssc_rx_unthrottle(void)
+{
+ AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDRX |
+ AT91C_SSC_RXBUFF | AT91C_SSC_OVRUN);
+}
+
+void ssc_rx_start(void)
+{
+ DEBUGPCRF("starting SSC RX\n");
+
+ /* Enable Reception */
+ AT91F_SSC_EnableRx(ssc);
+}
+
+void ssc_rx_stop(void)
+{
+ /* Disable reception */
+ AT91F_SSC_DisableRx(ssc);
+}
+
+void ssc_tx_init(void)
+{
+ /* IMPORTANT: Disable PA23 (PWM0) output, since it is connected to
+ * PA17 !! */
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPCD_PIO_MFIN_PWM);
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, OPENPCD_PIO_MFIN_SSC_TX |
+ OPENPCD_PIO_MFOUT_SSC_RX | OPENPCD_PIO_SSP_CKIN,
+ 0);
+}
+
+static int ssc_usb_in(struct req_ctx *rctx)
+{
+ struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0];
+ struct openpcd_hdr *pih = (struct openpcd_hdr *) &rctx->tx.data[0];
+
+ switch (poh->cmd) {
+ case OPENPCD_CMD_SSC_READ:
+ /* FIXME: allow host to specify mode */
+ ssc_rx_mode_set(SSC_MODE_EDGE_ONE_SHOT);
+ ssc_rx_start();
+ break;
+ case OPENPCD_CMD_SSC_WRITE:
+ /* FIXME: implement this */
+ //ssc_tx_start()
+ break;
+ }
+
+ req_ctx_put(rctx);
+ return -EINVAL;
+}
+
+void ssc_rx_init(void)
+{
+ rx_pdc = (AT91PS_PDC) &(ssc->SSC_RPR);
+
+ AT91F_SSC_CfgPMC();
+
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA,
+ OPENPCD_PIO_MFOUT_SSC_RX | OPENPCD_PIO_SSP_CKIN,
+ 0);
+
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SSC,
+ OPENPCD_IRQ_PRIO_SSC,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &ssc_irq);
+ /* Reset */
+ //ssc->SSC_CR = AT91C_SSC_SWRST;
+
+ /* don't divide clock */
+ ssc->SSC_CMR = 0;
+
+ ssc->SSC_RCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE |
+ AT91C_SSC_START_CONTINOUS;
+ /* Data bits per Data N = 32-1, Data words per Frame = 15-1 (=60 byte)*/
+ ssc->SSC_RFMR = 31 | AT91C_SSC_MSBF | (14 << 8);
+
+ ssc_rx_mode_set(SSC_MODE_EDGE_ONE_SHOT);
+
+ AT91F_PDC_EnableRx(rx_pdc);
+
+ /* Enable RX interrupts */
+ AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN |
+ AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF);
+ AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SSC);
+
+ usb_hdlr_register(&ssc_usb_in, OPENPCD_CMD_CLS_SSC);
+}
+
+void ssc_fini(void)
+{
+ usb_hdlr_unregister(OPENPCD_CMD_CLS_SSC);
+ AT91F_PDC_DisableRx(rx_pdc);
+ AT91F_SSC_DisableTx(ssc);
+ AT91F_SSC_DisableRx(ssc);
+ AT91F_SSC_DisableIt(ssc, 0xfff);
+ AT91F_PMC_DisablePeriphClock(AT91C_BASE_PMC,
+ ((unsigned int) 1 << AT91C_ID_SSC));
+}
diff --git a/firmware/src/picc/ssc_picc.h b/firmware/src/picc/ssc_picc.h
new file mode 100644
index 0000000..710ee45
--- /dev/null
+++ b/firmware/src/picc/ssc_picc.h
@@ -0,0 +1,15 @@
+#ifndef _SSC_H
+#define _SSC_H
+
+extern void ssc_rx_start(void);
+extern void ssc_rx_stop(void);
+
+/* Rx/Tx initialization separate, since Tx disables PWM output ! */
+extern void ssc_tx_init(void);
+extern void ssc_rx_init(void);
+
+extern void ssc_fini(void);
+
+extern void ssc_rx_unthrottle(void);
+
+#endif
diff --git a/firmware/src/picc/tc_fdt.c b/firmware/src/picc/tc_fdt.c
new file mode 100644
index 0000000..041001d
--- /dev/null
+++ b/firmware/src/picc/tc_fdt.c
@@ -0,0 +1,50 @@
+/* OpenPC TC (Timer / Clock) support code
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * PICC Simulator Side:
+ * In order to support responding to synchronous frames (REQA/WUPA/ANTICOL),
+ * we need a second Timer/Counter (TC2). This unit is reset by an external
+ * event (rising edge of modulation pause PCD->PICC) connected to TIOB2, and
+ * counts up to a configurable number of carrier clock cycles (RA). Once the
+ * RA value is reached, TIOA2 will see a rising edge. This rising edge will
+ * be interconnected to TF (Tx Frame) of the SSC to start transmitting our
+ * synchronous response.
+ *
+ */
+
+#include <lib_AT91SAM7.h>
+#include <AT91SAM7.h>
+#include <os/dbgu.h>
+
+#include "../openpcd.h"
+#include <os/tc_cdiv.h>
+#include <picc/tc_fdt.h>
+
+void tc_fdt_set(u_int16_t count)
+{
+ tcb->TCB_TC2.TC_RA = count;
+}
+
+void tc_fdt_init(void)
+{
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, AT91C_PA15_TF,
+ AT91C_PA26_TIOA2 | AT91C_PA27_TIOB2);
+ AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC,
+ ((unsigned int) 1 << AT91C_ID_TC2));
+ /* Enable Clock for TC2 */
+ tcb->TCB_TC2.TC_CCR = AT91C_TC_CLKEN;
+
+ /* Clock XC1, Wave Mode, No automatic reset on RC comp
+ * TIOA2 in RA comp = set, TIOA2 on RC comp = clear,
+ * TIOB2 as input, EEVT = TIOB2, Reset/Trigger on EEVT */
+ tcb->TCB_TC2.TC_CMR = AT91C_TC_CLKS_XC1 | AT91C_TC_WAVE |
+ AT91C_TC_WAVESEL_UP |
+ AT91C_TC_ACPA_SET | AT91C_TC_ACPC_CLEAR |
+ AT91C_TC_BEEVT_NONE | AT91C_TC_BCPB_NONE |
+ AT91C_TC_EEVT_TIOB | AT91C_TC_ETRGEDG_RISING |
+ AT91C_TC_ENETRG ;
+
+ /* Reset to start timers */
+ tcb->TCB_BCR = 1;
+}
+
diff --git a/firmware/src/picc/tc_fdt.h b/firmware/src/picc/tc_fdt.h
new file mode 100644
index 0000000..b39b935
--- /dev/null
+++ b/firmware/src/picc/tc_fdt.h
@@ -0,0 +1,9 @@
+#ifndef _TC_FDT_H
+#define _TC_FDT_H
+
+#include <sys/types.h>
+
+extern void tc_fdt_init(void);
+extern void tc_fdt_set(u_int16_t count);
+
+#endif
diff --git a/firmware/src/start/Cstartup.S b/firmware/src/start/Cstartup.S
new file mode 100644
index 0000000..e91fd86
--- /dev/null
+++ b/firmware/src/start/Cstartup.S
@@ -0,0 +1,386 @@
+/*------------------------------------------------------------------------------
+//*- ATMEL Microcontroller Software Support - ROUSSET -
+//*------------------------------------------------------------------------------
+//* The software is delivered "AS IS" without warranty or condition of any
+//* kind, either express, implied or statutory. This includes without
+//* limitation any warranty or condition with respect to merchantability or
+//* fitness for any particular purpose, or against the infringements of
+//* intellectual property rights of others.
+//*-----------------------------------------------------------------------------
+//*- File source : Cstartup.s
+//*- Object : Generic CStartup for KEIL and GCC No Use REMAP
+//*- Compilation flag : None
+//*-
+//*- 1.0 18/Oct/04 JPP : Creation
+//*- 1.1 21/Feb/05 JPP : Set Interrupt
+//*- 1.1 01/Apr/05 JPP : save SPSR
+//*-----------------------------------------------------------------------------*/
+
+#define CONFIG_DFU_SWITCH
+
+//#define DEBUG_LL
+
+#ifdef DEBUG_LL
+/* Debugging macros for switching on/off LED1 (green) */
+#define PIOA_PER 0xFFFFF400
+#define PIOA_OER 0xFFFFF410
+#define PIOA_SODR 0xFFFFF430
+#define PIOA_CODR 0xFFFFF434
+#define LED1 25 /* this only works on OpenPICC, not Olimex */
+ .macro led1on
+ ldr r2, =PIOA_CODR
+ mov r1, #(1 << LED1)
+ str r1, [r2]
+ .endm
+ .macro led1off
+ ldr r2, =PIOA_SODR
+ mov r1, #(1 << LED1)
+ str r1, [r2]
+ .endm
+ .macro ledinit
+ ldr r2, =PIOA_PER
+ mov r1, #(1 << LED1)
+ str r1, [r2]
+ ldr r2, =PIOA_OER
+ str r1, [r2]
+ led1off
+ .endm
+#else
+ .macro ledinit
+ .endm
+ .macro led1on
+ .endm
+ .macro led1off
+ .endm
+#endif
+
+ .equ IRQ_Stack_Size, 0x00000400
+
+ .equ AIC_IVR, (256)
+ .equ AIC_FVR, (260)
+ .equ AIC_EOICR, (304)
+ .equ AIC_MCR_RCR, (0xf00)
+ .equ AT91C_BASE_AIC, (0xFFFFF000)
+ .equ AT91C_PMC_PCER, (0xFFFFFC10)
+ .equ AT91C_BASE_PIOA, (0xFFFFF400)
+ .equ AT91C_ID_PIOA, (2)
+ .equ PIOA_PDSR, (0x3c)
+ .equ PIO_BOOTLDR, (1 << 27)
+ #.equ PIO_BOOTLDR, (1 << 6)
+
+
+/* #include "AT91SAM7S64_inc.h" */
+
+/* Exception Vectors in RAM */
+
+ .text
+ .arm
+ .section .vectram, "ax"
+resetvecR: B resetvecR
+undefvecR: B undefvecR
+swivecR: B swivecR
+pabtvecR: B pabtvecR
+dabtvecR: B dabtvecR
+rsvdvecR: B rsvdvecR
+irqvecR: B IRQ_Handler_EntryR
+fiqvecR:
+
+FIQ_Handler_EntryR:
+
+/*- Switch in SVC/User Mode to allow User Stack access for C code */
+/* because the FIQ is not yet acknowledged*/
+
+/*- Save and r0 in FIQ_Register */
+ mov r9,r0
+ ldr r0 , [r8, #AIC_FVR]
+ msr CPSR_c,#I_BIT | F_BIT | ARM_MODE_SVC
+
+/*- Save scratch/used registers and LR in User Stack */
+ stmfd sp!, { r1-r3, r12, lr}
+
+/*- Branch to the routine pointed by the AIC_FVR */
+ mov r14, pc
+ bx r0
+
+/*- Restore scratch/used registers and LR from User Stack */
+ ldmia sp!, { r1-r3, r12, lr}
+
+/*- Leave Interrupts disabled and switch back in FIQ mode */
+ msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ
+
+/*- Restore the R0 ARM_MODE_SVC register */
+ mov r0,r9
+
+/*- Restore the Program Counter using the LR_fiq directly in the PC */
+ subs pc,lr,#4
+
+ .global IRQ_Handler_EntryR
+ .func IRQ_Handler_EntryR
+
+IRQ_Handler_EntryR:
+
+/*- Manage Exception Entry */
+/*- Adjust and save LR_irq in IRQ stack */
+ sub lr, lr, #4
+ stmfd sp!, {lr}
+
+/*- Save SPSR need to be saved for nested interrupt */
+ mrs r14, SPSR
+ stmfd sp!, {r14}
+
+/*- Save and r0 in IRQ stack */
+ stmfd sp!, {r0}
+
+/*- Write in the IVR to support Protect Mode */
+/*- No effect in Normal Mode */
+/*- De-assert the NIRQ and clear the source in Protect Mode */
+ ldr r14, =AT91C_BASE_AIC
+ ldr r0 , [r14, #AIC_IVR]
+ str r14, [r14, #AIC_IVR]
+
+/*- Enable Interrupt and Switch in Supervisor Mode */
+ msr CPSR_c, #ARM_MODE_SVC
+
+/*- Save scratch/used registers and LR in User Stack */
+ stmfd sp!, { r1-r3, r12, r14}
+
+/*- Branch to the routine pointed by the AIC_IVR */
+ mov r14, pc
+ bx r0
+/*- Restore scratch/used registers and LR from User Stack*/
+ ldmia sp!, { r1-r3, r12, r14}
+
+/*- Disable Interrupt and switch back in IRQ mode */
+ msr CPSR_c, #I_BIT | ARM_MODE_IRQ
+
+/*- Mark the End of Interrupt on the AIC */
+ ldr r14, =AT91C_BASE_AIC
+ str r14, [r14, #AIC_EOICR]
+
+/*- Restore SPSR_irq and r0 from IRQ stack */
+ ldmia sp!, {r0}
+
+/*- Restore SPSR_irq and r0 from IRQ stack */
+ ldmia sp!, {r14}
+ msr SPSR_cxsf, r14
+
+/*- Restore adjusted LR_irq from IRQ stack directly in the PC */
+ ldmia sp!, {pc}^
+
+ .size IRQ_Handler_EntryR, . - IRQ_Handler_EntryR
+ .endfunc
+
+ .global remap
+ .func remap
+_remap:
+# led1on
+# Remap RAM to 0x00000000 for DFU
+ ldr r1, =AT91C_BASE_AIC
+ mov r2, #0x01
+ str r2, [r1, #AIC_MCR_RCR]
+
+ /* prepare c function call to main */
+ mov r0, #0 /* argc = 0 */
+ ldr lr,=exit
+ ldr r10,=main
+
+#ifdef CONFIG_DFU_SWITCH
+ /* check whether bootloader button is pressed */
+ ldr r1, =AT91C_PMC_PCER
+ mov r2, #(1 << AT91C_ID_PIOA)
+ str r2, [r1]
+
+ ldr r1, =AT91C_BASE_PIOA
+ ldr r2, [r1, #PIOA_PDSR]
+ tst r2, #PIO_BOOTLDR
+ ldrne r10,=dfu_main
+#endif
+
+ bx r10
+ .size remap, . - remap
+ .endfunc
+
+/* "exit" dummy added by mthomas to avoid sbrk write read etc. needed
+ by the newlib default "exit" */
+ .global exit
+ .func exit
+exit:
+ b .
+ .size exit, . - exit
+ .endfunc
+
+/*---------------------------------------------------------------
+//* ?EXEPTION_VECTOR
+//* This module is only linked if needed for closing files.
+//*---------------------------------------------------------------*/
+ .global AT91F_Default_FIQ_handler
+ .func AT91F_Default_FIQ_handler
+AT91F_Default_FIQ_handler:
+ b AT91F_Default_FIQ_handler
+ .size AT91F_Default_FIQ_handler, . - AT91F_Default_FIQ_handler
+ .endfunc
+
+ .global AT91F_Default_IRQ_handler
+ .func AT91F_Default_IRQ_handler
+AT91F_Default_IRQ_handler:
+ b AT91F_Default_IRQ_handler
+ .size AT91F_Default_IRQ_handler, . - AT91F_Default_IRQ_handler
+ .endfunc
+
+ .global AT91F_Spurious_handler
+ .func AT91F_Spurious_handler
+AT91F_Spurious_handler:
+ b AT91F_Spurious_handler
+ .size AT91F_Spurious_handler, . - AT91F_Spurious_handler
+ .endfunc
+
+
+
+#;------------------------------------------------------------------------------
+#;- Section Definition
+#;-----------------
+#;- Section
+#;- .internal_ram_top Top_Stack: used by the cstartup for vector initalisation
+#;- management defined by ld and affect from ldscript
+#;------------------------------------------------------------------------------
+ .section .internal_ram_top
+ .code 32
+ .align 0
+ .global Top_Stack
+Top_Stack:
+
+/*------------------------------------------------------------------------------
+*- Area Definition
+*------------------------------------------------------------------------------
+* .text is used instead of .section .text so it works with arm-aout too. */
+ .section .reset
+ .text
+ .global _startup
+ .func _startup
+_startup:
+reset:
+/*------------------------------------------------------------------------------
+//*- Exception vectors
+//*--------------------
+//*- These vectors can be read at address 0 or at RAM address
+//*- They ABSOLUTELY requires to be in relative addresssing mode in order to
+//*- guarantee a valid jump. For the moment, all are just looping.
+//*- If an exception occurs before remap, this would result in an infinite loop.
+//*- To ensure if a exeption occurs before start application to infinite loop.
+//*------------------------------------------------------------------------------*/
+
+ B InitReset /* 0x00 Reset handler */
+undefvec:
+ B undefvec /* 0x04 Undefined Instruction */
+swivec:
+ B swivec /* 0x08 Software Interrupt */
+pabtvec:
+ B pabtvec /* 0x0C Prefetch Abort */
+dabtvec:
+ B dabtvec /* 0x10 Data Abort */
+rsvdvec:
+ B rsvdvec /* 0x14 reserved */
+irqvec:
+ B irqvec /* 0x18 IRQ */
+fiqvec:
+ B fiqvec /* 0x1c FIQ */
+ .align 0
+.RAM_TOP:
+ .word Top_Stack
+
+InitReset:
+/*------------------------------------------------------------------------------
+/*- Low level Init (PMC, AIC, ? ....) by C function AT91F_LowLevelInit
+/*------------------------------------------------------------------------------*/
+ .extern AT91F_LowLevelInit
+/*- minumum C initialization */
+/*- call AT91F_LowLevelInit( void) */
+
+ ldr r13,.RAM_TOP /* temporary stack in internal RAM */
+/*--Call Low level init function in ABSOLUTE through the Interworking */
+ ldr r0,=AT91F_LowLevelInit
+ mov lr, pc
+ bx r0
+ ledinit
+/*------------------------------------------------------------------------------
+//*- Stack Sizes Definition
+//*------------------------
+//*- Interrupt Stack requires 2 words x 8 priority level x 4 bytes when using
+//*- the vectoring. This assume that the IRQ management.
+//*- The Interrupt Stack must be adjusted depending on the interrupt handlers.
+//*- Fast Interrupt not requires stack If in your application it required you must
+//*- be definehere.
+//*- The System stack size is not defined and is limited by the free internal
+//*- SRAM.
+//*------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+//*- Top of Stack Definition
+//*-------------------------
+//*- Interrupt and Supervisor Stack are located at the top of internal memory in
+//*- order to speed the exception handling context saving and restoring.
+//*- ARM_MODE_SVC (Application, C) Stack is located at the top of the external memory.
+//*------------------------------------------------------------------------------*/
+
+ .EQU IRQ_STACK_SIZE, (3*8*4)
+ .EQU ARM_MODE_FIQ, 0x11
+ .EQU ARM_MODE_IRQ, 0x12
+ .EQU ARM_MODE_SVC, 0x13
+
+ .EQU I_BIT, 0x80
+ .EQU F_BIT, 0x40
+
+/*------------------------------------------------------------------------------
+//*- Setup the stack for each mode
+//*-------------------------------*/
+ mov r0,r13
+
+/*- Set up Fast Interrupt Mode and set FIQ Mode Stack*/
+ msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT
+/*- Init the FIQ register*/
+ ldr r8, =AT91C_BASE_AIC
+
+/*- Set up Interrupt Mode and set IRQ Mode Stack*/
+ msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT
+ mov r13, r0 /* Init stack IRQ */
+ sub r0, r0, #IRQ_Stack_Size
+/*- Set up Supervisor Mode and set Supervisor Mode Stack*/
+ msr CPSR_c, #ARM_MODE_SVC
+ mov r13, r0 /* Init stack Sup */
+
+/*- Relocate DFU .data section (Copy from ROM to RAM)*/
+ ldr r1, =_etext_dfu
+ ldr r2, =_data_dfu
+ ldr r3, =_edata_dfu
+LoopRelDFU: cmp r2, r3
+ ldrlo r0, [r1], #4
+ strlo r0, [r2], #4
+ blo LoopRelDFU
+
+# Relocate .data section (Copy from ROM to RAM)
+ LDR R1, =_etext
+ LDR R2, =_data
+ LDR R3, =_edata
+LoopRel: CMP R2, R3
+ LDRLO R0, [R1], #4
+ STRLO R0, [R2], #4
+ BLO LoopRel
+
+# Clear .bss section (Zero init)
+ MOV R0, #0
+ LDR R1, =__bss_start__
+ LDR R2, =__bss_end__
+LoopZI: CMP R1, R2
+ STRLO R0, [R1], #4
+ BLO LoopZI
+
+ led1on
+
+ ldr r0, =_remap
+ bx r0
+
+ .size _startup, . - _startup
+ .endfunc
+
+ .end
+
diff --git a/firmware/src/start/Cstartup_SAM7.c b/firmware/src/start/Cstartup_SAM7.c
new file mode 100644
index 0000000..66dbe20
--- /dev/null
+++ b/firmware/src/start/Cstartup_SAM7.c
@@ -0,0 +1,89 @@
+//*----------------------------------------------------------------------------
+//* ATMEL Microcontroller Software Support - ROUSSET -
+//*----------------------------------------------------------------------------
+//* The software is delivered "AS IS" without warranty or condition of any
+//* kind, either express, implied or statutory. This includes without
+//* limitation any warranty or condition with respect to merchantability or
+//* fitness for any particular purpose, or against the infringements of
+//* intellectual property rights of others.
+//*----------------------------------------------------------------------------
+//* File Name : Cstartup_SAM7.c
+//* Object : Low level initializations written in C for GCC Tools
+//* Creation : 12/Jun/04
+//* 1.2 28/Feb/05 JPP : LIB change AT91C_WDTC_WDDIS & PLL
+//* 1.3 21/Mar/05 JPP : Change PLL Wait time
+//*----------------------------------------------------------------------------
+
+// Include the board file description
+#include <board.h>
+
+// The following functions must be write in ARM mode this function called directly
+// by exception vector
+extern void AT91F_Spurious_handler (void);
+extern void AT91F_Default_IRQ_handler (void);
+extern void AT91F_Default_FIQ_handler (void);
+
+//*----------------------------------------------------------------------------
+//* \fn AT91F_LowLevelInit
+//* \brief This function performs very low level HW initialization
+//* this function can be use a Stack, depending the compilation
+//* optimization mode
+//*----------------------------------------------------------------------------
+void
+AT91F_LowLevelInit (void)
+{
+ int i;
+ AT91PS_PMC pPMC = AT91C_BASE_PMC;
+ //* Set Flash Waite sate
+ // Single Cycle Access at Up to 30 MHz, or 40
+ // if MCK = 47923200 I have 50 Cycle for 1 usecond ( flied MC_FMR->FMCN
+ AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN) & (48 << 16)) | AT91C_MC_FWS_1FWS;
+
+ //* Watchdog Disable
+ AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
+
+ //* Set MCK at 47 923 200
+ // 1 Enabling the Main Oscillator:
+ // SCK = 1/32768 = 30.51 uSecond
+ // Start up time = 8 * 6 / SCK = 56 * 30.51 = 1,46484375 ms
+ pPMC->PMC_MOR = ((AT91C_CKGR_OSCOUNT) & (0x06 << 8)) | AT91C_CKGR_MOSCEN;
+ // Wait the startup time
+ while (!(pPMC->PMC_SR & AT91C_PMC_MOSCS));
+ // 2 Checking the Main Oscillator Frequency (Optional)
+ // 3 Setting PLL and divider:
+ // - div by 24 Fin = 0,7680 =(18,432 / 24)
+ // - Mul 125: Fout = 96,0000 =(0,7680 *125)
+ // for 96 MHz the erroe is 0.16%
+ // Field out NOT USED = 0
+ // PLLCOUNT pll startup time estimate at : 0.844 ms
+ // PLLCOUNT 28 = 0.000844 /(1/32768)
+#if 0
+ pPMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x05) |
+ (AT91C_CKGR_PLLCOUNT & (28 << 8)) |
+ (AT91C_CKGR_MUL & (25 << 16)));
+#else
+ pPMC->PMC_PLLR = ((AT91C_CKGR_DIV & 24) |
+ (AT91C_CKGR_PLLCOUNT & (28 << 8)) |
+ (AT91C_CKGR_MUL & (125 << 16)));
+#endif
+
+ // Wait the startup time
+ while (!(pPMC->PMC_SR & AT91C_PMC_LOCK));
+ while (!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
+ // 4. Selection of Master Clock and Processor Clock
+ // select the PLL clock divided by 2
+ pPMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
+ while (!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
+
+ pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK;
+ while (!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
+
+ // Set up the default interrupts handler vectors
+ AT91C_BASE_AIC->AIC_SVR[0] = (int) AT91F_Default_FIQ_handler;
+ for (i = 1; i < 31; i++)
+ {
+ AT91C_BASE_AIC->AIC_SVR[i] = (int) AT91F_Default_IRQ_handler;
+ }
+ AT91C_BASE_AIC->AIC_SPU = (int) AT91F_Spurious_handler;
+
+}
personal git repositories of Harald Welte. Your mileage may vary