summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2011-07-30 19:04:55 +0200
committerHarald Welte <laforge@gnumonks.org>2011-07-30 19:04:55 +0200
commita3de0a4ac29118c3ada946a0c8f7f602c9066ec1 (patch)
tree8408d463a3ea6910d7336e24d60611da8a50b77d /firmware
parentdd88fde8d2b78243c01871cabca37c9e46ebd03d (diff)
parentffbce3ea2cda51214be0bb7a107954f890f99b0d (diff)
Merge branch 'simtrace'
Diffstat (limited to 'firmware')
-rw-r--r--firmware/Makefile28
-rw-r--r--firmware/Makefile.dfu15
-rw-r--r--firmware/include/AT91SAM7.h2
-rw-r--r--firmware/include/lib_AT91SAM7.h16
-rw-r--r--firmware/include/openpcd.h3
-rw-r--r--firmware/include/simtrace_usb.h24
-rw-r--r--firmware/lib/vsprintf.c1
-rw-r--r--firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld94
-rw-r--r--firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld10
-rw-r--r--firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld10
-rw-r--r--firmware/link/AT91SAM7S64-ROM-sam7dfu-app.ld10
-rwxr-xr-xfirmware/scripts/git-version-gen151
-rwxr-xr-xfirmware/scripts/mkcompile_h8
-rw-r--r--firmware/src/dfu/dfu.c173
-rw-r--r--firmware/src/dfu/dfu.h26
-rw-r--r--firmware/src/openpcd.h7
-rw-r--r--firmware/src/os/dbgu.c2
-rw-r--r--firmware/src/os/req_ctx.c6
-rw-r--r--firmware/src/os/req_ctx.h2
-rw-r--r--firmware/src/os/usb_descriptors_openpcd.h14
-rw-r--r--firmware/src/pcd/usb_strings_app.txt1
-rw-r--r--firmware/src/pcd/usb_strings_dfu.txt1
-rw-r--r--firmware/src/picc/usb_strings_app.txt1
-rw-r--r--firmware/src/picc/usb_strings_dfu.txt1
-rw-r--r--firmware/src/simtrace.h41
-rw-r--r--firmware/src/simtrace/iso7816_uart.c641
-rw-r--r--firmware/src/simtrace/iso7816_uart.h6
-rw-r--r--firmware/src/simtrace/main_factory.c80
-rw-r--r--firmware/src/simtrace/main_simtrace.c165
-rw-r--r--firmware/src/simtrace/sim_switch.c95
-rw-r--r--firmware/src/simtrace/sim_switch.h7
-rw-r--r--firmware/src/simtrace/spi_flash.c144
-rw-r--r--firmware/src/simtrace/tc_etu.c128
-rw-r--r--firmware/src/simtrace/tc_etu.h4
-rw-r--r--firmware/src/simtrace/usb_strings_app.txt7
-rw-r--r--firmware/src/simtrace/usb_strings_dfu.txt6
-rw-r--r--firmware/src/start/Cstartup.S3
-rw-r--r--firmware/src/start/Cstartup_app.S2
38 files changed, 1870 insertions, 65 deletions
diff --git a/firmware/Makefile b/firmware/Makefile
index 08126c1..3f7a2e9 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -42,14 +42,14 @@ FLASH_TOOL = AT91FLASH
# MCU name and submodel
MCU = arm7tdmi
-#SUBMDL = AT91SAM7S64
-SUBMDL = AT91SAM7S128
+SUBMDL = AT91SAM7S64
+#SUBMDL = AT91SAM7S128
USE_THUMB_MODE = NO
#USE_THUMB_MODE = YES
## Create ROM-Image (final)
-RUN_MODE=RUN_FROM_ROM
+RUN_MODE:=RUN_FROM_ROM
## Create RAM-Image (debugging) - not used in this example
#RUN_MODE=RUN_FROM_RAM
@@ -70,7 +70,7 @@ PATH_TO_LINKSCRIPTS=link/
# Target file name (without extension).
TARGET:=main_reqa
-USBSTRINGS=src/picc/usb_strings_app.h src/pcd/usb_strings_app.h
+USBSTRINGS=src/picc/usb_strings_app.h src/pcd/usb_strings_app.h src/simtrace/usb_strings_app.h
# List C source files here. (C dependencies are automatically generated.)
# use file-extension c for "c-only"-files
@@ -112,6 +112,14 @@ SRCARM += src/picc/tc_fdt.c src/picc/ssc_picc.c src/picc/adc.c \
SRCARM += src/picc/$(TARGET).c
endif
+ifeq ($(BOARD), SIMTRACE)
+SUBMDL = AT91SAM7S128
+TARGET := main_simtrace
+SRCARM += src/simtrace/iso7816_uart.c src/simtrace/tc_etu.c \
+ src/simtrace/sim_switch.c src/simtrace/spi_flash.c
+SRCARM += src/simtrace/$(TARGET).c
+endif
+
# List C++ source files here.
# use file-extension cpp for C++-files (use extension .cpp)
@@ -202,6 +210,12 @@ CDEFS += -DPCD
CINCS = -Isrc/pcd
endif
+ifeq ($(BOARD),SIMTRACE)
+CDEFS += -DSIMTRACE
+CINCS = -Isrc/simtrace
+endif
+
+
# Place -I options here
CINCS += -Iinclude -Isrc
@@ -235,7 +249,7 @@ 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
+CFLAGS += -ffunction-sections -fdata-sections
# flags only for C
CONLYFLAGS += -Wnested-externs
@@ -301,11 +315,11 @@ LDFLAGS += -lc -lgcc
LDFLAGS += $(CPLUSPLUS_LIB)
LDFLAGS += $(patsubst %,-L%,$(EXTRA_LIBDIRS))
LDFLAGS += $(patsubst %,-l%,$(EXTRA_LIBS))
-#LDFLAGS += --gc-sections
+LDFLAGS += -Wl,--gc-sections -Wl,--entry=_startup
# Set Linker-Script Depending On Selected Memory and Controller
ifeq ($(RUN_MODE),RUN_FROM_RAM)
-LDFLAGS +=-T$(PATH_TO_LINKSCRIPTS)$(SUBMDL)-RAM.ld
+LDFLAGS +=-T$(PATH_TO_LINKSCRIPTS)$(SUBMDL)-RAM$(IMGTYPE).ld
else
LDFLAGS +=-T$(PATH_TO_LINKSCRIPTS)$(SUBMDL)-ROM$(IMGTYPE).ld
endif
diff --git a/firmware/Makefile.dfu b/firmware/Makefile.dfu
index c526fc2..3c797ef 100644
--- a/firmware/Makefile.dfu
+++ b/firmware/Makefile.dfu
@@ -41,8 +41,8 @@ FLASH_TOOL = AT91FLASH
# MCU name and submodel
MCU = arm7tdmi
-#SUBMDL = AT91SAM7S64
-SUBMDL = AT91SAM7S256
+SUBMDL = AT91SAM7S64
+#SUBMDL = AT91SAM7S256
USE_THUMB_MODE = NO
#USE_THUMB_MODE = YES
@@ -69,7 +69,7 @@ PATH_TO_LINKSCRIPTS=link/
# Target file name (without extension).
TARGET:=dfu
-USBSTRINGS=src/picc/usb_strings_dfu.h src/pcd/usb_strings_dfu.h
+USBSTRINGS=src/picc/usb_strings_dfu.h src/pcd/usb_strings_dfu.h src/simtrace/usb_strings_dfu.h
# List C source files here. (C dependencies are automatically generated.)
# use file-extension c for "c-only"-files
@@ -158,6 +158,7 @@ endif
ifeq ($(BOARD),OLIMEX)
CDEFS += -DOLIMEX
ADEFS += -DOLIMEX
+CINCS = -Isrc/simtrace
endif
ifeq ($(BOARD),PICC)
@@ -173,6 +174,14 @@ ADEFS += -DPCD
CINCS = -Isrc/pcd
endif
+ifeq ($(BOARD),SIMTRACE)
+SUBMDL = AT91SAM7S128
+CDEFS += -DSIMTRACE
+ADEFS += -DSIMTRACE
+CINCS = -Isrc/simtrace
+endif
+
+
# Place -I options here
CINCS += -Iinclude -Isrc
diff --git a/firmware/include/AT91SAM7.h b/firmware/include/AT91SAM7.h
index 53eb072..42743f6 100644
--- a/firmware/include/AT91SAM7.h
+++ b/firmware/include/AT91SAM7.h
@@ -1942,6 +1942,6 @@ typedef struct _AT91S_UDP {
#endif
#define AT91C_IFLASH_NB_OF_PAGES (AT91C_ISRAM_SIZE>>AT91C_IFLASH_PAGE_SHIFT)
-#define AT91C_IFLASH_LOCK_REGION_SIZE (AT91C_ISRAM_SIZE/AT91C_IFLASH_NB_OF_LOCK_BITS)
+#define AT91C_IFLASH_LOCK_REGION_SIZE (AT91C_IFLASH_SIZE/AT91C_IFLASH_NB_OF_LOCK_BITS)
#endif/*__AT91SAM7_H__*/
diff --git a/firmware/include/lib_AT91SAM7.h b/firmware/include/lib_AT91SAM7.h
index f26ac54..2aa7df6 100644
--- a/firmware/include/lib_AT91SAM7.h
+++ b/firmware/include/lib_AT91SAM7.h
@@ -444,6 +444,22 @@ static inline void AT91F_PIO_CfgPullup(
pPio->PIO_PPUER = pullupEnable;
}
+static inline void AT91F_PIO_CfgPullupEn(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int pullupEnable) // \arg enable pullup on PIO
+{
+ // Connect or not Pullup
+ pPio->PIO_PPUER = pullupEnable;
+}
+
+static inline void AT91F_PIO_CfgPullupDis(
+ AT91PS_PIO pPio, // \arg pointer to a PIO controller
+ unsigned int pullupEnable) // \arg enable pullup on PIO
+{
+ // Connect or not Pullup
+ pPio->PIO_PPUDR = pullupEnable;
+}
+
//*----------------------------------------------------------------------------
//* \fn AT91F_PIO_CfgDirectDrive
//* \brief Enable direct drive on PIO
diff --git a/firmware/include/openpcd.h b/firmware/include/openpcd.h
index e5a0ac7..ea32764 100644
--- a/firmware/include/openpcd.h
+++ b/firmware/include/openpcd.h
@@ -34,6 +34,8 @@ enum openpcd_cmd_class {
OPENPCD_CMD_CLS_ADC = 0x5,
OPENPCD_CMD_CLS_LIBRFID = 0x6,
OPENPCD_CMD_CLS_PRESENCE = 0x7,
+ /* SIM SCAN */
+ OPENPCD_CMD_CLS_SIM = 0x8,
/* PICC (transponder) side */
OPENPCD_CMD_CLS_PICC = 0xe,
@@ -102,6 +104,7 @@ enum openpcd_cmd_class {
#define OPENPCD_VENDOR_ID 0x16c0
+#define SIMTRACE_PRODUCT_ID 0x0762
#define OPENPCD_PRODUCT_ID 0x076b
#define OPENPICC_PRODUCT_ID 0x076c
#define OPENPCD_OUT_EP 0x01
diff --git a/firmware/include/simtrace_usb.h b/firmware/include/simtrace_usb.h
new file mode 100644
index 0000000..c020093
--- /dev/null
+++ b/firmware/include/simtrace_usb.h
@@ -0,0 +1,24 @@
+#ifndef SIMTRACE_USB_H
+#define SIMTRACE_USB_H
+
+//#include <stdint.h>
+
+/* this is kept compatible with OpenPCD protocol */
+struct simtrace_hdr {
+ u_int8_t cmd;
+ u_int8_t flags;
+ u_int8_t res[2];
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+enum simtrace_usb_msgt {
+ SIMTRACE_MSGT_NULL,
+ SIMTRACE_MSGT_DATA,
+ SIMTRACE_MSGT_RESET, /* reset was asserted, no more data */
+};
+
+/* flags for MSGT_DATA */
+#define SIMTRACE_FLAG_ATR 0x01 /* ATR immediately after reset */
+#define SIMTRACE_FLAG_WTIME_EXP 0x04 /* work waiting time expired */
+
+#endif /* SIMTRACE_USB_H */
diff --git a/firmware/lib/vsprintf.c b/firmware/lib/vsprintf.c
index 5da7c02..799eb78 100644
--- a/firmware/lib/vsprintf.c
+++ b/firmware/lib/vsprintf.c
@@ -17,6 +17,7 @@
*/
#include <stdarg.h>
+#include <limits.h>
#include <sys/types.h>
#include <string.h>
#include <asm/ctype.h>
diff --git a/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld b/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld
new file mode 100644
index 0000000..ad02776
--- /dev/null
+++ b/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld
@@ -0,0 +1,94 @@
+/* Memory Definitions */
+
+MEMORY
+{
+ /* reserve 16K DFU area on top of flash */
+ /* FLASH (rx) : ORIGIN = 0x00104000, LENGTH = (0x00020000 - 0x4000 - 0x400) */
+ /* reserve 1k DFU area on top of RAM */
+ DATA (rw) : ORIGIN = 0x00202000, LENGTH = (0x00008000 - 0x2000)
+ STACK (rw) : ORIGIN = 0x00208000, LENGTH = 0x00000000
+}
+
+
+/* Section Definitions */
+
+SECTIONS
+{
+ . = 0x00000000;
+ /* first section is .text which is used for code */
+ .text 0x00202000: AT ( 0x00000000 ) {
+ src/start/Cstartup_app.o (.text)
+ * (.text)
+ * (.rodata*)
+ . = ALIGN(4);
+
+ _etext = . ;
+ PROVIDE (etext = .);
+
+ _data = . ;
+ * (.fastrun)
+ * (.data)
+ . = ALIGN(4);
+ } >DATA
+
+ _edata = . ;
+ PROVIDE (edata = .);
+
+ /* .bss section which is used for uninitialized data */
+ .bss : {
+ __bss_start = . ;
+ __bss_start__ = . ;
+ *(.bss)
+ *(COMMON)
+ } >DATA
+
+ . = ALIGN(4);
+ __bss_end__ = . ;
+ __bss_end__ = . ;
+
+ PROVIDE (main = .);
+
+ _end = . ;
+
+ . = ALIGN(4);
+ .int_data : {
+ *(.internal_ram_top)
+ } >STACK
+
+ PROVIDE (end = .);
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+}
diff --git a/firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld b/firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld
index ebac6d4..7db540e 100644
--- a/firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld
+++ b/firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld
@@ -16,8 +16,8 @@ SECTIONS
. = 0x00000000;
/* first section is .text which is used for code */
.text 0x00104000: AT ( 0x00000000 ) {
- src/start/Cstartup_app.o (.text)
- * (.text)
+ src/start/Cstartup_app.o (.text*)
+ * (.text*)
* (.rodata*)
. = ALIGN(4);
} >FLASH
@@ -28,8 +28,8 @@ SECTIONS
/* 0x00200000 ... */
.data 0x00200028: AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.text) ) {
_data = . ;
- * (.fastrun)
- * (.data)
+ * (.fastrun*)
+ * (.data*)
. = ALIGN(4);
} >DATA
@@ -40,7 +40,7 @@ SECTIONS
.bss : {
__bss_start = . ;
__bss_start__ = . ;
- *(.bss)
+ *(.bss*)
*(COMMON)
} >DATA
diff --git a/firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld b/firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld
index 85bf7b8..7ec2089 100644
--- a/firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld
+++ b/firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld
@@ -16,8 +16,8 @@ SECTIONS
. = 0x00000000;
/* first section is .text which is used for code */
.text 0x00104000: AT ( 0x00000000 ) {
- src/start/Cstartup_app.o (.text)
- * (.text)
+ src/start/Cstartup_app.o (.text*)
+ * (.text*)
* (.rodata*)
. = ALIGN(4);
} >FLASH
@@ -28,8 +28,8 @@ SECTIONS
/* 0x00200000 ... */
.data 0x00200028: AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.text) ) {
_data = . ;
- * (.fastrun)
- * (.data)
+ * (.fastrun*)
+ * (.data*)
. = ALIGN(4);
} >DATA
@@ -40,7 +40,7 @@ SECTIONS
.bss : {
__bss_start = . ;
__bss_start__ = . ;
- *(.bss)
+ *(.bss*)
*(COMMON)
} >DATA
diff --git a/firmware/link/AT91SAM7S64-ROM-sam7dfu-app.ld b/firmware/link/AT91SAM7S64-ROM-sam7dfu-app.ld
index de24dd8..d45f691 100644
--- a/firmware/link/AT91SAM7S64-ROM-sam7dfu-app.ld
+++ b/firmware/link/AT91SAM7S64-ROM-sam7dfu-app.ld
@@ -16,8 +16,8 @@ SECTIONS
. = 0x00000000;
/* first section is .text which is used for code */
.text 0x00104000: AT ( 0x00000000 ) {
- src/start/Cstartup_app.o (.text)
- * (.text)
+ src/start/Cstartup_app.o (.text*)
+ * (.text*)
* (.rodata*)
. = ALIGN(4);
} >FLASH
@@ -28,8 +28,8 @@ SECTIONS
/* 0x00200000 ... */
.data 0x00200028: AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.text) ) {
_data = . ;
- * (.fastrun)
- * (.data)
+ * (.fastrun*)
+ * (.data*)
. = ALIGN(4);
} >DATA
@@ -40,7 +40,7 @@ SECTIONS
.bss : {
__bss_start = . ;
__bss_start__ = . ;
- *(.bss)
+ *(.bss*)
*(COMMON)
} >DATA
diff --git a/firmware/scripts/git-version-gen b/firmware/scripts/git-version-gen
new file mode 100755
index 0000000..42cf3d2
--- /dev/null
+++ b/firmware/scripts/git-version-gen
@@ -0,0 +1,151 @@
+#!/bin/sh
+# Print a version string.
+scriptversion=2010-01-28.01
+
+# Copyright (C) 2007-2010 Free Software Foundation, Inc.
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+
+# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
+# It may be run two ways:
+# - from a git repository in which the "git describe" command below
+# produces useful output (thus requiring at least one signed tag)
+# - from a non-git-repo directory containing a .tarball-version file, which
+# presumes this script is invoked like "./git-version-gen .tarball-version".
+
+# In order to use intra-version strings in your project, you will need two
+# separate generated version string files:
+#
+# .tarball-version - present only in a distribution tarball, and not in
+# a checked-out repository. Created with contents that were learned at
+# the last time autoconf was run, and used by git-version-gen. Must not
+# be present in either $(srcdir) or $(builddir) for git-version-gen to
+# give accurate answers during normal development with a checked out tree,
+# but must be present in a tarball when there is no version control system.
+# Therefore, it cannot be used in any dependencies. GNUmakefile has
+# hooks to force a reconfigure at distribution time to get the value
+# correct, without penalizing normal development with extra reconfigures.
+#
+# .version - present in a checked-out repository and in a distribution
+# tarball. Usable in dependencies, particularly for files that don't
+# want to depend on config.h but do want to track version changes.
+# Delete this file prior to any autoconf run where you want to rebuild
+# files to pick up a version string change; and leave it stale to
+# minimize rebuild time after unrelated changes to configure sources.
+#
+# It is probably wise to add these two files to .gitignore, so that you
+# don't accidentally commit either generated file.
+#
+# Use the following line in your configure.ac, so that $(VERSION) will
+# automatically be up-to-date each time configure is run (and note that
+# since configure.ac no longer includes a version string, Makefile rules
+# should not depend on configure.ac for version updates).
+#
+# AC_INIT([GNU project],
+# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
+# [bug-project@example])
+#
+# Then use the following lines in your Makefile.am, so that .version
+# will be present for dependencies, and so that .tarball-version will
+# exist in distribution tarballs.
+#
+# BUILT_SOURCES = $(top_srcdir)/.version
+# $(top_srcdir)/.version:
+# echo $(VERSION) > $@-t && mv $@-t $@
+# dist-hook:
+# echo $(VERSION) > $(distdir)/.tarball-version
+
+case $# in
+ 1) ;;
+ *) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
+esac
+
+tarball_version_file=$1
+nl='
+'
+
+# First see if there is a tarball-only version file.
+# then try "git describe", then default.
+if test -f $tarball_version_file
+then
+ v=`cat $tarball_version_file` || exit 1
+ case $v in
+ *$nl*) v= ;; # reject multi-line output
+ [0-9]*) ;;
+ *) v= ;;
+ esac
+ test -z "$v" \
+ && echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
+fi
+
+if test -n "$v"
+then
+ : # use $v
+elif
+ v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
+ || git describe --abbrev=4 HEAD 2>/dev/null` \
+ && case $v in
+ [0-9]*) ;;
+ v[0-9]*) ;;
+ *) (exit 1) ;;
+ esac
+then
+ # Is this a new git that lists number of commits since the last
+ # tag or the previous older version that did not?
+ # Newer: v6.10-77-g0f8faeb
+ # Older: v6.10-g0f8faeb
+ case $v in
+ *-*-*) : git describe is okay three part flavor ;;
+ *-*)
+ : git describe is older two part flavor
+ # Recreate the number of commits and rewrite such that the
+ # result is the same as if we were using the newer version
+ # of git describe.
+ vtag=`echo "$v" | sed 's/-.*//'`
+ numcommits=`git rev-list "$vtag"..HEAD | wc -l`
+ v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
+ ;;
+ esac
+
+ # Change the first '-' to a '.', so version-comparing tools work properly.
+ # Remove the "g" in git describe's output string, to save a byte.
+ v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
+else
+ v=UNKNOWN
+fi
+
+v=`echo "$v" |sed 's/^v//'`
+
+# Don't declare a version "dirty" merely because a time stamp has changed.
+git status > /dev/null 2>&1
+
+dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
+case "$dirty" in
+ '') ;;
+ *) # Append the suffix only if there isn't one already.
+ case $v in
+ *-dirty) ;;
+ *) v="$v-dirty" ;;
+ esac ;;
+esac
+
+# Omit the trailing newline, so that m4_esyscmd can use the result directly.
+echo "$v" | tr -d '\012'
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/firmware/scripts/mkcompile_h b/firmware/scripts/mkcompile_h
index 22ac262..c91c640 100755
--- a/firmware/scripts/mkcompile_h
+++ b/firmware/scripts/mkcompile_h
@@ -7,11 +7,11 @@ DATE=`LC_ALL=C LANG=C date +%Y%m%d-%H%M%S`
BY=`whoami`
HOST=`hostname | $TRUNCATE`
BYHOST=`echo ${BY}@${HOST} | $TRUNCATE`
-SVNREV=`svn info | grep \^Revision: | cut -c 11-`
+#SVNREV=`svn info | grep \^Revision: | cut -c 11-`
+#svn st | grep \^M >/dev/null
+#[ "$?" -eq "0" ] && SVNREV=${SVNREV}-unclean
-svn st | grep \^M >/dev/null
-
-[ "$?" -eq "0" ] && SVNREV=${SVNREV}-unclean
+SVNREV=`scripts/git-version-gen .tarball-version`
echo "#ifndef _COMPILE_H"
echo "#define _COMPILE_H"
diff --git a/firmware/src/dfu/dfu.c b/firmware/src/dfu/dfu.c
index 8425c28..0e22256 100644
--- a/firmware/src/dfu/dfu.c
+++ b/firmware/src/dfu/dfu.c
@@ -1,5 +1,5 @@
/* USB Device Firmware Update Implementation for OpenPCD
- * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ * (C) 2006-2011 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
@@ -37,6 +37,7 @@
#include <compile.h>
#define SAM7DFU_SIZE 0x4000
+#define SAM7DFU_RAM_SIZE 0x2000
/* If debug is enabled, we need to access debug functions from flash
* and therefore have to omit flashing */
@@ -69,6 +70,12 @@
#define led2on() AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2)
#define led2off() AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2)
+static int past_manifest = 0;
+static int switch_to_ram = 0; /* IRQ handler requests main to jump to RAM */
+static u_int16_t usb_if_nr = 0; /* last SET_INTERFACE */
+static u_int16_t usb_if_alt_nr = 0; /* last SET_INTERFACE AltSetting */
+static u_int16_t usb_if_alt_nr_dnload = 0; /* AltSetting during last dnload */
+
static void __dfufunc udp_init(void)
{
/* Set the PLL USB Divider */
@@ -210,14 +217,37 @@ static void __dfufunc udp_ep0_send_stall(void)
}
-static u_int8_t *ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
+static int first_download = 1;
+static u_int8_t *ptr, *ptr_max;
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)
+static void chk_first_dnload_set_ptr(void)
+{
+ if (!first_download)
+ return;
+
+ switch (usb_if_alt_nr) {
+ case 0:
+ ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
+ ptr_max = AT91C_IFLASH + AT91C_IFLASH_SIZE - ENVIRONMENT_SIZE;
+ break;
+ case 1:
+ ptr = (u_int8_t *) AT91C_IFLASH;
+ ptr_max = AT91C_IFLASH + SAM7DFU_SIZE;
+ break;
+ case 2:
+ ptr = (u_int8_t *) AT91C_ISRAM + SAM7DFU_RAM_SIZE;
+ ptr_max = AT91C_ISRAM + AT91C_ISRAM_SIZE;
+ break;
+ }
+ first_download = 0;
+}
+
+static int __dfufunc handle_dnload_flash(u_int16_t val, u_int16_t len)
{
- volatile u_int32_t *p = (volatile u_int32_t *)ptr;
+ volatile u_int32_t *p;
u_int8_t *pagebuf = (u_int8_t *) pagebuf32;
int i;
@@ -238,13 +268,20 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len)
dfu_status = DFU_STATUS_errADDRESS;
return RET_STALL;
}
+ chk_first_dnload_set_ptr();
+ p = (volatile u_int32_t *)ptr;
+
if (len == 0) {
DEBUGP("zero-size write -> MANIFEST_SYNC ");
- flash_page(p);
+ if (((unsigned long)p % AT91C_IFLASH_PAGE_SIZE) != 0)
+ flash_page(p);
dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
+ first_download = 1;
return RET_ZLP;
}
- if (ptr + len >= (u_int8_t *) AT91C_IFLASH + AT91C_IFLASH_SIZE - ENVIRONMENT_SIZE ) {
+
+ /* check if we would exceed end of memory */
+ if (ptr + len > ptr_max) {
DEBUGP("end of write exceeds flash end ");
dfu_state = DFU_STATE_dfuERROR;
dfu_status = DFU_STATUS_errADDRESS;
@@ -256,10 +293,10 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len)
DEBUGR(hexdump(pagebuf, len));
- /* we can only access the write buffer with correctly aligned
- * 32bit writes ! */
#ifndef DEBUG_DFU_NOFLASH
DEBUGP("copying ");
+ /* we can only access the write buffer with correctly aligned
+ * 32bit writes ! */
for (i = 0; i < len/4; i++) {
*p++ = pagebuf32[i];
/* If we have filled a page buffer, flash it */
@@ -274,6 +311,57 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len)
return RET_ZLP;
}
+static int __dfufunc handle_dnload_ram(u_int16_t val, u_int16_t len)
+{
+ 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;
+ }
+ chk_first_dnload_set_ptr();
+
+ if (len == 0) {
+ DEBUGP("zero-size write -> MANIFEST_SYNC ");
+ dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
+ first_download = 1;
+ return RET_ZLP;
+ }
+
+ /* check if we would exceed end of memory */
+ if (ptr + len >= ptr_max) {
+ DEBUGP("end of write exceeds RAM end ");
+ dfu_state = DFU_STATE_dfuERROR;
+ dfu_status = DFU_STATUS_errADDRESS;
+ return RET_STALL;
+ }
+
+ /* drectly copy into RAM */
+ DEBUGP("try_to_recv=%u ", len);
+ udp_ep0_recv_data(ptr, len);
+
+ DEBUGR(hexdump(ptr, len));
+
+ ptr += len;
+
+ return RET_ZLP;
+}
+
+static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len)
+{
+ usb_if_alt_nr_dnload = usb_if_alt_nr;
+ switch (usb_if_alt_nr) {
+ case 2:
+ return handle_dnload_ram(val, len);
+ default:
+ return handle_dnload_flash(val, len);
+ }
+}
+
#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)
{
@@ -285,9 +373,12 @@ static __dfufunc int handle_upload(u_int16_t val, u_int16_t len)
udp_ep0_send_stall();
return -EINVAL;
}
+ chk_first_dnload_set_ptr();
- if (ptr + len > AT91C_IFLASH_END)
+ if (ptr + len > AT91C_IFLASH_END) {
len = AT91C_IFLASH_END - (u_int8_t *)ptr;
+ first_download = 1;
+ }
udp_ep0_send_data((char *)ptr, len);
ptr+= len;
@@ -486,7 +577,16 @@ int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req,
case DFU_STATE_dfuMANIFEST:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
+ /* we don't want to change to WAIT_RST, as it
+ * would mean that we can not support another
+ * DFU transaction before doing the actual
+ * reset. Instead, we switch to idle and note
+ * that we've already been through MANIFST in
+ * the global variable 'past_manifest'.
+ */
+ //dfu_state = DFU_STATE_dfuMANIFEST_WAIT_RST;
dfu_state = DFU_STATE_dfuIDLE;
+ past_manifest = 1;
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
@@ -595,7 +695,7 @@ __dfustruct const struct _dfu_desc dfu_cfg_descriptor = {
.bLength = USB_DT_CONFIG_SIZE,
.bDescriptorType = USB_DT_CONFIG,
.wTotalLength = USB_DT_CONFIG_SIZE +
- 2* USB_DT_INTERFACE_SIZE +
+ 3* USB_DT_INTERFACE_SIZE +
USB_DT_DFU_SIZE,
.bNumInterfaces = 1,
.bConfigurationValue = 1,
@@ -637,6 +737,21 @@ __dfustruct const struct _dfu_desc dfu_cfg_descriptor = {
.iInterface = 0,
#endif
},
+ .uif[2] = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0x00,
+ .bAlternateSetting = 0x02,
+ .bNumEndpoints = 0x00,
+ .bInterfaceClass = 0xfe,
+ .bInterfaceSubClass = 0x01,
+ .bInterfaceProtocol = 0x02,
+#ifdef CONFIG_USB_STRING
+ .iInterface = 6,
+#else
+ .iInterface = 0,
+#endif
+ },
.func_dfu = DFU_FUNC_DESC,
};
@@ -820,9 +935,11 @@ static __dfufunc void dfu_udp_ep0_handler(void)
udp_ep0_send_stall();
break;
case STD_SET_INTERFACE:
- DEBUGE("SET INTERFACE ");
- /* FIXME: store the interface number somewhere, once
+ DEBUGE("SET INTERFACE(if=%d, alt=%d) ", wIndex, wValue);
+ /* store the interface number somewhere, once
* we need to support DFU flashing DFU */
+ usb_if_alt_nr = wValue;
+ usb_if_nr = wIndex;
udp_ep0_send_zlp();
break;
default:
@@ -858,12 +975,22 @@ static __dfufunc void dfu_udp_irq(void)
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);
+ dfu_state == DFU_STATE_dfuMANIFEST ||
+ past_manifest) {
+ AT91F_DBGU_Printk("sam7dfu: switching to APP mode\r\n");
+ switch (usb_if_alt_nr_dnload) {
+ case 2:
+ switch_to_ram = 1;
+ break;
+ default:
+ /* reset back into the main application */
+ AT91F_RSTSoftReset(AT91C_BASE_RSTC,
+ AT91C_RSTC_PROCRST|
+ AT91C_RSTC_PERRST|
+ AT91C_RSTC_EXTRST);
+ break;
+ }
}
-
}
if (isr & AT91C_UDP_EPINT0)
@@ -902,7 +1029,7 @@ void __dfufunc dfu_main(void)
AT91F_DBGU_Init();
AT91F_DBGU_Printk("\n\r\n\rsam7dfu - AT91SAM7 USB DFU bootloader\n\r"
- "(C) 2006-2008 by Harald Welte <hwelte@hmw-consulting.de>\n\r"
+ "(C) 2006-2011 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
@@ -945,6 +1072,16 @@ void __dfufunc dfu_main(void)
if( i== 0) {
AT91F_WDTRestart(AT91C_BASE_WDTC);
}
+ if (switch_to_ram) {
+ void (*ram_app_entry)(void);
+ int i;
+ for (i = 0; i < 32; i++)
+ AT91F_AIC_DisableIt(AT91C_BASE_AIC, i);
+ /* jump into RAM */
+ AT91F_DBGU_Printk("JUMP TO RAM\r\n");
+ ram_app_entry = AT91C_ISRAM + SAM7DFU_RAM_SIZE;
+ ram_app_entry();
+ }
}
}
diff --git a/firmware/src/dfu/dfu.h b/firmware/src/dfu/dfu.h
index a4184b4..c898197 100644
--- a/firmware/src/dfu/dfu.h
+++ b/firmware/src/dfu/dfu.h
@@ -61,6 +61,16 @@
.bInterfaceSubClass = 0x01, \
.bInterfaceProtocol = 0x01, \
.iInterface = 2, \
+ }, { \
+ .bLength = USB_DT_INTERFACE_SIZE, \
+ .bDescriptorType = USB_DT_INTERFACE, \
+ .bInterfaceNumber = 0x03, \
+ .bAlternateSetting = 0x00, \
+ .bNumEndpoints = 0x00, \
+ .bInterfaceClass = 0xfe, \
+ .bInterfaceSubClass = 0x01, \
+ .bInterfaceProtocol = 0x01, \
+ .iInterface = 3, \
}, \
}
#else
@@ -78,8 +88,18 @@
}, { \
.bLength = USB_DT_INTERFACE_SIZE, \
.bDescriptorType = USB_DT_INTERFACE, \
- .bInterfaceNumber = 0x02, \
- .bAlternateSetting = 0x00, \
+ .bInterfaceNumber = 0x01, \
+ .bAlternateSetting = 0x01, \
+ .bNumEndpoints = 0x00, \
+ .bInterfaceClass = 0xfe, \
+ .bInterfaceSubClass = 0x01, \
+ .bInterfaceProtocol = 0x01, \
+ .iInterface = 0, \
+ }, { \
+ .bLength = USB_DT_INTERFACE_SIZE, \
+ .bDescriptorType = USB_DT_INTERFACE, \
+ .bInterfaceNumber = 0x01, \
+ .bAlternateSetting = 0x02, \
.bNumEndpoints = 0x00, \
.bInterfaceClass = 0xfe, \
.bInterfaceSubClass = 0x01, \
@@ -98,7 +118,7 @@
struct _dfu_desc {
struct usb_config_descriptor ucfg;
- struct usb_interface_descriptor uif[2];
+ struct usb_interface_descriptor uif[3];
struct usb_dfu_func_descriptor func_dfu;
};
diff --git a/firmware/src/openpcd.h b/firmware/src/openpcd.h
index a65cd0e..3bc890e 100644
--- a/firmware/src/openpcd.h
+++ b/firmware/src/openpcd.h
@@ -10,11 +10,13 @@
#define USB_VENDOR_ID OPENPCD_VENDOR_ID
-#ifdef OLIMEX
+#if defined(OLIMEX) || defined(SIMTRACE)
#define OPENPCD_PIO_LED2 AT91C_PIO_PA17
#define OPENPCD_PIO_LED1 AT91C_PIO_PA18
#define OPENPCD_PIO_UDP_CNX AT91C_PIO_PA24
-#define OPENPCD_PIO_UDP_PUP AT91C_PIO_PA16
+#define OPENPCD_PIO_UDP_PUPv4 AT91C_PIO_PA16
+#define PIO_BOOTLDR AT91C_PIO_PA19 /* B1 used as bootloader switch */
+#define USB_PRODUCT_ID SIMTRACE_PRODUCT_ID
#else
#if defined(PCD)
#define OPENPCD_PIO_UDP_CNX AT91C_PIO_PA15
@@ -166,6 +168,7 @@
#define OPENPCD_IRQ_PRIO_SPI AT91C_AIC_PRIOR_HIGHEST
#define OPENPCD_IRQ_PRIO_SSC (AT91C_AIC_PRIOR_HIGHEST-1)
#define OPENPCD_IRQ_PRIO_SYS (AT91C_AIC_PRIOR_HIGHEST-2)
+#define OPENPCD_IRQ_PRIO_USART (AT91C_AIC_PRIOR_HIGHEST-3)
#define OPENPCD_IRQ_PRIO_TC_FDT (AT91C_AIC_PRIOR_LOWEST+3)
#define OPENPCD_IRQ_PRIO_UDP (AT91C_AIC_PRIOR_LOWEST+2)
#define OPENPCD_IRQ_PRIO_PIT (AT91C_AIC_PRIOR_LOWEST+1)
diff --git a/firmware/src/os/dbgu.c b/firmware/src/os/dbgu.c
index 026b56b..28d86a4 100644
--- a/firmware/src/os/dbgu.c
+++ b/firmware/src/os/dbgu.c
@@ -147,7 +147,7 @@ void AT91F_DBGU_Init(void)
sysirq_register(AT91SAM7_SYSIRQ_DBGU, &DBGU_irq_handler);
AT91F_DBGU_Printk("\n\r");
- AT91F_DBGU_Printk("(C) 2006 by Harald Welte <hwelte@hmw-consulting.de>\n\r"
+ AT91F_DBGU_Printk("(C) 2006-2011 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
diff --git a/firmware/src/os/req_ctx.c b/firmware/src/os/req_ctx.c
index 73b6035..cc8d57b 100644
--- a/firmware/src/os/req_ctx.c
+++ b/firmware/src/os/req_ctx.c
@@ -28,9 +28,9 @@
/* FIXME: locking, FIFO order processing */
-#ifdef __AT91SAM7S64__
-#define NUM_RCTX_SMALL 4
-#define NUM_RCTX_LARGE 2
+#if defined(__AT91SAM7S64__) || defined(RUN_FROM_RAM)
+#define NUM_RCTX_SMALL 16
+#define NUM_RCTX_LARGE 1
#else
#define NUM_RCTX_SMALL 8
#define NUM_RCTX_LARGE 4
diff --git a/firmware/src/os/req_ctx.h b/firmware/src/os/req_ctx.h
index ac9ab3f..94b5c5a 100644
--- a/firmware/src/os/req_ctx.h
+++ b/firmware/src/os/req_ctx.h
@@ -2,7 +2,7 @@
#define _REQ_CTX_H
#define RCTX_SIZE_LARGE 2048
-#define RCTX_SIZE_SMALL 64
+#define RCTX_SIZE_SMALL 128
#define MAX_HDRSIZE sizeof(struct openpcd_hdr)
#define MAX_REQSIZE (64-MAX_HDRSIZE)
diff --git a/firmware/src/os/usb_descriptors_openpcd.h b/firmware/src/os/usb_descriptors_openpcd.h
index ceb7ff6..58c54ec 100644
--- a/firmware/src/os/usb_descriptors_openpcd.h
+++ b/firmware/src/os/usb_descriptors_openpcd.h
@@ -20,8 +20,8 @@ const struct usb_device_descriptor dev_descriptor = {
.idProduct = USB_PRODUCT_ID,
.bcdDevice = 0x0030, /* Version 0.3 */
#ifdef CONFIG_USB_STRING
- .iManufacturer = 3,
- .iProduct = 4,
+ .iManufacturer = 4,
+ .iProduct = 5,
.iSerialNumber = 0,
#else
.iManufacturer = 0,
@@ -36,7 +36,7 @@ struct _desc {
struct usb_interface_descriptor uif;
struct usb_endpoint_descriptor ep[3];
#ifdef CONFIG_DFU
- struct usb_interface_descriptor uif_dfu[2];
+ struct usb_interface_descriptor uif_dfu[3];
#endif
};
@@ -46,9 +46,9 @@ const struct _desc cfg_descriptor = {
.bDescriptorType = USB_DT_CONFIG,
.wTotalLength = USB_DT_CONFIG_SIZE +
#ifdef CONFIG_DFU
- 3 * USB_DT_INTERFACE_SIZE +
+ 4 * USB_DT_INTERFACE_SIZE +
3 * USB_DT_ENDPOINT_SIZE,
- .bNumInterfaces = 3,
+ .bNumInterfaces = 4,
#else
1 * USB_DT_INTERFACE_SIZE +
3 * USB_DT_ENDPOINT_SIZE,
@@ -56,7 +56,7 @@ const struct _desc cfg_descriptor = {
#endif
.bConfigurationValue = 1,
#ifdef CONFIG_USB_STRING
- .iConfiguration = 5,
+ .iConfiguration = 6,
#else
.iConfiguration = 0,
#endif
@@ -73,7 +73,7 @@ const struct _desc cfg_descriptor = {
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0xff,
#ifdef CONFIG_USB_STRING
- .iInterface = 6,
+ .iInterface = 7,
#else
.iInterface = 0,
#endif
diff --git a/firmware/src/pcd/usb_strings_app.txt b/firmware/src/pcd/usb_strings_app.txt
index a4e9f57..ce295dc 100644
--- a/firmware/src/pcd/usb_strings_app.txt
+++ b/firmware/src/pcd/usb_strings_app.txt
@@ -1,5 +1,6 @@
OpenPCD DFU Interface - Application Partition
OpenPCD DFU Interface - Bootloader Partition
+OpenPCD DFU Interface - RAM
bitmanufaktur.de IT Solutions and hmw-consulting.de
OpenPCD RFID Reader - Runtime Mode
OpenPCD Runtime Configuration
diff --git a/firmware/src/pcd/usb_strings_dfu.txt b/firmware/src/pcd/usb_strings_dfu.txt
index a7714b7..9b18e60 100644
--- a/firmware/src/pcd/usb_strings_dfu.txt
+++ b/firmware/src/pcd/usb_strings_dfu.txt
@@ -3,3 +3,4 @@ OpenPCD RFID Reader - DFU Mode
OpenPCD DFU Configuration
OpenPCD DFU Interface - Application Partition
OpenPCD DFU Interface - Bootloader Partition
+OpenPCD DFU Interface - RAM
diff --git a/firmware/src/picc/usb_strings_app.txt b/firmware/src/picc/usb_strings_app.txt
index d892c72..5e8ed56 100644
--- a/firmware/src/picc/usb_strings_app.txt
+++ b/firmware/src/picc/usb_strings_app.txt
@@ -1,5 +1,6 @@
OpenPICC DFU Interface - Application Partition
OpenPICC DFU Interface - Bootloader Partition
+OpenPICC DFU Interface - RAM
bitmanufaktur.de IT Solutions and hmw-consulting.de
OpenPICC RFID Simulator - Runtime Mode
OpenPICC Runtime Configuration
diff --git a/firmware/src/picc/usb_strings_dfu.txt b/firmware/src/picc/usb_strings_dfu.txt
index 681c30a..008259d 100644
--- a/firmware/src/picc/usb_strings_dfu.txt
+++ b/firmware/src/picc/usb_strings_dfu.txt
@@ -3,3 +3,4 @@ OpenPICC RFID Simulator - DFU Mode
OpenPIIC DFU Configuration
OpenPICC DFU Interface - Application Partition
OpenPICC DFU Interface - Bootloader Partition
+OpenPICC DFU Interface - RAM
diff --git a/firmware/src/simtrace.h b/firmware/src/simtrace.h
new file mode 100644
index 0000000..40ed3ab
--- /dev/null
+++ b/firmware/src/simtrace.h
@@ -0,0 +1,41 @@
+
+#define USB_VENDOR_ID OPENPCD_VENDOR_ID
+
+#ifdef SIMTRACE
+#define OPENPCD_PIO_LED2 AT91C_PIO_PA17
+#define OPENPCD_PIO_LED1 AT91C_PIO_PA18
+#define OPENPCD_PIO_UDP_CNX AT91C_PIO_PA29
+#define OPENPCD_PIO_UDP_PUP AT91C_PIO_PA16
+#define USB_PRODUCT_ID SIMTRACE_PRODUCT_ID
+#else
+#error "unknown PCB"
+#endif
+
+/* 7816 UART for SIM-card side */
+#define SIMTRACE_PIO_CLK AT91C_PA2_SCK0
+#define SIMTRACE_PIO_CLK_T AT91C_PA4_TCLK0
+#define SIMTRACE_PIO_IO AT91C_PA6_TXD0
+#define SIMTRACE_PIO_IO_T AT91C_PA1_TIOB0
+#define SIMTRACE_PIO_nRST AT91C_PIO_PA7
+#define SIMTRACE_PIO_SW_SIM AT91C_PIO_PA8
+
+/* 7816 UART for phone side */
+#define SIMTRACE_PIO_nRST_PH AT91C_PIO_PA24
+#define SIMTRACE_PIO_CLK_PH AT91C_PA23_SCK1
+#define SIMTRACE_PIO_CLK_PH_T AT91C_PA28_TCLK1
+#define SIMTRACE_PIO_IO_PH_TX AT91C_PA22_TXD1
+#define SIMTRACE_PIO_IO_PH_RX AT91C_PA21_RXD1
+
+/* bus switch for SIM card connection */
+#define SIMTRACE_PIO_SC_SW AT91C_PIO_PA20
+#define SIMTRACE_PIO_IO_SW AT91C_PIO_PA19
+
+#define SIMTRACE_PIO_VCC_SIM AT91C_PIO_PA5
+#define SIMTRACE_PIO_VCC_PHONE AT91C_PIO_PA30
+
+/* SPI flash */
+#define PIO_SPIF_nWP AT91C_PIO_PA15
+#define PIO_SPIF_SCK AT91C_PA14_SPCK
+#define PIO_SPIF_MOSI AT91C_PA13_MOSI
+#define PIO_SPIF_MISO AT91C_PA12_MISO
+#define PIO_SPIF_nCS AT91C_PA11_NPCS0
diff --git a/firmware/src/simtrace/iso7816_uart.c b/firmware/src/simtrace/iso7816_uart.c
new file mode 100644
index 0000000..cd1a2f0
--- /dev/null
+++ b/firmware/src/simtrace/iso7816_uart.c
@@ -0,0 +1,641 @@
+/* Driver for AT91SAM7 USART0 in ISO7816-3 mode for passive sniffing
+ * (C) 2010 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 <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <AT91SAM7.h>
+#include <lib_AT91SAM7.h>
+#include <openpcd.h>
+
+#include <simtrace_usb.h>
+
+#include <os/usb_handler.h>
+#include <os/dbgu.h>
+#include <os/pio_irq.h>
+
+#include "../simtrace.h"
+#include "../openpcd.h"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static const AT91PS_USART usart = AT91C_BASE_US0;
+
+enum iso7816_3_state {
+ ISO7816_S_RESET, /* in Reset */
+ ISO7816_S_WAIT_ATR, /* waiting for ATR to start */
+ ISO7816_S_IN_ATR, /* while we are receiving the ATR */
+ ISO7816_S_WAIT_APDU, /* waiting for start of new APDU */
+ ISO7816_S_IN_APDU, /* inside a single APDU */
+ ISO7816_S_IN_PTS, /* while we are inside the PTS / PSS */
+};
+
+/* detailed sub-states of ISO7816_S_IN_ATR */
+enum atr_state {
+ ATR_S_WAIT_TS,
+ ATR_S_WAIT_T0,
+ ATR_S_WAIT_TA,
+ ATR_S_WAIT_TB,
+ ATR_S_WAIT_TC,
+ ATR_S_WAIT_TD,
+ ATR_S_WAIT_HIST,
+ ATR_S_WAIT_TCK,
+ ATR_S_DONE,
+};
+
+/* detailed sub-states of ISO7816_S_IN_PTS */
+enum pts_state {
+ PTS_S_WAIT_REQ_PTSS,
+ PTS_S_WAIT_REQ_PTS0,
+ PTS_S_WAIT_REQ_PTS1,
+ PTS_S_WAIT_REQ_PTS2,
+ PTS_S_WAIT_REQ_PTS3,
+ PTS_S_WAIT_REQ_PCK,
+ PTS_S_WAIT_RESP_PTSS = PTS_S_WAIT_REQ_PTSS | 0x10,
+ PTS_S_WAIT_RESP_PTS0 = PTS_S_WAIT_REQ_PTS0 | 0x10,
+ PTS_S_WAIT_RESP_PTS1 = PTS_S_WAIT_REQ_PTS1 | 0x10,
+ PTS_S_WAIT_RESP_PTS2 = PTS_S_WAIT_REQ_PTS2 | 0x10,
+ PTS_S_WAIT_RESP_PTS3 = PTS_S_WAIT_REQ_PTS3 | 0x10,
+ PTS_S_WAIT_RESP_PCK = PTS_S_WAIT_REQ_PCK | 0x10,
+};
+
+#define _PTSS 0
+#define _PTS0 1
+#define _PTS1 2
+#define _PTS2 3
+#define _PTS3 4
+#define _PCK 5
+
+struct iso7816_3_handle {
+ enum iso7816_3_state state;
+
+ u_int8_t fi;
+ u_int8_t di;
+ u_int8_t wi;
+ u_int32_t waiting_time;
+
+ enum atr_state atr_state;
+ u_int8_t atr_idx;
+ u_int8_t atr_hist_len;
+ u_int8_t atr_last_td;
+ u_int8_t atr[64];
+
+ enum pts_state pts_state;
+ u_int8_t pts_req[6];
+ u_int8_t pts_resp[6];
+
+ struct simtrace_hdr sh;
+
+ int rctx_must_be_sent;
+ struct req_ctx *rctx;
+};
+
+struct iso7816_3_handle isoh;
+
+
+/* Table 6 from ISO 7816-3 */
+static const u_int16_t fi_table[] = {
+ 0, 372, 558, 744, 1116, 1488, 1860, 0,
+ 0, 512, 768, 1024, 1536, 2048, 0, 0
+};
+
+/* Table 7 from ISO 7816-3 */
+static const u_int8_t di_table[] = {
+ 0, 1, 2, 4, 8, 16, 0, 0,
+ 0, 0, 2, 4, 8, 16, 32, 64,
+};
+
+/* compute the F/D ratio based on Fi and Di values */
+static int compute_fidi_ratio(u_int8_t fi, u_int8_t di)
+{
+ u_int16_t f, d;
+ int ret;
+
+ if (fi >= ARRAY_SIZE(fi_table) ||
+ di >= ARRAY_SIZE(di_table))
+ return -EINVAL;
+
+ f = fi_table[fi];
+ if (f == 0)
+ return -EINVAL;
+
+ d = di_table[di];
+ if (d == 0)
+ return -EINVAL;
+
+ if (di < 8)
+ ret = f / d;
+ else
+ ret = f * d;
+
+ return ret;
+}
+
+static void refill_rctx(struct iso7816_3_handle *ih)
+{
+ struct req_ctx *rctx;
+
+ rctx = req_ctx_find_get(0, RCTX_STATE_FREE,
+ RCTX_STATE_LIBRFID_BUSY);
+ if (!rctx) {
+ ih->rctx = NULL;
+ return;
+ }
+
+ ih->sh.cmd = SIMTRACE_MSGT_DATA;
+
+ /* reserve spece at start of rctx */
+ rctx->tot_len = sizeof(struct simtrace_hdr);
+
+ ih->rctx = rctx;
+}
+
+static void send_rctx(struct iso7816_3_handle *ih)
+{
+ struct req_ctx *rctx = ih->rctx;
+
+ if (!rctx)
+ return;
+
+ /* copy the simtrace header */
+ memcpy(rctx->data, &ih->sh, sizeof(ih->sh));
+
+ req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING);
+
+ memset(&ih->sh, 0, sizeof(ih->sh));
+ ih->rctx = NULL;
+}
+
+
+/* Update the ATR sub-state */
+static void set_atr_state(struct iso7816_3_handle *ih, enum atr_state new_atrs)
+{
+ if (new_atrs == ATR_S_WAIT_TS) {
+ ih->atr_idx = 0;
+ ih->atr_hist_len = 0;
+ ih->atr_last_td = 0;
+ memset(ih->atr, 0, sizeof(ih->atr));
+ } else if (ih->atr_state == new_atrs)
+ return;
+
+ //DEBUGPCR("ATR state %u -> %u", ih->atr_state, new_atrs);
+ ih->atr_state = new_atrs;
+}
+
+#define ISO7816_3_INIT_WTIME 9600
+#define ISO7816_3_DEFAULT_WI 10
+
+static void update_fidi(struct iso7816_3_handle *ih)
+{
+ int rc;
+
+ rc = compute_fidi_ratio(ih->fi, ih->di);
+ if (rc > 0 && rc < 0x400) {
+ DEBUGPCR("computed Fi(%u) Di(%u) ratio: %d", ih->fi, ih->di, rc);
+ /* make sure UART uses new F/D ratio */
+ usart->US_CR |= AT91C_US_RXDIS | AT91C_US_RSTRX;
+ usart->US_FIDI = rc & 0x3ff;
+ usart->US_CR |= AT91C_US_RXEN | AT91C_US_STTTO;
+ /* notify ETU timer about this */
+ tc_etu_set_etu(rc);
+ } else
+ DEBUGPCRF("computed FiDi ratio %d unsupported", rc);
+}
+
+/* Update the ISO 7816-3 APDU receiver state */
+static void set_state(struct iso7816_3_handle *ih, enum iso7816_3_state new_state)
+{
+ if (new_state == ISO7816_S_RESET) {
+ usart->US_CR |= AT91C_US_RXDIS | AT91C_US_RSTRX;
+ } else if (new_state == ISO7816_S_WAIT_ATR) {
+ /* Reset to initial Fi / Di ratio */
+ ih->fi = 1;
+ ih->di = 1;
+ update_fidi(ih);
+ /* initialize todefault WI, this will be overwritten if we
+ * receive TC2, and it will be programmed into hardware after
+ * ATR is finished */
+ ih->wi = ISO7816_3_DEFAULT_WI;
+ /* update waiting time to initial waiting time */
+ ih->waiting_time = ISO7816_3_INIT_WTIME;
+ tc_etu_set_wtime(ih->waiting_time);
+ /* Set ATR sub-state to initial state */
+ set_atr_state(ih, ATR_S_WAIT_TS);
+ /* Notice that we are just coming out of reset */
+ ih->sh.flags |= SIMTRACE_FLAG_ATR;
+ }
+
+ if (ih->state == new_state)
+ return;
+
+ //DEBUGPCR("7816 state %u -> %u", ih->state, new_state);
+ ih->state = new_state;
+}
+
+/* determine the next ATR state based on received interface byte */
+static enum atr_state next_intb_state(struct iso7816_3_handle *ih, u_int8_t ch)
+{
+ switch (ih->atr_state) {
+ case ATR_S_WAIT_TD:
+ case ATR_S_WAIT_T0:
+ ih->atr_last_td = ch;
+ goto from_td;
+ case ATR_S_WAIT_TC:
+ if ((ih->atr_last_td & 0x0f) == 0x02) {
+ /* TC2 contains WI */
+ ih->wi = ch;
+ }
+ goto from_tc;
+ case ATR_S_WAIT_TB:
+ goto from_tb;
+ case ATR_S_WAIT_TA:
+ goto from_ta;
+ default:
+ DEBUGPCR("something wrong, old_state != TA");
+ return ATR_S_WAIT_TCK;
+ }
+
+from_td:
+ if (ih->atr_last_td & 0x10)
+ return ATR_S_WAIT_TA;
+from_ta:
+ if (ih->atr_last_td & 0x20)
+ return ATR_S_WAIT_TB;
+from_tb:
+ if (ih->atr_last_td & 0x40)
+ return ATR_S_WAIT_TC;
+from_tc:
+ if (ih->atr_last_td & 0x80)
+ return ATR_S_WAIT_TD;
+
+ return ATR_S_WAIT_HIST;
+}
+
+/* process an incomng ATR byte */
+static enum iso7816_3_state
+process_byte_atr(struct iso7816_3_handle *ih, u_int8_t byte)
+{
+ /* add byte to ATR buffer */
+ ih->atr[ih->atr_idx] = byte;
+ ih->atr_idx++;
+
+ switch (ih->atr_state) {
+ case ATR_S_WAIT_TS:
+ /* FIXME: if we don't have the RST line we might get this */
+ if (byte == 0) {
+ ih->atr_idx--;
+ break;
+ }
+ /* FIXME: check inverted logic */
+ set_atr_state(ih, ATR_S_WAIT_T0);
+ break;
+ case ATR_S_WAIT_T0:
+ /* obtain the number of historical bytes */
+ ih->atr_hist_len = byte & 0xf;
+ /* Mask out the hist-byte-length to indiicate T=0 */
+ set_atr_state(ih, next_intb_state(ih, byte & 0xf0));
+ break;
+ case ATR_S_WAIT_TA:
+ case ATR_S_WAIT_TB:
+ case ATR_S_WAIT_TC:
+ case ATR_S_WAIT_TD:
+ set_atr_state(ih, next_intb_state(ih, byte));
+ break;
+ case ATR_S_WAIT_HIST:
+ ih->atr_hist_len--;
+ /* after all historical bytes are recieved, go to TCK */
+ if (ih->atr_hist_len == 0)
+ set_atr_state(ih, ATR_S_WAIT_TCK);
+ break;
+ case ATR_S_WAIT_TCK:
+ /* FIXME: process and verify the TCK */
+ set_atr_state(ih, ATR_S_DONE);
+ /* send off the USB context */
+ ih->rctx_must_be_sent = 1;
+ /* update the waiting time */
+ ih->waiting_time = 960 * di_table[ih->di] * ih->wi;
+ tc_etu_set_wtime(ih->waiting_time);
+ return ISO7816_S_WAIT_APDU;
+ }
+
+ return ISO7816_S_IN_ATR;
+}
+
+/* Update the ATR sub-state */
+static void set_pts_state(struct iso7816_3_handle *ih, enum pts_state new_ptss)
+{
+ //DEBUGPCR("PTS state %u -> %u", ih->pts_state, new_ptss);
+ ih->pts_state = new_ptss;
+}
+
+/* Determine the next PTS state */
+static enum pts_state next_pts_state(struct iso7816_3_handle *ih)
+{
+ u_int8_t is_resp = ih->pts_state & 0x10;
+ u_int8_t sstate = ih->pts_state & 0x0f;
+ u_int8_t *pts_ptr;
+
+ if (!is_resp)
+ pts_ptr = ih->pts_req;
+ else
+ pts_ptr = ih->pts_resp;
+
+ switch (sstate) {
+ case PTS_S_WAIT_REQ_PTSS:
+ goto from_ptss;
+ case PTS_S_WAIT_REQ_PTS0:
+ goto from_pts0;
+ case PTS_S_WAIT_REQ_PTS1:
+ goto from_pts1;
+ case PTS_S_WAIT_REQ_PTS2:
+ goto from_pts2;
+ case PTS_S_WAIT_REQ_PTS3:
+ goto from_pts3;
+ }
+
+ if (ih->pts_state == PTS_S_WAIT_REQ_PCK)
+ return PTS_S_WAIT_RESP_PTSS;
+
+from_ptss:
+ return PTS_S_WAIT_REQ_PTS0 | is_resp;
+from_pts0:
+ if (pts_ptr[_PTS0] & (1 << 4))
+ return PTS_S_WAIT_REQ_PTS1 | is_resp;
+from_pts1:
+ if (pts_ptr[_PTS0] & (1 << 5))
+ return PTS_S_WAIT_REQ_PTS2 | is_resp;
+from_pts2:
+ if (pts_ptr[_PTS0] & (1 << 6))
+ return PTS_S_WAIT_REQ_PTS3 | is_resp;
+from_pts3:
+ return PTS_S_WAIT_REQ_PCK | is_resp;
+}
+
+static enum iso7816_3_state
+process_byte_pts(struct iso7816_3_handle *ih, u_int8_t byte)
+{
+ switch (ih->pts_state) {
+ case PTS_S_WAIT_REQ_PTSS:
+ ih->pts_req[_PTSS] = byte;
+ break;
+ case PTS_S_WAIT_REQ_PTS0:
+ ih->pts_req[_PTS0] = byte;
+ break;
+ case PTS_S_WAIT_REQ_PTS1:
+ ih->pts_req[_PTS1] = byte;
+ break;
+ case PTS_S_WAIT_REQ_PTS2:
+ ih->pts_req[_PTS2] = byte;
+ break;
+ case PTS_S_WAIT_REQ_PTS3:
+ ih->pts_req[_PTS3] = byte;
+ break;
+ case PTS_S_WAIT_REQ_PCK:
+ /* FIXME: check PCK */
+ ih->pts_req[_PCK] = byte;
+ break;
+ case PTS_S_WAIT_RESP_PTSS:
+ ih->pts_resp[_PTSS] = byte;
+ break;
+ case PTS_S_WAIT_RESP_PTS0:
+ ih->pts_resp[_PTS0] = byte;
+ break;
+ case PTS_S_WAIT_RESP_PTS1:
+ /* This must be TA1 */
+ ih->fi = byte >> 4;
+ ih->di = byte & 0xf;
+ DEBUGPCR("found Fi=%u Di=%u", ih->fi, ih->di);
+ ih->pts_resp[_PTS1] = byte;
+ break;
+ case PTS_S_WAIT_RESP_PTS2:
+ ih->pts_resp[_PTS2] = byte;
+ break;
+ case PTS_S_WAIT_RESP_PTS3:
+ ih->pts_resp[_PTS3] = byte;
+ break;
+ case PTS_S_WAIT_RESP_PCK:
+ ih->pts_resp[_PCK] = byte;
+ /* FIXME: check PCK */
+ set_pts_state(ih, PTS_S_WAIT_REQ_PTSS);
+ /* update baud rate generator with Fi/Di */
+ update_fidi(ih);
+ /* Wait for the next APDU */
+ return ISO7816_S_WAIT_APDU;
+ }
+ /* calculate the next state and set it */
+ set_pts_state(ih, next_pts_state(ih));
+
+ return ISO7816_S_IN_PTS;
+}
+
+static void process_byte(struct iso7816_3_handle *ih, u_int8_t byte)
+{
+ int new_state = -1;
+ struct req_ctx *rctx;
+
+ if (!ih->rctx)
+ refill_rctx(ih);
+
+ switch (ih->state) {
+ case ISO7816_S_RESET:
+ break;
+ case ISO7816_S_WAIT_ATR:
+ case ISO7816_S_IN_ATR:
+ new_state = process_byte_atr(ih, byte);
+ break;
+ case ISO7816_S_WAIT_APDU:
+ if (byte == 0xff) {
+ new_state = process_byte_pts(ih, byte);
+ goto out_silent;
+ }
+ case ISO7816_S_IN_APDU:
+ new_state = ISO7816_S_IN_APDU;
+ break;
+ case ISO7816_S_IN_PTS:
+ new_state = process_byte_pts(ih, byte);
+ goto out_silent;
+ }
+
+ /* The USB buffer could be gone in case the timer expired or code above
+ * this line explicitly sent it off */
+ if (!ih->rctx)
+ refill_rctx(ih);
+
+ rctx = ih->rctx;
+ if (!rctx) {
+ DEBUGPCR("==> Lost byte, missing rctx");
+ return;
+ }
+
+ /* store the byte in the USB request context */
+ rctx->data[rctx->tot_len] = byte;
+ rctx->tot_len++;
+
+ if (rctx->tot_len >= rctx->size || ih->rctx_must_be_sent) {
+ ih->rctx_must_be_sent = 0;
+ send_rctx(ih);
+ }
+
+out_silent:
+ if (new_state != -1)
+ set_state(ih, new_state);
+}
+
+/* timeout of work waiting time during receive */
+void iso7816_wtime_expired(void)
+{
+ /* Always flush the URB at Rx timeout as this indicates end of APDU */
+ if (isoh.rctx) {
+ isoh.sh.flags |= SIMTRACE_FLAG_WTIME_EXP;
+ send_rctx(&isoh);
+ }
+ if (isoh.state == ISO7816_S_IN_PTS) {
+ /* Timout during PTS: Card does not support PTS */
+ }
+ set_state(&isoh, ISO7816_S_WAIT_APDU);
+}
+
+static __ramfunc void usart_irq(void)
+{
+ u_int32_t csr = usart->US_CSR;
+ u_int8_t octet;
+
+ //DEBUGP("USART IRQ, CSR=0x%08x\n", csr);
+
+ if (csr & AT91C_US_RXRDY) {
+ /* at least one character received */
+ octet = usart->US_RHR & 0xff;
+ //DEBUGP("%02x ", octet);
+ process_byte(&isoh, octet);
+ }
+
+ if (csr & AT91C_US_TXRDY) {
+ /* nothing to transmit anymore */
+ }
+
+ if (csr & (AT91C_US_PARE|AT91C_US_FRAME|AT91C_US_OVRE)) {
+ /* FIXME: some error has occurrerd */
+ }
+}
+
+/* handler for the RST input pin state change */
+static void reset_pin_irq(u_int32_t pio)
+{
+ if (!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, pio)) {
+ DEBUGPCR("nRST");
+ set_state(&isoh, ISO7816_S_RESET);
+ } else {
+ DEBUGPCR("RST");
+ set_state(&isoh, ISO7816_S_WAIT_ATR);
+ }
+}
+
+void iso_uart_dump(void)
+{
+ u_int32_t csr = usart->US_CSR;
+
+ DEBUGPCR("USART CSR=0x%08x", csr);
+}
+
+void iso_uart_rst(unsigned int state)
+{
+ DEBUGPCR("USART set nRST set state=%u", state);
+ switch (state) {
+ case 0:
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_nRST);
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_nRST);
+ break;
+ case 1:
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_nRST);
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_nRST);
+ break;
+ default:
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SIMTRACE_PIO_nRST);
+ break;
+ }
+}
+
+void iso_uart_rx_mode(void)
+{
+ DEBUGPCR("USART Entering Rx Mode");
+ /* Enable receive interrupts */
+ usart->US_IER = AT91C_US_RXRDY | AT91C_US_OVRE | AT91C_US_FRAME |
+ AT91C_US_PARE | AT91C_US_NACK | AT91C_US_ITERATION;
+
+ /* call interrupt handler once to set initial state RESET / ATR */
+ reset_pin_irq(SIMTRACE_PIO_nRST);
+}
+
+void iso_uart_clk_master(unsigned int master)
+{
+ DEBUGPCR("USART Clock Master %u", master);
+ if (master) {
+ usart->US_MR = AT91C_US_USMODE_ISO7816_0 | AT91C_US_CLKS_CLOCK |
+ AT91C_US_CHRL_8_BITS | AT91C_US_NBSTOP_1_BIT |
+ AT91C_US_CKLO;
+ usart->US_BRGR = (0x0000 << 16) | 16;
+ } else {
+ usart->US_MR = AT91C_US_USMODE_ISO7816_0 | AT91C_US_CLKS_EXT |
+ AT91C_US_CHRL_8_BITS | AT91C_US_NBSTOP_1_BIT |
+ AT91C_US_CKLO;
+ usart->US_BRGR = (0x0000 << 16) | 0x0001;
+ }
+}
+
+void iso_uart_init(void)
+{
+ DEBUGPCR("USART Initializing");
+
+ refill_rctx(&isoh);
+
+ /* make sure we get clock from the power management controller */
+ AT91F_US0_CfgPMC();
+
+ /* configure all 3 signals as input */
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, SIMTRACE_PIO_IO, SIMTRACE_PIO_CLK);
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SIMTRACE_PIO_nRST);
+
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_US0,
+ OPENPCD_IRQ_PRIO_USART,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &usart_irq);
+ AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_US0);
+
+ usart->US_CR = AT91C_US_RXDIS | AT91C_US_TXDIS |
+ (AT91C_US_RSTRX | AT91C_US_RSTTX);
+ /* FIXME: wait for some time */
+ usart->US_CR = AT91C_US_RXDIS | AT91C_US_TXDIS;
+
+ /* ISO7816 T=0 mode with external clock input */
+ usart->US_MR = AT91C_US_USMODE_ISO7816_0 | AT91C_US_CLKS_EXT |
+ AT91C_US_CHRL_8_BITS | AT91C_US_NBSTOP_1_BIT |
+ AT91C_US_CKLO;
+
+ /* Disable all interrupts */
+ usart->US_IDR = 0xff;
+ /* Clock Divider = 1, i.e. no division of SCLK */
+ usart->US_BRGR = (0x0000 << 16) | 0x0001;
+ /* Disable Receiver Time-out */
+ usart->US_RTOR = 0;
+ /* Disable Transmitter Timeguard */
+ usart->US_TTGR = 0;
+
+ pio_irq_register(SIMTRACE_PIO_nRST, &reset_pin_irq);
+ AT91F_PIO_CfgInputFilter(AT91C_BASE_PIOA, SIMTRACE_PIO_nRST);
+ pio_irq_enable(SIMTRACE_PIO_nRST);
+}
diff --git a/firmware/src/simtrace/iso7816_uart.h b/firmware/src/simtrace/iso7816_uart.h
new file mode 100644
index 0000000..ed1c898
--- /dev/null
+++ b/firmware/src/simtrace/iso7816_uart.h
@@ -0,0 +1,6 @@
+
+void iso_uart_dump(void);
+void iso_uart_rst(unsigned int state);
+void iso_uart_rx_mode(void);
+void iso_uart_clk_master(unsigned int master);
+void iso_uart_init(void);
diff --git a/firmware/src/simtrace/main_factory.c b/firmware/src/simtrace/main_factory.c
new file mode 100644
index 0000000..3585fa6
--- /dev/null
+++ b/firmware/src/simtrace/main_factory.c
@@ -0,0 +1,80 @@
+/* SIMtrace factory programming
+ * (C) 2011 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 <errno.h>
+#include <include/lib_AT91SAM7.h>
+#include <include/openpcd.h>
+#include <os/dbgu.h>
+#include <os/led.h>
+#include <os/pcd_enumerate.h>
+#include <os/usb_handler.h>
+#include "../openpcd.h"
+#include "../simtrace.h"
+#include <os/main.h>
+#include <os/pio_irq.h>
+
+#include <simtrace/tc_etu.h>
+#include <simtrace/iso7816_uart.h>
+#include <simtrace/sim_switch.h>
+
+void _init_func(void)
+{
+ /* low-level hardware initialization */
+ pio_irq_init();
+ spiflash_init();
+
+ /* high-level protocol */
+ //opicc_usbapi_init();
+ led_switch(1, 0);
+ led_switch(2, 1);
+}
+
+static void help(void)
+{
+ DEBUGPCR("f: read flash ID\r\n");
+}
+
+int _main_dbgu(char key)
+{
+ static int i = 0;
+ DEBUGPCRF("main_dbgu");
+
+ switch (key) {
+ case 'f':
+ spiflash_id();
+ break;
+ case '?':
+ help();
+ break;
+ }
+
+ return -EINVAL;
+}
+
+void _main_func(void)
+{
+ /* first we try to get rid of pending to-be-sent stuff */
+ usb_out_process();
+
+ /* next we deal with incoming requests from USB EP1 (OUT) */
+ usb_in_process();
+
+ udp_unthrottle();
+}
diff --git a/firmware/src/simtrace/main_simtrace.c b/firmware/src/simtrace/main_simtrace.c
new file mode 100644
index 0000000..f919690
--- /dev/null
+++ b/firmware/src/simtrace/main_simtrace.c
@@ -0,0 +1,165 @@
+/* OpenPICC Main Program
+ * (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 <errno.h>
+#include <include/lib_AT91SAM7.h>
+#include <include/openpcd.h>
+#include <os/dbgu.h>
+#include <os/led.h>
+#include <os/pcd_enumerate.h>
+#include <os/usb_handler.h>
+#include "../openpcd.h"
+#include "../simtrace.h"
+#include <os/main.h>
+#include <os/pio_irq.h>
+
+#include <simtrace/tc_etu.h>
+#include <simtrace/iso7816_uart.h>
+#include <simtrace/sim_switch.h>
+
+enum simtrace_md {
+ SIMTRACE_MD_OFF,
+ SIMTRACE_MD_SNIFFER,
+ SIMTRACE_MD_MITM,
+};
+
+#define UART1_PINS (SIMTRACE_PIO_nRST_PH | \
+ SIMTRACE_PIO_CLK_PH | \
+ SIMTRACE_PIO_CLK_PH_T | \
+ SIMTRACE_PIO_IO_PH_RX | \
+ SIMTRACE_PIO_IO_PH_TX)
+
+#define UART0_PINS (SIMTRACE_PIO_nRST | \
+ SIMTRACE_PIO_CLK | \
+ SIMTRACE_PIO_CLK_T | \
+ SIMTRACE_PIO_IO | \
+ SIMTRACE_PIO_IO_T)
+
+static void simtrace_set_mode(enum simtrace_md mode)
+{
+ switch (mode) {
+ case SIMTRACE_MD_SNIFFER:
+ DEBUGPCR("MODE: SNIFFER\n");
+
+ /* switch UART1 pins to input, no pull-up */
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, UART1_PINS);
+ AT91F_PIO_CfgPullupDis(AT91C_BASE_PIOA, UART1_PINS);
+
+ /* switch VCC_SIM pin into output mode, as in the first
+ * generation prototype we use it directly to supply Vcc
+ * to the SIM */
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_SIM);
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_SIM);
+
+ /* switch UART0 pins to 'ISO7816 card mode' */
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, UART0_PINS);
+ AT91F_PIO_CfgPullupDis(AT91C_BASE_PIOA, UART0_PINS);
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, SIMTRACE_PIO_IO, SIMTRACE_PIO_CLK);
+ sim_switch_mode(1, 1);
+ break;
+ case SIMTRACE_MD_MITM:
+ DEBUGPCR("MODE: MITM\n");
+ /* switch UART1 pins to 'ISO7816 card mode' */
+ /* switch UART0 pins to 'ISO7816 reader mode' */
+ sim_switch_mode(0, 0);
+ break;
+ }
+}
+
+void _init_func(void)
+{
+ /* low-level hardware initialization */
+ pio_irq_init();
+ iso_uart_init();
+ tc_etu_init();
+ sim_switch_init();
+
+ usbtest_init();
+
+ /* high-level protocol */
+ //opicc_usbapi_init();
+ led_switch(1, 0);
+ led_switch(2, 1);
+
+ iso_uart_rx_mode();
+ simtrace_set_mode(SIMTRACE_MD_SNIFFER);
+}
+
+
+static void help(void)
+{
+ DEBUGPCR("r: iso uart Rx mode\r\n"
+ "c: toggle clock master/slave\r\n"
+ "l: set nRST to low (active)\r\n"
+ "h: set nRST to high (inactive)\r\n"
+ "o: set nRST to input\r\n"
+ "r: set Rx mode for UART\r\n"
+ "s: disconnect SIM bus switch\r\n"
+ "S: connect SIM bus switch\r\n");
+}
+
+int _main_dbgu(char key)
+{
+ static int i = 0;
+ DEBUGPCRF("main_dbgu");
+
+ switch (key) {
+ case 's':
+ simtrace_set_mode(SIMTRACE_MD_MITM);
+ break;
+ case 'S':
+ simtrace_set_mode(SIMTRACE_MD_SNIFFER);
+ break;
+ case 'r':
+ iso_uart_rx_mode();
+ break;
+ case 'c':
+ iso_uart_clk_master(i++ & 1);
+ break;
+ case 'l':
+ iso_uart_rst(0);
+ break;
+ case 'h':
+ iso_uart_rst(1);
+ break;
+ case 'o':
+ iso_uart_rst(2);
+ break;
+ case 'd':
+ iso_uart_dump();
+ break;
+ case '?':
+ help();
+ break;
+ }
+
+ return -EINVAL;
+}
+
+void _main_func(void)
+{
+ /* first we try to get rid of pending to-be-sent stuff */
+ usb_out_process();
+
+ /* next we deal with incoming requests from USB EP1 (OUT) */
+ usb_in_process();
+
+ udp_unthrottle();
+}
diff --git a/firmware/src/simtrace/sim_switch.c b/firmware/src/simtrace/sim_switch.c
new file mode 100644
index 0000000..f83290f
--- /dev/null
+++ b/firmware/src/simtrace/sim_switch.c
@@ -0,0 +1,95 @@
+/*
+ * (C) 2011 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 <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <AT91SAM7.h>
+#include <lib_AT91SAM7.h>
+#include <openpcd.h>
+
+#include <simtrace_usb.h>
+
+#include <os/usb_handler.h>
+#include <os/dbgu.h>
+#include <os/pio_irq.h>
+
+#include "../simtrace.h"
+#include "../openpcd.h"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+void sim_switch_mode(int connect_io, int connect_misc)
+{
+ if (connect_io)
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_IO_SW);
+ else
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_IO_SW);
+
+ if (connect_misc)
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_SC_SW);
+ else
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_SC_SW);
+}
+
+static void sw_sim_irq(u_int32_t pio)
+{
+
+ if (!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, pio))
+ DEBUGPCR("SIM card inserted");
+ else
+ DEBUGPCR("SIM card removed");
+}
+
+static void vcc_phone_irq(u_int32_t pio)
+{
+ if (!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, pio))
+ DEBUGPCR("VCC_PHONE off");
+ else
+ DEBUGPCR("VCC_PHONE on");
+}
+
+void sim_switch_init(void)
+{
+ DEBUGPCR("ISO_SW Initializing");
+
+ /* make sure we get clock from the power management controller */
+ AT91F_US0_CfgPMC();
+
+ /* configure both signals as output */
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_SC_SW |
+ SIMTRACE_PIO_IO_SW);
+
+ /* configure sim card detect */
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SIMTRACE_PIO_SW_SIM);
+ AT91F_PIO_CfgInputFilter(AT91C_BASE_PIOA, SIMTRACE_PIO_SW_SIM);
+ pio_irq_register(SIMTRACE_PIO_SW_SIM, &sw_sim_irq);
+ pio_irq_enable(SIMTRACE_PIO_SW_SIM);
+ /* configure VCC_PHONE detection */
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_PHONE);
+ AT91F_PIO_CfgPullupDis(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_PHONE);
+ AT91F_PIO_CfgInputFilter(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_PHONE);
+ pio_irq_register(SIMTRACE_PIO_VCC_PHONE, &vcc_phone_irq);
+ pio_irq_enable(SIMTRACE_PIO_VCC_PHONE);
+
+#if 0
+ AT91F_ADC_CfgPMC();
+ AT91F_ADC_EnableChannel(AT91C_BASE_ADC, AT91C_ADC_CH7);
+#endif
+}
diff --git a/firmware/src/simtrace/sim_switch.h b/firmware/src/simtrace/sim_switch.h
new file mode 100644
index 0000000..01a6a66
--- /dev/null
+++ b/firmware/src/simtrace/sim_switch.h
@@ -0,0 +1,7 @@
+#ifndef SIMTRACE_ISO_SW_H
+#define SIMTRACE_ISO_SW_H
+
+void sim_switch_mode(int connect_io, int connect_misc);
+void sim_switch_init(void);
+
+#endif
diff --git a/firmware/src/simtrace/spi_flash.c b/firmware/src/simtrace/spi_flash.c
new file mode 100644
index 0000000..98bc369
--- /dev/null
+++ b/firmware/src/simtrace/spi_flash.c
@@ -0,0 +1,144 @@
+/* Driver for a SST25VF040B spi flash attached to AT91SAM7 SPI
+ * (C) 2011 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 <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <AT91SAM7.h>
+#include <lib_AT91SAM7.h>
+#include <openpcd.h>
+
+#include <simtrace_usb.h>
+
+#include <os/usb_handler.h>
+#include <os/dbgu.h>
+#include <os/pio_irq.h>
+
+#include "../simtrace.h"
+#include "../openpcd.h"
+
+#define DEBUGPSPI DEBUGP
+//#define DEBUGPSPI(x, y ...) do { } while (0)
+
+static const AT91PS_SPI pSPI = AT91C_BASE_SPI;
+
+void spiflash_write_protect(int on)
+{
+ if (on)
+ AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, PIO_SPIF_nWP);
+ else
+ AT91F_PIO_SetOutput(AT91C_BASE_PIOA, PIO_SPIF_nWP);
+}
+
+#define SPI_PERIPHA (PIO_SPIF_SCK|PIO_SPIF_MOSI|PIO_SPIF_MISO|PIO_SPIF_nCS)
+
+static __ramfunc void spi_irq(void)
+{
+ u_int32_t status = pSPI->SPI_SR;
+
+ AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_SPI);
+}
+
+void spiflash_init(void)
+{
+ DEBUGP("spiflash_init\r\n");
+
+ /* activate and enable the write protection */
+ AT91F_PIO_CfgPullupDis(AT91C_BASE_PIOA, PIO_SPIF_nWP);
+ AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, PIO_SPIF_nWP);
+ spiflash_write_protect(1);
+
+ /* Configure PIOs for SCK, MOSI, MISO and nCS */
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, SPI_PERIPHA, 0);
+
+ AT91F_SPI_CfgPMC();
+ /* Spansion flash in v1.0p only supprts Mode 3 or Mode 0 */
+ /* Mode 3: CPOL=1 nCPHA=0 CSAAT=0 BITS=0(8) MCK/2 */
+ AT91F_SPI_CfgCs(AT91C_BASE_SPI, 0, AT91C_SPI_CPOL |
+ AT91C_SPI_BITS_8 |
+ (64 << 8));
+
+ /* SPI master mode, fixed CS, CS = 0 */
+ AT91F_SPI_CfgMode(AT91C_BASE_SPI, AT91C_SPI_MSTR |
+ AT91C_SPI_PS_FIXED |
+ (0 << 16));
+
+ /* configure interrupt controller for SPI IRQ */
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SPI,
+ OPENPCD_IRQ_PRIO_SPI,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &spi_irq);
+ //AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SPI);
+
+ /* Enable the SPI Controller */
+ AT91F_SPI_Enable(AT91C_BASE_SPI);
+ AT91F_SPI_EnableIt(AT91C_BASE_SPI, AT91C_SPI_MODF |
+ AT91C_SPI_OVRES |
+ AT91C_SPI_ENDRX |
+ AT91C_SPI_ENDTX);
+}
+
+static int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len,
+ u_int8_t *rx_data, u_int16_t *rx_len)
+{
+ u_int16_t tx_cur = 0;
+ u_int16_t rx_len_max = 0;
+ u_int16_t rx_cnt = 0;
+
+ DEBUGPSPI("spi_transceive: enter(tx_len=%u) ", tx_len);
+
+ if (rx_len) {
+ rx_len_max = *rx_len;
+ *rx_len = 0;
+ }
+
+ //AT91F_SPI_Enable(pSPI);
+ while (1) {
+ u_int32_t sr = pSPI->SPI_SR;
+ u_int8_t tmp;
+ if (sr & AT91C_SPI_RDRF) {
+ tmp = pSPI->SPI_RDR;
+ rx_cnt++;
+ if (rx_len && *rx_len < rx_len_max)
+ rx_data[(*rx_len)++] = tmp;
+ }
+ if (sr & AT91C_SPI_TDRE) {
+ if (tx_len > tx_cur)
+ pSPI->SPI_TDR = tx_data[tx_cur++];
+ }
+ if (tx_cur >= tx_len && rx_cnt >= tx_len)
+ break;
+ }
+ //AT91F_SPI_Disable(pSPI);
+ if (rx_data)
+ DEBUGPSPI(" leave(%02x %02x)\r\n", rx_data[0], rx_data[1]);
+ else
+ DEBUGPSPI("leave()\r\n");
+
+ return 0;
+}
+
+void spiflash_id(void)
+{
+ const u_int8_t tx_data[] = { 0x9f, 0, 0, 0 };
+ u_int8_t rx_data[] = { 0,0,0,0 };
+ u_int16_t rx_len = sizeof(rx_data);
+
+ spi_transceive(tx_data, sizeof(tx_data), rx_data, &rx_len);
+ DEBUGP("SPI ID: %02x %02x %02x\n", rx_data[1], rx_data[2], rx_data[3]);
+}
diff --git a/firmware/src/simtrace/tc_etu.c b/firmware/src/simtrace/tc_etu.c
new file mode 100644
index 0000000..fc52033
--- /dev/null
+++ b/firmware/src/simtrace/tc_etu.c
@@ -0,0 +1,128 @@
+/* SimTrace TC (Timer / Clock) support code
+ * (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 <AT91SAM7.h>
+#include <os/dbgu.h>
+
+#include "../openpcd.h"
+
+static AT91PS_TCB tcb;
+static AT91PS_TC tcetu = AT91C_BASE_TC0;
+
+static u_int16_t waiting_time = 9600;
+static u_int16_t clocks_per_etu = 372;
+static u_int16_t wait_events;
+
+static __ramfunc void tc_etu_irq(void)
+{
+ u_int32_t sr = tcetu->TC_SR;
+ static u_int16_t nr_events;
+
+ if (sr & AT91C_TC_ETRGS) {
+ /* external trigger, i.e. we have seen a bit on I/O */
+ //DEBUGPCR("tE");
+ nr_events = 0;
+ /* Make sure we don't accept any additional external trigger */
+ /* Enabling the line below will cause race conditions. We
+ * thus re-trigger at all zero-bits in the byte and thus wait
+ * up to 12 etu longer than required */
+ //tcetu->TC_CMR &= ~AT91C_TC_ENETRG;
+ }
+
+ if (sr & AT91C_TC_CPCS) {
+ /* Compare C event has occurred, i.e. 1 etu expired */
+ //DEBUGPCR("tC");
+ nr_events++;
+ if (nr_events >= wait_events) {
+ /* enable external triggers again to catch start bit */
+ tcetu->TC_CMR |= AT91C_TC_ENETRG;
+
+ /* disable and re-enable clock to make it stop */
+ tcetu->TC_CCR = AT91C_TC_CLKDIS;
+ tcetu->TC_CCR = AT91C_TC_CLKEN;
+
+ //DEBUGPCR("%u", nr_events);
+
+ /* Indicate that the waiting time has expired */
+ iso7816_wtime_expired();
+ }
+ }
+}
+
+static void recalc_nr_events(void)
+{
+ wait_events = waiting_time/12;
+ /* clocks_per_etu * 12 equals 'sbit + 8 data bits + parity + 2 stop bits */
+ tcetu->TC_RC = clocks_per_etu * 12;
+}
+
+void tc_etu_set_wtime(u_int16_t wtime)
+{
+ waiting_time = wtime;
+ recalc_nr_events();
+ //DEBUGPCR("wtime=%u, actually waiting %u", wtime, wait_events * 12);
+}
+
+void tc_etu_set_etu(u_int16_t etu)
+{
+ clocks_per_etu = etu;
+ recalc_nr_events();
+}
+
+void tc_etu_init(void)
+{
+ /* Cfg PA4(TCLK0), PA0(TIOA0), PA1(TIOB0) */
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0,
+ AT91C_PA4_TCLK0 | AT91C_PA0_TIOA0 | AT91C_PA1_TIOB0);
+
+ AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC,
+ ((unsigned int) 1 << AT91C_ID_TC0));
+
+ /* Connect TCLK0 to XC0 */
+ tcb->TCB_BMR &= ~(AT91C_TCB_TC0XC0S);
+ tcb->TCB_BMR |= AT91C_TCB_TC0XC0S_TCLK0;
+
+ /* Register Interrupt handler */
+ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,
+ OPENPCD_IRQ_PRIO_TC_FDT,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &tc_etu_irq);
+ AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0);
+
+ /* enable interrupts for Compare-C and External Trigger */
+ tcetu->TC_IER = AT91C_TC_CPCS | AT91C_TC_ETRGS;
+
+ tcetu->TC_CMR = AT91C_TC_CLKS_XC0 | /* XC0 (TCLK0) clock */
+ AT91C_TC_WAVE | /* Wave Mode */
+ AT91C_TC_ETRGEDG_FALLING |/* Ext trig on falling edge */
+ AT91C_TC_EEVT_TIOB | /* Ext trigger is TIOB0 */
+ AT91C_TC_ENETRG | /* Enable ext. trigger */
+ AT91C_TC_WAVESEL_UP_AUTO |/* Wave mode UP */
+ AT91C_TC_ACPA_SET | /* Set TIOA0 on A compare */
+ AT91C_TC_ACPC_CLEAR | /* Clear TIOA0 on C compare */
+ AT91C_TC_ASWTRG_CLEAR; /* Clear TIOa0 on software trigger */
+
+ tc_etu_set_etu(372);
+
+ /* Enable master clock for TC0 */
+ tcetu->TC_CCR = AT91C_TC_CLKEN;
+
+ /* Reset to start timers */
+ tcb->TCB_BCR = 1;
+}
diff --git a/firmware/src/simtrace/tc_etu.h b/firmware/src/simtrace/tc_etu.h
new file mode 100644
index 0000000..59d9031
--- /dev/null
+++ b/firmware/src/simtrace/tc_etu.h
@@ -0,0 +1,4 @@
+
+void tc_etu_set_wtime(u_int16_t wtime);
+void tc_etu_set_etu(u_int16_t etu);
+void tc_etu_init(void);
diff --git a/firmware/src/simtrace/usb_strings_app.txt b/firmware/src/simtrace/usb_strings_app.txt
new file mode 100644
index 0000000..02cf326
--- /dev/null
+++ b/firmware/src/simtrace/usb_strings_app.txt
@@ -0,0 +1,7 @@
+SimTrace DFU Interface - Application Partition
+SimTrace DFU Interface - Bootloader Partition
+SimTrace DFU Interface - RAM
+sysmocom - systems for mobile communications GmbH
+SimTrace SIM Sniffer - Runtime Mode
+SimTrace Runtime Configuration
+SimTrace Runtime Interface
diff --git a/firmware/src/simtrace/usb_strings_dfu.txt b/firmware/src/simtrace/usb_strings_dfu.txt
new file mode 100644
index 0000000..2f65684
--- /dev/null
+++ b/firmware/src/simtrace/usb_strings_dfu.txt
@@ -0,0 +1,6 @@
+sysmocom - systems for mobile communications GmbH
+SimTrace SIM Sniffer - DFU Mode
+SimTrace DFU Configuration
+SimTrace DFU Interface - Application Partition
+SimTrace DFU Interface - Bootloader Partition
+SimTrace DFU Interface - RAM
diff --git a/firmware/src/start/Cstartup.S b/firmware/src/start/Cstartup.S
index a28b400..e262b8f 100644
--- a/firmware/src/start/Cstartup.S
+++ b/firmware/src/start/Cstartup.S
@@ -98,6 +98,9 @@
/* Olimex SAM7-Pxxx boards have a button B1 on PA19 that is low-active */
.equ PIO_BOOTLDR, (1 << 19)
#define CONFIG_DFU_SWITCH_INV
+#elif defined(SIMTRACE)
+ .equ PIO_BOOTLDR, (1 << 31)
+#define CONFIG_DFU_SWITCH_INV
#else
#error please define PIO_BOOTLDR for your board
#endif
diff --git a/firmware/src/start/Cstartup_app.S b/firmware/src/start/Cstartup_app.S
index 448cc93..197be66 100644
--- a/firmware/src/start/Cstartup_app.S
+++ b/firmware/src/start/Cstartup_app.S
@@ -79,6 +79,7 @@
.global _startup
.func _startup
_startup:
+#ifndef RUN_FROM_RAM
/* Relocate .data section (copy from Flash to RAM) */
ldr r1, =_etext
ldr r2, =_data
@@ -87,6 +88,7 @@ loop_r: cmp r2, r3
ldrlo r0, [r1], #4
strlo r0, [r2], #4
blo loop_r
+#endif
/* Clear .bss section (Zero init) */
mov r0, #0
personal git repositories of Harald Welte. Your mileage may vary