summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--openpicc/Makefile.dfu566
-rw-r--r--openpicc/application/flash.c68
-rw-r--r--openpicc/application/flash.h5
-rw-r--r--openpicc/config/board.h19
-rw-r--r--openpicc/dfu/dbgu.c140
-rw-r--r--openpicc/dfu/dbgu.h25
-rw-r--r--openpicc/dfu/dfu.c938
-rw-r--r--openpicc/dfu/dfu.h143
-rw-r--r--openpicc/dfu/usb_strings_dfu.h120
-rw-r--r--openpicc/dfu/usb_strings_dfu.txt5
-rw-r--r--openpicc/include/compile.h9
-rw-r--r--openpicc/include/usb_ch9.h550
-rw-r--r--openpicc/include/usb_dfu.h81
-rw-r--r--openpicc/os/boot/Cstartup.S450
-rw-r--r--openpicc/os/boot/Cstartup_SAM7.c101
-rw-r--r--openpicc/os/boot/Cstartup_app.S194
16 files changed, 3375 insertions, 39 deletions
diff --git a/openpicc/Makefile.dfu b/openpicc/Makefile.dfu
new file mode 100644
index 0000000..9a6f5fd
--- /dev/null
+++ b/openpicc/Makefile.dfu
@@ -0,0 +1,566 @@
+# 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=-sam7dfu-dfu
+
+# 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:=dfu
+
+USBSTRINGS=dfu/usb_strings_dfu.h
+
+# 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
+
+SRCARM = os/boot/Cstartup_SAM7.c os/core/ARM7_AT91SAM7S/lib_AT91SAM7.c \
+ dfu/dfu.c dfu/dbgu.c application/flash.c
+
+# 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 =
+
+# List Assembler source files here which must be assembled in ARM-Mode..
+ASRCARM = os/boot/Cstartup.S
+
+ifeq ($(DEBUG),1)
+SRCARM += lib/vsprintf.c lib/ctype.c lib/string.c
+ASRCARM += lib/div64.S
+endif
+
+## 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 = os/core/ARM7_AT91SAM7S config
+
+# 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__ -DCONFIG_USB_STRING
+
+ifdef DEBUG
+CDEFS += -DDEBUG
+ADEFS += -DDEBUG
+endif
+
+ifeq ($(BOARD),OLIMEX)
+CDEFS += -DOLIMEX
+ADEFS += -DOLIMEX
+endif
+
+ifeq ($(BOARD),PICC)
+CDEFS += -DPICC
+ADEFS += -DPICC
+CINCS = -Isrc/picc
+endif
+
+ifeq ($(BOARD),PCD)
+SUBMDL = AT91SAM7S128
+CDEFS += -DPCD
+ADEFS += -DPCD
+CINCS = -Isrc/pcd
+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) -DBOARD=$(BOARD)
+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 include/compile.h $(USBSTRINGS)
+ @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/*
+ $(REMOVE) src/picc/usb_strings_dfu.h
+ $(REMOVE) src/dfu/usb_strings_dfu.h
+ $(REMOVE) scripts/usbstring
+
+.PHONY: include/compile.h
+include/compile.h:
+ scripts/mkcompile_h > $@
+
+.PHONY:
+$(USBSTRINGS): %.h : %.txt ./scripts/usbstring
+ cat $< | ./scripts/usbstring > $@
+
+scripts/usbstring: scripts/usbstring.c
+ gcc $^ -o $@
+
+
+# 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/openpicc/application/flash.c b/openpicc/application/flash.c
new file mode 100644
index 0000000..c729ff8
--- /dev/null
+++ b/openpicc/application/flash.c
@@ -0,0 +1,68 @@
+#include <sys/types.h>
+#include <lib_AT91SAM7.h>
+#include <AT91SAM7.h>
+#include <dfu/dbgu.h>
+#include <board.h>
+
+#define EFCS_CMD_WRITE_PAGE 0x1
+#define EFCS_CMD_SET_LOCK_BIT 0x2
+#define EFCS_CMD_WRITE_PAGE_LOCK 0x3
+#define EFCS_CMD_CLEAR_LOCK 0x4
+#define EFCS_CMD_ERASE_ALL 0x8
+#define EFCS_CMD_SET_NVM_BIT 0xb
+#define EFCS_CMD_CLEAR_NVM_BIT 0xd
+#define EFCS_CMD_SET_SECURITY_BIT 0xf
+
+static u_int16_t page_from_ramaddr(const void *addr)
+{
+ u_int32_t ramaddr = (u_int32_t) addr;
+ ramaddr -= (u_int32_t) AT91C_IFLASH;
+ return ((ramaddr >> AT91C_IFLASH_PAGE_SHIFT));
+}
+#define PAGES_PER_LOCKREGION (AT91C_IFLASH_LOCK_REGION_SIZE>>AT91C_IFLASH_PAGE_SHIFT)
+#define IS_FIRST_PAGE_OF_LOCKREGION(x) ((x % PAGES_PER_LOCKREGION) == 0)
+#define LOCKREGION_FROM_PAGE(x) (x / PAGES_PER_LOCKREGION)
+
+static int is_page_locked(u_int16_t page)
+{
+ u_int16_t lockregion = LOCKREGION_FROM_PAGE(page);
+
+ return (AT91C_BASE_MC->MC_FSR & (lockregion << 16));
+}
+
+static void unlock_page(u_int16_t page)
+{
+ page &= 0x3ff;
+ AT91F_MC_EFC_PerformCmd(AT91C_BASE_MC, AT91C_MC_FCMD_UNLOCK |
+ AT91C_MC_CORRECT_KEY | (page << 8));
+}
+
+void flash_page(u_int8_t *addr)
+{
+ u_int16_t page = page_from_ramaddr(addr) & 0x3ff;
+ u_int32_t fsr = AT91F_MC_EFC_GetStatus(AT91C_BASE_MC);
+ DEBUGP("flash_page(0x%x=%u) ", addr, page);
+
+ if (is_page_locked(page)) {
+ DEBUGP("unlocking ");
+ unlock_page(page);
+ }
+
+ if (!(fsr & AT91C_MC_FRDY)) {
+ DEBUGP("NOT_FLASHING ");
+ return;
+ }
+
+ DEBUGP("performing start_prog ");
+
+ AT91F_MC_EFC_PerformCmd(AT91C_BASE_MC, AT91C_MC_FCMD_START_PROG |
+ AT91C_MC_CORRECT_KEY | (page << 8));
+}
+
+void flash_init(void)
+{
+ unsigned int fmcn = AT91F_MC_EFC_ComputeFMCN(MCK);
+
+ AT91F_MC_EFC_CfgModeReg(AT91C_BASE_MC, (fmcn&0xff) << 16 |
+ AT91C_MC_FWS_3FWS);
+}
diff --git a/openpicc/application/flash.h b/openpicc/application/flash.h
new file mode 100644
index 0000000..b812714
--- /dev/null
+++ b/openpicc/application/flash.h
@@ -0,0 +1,5 @@
+#ifndef _FLASH_H
+#define _FLASH_H
+extern void flash_page(u_int8_t *addr);
+extern void flash_init(void);
+#endif
diff --git a/openpicc/config/board.h b/openpicc/config/board.h
index 065c26d..c052d1e 100644
--- a/openpicc/config/board.h
+++ b/openpicc/config/board.h
@@ -61,6 +61,25 @@
#define OPENPICC_PIO_PLL_INHIBIT AT91C_PIO_PA24
#define OPENPICC_PIO_PLL_LOCK AT91C_PIO_PA4
+#define OPENPCD_PIO_UDP_CNX NO_UDP_CNX
+#define OPENPCD_PIO_UDP_PUPv4 AT91C_PIO_PA16
+#define OPENPCD_PIO_LED1 AT91C_PIO_PA25
+#define OPENPCD_PIO_LED2 AT91C_PIO_PA12
+#define PIO_BOOTLDR AT91C_PIO_PA6
+
+#define OPENPCD_VENDOR_ID 0x16c0
+#define OPENPCD_PRODUCT_ID 0x076b
+#define OPENPICC_PRODUCT_ID 0x076c
+
+#define USB_PRODUCT_ID OPENPICC_PRODUCT_ID
+#define USB_VENDOR_ID OPENPCD_VENDOR_ID
+
+/*----------------------*/
+/* interrupt priorities */
+/*----------------------*/
+
+#define OPENPCD_IRQ_PRIO_UDP (AT91C_AIC_PRIOR_LOWEST+2)
+
/*-----------------*/
/* task priorities */
/*-----------------*/
diff --git a/openpicc/dfu/dbgu.c b/openpicc/dfu/dbgu.c
new file mode 100644
index 0000000..ded704b
--- /dev/null
+++ b/openpicc/dfu/dbgu.c
@@ -0,0 +1,140 @@
+/* AT91SAM7 debug function implementation for OpenPCD
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program 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 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <lib_AT91SAM7.h>
+#include <board.h>
+#include <dfu/dbgu.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#define USART_SYS_LEVEL 4
+void AT91F_DBGU_Ready(void)
+{
+ while (!(AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXEMPTY)) ;
+}
+
+static void DBGU_irq_handler(void)
+{
+ static char value;
+
+ AT91F_DBGU_Get(&value);
+ switch (value) {
+ case '9':
+ AT91F_DBGU_Printk("Resetting SAM7\n\r");
+ AT91F_RSTSoftReset(AT91C_BASE_RSTC, AT91C_RSTC_PROCRST|
+ AT91C_RSTC_PERRST|AT91C_RSTC_EXTRST);
+ break;
+ default:
+ AT91F_DBGU_Printk("\n\r");
+ }
+}
+
+void AT91F_DBGU_Init(void)
+{
+ /* 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(AT91C_BASE_DBGU,
+ MCK, AT91C_US_ASYNC_MODE,
+ AT91C_DBGU_BAUD, 0);
+
+ /* 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_ID_SYS, USART_SYS_LEVEL,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
+ DBGU_irq_handler);
+ AT91F_AIC_EnableIt(AT91C_ID_SYS);
+
+}
+
+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++);
+ }
+}
+
+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);
+ }
+}
+
+#ifdef DEBUG
+
+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);
+}
+
+
+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;
+}
+
+static char dbg_buf[2048];
+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);
+}
+
+#endif
diff --git a/openpicc/dfu/dbgu.h b/openpicc/dfu/dbgu.h
new file mode 100644
index 0000000..5ec8a49
--- /dev/null
+++ b/openpicc/dfu/dbgu.h
@@ -0,0 +1,25 @@
+#ifndef dbgu_h
+#define dbgu_h
+
+#define AT91C_DBGU_BAUD 115200
+
+#define DEBUGP(x, args ...) debugp(x, ## args)
+#define DEBUGPCR(x, args ...) DEBUGP(x "\r\n", ## args)
+#define DEBUGPCRF(x, args ...) DEBUGPCR("%s(%d): " x, __FUNCTION__, __LINE__, ## args)
+
+extern void AT91F_DBGU_Init(void);
+extern void AT91F_DBGU_Printk(char *buffer);
+extern int AT91F_DBGU_Get(char *val);
+extern void AT91F_DBGU_Ready(void);
+
+#ifdef DEBUG
+extern void debugp(const char *format, ...);
+extern const char *hexdump(const void *data, unsigned int len);
+extern void AT91F_DBGU_Frame(char *buffer);
+#else
+#define debugp(x, args ...)
+#define hexdump(x, args ...)
+#define AT91F_DBGU_Frame(x)
+#endif
+
+#endif /* dbgu_h */
diff --git a/openpicc/dfu/dfu.c b/openpicc/dfu/dfu.c
new file mode 100644
index 0000000..af09a62
--- /dev/null
+++ b/openpicc/dfu/dfu.c
@@ -0,0 +1,938 @@
+/* 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
+ *
+ * This program 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 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <errno.h>
+#include <usb_ch9.h>
+#include <usb_dfu.h>
+#include <board.h>
+#include <lib_AT91SAM7.h>
+
+#include "usb_strings_dfu.h"
+
+#include <dfu/dfu.h>
+#include <dfu/dbgu.h>
+#include <application/flash.h>
+//#include <os/pcd_enumerate.h>
+//#include "../openpcd.h"
+
+#include <compile.h>
+
+#define SAM7DFU_SIZE 0x4000
+
+/* If debug is enabled, we need to access debug functions from flash
+ * and therefore have to omit flashing */
+#define DEBUG_DFU_NOFLASH
+
+#ifdef DEBUG
+#define DEBUG_DFU_EP0
+//#define DEBUG_DFU_RECV
+#endif
+
+#ifdef DEBUG_DFU_EP0
+#define DEBUGE DEBUGP
+#else
+#define DEBUGE(x, args ...)
+#endif
+
+#ifdef DEBUG_DFU_RECV
+#define DEBUGR DEBUGP
+#else
+#define DEBUGR(x, args ...)
+#endif
+
+#define RET_NOTHING 0
+#define RET_ZLP 1
+#define RET_STALL 2
+
+#define led1on() AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1)
+#define led1off() AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1)
+
+#define led2on() AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2)
+#define led2off() AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2)
+
+static 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 */
+#if defined(PCD)
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
+#endif
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4);
+}
+
+/* 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) ;
+ }
+}
+
+static void udp_ep0_recv_clean(void)
+{
+ unsigned int i;
+ u_int8_t dummy;
+ const AT91PS_UDP pUdp = AT91C_BASE_UDP;
+
+ while (!(pUdp->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0)) ;
+
+ for (i = 0; i < (pUdp->UDP_CSR[0] >> 16); i++)
+ dummy = pUdp->UDP_FDR[0];
+
+ pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
+}
+
+/* receive data from EP0 */
+static int __dfufunc udp_ep0_recv_data(u_int8_t *data, u_int16_t len)
+{
+ AT91PS_UDP pUdp = AT91C_BASE_UDP;
+ AT91_REG csr;
+ u_int16_t i, num_rcv;
+ u_int32_t num_rcv_total = 0;
+
+ do {
+ /* FIXME: do we need to check whether we've been interrupted
+ * by a RX SETUP stage? */
+ do {
+ csr = pUdp->UDP_CSR[0];
+ DEBUGR("CSR=%08x ", csr);
+ } while (!(csr & AT91C_UDP_RX_DATA_BK0)) ;
+
+ num_rcv = pUdp->UDP_CSR[0] >> 16;
+
+ /* make sure we don't read more than requested */
+ if (num_rcv_total + num_rcv > len)
+ num_rcv = num_rcv_total - len;
+
+ DEBUGR("num_rcv = %u ", num_rcv);
+ for (i = 0; i < num_rcv; i++)
+ *data++ = pUdp->UDP_FDR[0];
+ pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
+
+ num_rcv_total += num_rcv;
+
+ /* we need to continue to pull data until we either receive
+ * a packet < endpoint size or == 0 */
+ } while (num_rcv == 8 && num_rcv_total < len);
+
+ DEBUGE("ep0_rcv_returning(%u total) ", num_rcv_total);
+
+ return num_rcv_total;
+}
+
+/* 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 *ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
+static __dfudata u_int8_t dfu_status;
+__dfudata u_int32_t dfu_state = DFU_STATE_appIDLE;
+static u_int32_t pagebuf32[AT91C_IFLASH_PAGE_SIZE/4];
+
+static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len)
+{
+ volatile u_int32_t *p = (volatile u_int32_t *)ptr;
+ u_int8_t *pagebuf = (u_int8_t *) pagebuf32;
+ int i;
+
+ DEBUGE("download ");
+
+ if (len > AT91C_IFLASH_PAGE_SIZE) {
+ /* Too big. Not that we'd really care, but it's a
+ * DFU protocol violation */
+ DEBUGP("length exceeds flash page size ");
+ dfu_state = DFU_STATE_dfuERROR;
+ dfu_status = DFU_STATUS_errADDRESS;
+ return RET_STALL;
+ }
+ if (len & 0x3) {
+ /* reject non-four-byte-aligned writes */
+ DEBUGP("not four-byte-aligned length ");
+ dfu_state = DFU_STATE_dfuERROR;
+ dfu_status = DFU_STATUS_errADDRESS;
+ return RET_STALL;
+ }
+ if (len == 0) {
+ DEBUGP("zero-size write -> MANIFEST_SYNC ");
+ flash_page(p);
+ dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
+ return RET_ZLP;
+ }
+ if (ptr + len >= (u_int8_t *) AT91C_IFLASH + AT91C_IFLASH_SIZE - ENVIRONMENT_SIZE ) {
+ DEBUGP("end of write exceeds flash end ");
+ dfu_state = DFU_STATE_dfuERROR;
+ dfu_status = DFU_STATUS_errADDRESS;
+ return RET_STALL;
+ }
+
+ DEBUGP("try_to_recv=%u ", len);
+ udp_ep0_recv_data(pagebuf, len);
+
+ DEBUGR(hexdump(pagebuf, len));
+
+ /* we can only access the write buffer with correctly aligned
+ * 32bit writes ! */
+#ifndef DEBUG_DFU_NOFLASH
+ DEBUGP("copying ");
+ for (i = 0; i < len/4; i++) {
+ *p++ = pagebuf32[i];
+ /* If we have filled a page buffer, flash it */
+ if (((unsigned long)p % AT91C_IFLASH_PAGE_SIZE) == 0) {
+ DEBUGP("page_full ");
+ flash_page(p-1);
+ }
+ }
+ ptr = (u_int8_t *) p;
+#endif
+
+ return RET_ZLP;
+}
+
+#define AT91C_IFLASH_END ((u_int8_t *)AT91C_IFLASH + AT91C_IFLASH_SIZE)
+static __dfufunc int handle_upload(u_int16_t val, u_int16_t len)
+{
+ DEBUGE("upload ");
+ if (len > AT91C_IFLASH_PAGE_SIZE) {
+ /* Too big */
+ dfu_state = DFU_STATE_dfuERROR;
+ dfu_status = DFU_STATUS_errADDRESS;
+ udp_ep0_send_stall();
+ return -EINVAL;
+ }
+
+ if (ptr + len > AT91C_IFLASH_END)
+ len = AT91C_IFLASH_END - (u_int8_t *)ptr;
+
+ udp_ep0_send_data((char *)ptr, len);
+ ptr+= len;
+
+ return len;
+}
+
+static __dfufunc void handle_getstatus(void)
+{
+ struct dfu_status dstat;
+ u_int32_t fsr = AT91F_MC_EFC_GetStatus(AT91C_BASE_MC);
+
+ DEBUGE("getstatus(fsr=0x%08x) ", fsr);
+
+ switch (dfu_state) {
+ case DFU_STATE_dfuDNLOAD_SYNC:
+ case DFU_STATE_dfuDNBUSY:
+ if (fsr & AT91C_MC_PROGE) {
+ DEBUGE("errPROG ");
+ dfu_status = DFU_STATUS_errPROG;
+ dfu_state = DFU_STATE_dfuERROR;
+ } else if (fsr & AT91C_MC_LOCKE) {
+ DEBUGE("errWRITE ");
+ dfu_status = DFU_STATUS_errWRITE;
+ dfu_state = DFU_STATE_dfuERROR;
+ } else if (fsr & AT91C_MC_FRDY) {
+ DEBUGE("DNLOAD_IDLE ");
+ dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
+ } else {
+ DEBUGE("DNBUSY ");
+ dfu_state = DFU_STATE_dfuDNBUSY;
+ }
+ break;
+ case DFU_STATE_dfuMANIFEST_SYNC:
+ dfu_state = DFU_STATE_dfuMANIFEST;
+ break;
+ }
+
+ /* send status response */
+ dstat.bStatus = dfu_status;
+ dstat.bState = dfu_state;
+ dstat.iString = 0;
+ /* FIXME: set dstat.bwPollTimeout */
+
+ 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, ret = RET_NOTHING;
+
+ DEBUGE("old_state = %u ", dfu_state);
+
+ switch (dfu_state) {
+ case DFU_STATE_appIDLE:
+ switch (req) {
+ case USB_REQ_DFU_GETSTATUS:
+ handle_getstatus();
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate();
+ break;
+ case USB_REQ_DFU_DETACH:
+ dfu_state = DFU_STATE_appDETACH;
+ ret = RET_ZLP;
+ goto out;
+ break;
+ default:
+ ret = RET_STALL;
+ }
+ 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;
+ ret = RET_STALL;
+ goto out;
+ 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;
+ ret = RET_STALL;
+ goto out;
+ }
+ dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
+ ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
+ ret = handle_dnload(val, len);
+ break;
+ case USB_REQ_DFU_UPLOAD:
+ ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
+ dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
+ handle_upload(val, len);
+ break;
+ case USB_REQ_DFU_ABORT:
+ /* no zlp? */
+ ret = RET_ZLP;
+ break;
+ case USB_REQ_DFU_GETSTATUS:
+ handle_getstatus();
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate();
+ break;
+ default:
+ dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ goto out;
+ 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;
+ ret = RET_STALL;
+ goto out;
+ }
+ break;
+ case DFU_STATE_dfuDNBUSY:
+ switch (req) {
+ case USB_REQ_DFU_GETSTATUS:
+ /* FIXME: only accept getstatus if bwPollTimeout
+ * has elapsed */
+ handle_getstatus();
+ break;
+ default:
+ dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ goto out;
+ }
+ break;
+ case DFU_STATE_dfuDNLOAD_IDLE:
+ switch (req) {
+ case USB_REQ_DFU_DNLOAD:
+ dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
+ ret = handle_dnload(val, len);
+ break;
+ case USB_REQ_DFU_ABORT:
+ dfu_state = DFU_STATE_dfuIDLE;
+ ret = RET_ZLP;
+ break;
+ case USB_REQ_DFU_GETSTATUS:
+ handle_getstatus();
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate();
+ break;
+ default:
+ dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ break;
+ }
+ break;
+ case DFU_STATE_dfuMANIFEST_SYNC:
+ switch (req) {
+ case USB_REQ_DFU_GETSTATUS:
+ handle_getstatus();
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate();
+ break;
+ default:
+ dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ break;
+ }
+ break;
+ case DFU_STATE_dfuMANIFEST:
+ dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_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? */
+ ret = RET_ZLP;
+ break;
+ case USB_REQ_DFU_GETSTATUS:
+ handle_getstatus();
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate();
+ break;
+ default:
+ dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_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;
+ dfu_status = DFU_STATUS_OK;
+ /* no zlp? */
+ ret = RET_ZLP;
+ break;
+ default:
+ dfu_state = DFU_STATE_dfuERROR;
+ ret = RET_STALL;
+ break;
+ }
+ break;
+ }
+
+out:
+ DEBUGE("new_state = %u\r\n", dfu_state);
+
+ switch (ret) {
+ case RET_NOTHING:
+ break;
+ case RET_ZLP:
+ udp_ep0_send_zlp();
+ break;
+ case RET_STALL:
+ udp_ep0_send_stall();
+ break;
+ }
+ 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 = USB_VENDOR_ID,
+ .idProduct = USB_PRODUCT_ID,
+ .bcdDevice = 0x0000,
+ .iManufacturer = 1,
+ .iProduct = 2,
+ .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,
+#ifdef CONFIG_USB_STRING
+ .iConfiguration = 3,
+#else
+ .iConfiguration = 0,
+#endif
+ .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,
+#ifdef CONFIG_USB_STRING
+ .iInterface = 4,
+#else
+ .iInterface = 0,
+#endif
+ },
+ .uif[1] = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0x00,
+ .bAlternateSetting = 0x01,
+ .bNumEndpoints = 0x00,
+ .bInterfaceClass = 0xfe,
+ .bInterfaceSubClass = 0x01,
+ .bInterfaceProtocol = 0x02,
+#ifdef CONFIG_USB_STRING
+ .iInterface = 5,
+#else
+ .iInterface = 0,
+#endif
+ },
+
+ .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\r\n");
+ return;
+ }
+
+ DEBUGE("len=%d ", csr >> 16);
+ if (csr >> 16 == 0) {
+ DEBUGE("empty packet\r\n");
+ 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) {
+ u_int8_t desc_type, desc_index;
+ case STD_GET_DESCRIPTOR:
+ DEBUGE("GET_DESCRIPTOR ");
+ desc_type = wValue >> 8;
+ desc_index = wValue & 0xff;
+ switch (desc_type) {
+ case USB_DT_DEVICE:
+ /* Return Device Descriptor */
+ udp_ep0_send_data((const char *)
+ &dfu_dev_descriptor,
+ MIN(sizeof(dfu_dev_descriptor),
+ wLength));
+ break;
+ case USB_DT_CONFIG:
+ /* Return Configuration Descriptor */
+ udp_ep0_send_data((const char *)
+ &dfu_cfg_descriptor,
+ MIN(sizeof(dfu_cfg_descriptor),
+ wLength));
+ break;
+ case USB_DT_STRING:
+ /* Return String Descriptor */
+ if (desc_index > ARRAY_SIZE(usb_strings)) {
+ udp_ep0_send_stall();
+ break;
+ }
+ DEBUGE("bLength=%u, wLength=%u ",
+ usb_strings[desc_index]->bLength, wLength);
+ udp_ep0_send_data((const char *) usb_strings[desc_index],
+ MIN(usb_strings[desc_index]->bLength,
+ wLength));
+ break;
+ case USB_DT_CS_DEVICE:
+ /* Return Function descriptor */
+ udp_ep0_send_data((const char *) &dfu_cfg_descriptor.func_dfu,
+ MIN(sizeof(dfu_cfg_descriptor.func_dfu),
+ wLength));
+ break;
+ default:
+ udp_ep0_send_stall();
+ break;
+ }
+ 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 ");
+ /* FIXME: store the interface number somewhere, once
+ * we need to support DFU flashing DFU */
+ udp_ep0_send_zlp();
+ 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;
+ }
+ DEBUGE("\r\n");
+}
+
+/* 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;
+ led1on();
+
+ if (isr & AT91C_UDP_ENDBUSRES) {
+ led2on();
+ 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 (dfu_state == DFU_STATE_dfuMANIFEST_WAIT_RST ||
+ dfu_state == DFU_STATE_dfuMANIFEST) {
+ AT91F_RSTSoftReset(AT91C_BASE_RSTC, AT91C_RSTC_PROCRST|
+ AT91C_RSTC_PERRST|
+ AT91C_RSTC_EXTRST);
+ }
+
+ }
+
+ if (isr & AT91C_UDP_EPINT0)
+ dfu_udp_ep0_handler();
+
+ /* clear all interrupts */
+ pUDP->UDP_ICR = isr;
+
+ AT91F_AIC_ClearIt(AT91C_ID_UDP);
+
+ led1off();
+}
+
+/* this is only called once before DFU mode, no __dfufunc required */
+static void dfu_switch(void)
+{
+ AT91PS_AIC pAic = AT91C_BASE_AIC;
+
+ DEBUGE("\r\nsam7dfu: switching to DFU mode\r\n");
+
+ dfu_state = DFU_STATE_appDETACH;
+ AT91F_RSTSoftReset(AT91C_BASE_RSTC, AT91C_RSTC_PROCRST|
+ AT91C_RSTC_PERRST|AT91C_RSTC_EXTRST);
+
+ /* We should never reach here, but anyway avoid returning to the
+ * caller since he doesn't expect us to do so */
+ while (1) ;
+}
+
+void __dfufunc dfu_main(void)
+{
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1);
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2);
+ led1off();
+ led2off();
+
+ AT91F_DBGU_Init();
+ AT91F_DBGU_Printk("\n\r\n\rsam7dfu - AT91SAM7 USB DFU bootloader\n\r"
+ "(C) 2006 by Harald Welte <hwelte@hmw-consulting.de>\n\r"
+ "This software is FREE SOFTWARE licensed under GNU GPL\n\r");
+ AT91F_DBGU_Printk("Version " COMPILE_SVNREV
+ " compiled " COMPILE_DATE
+ " by " COMPILE_BY "\n\r\n\r");
+
+ udp_init();
+
+ dfu_state = DFU_STATE_dfuIDLE;
+
+ /* 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_ID_UDP);
+
+ /* End-of-Bus-Reset is always enabled */
+
+ /* Clear for set the Pull up resistor */
+#if defined(PCD)
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
+#endif
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4);
+
+ flash_init();
+
+ AT91F_DBGU_Printk("You may now start the DFU up/download process\r\n");
+ /* do nothing, since all of DFU is interrupt driven */
+ int i = 0;
+ while (1) {
+ /* Occasionally reset watchdog */
+ i = (i+1) % 10000;
+ if( i== 0) {
+ AT91F_WDTRestart(AT91C_BASE_WDTC);
+ }
+ }
+}
+
+const struct dfuapi __dfufunctab dfu_api = {
+ .udp_init = &udp_init,
+ .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/openpicc/dfu/dfu.h b/openpicc/dfu/dfu.h
new file mode 100644
index 0000000..77f80a1
--- /dev/null
+++ b/openpicc/dfu/dfu.h
@@ -0,0 +1,143 @@
+#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
+ *
+ * This program 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 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <usb_ch9.h>
+#include <usb_dfu.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 */
+#ifdef CONFIG_USB_STRING
+#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, \
+ }, { \
+ .bLength = USB_DT_INTERFACE_SIZE, \
+ .bDescriptorType = USB_DT_INTERFACE, \
+ .bInterfaceNumber = 0x02, \
+ .bAlternateSetting = 0x00, \
+ .bNumEndpoints = 0x00, \
+ .bInterfaceClass = 0xfe, \
+ .bInterfaceSubClass = 0x01, \
+ .bInterfaceProtocol = 0x01, \
+ .iInterface = 2, \
+ }, \
+}
+#else
+#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 = 0, \
+ }, { \
+ .bLength = USB_DT_INTERFACE_SIZE, \
+ .bDescriptorType = USB_DT_INTERFACE, \
+ .bInterfaceNumber = 0x02, \
+ .bAlternateSetting = 0x00, \
+ .bNumEndpoints = 0x00, \
+ .bInterfaceClass = 0xfe, \
+ .bInterfaceSubClass = 0x01, \
+ .bInterfaceProtocol = 0x01, \
+ .iInterface = 0, \
+ }, \
+}
+#endif
+
+#define __dfufunctab __attribute__ ((section (".dfu.functab")))
+#define __dfudata __attribute__ ((section (".data.shared")))
+#define __dfufunc
+#define __dfustruct const
+
+#define DFU_API_LOCATION ((const struct dfuapi *) 0x00103fd0)
+
+struct _dfu_desc {
+ struct usb_config_descriptor ucfg;
+ struct usb_interface_descriptor uif[2];
+ struct usb_dfu_func_descriptor func_dfu;
+};
+
+struct dfuapi {
+ void (*udp_init)(void);
+ 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_int32_t *dfu_state;
+ const struct usb_device_descriptor *dfu_dev_descriptor;
+ const struct _dfu_desc *dfu_cfg_descriptor;
+};
+
+/* From openpcd/firmware/src/os/pcd_enumerate.h */
+/* 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 /* _DFU_H */
diff --git a/openpicc/dfu/usb_strings_dfu.h b/openpicc/dfu/usb_strings_dfu.h
new file mode 100644
index 0000000..24fde2f
--- /dev/null
+++ b/openpicc/dfu/usb_strings_dfu.h
@@ -0,0 +1,120 @@
+#ifndef _USB_STRINGS_H
+#define _USB_STRINGS_H
+
+/* THIS FILE IS AUTOGENERATED, DO NOT MODIFY MANUALLY */
+
+#include <usb_ch9.h>
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static const struct {
+ struct usb_descriptor_header hdr;
+ u_int16_t wData[];
+} __attribute__((packed)) string0 = {
+ .hdr = {
+ .bLength = sizeof(struct usb_descriptor_header) + 1 * sizeof(u_int16_t),
+ .bDescriptorType = USB_DT_STRING,
+ },
+ .wData = {0x0409 /* English */ },
+};
+
+/* String 1 "bitmanufaktur.de IT Solutions and hmw-consulting.de" */
+static const struct {
+ struct usb_descriptor_header hdr;
+ u_int16_t wData[];
+} __attribute__((packed)) string1 = {
+ .hdr = {
+ .bLength = sizeof(struct usb_descriptor_header) + 51 * sizeof(u_int16_t),
+ .bDescriptorType = USB_DT_STRING,
+ },
+ .wData = { 0x0062, 0x0069, 0x0074, 0x006d, 0x0061, 0x006e,
+ 0x0075, 0x0066, 0x0061, 0x006b, 0x0074, 0x0075,
+ 0x0072, 0x002e, 0x0064, 0x0065, 0x0020, 0x0049,
+ 0x0054, 0x0020, 0x0053, 0x006f, 0x006c, 0x0075,
+ 0x0074, 0x0069, 0x006f, 0x006e, 0x0073, 0x0020,
+ 0x0061, 0x006e, 0x0064, 0x0020, 0x0068, 0x006d,
+ 0x0077, 0x002d, 0x0063, 0x006f, 0x006e, 0x0073,
+ 0x0075, 0x006c, 0x0074, 0x0069, 0x006e, 0x0067,
+ 0x002e, 0x0064, 0x0065, },
+};
+
+/* String 2 "OpenPICC RFID Simulator - DFU Mode" */
+static const struct {
+ struct usb_descriptor_header hdr;
+ u_int16_t wData[];
+} __attribute__((packed)) string2 = {
+ .hdr = {
+ .bLength = sizeof(struct usb_descriptor_header) + 34 * sizeof(u_int16_t),
+ .bDescriptorType = USB_DT_STRING,
+ },
+ .wData = { 0x004f, 0x0070, 0x0065, 0x006e, 0x0050, 0x0049,
+ 0x0043, 0x0043, 0x0020, 0x0052, 0x0046, 0x0049,
+ 0x0044, 0x0020, 0x0053, 0x0069, 0x006d, 0x0075,
+ 0x006c, 0x0061, 0x0074, 0x006f, 0x0072, 0x0020,
+ 0x002d, 0x0020, 0x0044, 0x0046, 0x0055, 0x0020,
+ 0x004d, 0x006f, 0x0064, 0x0065, },
+};
+
+/* String 3 "OpenPIIC DFU Configuration" */
+static const struct {
+ struct usb_descriptor_header hdr;
+ u_int16_t wData[];
+} __attribute__((packed)) string3 = {
+ .hdr = {
+ .bLength = sizeof(struct usb_descriptor_header) + 26 * sizeof(u_int16_t),
+ .bDescriptorType = USB_DT_STRING,
+ },
+ .wData = { 0x004f, 0x0070, 0x0065, 0x006e, 0x0050, 0x0049,
+ 0x0049, 0x0043, 0x0020, 0x0044, 0x0046, 0x0055,
+ 0x0020, 0x0043, 0x006f, 0x006e, 0x0066, 0x0069,
+ 0x0067, 0x0075, 0x0072, 0x0061, 0x0074, 0x0069,
+ 0x006f, 0x006e, },
+};
+
+/* String 4 "OpenPICC DFU Interface - Application Partition" */
+static const struct {
+ struct usb_descriptor_header hdr;
+ u_int16_t wData[];
+} __attribute__((packed)) string4 = {
+ .hdr = {
+ .bLength = sizeof(struct usb_descriptor_header) + 46 * sizeof(u_int16_t),
+ .bDescriptorType = USB_DT_STRING,
+ },
+ .wData = { 0x004f, 0x0070, 0x0065, 0x006e, 0x0050, 0x0049,
+ 0x0043, 0x0043, 0x0020, 0x0044, 0x0046, 0x0055,
+ 0x0020, 0x0049, 0x006e, 0x0074, 0x0065, 0x0072,
+ 0x0066, 0x0061, 0x0063, 0x0065, 0x0020, 0x002d,
+ 0x0020, 0x0041, 0x0070, 0x0070, 0x006c, 0x0069,
+ 0x0063, 0x0061, 0x0074, 0x0069, 0x006f, 0x006e,
+ 0x0020, 0x0050, 0x0061, 0x0072, 0x0074, 0x0069,
+ 0x0074, 0x0069, 0x006f, 0x006e, },
+};
+
+/* String 5 "OpenPICC DFU Interface - Bootloader Partition" */
+static const struct {
+ struct usb_descriptor_header hdr;
+ u_int16_t wData[];
+} __attribute__((packed)) string5 = {
+ .hdr = {
+ .bLength = sizeof(struct usb_descriptor_header) + 45 * sizeof(u_int16_t),
+ .bDescriptorType = USB_DT_STRING,
+ },
+ .wData = { 0x004f, 0x0070, 0x0065, 0x006e, 0x0050, 0x0049,
+ 0x0043, 0x0043, 0x0020, 0x0044, 0x0046, 0x0055,
+ 0x0020, 0x0049, 0x006e, 0x0074, 0x0065, 0x0072,
+ 0x0066, 0x0061, 0x0063, 0x0065, 0x0020, 0x002d,
+ 0x0020, 0x0042, 0x006f, 0x006f, 0x0074, 0x006c,
+ 0x006f, 0x0061, 0x0064, 0x0065, 0x0072, 0x0020,
+ 0x0050, 0x0061, 0x0072, 0x0074, 0x0069, 0x0074,
+ 0x0069, 0x006f, 0x006e, },
+};
+
+static const struct usb_descriptor_header *usb_strings[] = {
+ (struct usb_descriptor_header *) &string0,
+ (struct usb_descriptor_header *) &string1,
+ (struct usb_descriptor_header *) &string2,
+ (struct usb_descriptor_header *) &string3,
+ (struct usb_descriptor_header *) &string4,
+ (struct usb_descriptor_header *) &string5,
+};
+
+#endif /* _USB_STRINGS_H */
diff --git a/openpicc/dfu/usb_strings_dfu.txt b/openpicc/dfu/usb_strings_dfu.txt
new file mode 100644
index 0000000..681c30a
--- /dev/null
+++ b/openpicc/dfu/usb_strings_dfu.txt
@@ -0,0 +1,5 @@
+bitmanufaktur.de IT Solutions and hmw-consulting.de
+OpenPICC RFID Simulator - DFU Mode
+OpenPIIC DFU Configuration
+OpenPICC DFU Interface - Application Partition
+OpenPICC DFU Interface - Bootloader Partition
diff --git a/openpicc/include/compile.h b/openpicc/include/compile.h
new file mode 100644
index 0000000..14ec5dd
--- /dev/null
+++ b/openpicc/include/compile.h
@@ -0,0 +1,9 @@
+#ifndef _COMPILE_H
+#define _COMPILE_H
+
+/* This file is auto generated */
+#define COMPILE_DATE "20071107-171917"
+#define COMPILE_BY "henryk@dawn.ploetzli.ch"
+#define COMPILE_SVNREV "313-unclean"
+
+#endif /* _COMPILE_H */
diff --git a/openpicc/include/usb_ch9.h b/openpicc/include/usb_ch9.h
new file mode 100644
index 0000000..46066f2
--- /dev/null
+++ b/openpicc/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[0]; /* 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/openpicc/include/usb_dfu.h b/openpicc/include/usb_dfu.h
new file mode 100644
index 0000000..5000edc
--- /dev/null
+++ b/openpicc/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/openpicc/os/boot/Cstartup.S b/openpicc/os/boot/Cstartup.S
new file mode 100644
index 0000000..83e7696
--- /dev/null
+++ b/openpicc/os/boot/Cstartup.S
@@ -0,0 +1,450 @@
+/* AT91SAM7 low-level startup outines for OpenPCD / OpenPICC DFU loader
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program 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 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ *
+ */
+
+/*------------------------------------------------------------------------------
+//*- 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
+//*-----------------------------------------------------------------------------*/
+
+/* Enable DFU by press of hardware POI_BOOTLDR switch */
+#define CONFIG_DFU_SWITCH
+
+/* Enable DFU by magic value in RAM and software reset */
+#define CONFIG_DFU_MAGIC
+
+//#define DEBUG_LL
+
+#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 */
+
+#ifdef DEBUG_LL
+/* Debugging macros for switching on/off LED1 (green) */
+ .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 FIQ_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)
+#if defined(PCD)
+ .equ PIO_BOOTLDR, (1 << 27)
+#elif defined(PICC)
+ .equ PIO_BOOTLDR, (1 << 6)
+#elif defined(OLIMEX)
+ .equ PIO_BOOTLDR, (1 << 19)
+#else
+#error please define PIO_BOOTLDR
+#endif
+
+
+/* #include "AT91SAM7S64_inc.h" */
+
+/* Exception Vectors in RAM */
+
+ .text
+ .arm
+ .section .vectram, "ax"
+
+ .global _remap_call_dfu
+ .func _remap_call_dfu
+_remap_call_dfu:
+ led1on
+ /* Remap RAM to 0x00000000 for DFU */
+ ldr r1, =AT91C_BASE_AIC
+ mov r2, #0x01
+ str r2, [r1, #AIC_MCR_RCR]
+
+ ldr r4, =dfu_main
+ bx r4
+
+ .size _remap_call_dfu, . - _remap_call_dfu
+ .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
+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 IRQ_Handler_Entry /* 0x18 IRQ */
+fiqvec:
+ ldr pc, [pc, #-0xF20] /* 0x1c FIQ */
+
+dfu_state_dummy:
+ .word 0
+
+ .global IRQ_Handler_Entry
+ .func IRQ_Handler_Entry
+
+FIQ_Handler_Entry:
+
+/*- 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
+
+IRQ_Handler_Entry:
+
+ /*- 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_Entry, . - IRQ_Handler_Entry
+ .endfunc
+ .align 0
+.RAM_TOP:
+ .word Top_Stack
+
+ .global _startup
+ .func _startup
+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
+
+/*------------------------------------------------------------------------------
+//*- 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 ARM_MODE_FIQ, 0x11
+ .EQU ARM_MODE_IRQ, 0x12
+ .EQU ARM_MODE_SVC, 0x13
+
+ .EQU I_BIT, 0x80
+ .EQU F_BIT, 0x40
+
+
+#define AT91C_RSTC_RSR 0xFFFFFD04
+#define AT91C_RSTC_RSTTYP_SOFTWARE (0x03 << 8)
+#define DFU_STATE_appDETACH 1
+
+
+/*------------------------------------------------------------------------------
+//*- 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
+ mov r13, r0
+ sub r0, r0, #FIQ_Stack_Size
+
+/*- 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 | I_BIT | F_BIT
+ mov r13, r0 /* Init stack Sup */
+
+/* - Enable Interrupts and FIQ */
+ msr CPSR_c, #ARM_MODE_SVC
+
+#ifdef CONFIG_DFU_MAGIC
+ ldr r1, =AT91C_RSTC_RSR
+ ldr r2, [r1]
+ #and r2, r2, AT91C_RSTC_RSTTYP
+ tst r2, #AT91C_RSTC_RSTTYP_SOFTWARE
+ beq dfu_magic_end
+
+ ldr r1, =dfu_state
+ ldr r2, [r1]
+ cmp r2, #DFU_STATE_appDETACH
+ beq _reloc_dfu
+dfu_magic_end:
+#endif
+
+# Relocate DFU .data.shared section (Copy from ROM to RAM)
+ LDR R1, =_etext
+ LDR R2, =_data_shared
+ LDR R3, =_edata_shared
+LoopRelDS: CMP R2, R3
+ LDRLO R0, [R1], #4
+ STRLO R0, [R2], #4
+ BLO LoopRelDS
+
+/*
+# Clear DFU .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
+*/
+
+ /* prepare c function call to main */
+ mov r0, #0 /* argc = 0 */
+ ldr lr, =exit
+ ldr r10, =0x00104000
+
+#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
+ bne _reloc_dfu
+#endif
+
+ bx r10
+
+_reloc_dfu:
+ /* Relocate DFU .data section (Copy from ROM to RAM) */
+ LDR R1, =_data_flash
+ LDR R2, =_data
+ LDR R3, =_edata
+LoopRel: CMP R2, R3
+ LDRLO R0, [R1], #4
+ STRLO R0, [R2], #4
+ BLO LoopRel
+
+ /* Clear DFU .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
+
+ /* relocate DFU .text into RAM */
+ ldr r1, =0x00100000
+ ldr r2, =0x00200000
+ ldr r3, =_etext
+ add r3, r3, r2
+loop_rel_t: cmp r2, r3
+ ldrlo r4, [r1], #4
+ strlo r4, [r2], #4
+ blo loop_rel_t
+ ldr r4, =_remap_call_dfu
+ bx r4
+
+ .size _startup, . - _startup
+ .endfunc
+
+/* "exit" dummy 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
+
+
+
+ .end
+
diff --git a/openpicc/os/boot/Cstartup_SAM7.c b/openpicc/os/boot/Cstartup_SAM7.c
index 450a95e..4ab263f 100644
--- a/openpicc/os/boot/Cstartup_SAM7.c
+++ b/openpicc/os/boot/Cstartup_SAM7.c
@@ -8,60 +8,83 @@
//* intellectual property rights of others.
//*----------------------------------------------------------------------------
//* File Name : Cstartup_SAM7.c
-//* Object : Low level initializations written in C for IAR
-//* tools
-//* 1.0 08/Sep/04 JPP : Creation
-//* 1.10 10/Sep/04 JPP : Update AT91C_CKGR_PLLCOUNT filed
+//* 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)
+void
+AT91F_LowLevelInit (void)
{
- AT91PS_PMC pPMC = AT91C_BASE_PMC;
-
- //* Set flash wait state
- // Single Cycle Access at Up to 30 MHz, or 40
- // if MCK = 47923200 I have 50 Cycle for 1 useconde ( flied MC_FMR->FMCN
- AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN) & (75 << 16)) | AT91C_MC_FWS_1FWS;
+ volatile int i;
+
+ //* Debounce power supply
+ for(i=0;i<1024;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 Enable
- AT91C_BASE_WDTC->WDTC_WDMR = (0x80 << 16) | AT91C_WDTC_WDRSTEN | 0x80;
+ //* 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
- //* Set MCK at 47 923 200
- // 1 Enabling the Main Oscillator:
- // SCK = 1/32768 = 30.51 uSeconde
- // 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
+ // 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));
- while (!(pPMC->PMC_SR & AT91C_PMC_MOSCS));
- // 2 Checking the Main Oscillator Frequency (Optional)
- // 3 Setting PLL and divider:
- // - div by 5 Fin = 3,6864 =(18,432 / 5)
- // - Mul 25+1: Fout = 95,8464 =(3,6864 *26)
- // for 96 MHz the erroe is 0.16%
- //eld out NOT USED = 0 Fi
- pPMC->PMC_PLLR = ((AT91C_CKGR_DIV & 5) |
- (AT91C_CKGR_PLLCOUNT & (28 << 8)) |
- (AT91C_CKGR_MUL & (25 << 16)));
+ pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK;
+ while (!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
- // Wait the startup time
- while (!(pPMC->PMC_SR & AT91C_PMC_LOCK));
-
- // 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));
+ // 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;
- pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK;
- while (!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
}
diff --git a/openpicc/os/boot/Cstartup_app.S b/openpicc/os/boot/Cstartup_app.S
new file mode 100644
index 0000000..448cc93
--- /dev/null
+++ b/openpicc/os/boot/Cstartup_app.S
@@ -0,0 +1,194 @@
+/* Cstartup header for the application to be started by at91dfu
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program 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 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ *
+ */
+
+
+//#define DEBUG_LL
+
+ .equ AIC_FVR, (260)
+ .equ AIC_EOICR, (304)
+ .equ AT91C_BASE_AIC, (0xFFFFF000)
+ .equ ARM_MODE_FIQ, 0x11
+ .equ ARM_MODE_IRQ, 0x12
+ .equ ARM_MODE_SVC, 0x13
+
+ .equ I_BIT, 0x80
+ .equ F_BIT, 0x40
+
+
+#define AT91C_BASE_PIOA 0xFFFFF400
+#define AT91C_BASE_TC0 0xFFFA0000
+#define AT91C_TC_SWTRG (1 << 2)
+#define PIOA_SODR 0x30
+#define PIOA_CODR 0x34
+#define PIOA_PDSR 0x3c
+#define PIOA_ISR 0x4c
+#define PIOA_IDR 0x44
+#define PIO_DATA (1 << 27)
+#define TC_CCR 0x00
+
+
+#define PIO_LED1 (1 << 25) /* this only works on OpenPICC, not Olimex */
+
+#ifdef DEBUG_LL
+/* Debugging macros for switching on/off LED1 (green) */
+#define PIOA_PER 0xFFFFF400
+#define PIOA_OER 0xFFFFF410
+ .macro led1on
+ ldr r2, =AT91C_BASE_PIOA
+ mov r1, #PIO_LED1
+ str r1, [r2, #PIOA_CODR]
+ .endm
+ .macro led1off
+ ldr r2, =AT91C_BASE_PIOA
+ mov r1, #PIO_LED1
+ str r1, [r2, #PIOA_SODR]
+ .endm
+ .macro ledinit
+ ldr r2, =PIOA_PER
+ mov r1, #PIO_LED1
+ str r1, [r2]
+ ldr r2, =PIOA_OER
+ str r1, [r2]
+ led1off
+ .endm
+#else
+ .macro ledinit
+ .endm
+ .macro led1on
+ .endm
+ .macro led1off
+ .endm
+#endif
+
+ .global _startup
+ .func _startup
+_startup:
+ /* Relocate .data section (copy from Flash to RAM) */
+ ldr r1, =_etext
+ ldr r2, =_data
+ ldr r3, =_edata
+loop_r: cmp r2, r3
+ ldrlo r0, [r1], #4
+ strlo r0, [r2], #4
+ blo loop_r
+
+ /* Clear .bss section (Zero init) */
+ mov r0, #0
+ ldr r1, =__bss_start__
+ ldr r2, =__bss_end__
+loop_z: cmp r1, r2
+ strlo r0, [r1], #4
+ blo loop_z
+
+ /* initialize FIQ mode registers */
+ msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT
+ ldr r10, =AT91C_BASE_PIOA
+ ldr r12, =AT91C_BASE_TC0
+ mov r9, #AT91C_TC_SWTRG
+ msr CPSR_c, #ARM_MODE_SVC
+
+ led1on
+
+ /* prepare C function call to main */
+ mov r0, #0 /* argc = 0 */
+ ldr lr, =exit
+ ldr r10, =main
+
+ bx r10
+
+ .size _startup, . - _startup
+ .endfunc
+
+/* "exit" dummy to avoid sbrk write read etc. needed by the newlib default "exit" */
+ .global exit
+ .func exit
+exit:
+ b .
+ .size exit, . - exit
+ .endfunc
+
+
+#define LED_TRIGGER
+#define CALL_PIO_IRQ_DEMUX
+
+ .text
+ .arm
+ .section .fastrun, "ax"
+
+ .global fiq_handler
+ .func fiq_handler
+fiq_handler:
+ /* code that uses pre-initialized FIQ reg */
+ /* r8 AT91C_BASE_AIC (dfu init)
+ r9 AT91C_TC_SWTRG
+ r10 AT91C_BASE_PIOA
+ r11 tmp
+ r12 AT91C_BASE_TC0
+ r13 stack
+ r14 lr
+ */
+
+ ldr r8, [r10, #PIOA_ISR]
+ tst r8, #PIO_DATA /* check for PIO_DATA change */
+ ldrne r11, [r10, #PIOA_PDSR]
+ tstne r11, #PIO_DATA /* check for PIO_DATA == 1 */
+ strne r9, [r12, #TC_CCR] /* software trigger */
+#ifdef LED_TRIGGER
+ movne r11, #PIO_LED1
+ strne r11, [r10, #PIOA_CODR] /* enable LED */
+#endif
+
+#if 1
+ movne r11, #PIO_DATA
+ strne r11, [r10, #PIOA_IDR] /* disable further PIO_DATA FIQ */
+#endif
+
+ /*- Mark the End of Interrupt on the AIC */
+ ldr r11, =AT91C_BASE_AIC
+ str r11, [r11, #AIC_EOICR]
+
+#ifdef LED_TRIGGER
+ mov r11, #PIO_LED1
+ str r11, [r10, #PIOA_SODR] /* disable LED */
+#endif
+
+#ifdef CALL_PIO_IRQ_DEMUX
+ /* push r0, r1-r3, r12, r14 onto FIQ stack */
+ stmfd sp!, { r0-r3, r12, lr}
+ mov r0, r8
+
+ /* enable interrupts while handling demux */
+ /* msr CPSR_c, #F_BIT | ARM_MODE_SVC */
+
+ /* Call C function, give PIOA_ISR as argument */
+ ldr r11, =__pio_irq_demux
+ mov r14, pc
+ bx r11
+
+ /* msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ */
+ ldmia sp!, { r0-r3, r12, lr }
+#endif
+
+ /*- Restore the Program Counter using the LR_fiq directly in the PC */
+ subs pc, lr, #4
+
+ .size fiq_handler, . - fiq_handler
+ .endfunc
+ .end
+
personal git repositories of Harald Welte. Your mileage may vary