From 50b1aff6f6f2a3a127f6121c5dedd8c2fa5a1c4d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 14 Nov 2010 23:04:16 +0100 Subject: Initial version of a SAM7 USART based ISO7816-3 T=0 sniffer --- firmware/include/openpcd.h | 3 + firmware/src/openpcd.h | 7 +- firmware/src/simtrace.h | 18 ++ firmware/src/simtrace/iso7816_uart.c | 399 ++++++++++++++++++++++++++++++ firmware/src/simtrace/main_simtrace.c | 98 ++++++++ firmware/src/simtrace/usb_strings_app.txt | 6 + 6 files changed, 529 insertions(+), 2 deletions(-) create mode 100644 firmware/src/simtrace.h create mode 100644 firmware/src/simtrace/iso7816_uart.c create mode 100644 firmware/src/simtrace/main_simtrace.c create mode 100644 firmware/src/simtrace/usb_strings_app.txt 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/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/simtrace.h b/firmware/src/simtrace.h new file mode 100644 index 0000000..5a27c31 --- /dev/null +++ b/firmware/src/simtrace.h @@ -0,0 +1,18 @@ + +#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_PA24 +#define OPENPCD_PIO_UDP_PUP AT91C_PIO_PA16 +#define USB_PRODUCT_ID SIMTRACE_PRODUCT_ID +#else +#error "unknown PCB" +#endif + +#define SIMTRACE_PIO_CLK AT91C_PA2_SCK0 +#define SIMTRACE_PIO_IO AT91C_PA6_TXD0 +#define SIMTRACE_PIO_nRST AT91C_PIO_PA7 + + diff --git a/firmware/src/simtrace/iso7816_uart.c b/firmware/src/simtrace/iso7816_uart.c new file mode 100644 index 0000000..9022830 --- /dev/null +++ b/firmware/src/simtrace/iso7816_uart.c @@ -0,0 +1,399 @@ +/* Driver for AT91SAM7 USART0 in ISO7816-3 mode + * (C) 2010 by Harald Welte + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#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, + ISO7816_S_WAIT_READER, /* waiting for data from reader */ + ISO7816_S_WAIT_CARD, /* waiting for data from card */ +}; + +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, +}; + +struct iso7816_3_handle { + enum iso7816_3_state state; + + u_int8_t fi; + u_int8_t di; + + u_int8_t atr_idx; + u_int8_t atr_hist_len; + u_int8_t atr_last_td; + enum atr_state atr_state; + u_int8_t atr[64]; + + u_int16_t apdu_len; + u_int16_t apdu_idx; +}; + +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, +}; + +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 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; +} + +static void set_state(struct iso7816_3_handle *ih, enum iso7816_3_state new_state) +{ + if (new_state == ISO7816_S_WAIT_ATR) { + int rc; + /* Initial Fi / Di ratio */ + ih->fi = 1; + ih->di = 1; + rc = compute_fidi_ratio(ih->fi, ih->di); + DEBUGPCRF("computed Fi(%u) Di(%u) ratio: %d", ih->fi, ih->di, rc); + usart->US_FIDI = rc & 0x3ff; + set_atr_state(ih, ATR_S_WAIT_TS); + } else if (new_state == ISO7816_S_WAIT_READER) { + /* CLA INS P1 P2 LEN */ + ih->apdu_len = 5; + ih->apdu_idx = 0; + } else if (new_state == ISO7816_S_WAIT_CARD) { + /* 8.2.2 procedure bytes sent by the card */ + /* FIXME: NULL byte and similar oddities */ + ih->apdu_len += 2; + } + + 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: + goto from_tc; + case ATR_S_WAIT_TB: + goto from_tb; + case ATR_S_WAIT_TA: + if ((ih->atr_last_td & 0x0f) == 0) { + /* This must be TA1 */ + ih->fi = ch >> 4; + ih->di = ch & 0xf; + DEBUGPCR("found Fi=%u Di=%u", ih->fi, ih->di); + } + goto from_ta; + } + + 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) +{ + int rc; + + /* 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: + ih->atr_hist_len = byte & 0xf; + 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--; + if (ih->atr_hist_len == 0) + set_atr_state(ih, ATR_S_WAIT_TCK); + break; + case ATR_S_WAIT_TCK: + /* FIXME: process TCK */ + set_atr_state(ih, ATR_S_DONE); + /* FIXME: update Fi/Di */ + rc = compute_fidi_ratio(ih->fi, ih->di); + if (rc > 0 && rc < 0x400) { + DEBUGPCR("computed FiDi ratio %d", rc); + /* update baud rate generator in UART */ + usart->US_CR |= AT91C_US_RXDIS| AT91C_US_RSTRX; + usart->US_FIDI = rc & 0x3ff; + usart->US_CR |= AT91C_US_RXEN; + } else + DEBUGPCRF("computed FiDi ratio %d unsupported", rc); + return ISO7816_S_WAIT_READER; + } + + return ISO7816_S_IN_ATR; +} + +/* process an incomng byte from the reader */ +static enum iso7816_3_state +process_byte_reader(struct iso7816_3_handle *ih, u_int8_t byte) +{ + /* add response length to total number of expected bytes */ + if (ih->apdu_idx == 4) + ih->apdu_len += byte; + + ih->apdu_idx++; + + /* once we have received all bytes, transition to card response */ + if (ih->apdu_idx == ih->apdu_len) + return ISO7816_S_WAIT_CARD; + + return ISO7816_S_WAIT_READER; +} + +/* process an incomng byte from the card */ +static enum iso7816_3_state +process_byte_card(struct iso7816_3_handle *ih, u_int8_t byte) +{ + ih->apdu_idx++; + + /* once we have received all bytes, apdu is finished */ + if (ih->apdu_idx == ih->apdu_len) + return ISO7816_S_WAIT_READER; + + return ISO7816_S_WAIT_CARD; +} + + +void process_byte(struct iso7816_3_handle *ih, u_int8_t byte) +{ + int new_state = -1; + + 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_READER: + new_state = process_byte_reader(ih, byte); + break; + case ISO7816_S_WAIT_CARD: + //new_state = process_byte_card(ih, byte); + break; + } + + if (new_state != -1) + set_state(ih, new_state); +} + +static int __ramfunc 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)) { + /* some error has occurrerd */ + } +} + +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 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; + + /* Enable the receiver */ + usart->US_CR = AT91C_US_RXEN; + + set_state(&isoh, ISO7816_S_WAIT_ATR); +} + +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"); + + 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; + + 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; +} diff --git a/firmware/src/simtrace/main_simtrace.c b/firmware/src/simtrace/main_simtrace.c new file mode 100644 index 0000000..d5a22dd --- /dev/null +++ b/firmware/src/simtrace/main_simtrace.c @@ -0,0 +1,98 @@ +/* OpenPICC Main Program + * (C) 2006 by Harald Welte + * + * 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 +#include +#include +#include +#include +#include +#include +#include "../openpcd.h" +#include +#include +#include +#include + +//#include + +void _init_func(void) +{ + /* low-level hardware initialization */ + pio_irq_init(); + iso_uart_init(); + + /* high-level protocol */ + //opicc_usbapi_init(); + led_switch(1, 0); + led_switch(2, 1); +} + +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"); +} + +int _main_dbgu(char key) +{ + static int i = 0; + DEBUGPCRF("main_dbgu"); + + switch (key) { + 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 reqyests from USB EP1 (OUT) */ + usb_in_process(); + + udp_unthrottle(); +} diff --git a/firmware/src/simtrace/usb_strings_app.txt b/firmware/src/simtrace/usb_strings_app.txt new file mode 100644 index 0000000..c1d3c95 --- /dev/null +++ b/firmware/src/simtrace/usb_strings_app.txt @@ -0,0 +1,6 @@ +SimTrace DFU Interface - Application Partition +SimTrace DFU Interface - Bootloader Partition +hmw-consulting.de +SimTrace SIM Sniffer - Runtime Mode +SimTrace Runtime Configuration +SimTrace Runtime Interface -- cgit v1.2.3 From 9520b0bea118668d81e3e1a53cdc2e1b43f169f9 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 14 Nov 2010 23:44:46 +0100 Subject: simtrace: introduce RST pin handling --- firmware/src/simtrace/iso7816_uart.c | 44 ++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/firmware/src/simtrace/iso7816_uart.c b/firmware/src/simtrace/iso7816_uart.c index 9022830..6ed797c 100644 --- a/firmware/src/simtrace/iso7816_uart.c +++ b/firmware/src/simtrace/iso7816_uart.c @@ -11,6 +11,7 @@ #include #include +#include #include "../simtrace.h" #include "../openpcd.h" @@ -111,14 +112,18 @@ static void set_atr_state(struct iso7816_3_handle *ih, enum atr_state new_atrs) static void set_state(struct iso7816_3_handle *ih, enum iso7816_3_state new_state) { - if (new_state == ISO7816_S_WAIT_ATR) { + if (new_state == ISO7816_S_RESET) { + usart->US_CR |= AT91C_US_RXDIS | AT91C_US_RSTRX; + } else if (new_state == ISO7816_S_WAIT_ATR) { int rc; /* Initial Fi / Di ratio */ ih->fi = 1; ih->di = 1; rc = compute_fidi_ratio(ih->fi, ih->di); DEBUGPCRF("computed Fi(%u) Di(%u) ratio: %d", ih->fi, ih->di, rc); + usart->US_CR |= AT91C_US_RXDIS | AT91C_US_RSTRX; usart->US_FIDI = rc & 0x3ff; + usart->US_CR |= AT91C_US_RXEN; set_atr_state(ih, ATR_S_WAIT_TS); } else if (new_state == ISO7816_S_WAIT_READER) { /* CLA INS P1 P2 LEN */ @@ -157,11 +162,11 @@ static enum atr_state next_intb_state(struct iso7816_3_handle *ih, u_int8_t ch) DEBUGPCR("found Fi=%u Di=%u", ih->fi, ih->di); } goto from_ta; + default: + DEBUGPCR("something wrong, old_state != TA"); + return ATR_S_WAIT_TCK; } - DEBUGPCR("something wrong, old_state != TA"); - return ATR_S_WAIT_TCK; - from_td: if (ih->atr_last_td & 0x10) return ATR_S_WAIT_TA; @@ -278,7 +283,7 @@ void process_byte(struct iso7816_3_handle *ih, u_int8_t byte) new_state = process_byte_reader(ih, byte); break; case ISO7816_S_WAIT_CARD: - //new_state = process_byte_card(ih, byte); + new_state = process_byte_card(ih, byte); break; } @@ -286,7 +291,7 @@ void process_byte(struct iso7816_3_handle *ih, u_int8_t byte) set_state(ih, new_state); } -static int __ramfunc usart_irq(void) +static __ramfunc void usart_irq(void) { u_int32_t csr = usart->US_CSR; u_int8_t octet; @@ -309,6 +314,18 @@ static int __ramfunc usart_irq(void) } } +/* 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; @@ -318,7 +335,7 @@ void iso_uart_dump(void) void iso_uart_rst(unsigned int state) { - DEBUGPCR("USART nRST set state=%u", state); + DEBUGPCR("USART set nRST set state=%u", state); switch (state) { case 0: AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_nRST); @@ -341,10 +358,9 @@ void iso_uart_rx_mode(void) usart->US_IER = AT91C_US_RXRDY | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_NACK | AT91C_US_ITERATION; - /* Enable the receiver */ - usart->US_CR = AT91C_US_RXEN; - set_state(&isoh, ISO7816_S_WAIT_ATR); + /* call interrupt handler once to set initial state RESET / ATR */ + reset_pin_irq(SIMTRACE_PIO_nRST); } void iso_uart_clk_master(unsigned int master) @@ -367,23 +383,23 @@ void iso_uart_init(void) { DEBUGPCR("USART Initializing"); + /* 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; @@ -396,4 +412,8 @@ void iso_uart_init(void) 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); } -- cgit v1.2.3 From 815283e30574fb25cfdd105970387bbd9ae10394 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 15 Nov 2010 14:59:14 +0100 Subject: ausb: make ausb_test compile again --- host/ausb/Makefile | 2 +- host/ausb/ausb_test.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/host/ausb/Makefile b/host/ausb/Makefile index 6269739..fa42f1f 100644 --- a/host/ausb/Makefile +++ b/host/ausb/Makefile @@ -14,7 +14,7 @@ libausb.so: $(OBJS) %.o: %.c $(CC) $(CFLAGS) -o $@ -c $^ -ausb_test: ausb_test.o ausb.o +ausb_test: ausb_test.o libausb.a $(CC) $(CFLAGS) -lusb -o $@ $^ clean: diff --git a/host/ausb/ausb_test.c b/host/ausb/ausb_test.c index f7bfdee..db4f0ab 100644 --- a/host/ausb/ausb_test.c +++ b/host/ausb/ausb_test.c @@ -33,7 +33,7 @@ static void int_cb(struct usbdevfs_urb *uurb) { struct ausb_dev_handle *ah = uurb->usercontext; - fprintf(stdout, __FUNCTION__ " called, "); + fprintf(stdout, "int_cb() called, "); ausb_dump_urb(uurb); -- cgit v1.2.3 From 3c29506f17ff4a30a3d988361c67d2ec1af13eeb Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 18 Nov 2010 14:09:31 +0100 Subject: simtrace: add TC based waiting time counter, signal ATR / expiry via USB --- firmware/include/simtrace_usb.h | 24 ++++ firmware/src/simtrace.h | 2 - firmware/src/simtrace/iso7816_uart.c | 226 +++++++++++++++++++++++----------- firmware/src/simtrace/iso7816_uart.h | 6 + firmware/src/simtrace/main_simtrace.c | 10 +- firmware/src/simtrace/tc_etu.c | 124 +++++++++++++++++++ firmware/src/simtrace/tc_etu.h | 4 + 7 files changed, 316 insertions(+), 80 deletions(-) create mode 100644 firmware/include/simtrace_usb.h create mode 100644 firmware/src/simtrace/iso7816_uart.h create mode 100644 firmware/src/simtrace/tc_etu.c create mode 100644 firmware/src/simtrace/tc_etu.h 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 + +/* 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/src/simtrace.h b/firmware/src/simtrace.h index 5a27c31..e787dff 100644 --- a/firmware/src/simtrace.h +++ b/firmware/src/simtrace.h @@ -14,5 +14,3 @@ #define SIMTRACE_PIO_CLK AT91C_PA2_SCK0 #define SIMTRACE_PIO_IO AT91C_PA6_TXD0 #define SIMTRACE_PIO_nRST AT91C_PIO_PA7 - - diff --git a/firmware/src/simtrace/iso7816_uart.c b/firmware/src/simtrace/iso7816_uart.c index 6ed797c..18335f6 100644 --- a/firmware/src/simtrace/iso7816_uart.c +++ b/firmware/src/simtrace/iso7816_uart.c @@ -1,5 +1,20 @@ -/* Driver for AT91SAM7 USART0 in ISO7816-3 mode +/* Driver for AT91SAM7 USART0 in ISO7816-3 mode for passive sniffing * (C) 2010 by Harald Welte + * + * 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 @@ -9,6 +24,8 @@ #include #include +#include + #include #include #include @@ -23,11 +40,12 @@ 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, - ISO7816_S_WAIT_READER, /* waiting for data from reader */ - ISO7816_S_WAIT_CARD, /* waiting for data from card */ + 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 */ }; +/* detailed sub-states of ISO7816_S_IN_ATR */ enum atr_state { ATR_S_WAIT_TS, ATR_S_WAIT_T0, @@ -45,6 +63,8 @@ struct iso7816_3_handle { u_int8_t fi; u_int8_t di; + u_int8_t wi; + u_int32_t waiting_time; u_int8_t atr_idx; u_int8_t atr_hist_len; @@ -52,8 +72,9 @@ struct iso7816_3_handle { enum atr_state atr_state; u_int8_t atr[64]; - u_int16_t apdu_len; - u_int16_t apdu_idx; + struct simtrace_hdr sh; + + struct req_ctx *rctx; }; struct iso7816_3_handle isoh; @@ -71,6 +92,7 @@ static const u_int8_t di_table[] = { 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; @@ -96,6 +118,43 @@ static int compute_fidi_ratio(u_int8_t fi, u_int8_t di) 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) { @@ -110,30 +169,48 @@ static void set_atr_state(struct iso7816_3_handle *ih, enum 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) { - int rc; - /* Initial Fi / Di ratio */ + /* Reset to initial Fi / Di ratio */ ih->fi = 1; ih->di = 1; - rc = compute_fidi_ratio(ih->fi, ih->di); - DEBUGPCRF("computed Fi(%u) Di(%u) ratio: %d", ih->fi, ih->di, rc); - usart->US_CR |= AT91C_US_RXDIS | AT91C_US_RSTRX; - usart->US_FIDI = rc & 0x3ff; - usart->US_CR |= AT91C_US_RXEN; + 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); - } else if (new_state == ISO7816_S_WAIT_READER) { - /* CLA INS P1 P2 LEN */ - ih->apdu_len = 5; - ih->apdu_idx = 0; - } else if (new_state == ISO7816_S_WAIT_CARD) { - /* 8.2.2 procedure bytes sent by the card */ - /* FIXME: NULL byte and similar oddities */ - ih->apdu_len += 2; - } + /* Notice that we are just coming out of reset */ + ih->sh.flags |= SIMTRACE_FLAG_ATR; + } if (ih->state == new_state) return; @@ -151,6 +228,10 @@ static enum atr_state next_intb_state(struct iso7816_3_handle *ih, u_int8_t ch) 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; @@ -204,7 +285,9 @@ process_byte_atr(struct iso7816_3_handle *ih, u_int8_t byte) 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: @@ -215,62 +298,31 @@ process_byte_atr(struct iso7816_3_handle *ih, u_int8_t 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 TCK */ + /* FIXME: process and verify the TCK */ set_atr_state(ih, ATR_S_DONE); - /* FIXME: update Fi/Di */ - rc = compute_fidi_ratio(ih->fi, ih->di); - if (rc > 0 && rc < 0x400) { - DEBUGPCR("computed FiDi ratio %d", rc); - /* update baud rate generator in UART */ - usart->US_CR |= AT91C_US_RXDIS| AT91C_US_RSTRX; - usart->US_FIDI = rc & 0x3ff; - usart->US_CR |= AT91C_US_RXEN; - } else - DEBUGPCRF("computed FiDi ratio %d unsupported", rc); - return ISO7816_S_WAIT_READER; + /* update baud rate generator with Fi/Di */ + update_fidi(ih); + /* 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; } -/* process an incomng byte from the reader */ -static enum iso7816_3_state -process_byte_reader(struct iso7816_3_handle *ih, u_int8_t byte) -{ - /* add response length to total number of expected bytes */ - if (ih->apdu_idx == 4) - ih->apdu_len += byte; - - ih->apdu_idx++; - - /* once we have received all bytes, transition to card response */ - if (ih->apdu_idx == ih->apdu_len) - return ISO7816_S_WAIT_CARD; - - return ISO7816_S_WAIT_READER; -} - -/* process an incomng byte from the card */ -static enum iso7816_3_state -process_byte_card(struct iso7816_3_handle *ih, u_int8_t byte) -{ - ih->apdu_idx++; - - /* once we have received all bytes, apdu is finished */ - if (ih->apdu_idx == ih->apdu_len) - return ISO7816_S_WAIT_READER; - - return ISO7816_S_WAIT_CARD; -} - - -void process_byte(struct iso7816_3_handle *ih, u_int8_t byte) +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: @@ -279,18 +331,40 @@ void process_byte(struct iso7816_3_handle *ih, u_int8_t byte) case ISO7816_S_IN_ATR: new_state = process_byte_atr(ih, byte); break; - case ISO7816_S_WAIT_READER: - new_state = process_byte_reader(ih, byte); - break; - case ISO7816_S_WAIT_CARD: - new_state = process_byte_card(ih, byte); + case ISO7816_S_WAIT_APDU: + case ISO7816_S_IN_APDU: + new_state = ISO7816_S_IN_APDU; break; } + 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) + send_rctx(ih); + 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); + } + set_state(&isoh, ISO7816_S_WAIT_APDU); +} + static __ramfunc void usart_irq(void) { u_int32_t csr = usart->US_CSR; @@ -301,7 +375,7 @@ static __ramfunc void usart_irq(void) if (csr & AT91C_US_RXRDY) { /* at least one character received */ octet = usart->US_RHR & 0xff; - DEBUGP("%02x ", octet); + //DEBUGP("%02x ", octet); process_byte(&isoh, octet); } @@ -310,7 +384,7 @@ static __ramfunc void usart_irq(void) } if (csr & (AT91C_US_PARE|AT91C_US_FRAME|AT91C_US_OVRE)) { - /* some error has occurrerd */ + /* FIXME: some error has occurrerd */ } } @@ -358,7 +432,6 @@ void iso_uart_rx_mode(void) 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); } @@ -383,6 +456,8 @@ void iso_uart_init(void) { DEBUGPCR("USART Initializing"); + refill_rctx(&isoh); + /* make sure we get clock from the power management controller */ AT91F_US0_CfgPMC(); @@ -395,7 +470,8 @@ void iso_uart_init(void) 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); + 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; 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_simtrace.c b/firmware/src/simtrace/main_simtrace.c index d5a22dd..5e4302e 100644 --- a/firmware/src/simtrace/main_simtrace.c +++ b/firmware/src/simtrace/main_simtrace.c @@ -27,22 +27,26 @@ #include #include "../openpcd.h" #include -#include -#include #include -//#include +#include +#include void _init_func(void) { /* low-level hardware initialization */ pio_irq_init(); iso_uart_init(); + tc_etu_init(); + + usbtest_init(); /* high-level protocol */ //opicc_usbapi_init(); led_switch(1, 0); led_switch(2, 1); + + iso_uart_rx_mode(); } static void help(void) diff --git a/firmware/src/simtrace/tc_etu.c b/firmware/src/simtrace/tc_etu.c new file mode 100644 index 0000000..93d2da0 --- /dev/null +++ b/firmware/src/simtrace/tc_etu.c @@ -0,0 +1,124 @@ +/* SimTrace TC (Timer / Clock) support code + * (C) 2006 by Harald Welte + * + * 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 +#include +#include + +#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 */ + 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(); +} + +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); -- cgit v1.2.3 From 450a9326082248bcf62920f3ee078df8dcb07310 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 18 Nov 2010 15:12:42 +0100 Subject: simtrace: Introduce code for proper handling of PTS / PPS --- firmware/src/simtrace/iso7816_uart.c | 160 ++++++++++++++++++++++++++++++++--- 1 file changed, 148 insertions(+), 12 deletions(-) diff --git a/firmware/src/simtrace/iso7816_uart.c b/firmware/src/simtrace/iso7816_uart.c index 18335f6..12669c4 100644 --- a/firmware/src/simtrace/iso7816_uart.c +++ b/firmware/src/simtrace/iso7816_uart.c @@ -43,6 +43,7 @@ enum iso7816_3_state { 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 */ @@ -58,6 +59,29 @@ enum atr_state { 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; @@ -66,12 +90,16 @@ struct iso7816_3_handle { 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; - enum atr_state atr_state; 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; struct req_ctx *rctx; @@ -215,7 +243,7 @@ static void set_state(struct iso7816_3_handle *ih, enum iso7816_3_state new_stat if (ih->state == new_state) return; - DEBUGPCR("7816 state %u -> %u", ih->state, new_state); + //DEBUGPCR("7816 state %u -> %u", ih->state, new_state); ih->state = new_state; } @@ -236,12 +264,6 @@ static enum atr_state next_intb_state(struct iso7816_3_handle *ih, u_int8_t ch) case ATR_S_WAIT_TB: goto from_tb; case ATR_S_WAIT_TA: - if ((ih->atr_last_td & 0x0f) == 0) { - /* This must be TA1 */ - ih->fi = ch >> 4; - ih->di = ch & 0xf; - DEBUGPCR("found Fi=%u Di=%u", ih->fi, ih->di); - } goto from_ta; default: DEBUGPCR("something wrong, old_state != TA"); @@ -268,8 +290,6 @@ from_tc: static enum iso7816_3_state process_byte_atr(struct iso7816_3_handle *ih, u_int8_t byte) { - int rc; - /* add byte to ATR buffer */ ih->atr[ih->atr_idx] = byte; ih->atr_idx++; @@ -305,8 +325,6 @@ process_byte_atr(struct iso7816_3_handle *ih, u_int8_t byte) case ATR_S_WAIT_TCK: /* FIXME: process and verify the TCK */ set_atr_state(ih, ATR_S_DONE); - /* update baud rate generator with Fi/Di */ - update_fidi(ih); /* update the waiting time */ ih->waiting_time = 960 * di_table[ih->di] * ih->wi; tc_etu_set_wtime(ih->waiting_time); @@ -316,6 +334,113 @@ process_byte_atr(struct iso7816_3_handle *ih, u_int8_t byte) 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; @@ -332,9 +457,16 @@ static void process_byte(struct iso7816_3_handle *ih, u_int8_t byte) 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; } rctx = ih->rctx; @@ -350,6 +482,7 @@ static void process_byte(struct iso7816_3_handle *ih, u_int8_t byte) if (rctx->tot_len >= rctx->size) send_rctx(ih); +out_silent: if (new_state != -1) set_state(ih, new_state); } @@ -362,6 +495,9 @@ void iso7816_wtime_expired(void) 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); } -- cgit v1.2.3 From 629c4f81b89c41ffc2006b7af06ae734cdcbc864 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 18 Nov 2010 15:29:43 +0100 Subject: simtrace: fix problems causing bogus waiting time expirations --- firmware/src/simtrace/tc_etu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/firmware/src/simtrace/tc_etu.c b/firmware/src/simtrace/tc_etu.c index 93d2da0..fc52033 100644 --- a/firmware/src/simtrace/tc_etu.c +++ b/firmware/src/simtrace/tc_etu.c @@ -40,7 +40,10 @@ static __ramfunc void tc_etu_irq(void) //DEBUGPCR("tE"); nr_events = 0; /* Make sure we don't accept any additional external trigger */ - tcetu->TC_CMR &= ~AT91C_TC_ENETRG; + /* 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) { @@ -74,6 +77,7 @@ 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) -- cgit v1.2.3 From 012362ba7d742b9ae304b09453ba6d9a49dc9d0b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 18 Nov 2010 23:04:21 +0100 Subject: ausb: fix interrupt URB callback --- host/ausb/ausb_test.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/host/ausb/ausb_test.c b/host/ausb/ausb_test.c index db4f0ab..e8493bb 100644 --- a/host/ausb/ausb_test.c +++ b/host/ausb/ausb_test.c @@ -29,16 +29,26 @@ static struct usb_device *find_cj_usbdev(int num) return NULL; } -static void int_cb(struct usbdevfs_urb *uurb) +static void int_cb(struct usbdevfs_urb *uurb, void *data) { struct ausb_dev_handle *ah = uurb->usercontext; + unsigned char *buffer = uurb->buffer; + int i; fprintf(stdout, "int_cb() called, "); ausb_dump_urb(uurb); - if (ausb_submit_urb(ah, uurb)) + for (i = 0; i < uurb->actual_length; i++) + printf("%02x ", buffer[i]); + + if (ausb_submit_urb(ah, uurb)) { fprintf(stderr, "unable to resubmit urb\n"); + ausb_close(ah); + exit(1); + } + + fflush(stdout); } int main(int argc, char **argv) @@ -76,6 +86,8 @@ int main(int argc, char **argv) exit(1); } + ausb_register_callback(ah, USBDEVFS_URB_TYPE_INTERRUPT, &int_cb, ah); + #if 1 ausb_fill_int_urb(uurb, 0x81, buffer, sizeof(buffer)); if (ausb_submit_urb(ah, uurb)) { -- cgit v1.2.3 From 6492c2959cbea6dd6d46fc64267b88c19cf14e8a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 18 Nov 2010 23:06:43 +0100 Subject: req_ctx: Increase size of small req_ctx to 128 and have 16 instead of 8 This is required to deal with bursts in SIM comminication while using the SIMTRACE firmware --- firmware/src/os/req_ctx.c | 4 ++-- firmware/src/os/req_ctx.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/src/os/req_ctx.c b/firmware/src/os/req_ctx.c index 73b6035..0e4816e 100644 --- a/firmware/src/os/req_ctx.c +++ b/firmware/src/os/req_ctx.c @@ -29,8 +29,8 @@ /* FIXME: locking, FIFO order processing */ #ifdef __AT91SAM7S64__ -#define NUM_RCTX_SMALL 4 -#define NUM_RCTX_LARGE 2 +#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) -- cgit v1.2.3 From e50e2f8c62a262c6ee109204b30b485a5bb3c074 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 18 Nov 2010 23:55:58 +0100 Subject: simtrace: Commit Makefile changes to support build of simtrace WARNING These changes will enable the simtrace firmware to be built like this: make -f Makefile.dfu BOARD=OLIMEX make BOARD=SIMTRACE DEBUG=1 TARGET=main_simtrace --- firmware/Makefile | 17 ++++++++++++++--- firmware/Makefile.dfu | 7 ++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/firmware/Makefile b/firmware/Makefile index 08126c1..9b75b3a 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -42,8 +42,8 @@ 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 @@ -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,11 @@ SRCARM += src/picc/tc_fdt.c src/picc/ssc_picc.c src/picc/adc.c \ SRCARM += src/picc/$(TARGET).c endif +ifeq ($(BOARD), SIMTRACE) +SRCARM += src/simtrace/iso7816_uart.c src/simtrace/tc_etu.c +SRCARM += src/simtrace/$(TARGET).c +endif + # List C++ source files here. # use file-extension cpp for C++-files (use extension .cpp) @@ -202,6 +207,12 @@ CDEFS += -DPCD CINCS = -Isrc/pcd endif +ifeq ($(BOARD),SIMTRACE) +CDEFS += -DSIMTRACE +CINCS = -Isrc/simtrace +endif + + # Place -I options here CINCS += -Iinclude -Isrc diff --git a/firmware/Makefile.dfu b/firmware/Makefile.dfu index c526fc2..45a042e 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) -- cgit v1.2.3 From de125b725076e84134d5e9e9d3c56d3ef0bcf075 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 21 Nov 2010 20:18:23 +0100 Subject: simtrace: Make sure ATR is sent in its own RCTX and we re-allocate in time --- firmware/src/simtrace/iso7816_uart.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/firmware/src/simtrace/iso7816_uart.c b/firmware/src/simtrace/iso7816_uart.c index 12669c4..cd1a2f0 100644 --- a/firmware/src/simtrace/iso7816_uart.c +++ b/firmware/src/simtrace/iso7816_uart.c @@ -102,6 +102,7 @@ struct iso7816_3_handle { struct simtrace_hdr sh; + int rctx_must_be_sent; struct req_ctx *rctx; }; @@ -325,6 +326,8 @@ process_byte_atr(struct iso7816_3_handle *ih, u_int8_t byte) 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); @@ -469,6 +472,11 @@ static void process_byte(struct iso7816_3_handle *ih, u_int8_t 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"); @@ -479,8 +487,10 @@ static void process_byte(struct iso7816_3_handle *ih, u_int8_t byte) rctx->data[rctx->tot_len] = byte; rctx->tot_len++; - if (rctx->tot_len >= rctx->size) + 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) -- cgit v1.2.3 From 855b8fdd853cc25a95094364e0fc57c1ffbb5cc0 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 21 Nov 2010 20:19:05 +0100 Subject: AT91SAM7.h: Fix computation of AT91C_IFLASH_LOCK_REGION_SIZE --- firmware/include/AT91SAM7.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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__*/ -- cgit v1.2.3 From 9fa56a331ce29305835b9561ed9cc3ef169be1b9 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 9 Dec 2010 23:31:40 +0800 Subject: add missing usb_strings_dfu.txt file to simtrace directory --- firmware/src/simtrace/usb_strings_dfu.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 firmware/src/simtrace/usb_strings_dfu.txt diff --git a/firmware/src/simtrace/usb_strings_dfu.txt b/firmware/src/simtrace/usb_strings_dfu.txt new file mode 100644 index 0000000..ec93813 --- /dev/null +++ b/firmware/src/simtrace/usb_strings_dfu.txt @@ -0,0 +1,5 @@ +hmw-consulting.de +SimTrace RFID Simulator - DFU Mode +SimTrace DFU Configuration +SimTrace DFU Interface - Application Partition +SimTrace DFU Interface - Bootloader Partition -- cgit v1.2.3 From ca1d468c1834448708e2f20d11a653297acb6d69 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 31 Jan 2011 11:47:38 +0100 Subject: vsprintf.c: Fix compilation by including limits.h The INT_MAX define was not known to this code with a GCC 4.5.2/binutils 2.21/newlib 1.19.0 toolchain as build for osmocomBB. Include limits.h to fix that. --- firmware/lib/vsprintf.c | 1 + 1 file changed, 1 insertion(+) 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 +#include #include #include #include -- cgit v1.2.3 From c50a7dc7063d4846b10c7d2b4b4020b239b84b7d Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 31 Jan 2011 11:49:47 +0100 Subject: typo: Fix typo, transform reqyests to requests. --- firmware/src/pcd/main_dumbreader.c | 2 +- firmware/src/pcd/main_hid.c | 2 +- firmware/src/pcd/main_presence.c | 2 +- firmware/src/pcd/main_pwm.c | 2 +- firmware/src/pcd/main_usb.c | 2 +- firmware/src/picc/main_openpicc.c | 2 +- firmware/src/simtrace/main_simtrace.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/firmware/src/pcd/main_dumbreader.c b/firmware/src/pcd/main_dumbreader.c index 62695f0..9c8dd13 100644 --- a/firmware/src/pcd/main_dumbreader.c +++ b/firmware/src/pcd/main_dumbreader.c @@ -88,7 +88,7 @@ void _main_func(void) /* first we try to get rid of pending to-be-sent stuff */ usb_out_process(); - /* next we deal with incoming reqyests from USB EP1 (OUT) */ + /* next we deal with incoming requests from USB EP1 (OUT) */ usb_in_process(); rc632_unthrottle(); diff --git a/firmware/src/pcd/main_hid.c b/firmware/src/pcd/main_hid.c index 9735c3d..c9d8fd1 100644 --- a/firmware/src/pcd/main_hid.c +++ b/firmware/src/pcd/main_hid.c @@ -50,7 +50,7 @@ void _main_func(void) /* first we try to get rid of pending to-be-sent stuff */ usb_out_process(); - /* next we deal with incoming reqyests from USB EP1 (OUT) */ + /* next we deal with incoming requests from USB EP1 (OUT) */ usb_in_process(); /* try unthrottling sources since we now are [more] likely to diff --git a/firmware/src/pcd/main_presence.c b/firmware/src/pcd/main_presence.c index f61878f..4ead264 100644 --- a/firmware/src/pcd/main_presence.c +++ b/firmware/src/pcd/main_presence.c @@ -157,7 +157,7 @@ void _main_func(void) /* first we try to get rid of pending to-be-sent stuff */ usb_out_process(); - /* next we deal with incoming reqyests from USB EP1 (OUT) */ + /* next we deal with incoming requests from USB EP1 (OUT) */ usb_in_process(); rc632_unthrottle(); } diff --git a/firmware/src/pcd/main_pwm.c b/firmware/src/pcd/main_pwm.c index 7db6b72..50fd363 100644 --- a/firmware/src/pcd/main_pwm.c +++ b/firmware/src/pcd/main_pwm.c @@ -262,7 +262,7 @@ void _main_func(void) /* first we try to get rid of pending to-be-sent stuff */ usb_out_process(); - /* next we deal with incoming reqyests from USB EP1 (OUT) */ + /* next we deal with incoming requests from USB EP1 (OUT) */ usb_in_process(); /* try unthrottling sources since we now are [more] likely to diff --git a/firmware/src/pcd/main_usb.c b/firmware/src/pcd/main_usb.c index fcd3306..7892e77 100644 --- a/firmware/src/pcd/main_usb.c +++ b/firmware/src/pcd/main_usb.c @@ -35,7 +35,7 @@ void _main_func(void) /* first we try to get rid of pending to-be-sent stuff */ usb_out_process(); - /* next we deal with incoming reqyests from USB EP1 (OUT) */ + /* next we deal with incoming requests from USB EP1 (OUT) */ usb_in_process(); /* try unthrottling sources since we now are [more] likely to diff --git a/firmware/src/picc/main_openpicc.c b/firmware/src/picc/main_openpicc.c index 74700f8..93ca4b6 100644 --- a/firmware/src/picc/main_openpicc.c +++ b/firmware/src/picc/main_openpicc.c @@ -251,7 +251,7 @@ void _main_func(void) /* first we try to get rid of pending to-be-sent stuff */ usb_out_process(); - /* next we deal with incoming reqyests from USB EP1 (OUT) */ + /* 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 index 5e4302e..740d35d 100644 --- a/firmware/src/simtrace/main_simtrace.c +++ b/firmware/src/simtrace/main_simtrace.c @@ -95,7 +95,7 @@ void _main_func(void) /* first we try to get rid of pending to-be-sent stuff */ usb_out_process(); - /* next we deal with incoming reqyests from USB EP1 (OUT) */ + /* next we deal with incoming requests from USB EP1 (OUT) */ usb_in_process(); udp_unthrottle(); -- cgit v1.2.3 From a59c6e2073d8f6126429b7ad17459a3b42237cde Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 15 Jun 2011 10:33:46 +0200 Subject: update USB strings (company name and some copy+paste mistakes) --- firmware/src/simtrace/usb_strings_app.txt | 2 +- firmware/src/simtrace/usb_strings_dfu.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/src/simtrace/usb_strings_app.txt b/firmware/src/simtrace/usb_strings_app.txt index c1d3c95..ba24b2b 100644 --- a/firmware/src/simtrace/usb_strings_app.txt +++ b/firmware/src/simtrace/usb_strings_app.txt @@ -1,6 +1,6 @@ SimTrace DFU Interface - Application Partition SimTrace DFU Interface - Bootloader Partition -hmw-consulting.de +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 index ec93813..ae2ff6a 100644 --- a/firmware/src/simtrace/usb_strings_dfu.txt +++ b/firmware/src/simtrace/usb_strings_dfu.txt @@ -1,5 +1,5 @@ -hmw-consulting.de -SimTrace RFID Simulator - DFU Mode +sysmocom - systems for mobile communications GmbH +SimTrace SIM Sniffer - DFU Mode SimTrace DFU Configuration SimTrace DFU Interface - Application Partition SimTrace DFU Interface - Bootloader Partition -- cgit v1.2.3 From ff741ee31fe2a6b25f8f7fcfb1397bb0c82616d6 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 16 Jun 2011 21:00:02 +0200 Subject: simtrace: add more definitions regarding real hw prototype --- firmware/Makefile | 2 ++ firmware/Makefile.dfu | 8 ++++++++ firmware/src/simtrace.h | 20 +++++++++++++++++++- firmware/src/start/Cstartup.S | 3 +++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/firmware/Makefile b/firmware/Makefile index 9b75b3a..57c983e 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -113,6 +113,8 @@ SRCARM += src/picc/$(TARGET).c endif ifeq ($(BOARD), SIMTRACE) +SUBMDL = AT91SAM7S256 +TARGET := main_simtrace SRCARM += src/simtrace/iso7816_uart.c src/simtrace/tc_etu.c SRCARM += src/simtrace/$(TARGET).c endif diff --git a/firmware/Makefile.dfu b/firmware/Makefile.dfu index 45a042e..dbe9b35 100644 --- a/firmware/Makefile.dfu +++ b/firmware/Makefile.dfu @@ -174,6 +174,14 @@ ADEFS += -DPCD CINCS = -Isrc/pcd endif +ifeq ($(BOARD),SIMTRACE) +SUBMDL = AT91SAM7S256 +CDEFS += -DSIMTRACE +ADEFS += -DSIMTRACE +CINCS = -Isrc/simtrace +endif + + # Place -I options here CINCS += -Iinclude -Isrc diff --git a/firmware/src/simtrace.h b/firmware/src/simtrace.h index e787dff..d7faa96 100644 --- a/firmware/src/simtrace.h +++ b/firmware/src/simtrace.h @@ -4,13 +4,31 @@ #ifdef 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_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_IO AT91C_PA6_TXD0 #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_PIO_PA23 +#define SIMTRACE_PIO_IO_PH AT91C_PIO_PA22 + +/* bus switch for SIM card connection */ +#define SIMTRACE_PIO_SC_SW AT91C_PIO_PA20 +#define SIMTRACE_PIO_IO_SW AT91C_PIO_PA19 + +/* SPI flash */ +#define PIO_SPIF_nWP AT91C_PIO_PA15 +#define PIO_SPIF_SCK AT91C_PIO_PA14 +#define PIO_SPIF_MOSI AT91C_PIO_PA13 +#define PIO_SPIF_MISO AT91C_PIO_PA12 +#define PIO_SPIF_nCS AT91C_PIO_PA11 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 -- cgit v1.2.3 From cda126a7ef6fbb54a18a4786c15117800a13f7b3 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 16 Jun 2011 21:16:13 +0200 Subject: simtrace: add support for the analog bus switch --- firmware/Makefile | 3 +- firmware/src/os/dbgu.c | 2 +- firmware/src/simtrace/main_simtrace.c | 11 ++++- firmware/src/simtrace/sim_switch.c | 76 +++++++++++++++++++++++++++++++++++ firmware/src/simtrace/sim_switch.h | 7 ++++ 5 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 firmware/src/simtrace/sim_switch.c create mode 100644 firmware/src/simtrace/sim_switch.h diff --git a/firmware/Makefile b/firmware/Makefile index 57c983e..9a95d44 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -115,7 +115,8 @@ endif ifeq ($(BOARD), SIMTRACE) SUBMDL = AT91SAM7S256 TARGET := main_simtrace -SRCARM += src/simtrace/iso7816_uart.c src/simtrace/tc_etu.c +SRCARM += src/simtrace/iso7816_uart.c src/simtrace/tc_etu.c \ + src/simtrace/sim_switch.c SRCARM += src/simtrace/$(TARGET).c endif 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 \n\r" + AT91F_DBGU_Printk("(C) 2006-2011 by Harald Welte \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/simtrace/main_simtrace.c b/firmware/src/simtrace/main_simtrace.c index 740d35d..581fd59 100644 --- a/firmware/src/simtrace/main_simtrace.c +++ b/firmware/src/simtrace/main_simtrace.c @@ -31,6 +31,7 @@ #include #include +#include void _init_func(void) { @@ -38,6 +39,7 @@ void _init_func(void) pio_irq_init(); iso_uart_init(); tc_etu_init(); + sim_switch_init(); usbtest_init(); @@ -55,7 +57,9 @@ static void help(void) "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"); + "o: set nRST to input\r\n" + "s: disconnect SIM bus switch\r\n" + "S: connect SIM bus switch\r\n"); } int _main_dbgu(char key) @@ -64,6 +68,11 @@ int _main_dbgu(char key) DEBUGPCRF("main_dbgu"); switch (key) { + case 's': + sim_switch_mode(0, 0); + break; + case 'S': + sim_switch_mode(1, 1); case 'r': iso_uart_rx_mode(); break; diff --git a/firmware/src/simtrace/sim_switch.c b/firmware/src/simtrace/sim_switch.c new file mode 100644 index 0000000..4f5621c --- /dev/null +++ b/firmware/src/simtrace/sim_switch.c @@ -0,0 +1,76 @@ +/* + * (C) 2011 by Harald Welte + * + * 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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#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_SetOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_IO_SW); + else + AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_IO_SW); + + if (connect_misc) + AT91F_PIO_SetOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_SC_SW); + else + AT91F_PIO_ClearOutput(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"); +} + +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); +} 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 -- cgit v1.2.3 From ebaba1be96a6970705eb805dc3afc1d54f489ac8 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 17 Jun 2011 09:55:18 +0200 Subject: simtrace: introduce mode sniffer / mitm switching --- firmware/include/lib_AT91SAM7.h | 16 ++++++++++++ firmware/src/simtrace.h | 10 ++++++-- firmware/src/simtrace/main_simtrace.c | 48 +++++++++++++++++++++++++++++++++-- firmware/src/simtrace/sim_switch.c | 8 +++--- 4 files changed, 74 insertions(+), 8 deletions(-) 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/src/simtrace.h b/firmware/src/simtrace.h index d7faa96..6b8f753 100644 --- a/firmware/src/simtrace.h +++ b/firmware/src/simtrace.h @@ -13,19 +13,25 @@ /* 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_PIO_PA23 -#define SIMTRACE_PIO_IO_PH AT91C_PIO_PA22 +#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 + /* SPI flash */ #define PIO_SPIF_nWP AT91C_PIO_PA15 #define PIO_SPIF_SCK AT91C_PIO_PA14 diff --git a/firmware/src/simtrace/main_simtrace.c b/firmware/src/simtrace/main_simtrace.c index 581fd59..8945a56 100644 --- a/firmware/src/simtrace/main_simtrace.c +++ b/firmware/src/simtrace/main_simtrace.c @@ -26,6 +26,7 @@ #include #include #include "../openpcd.h" +#include "../simtrace.h" #include #include @@ -51,6 +52,49 @@ void _init_func(void) iso_uart_rx_mode(); } +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); + AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_SIM); + AT91F_PIO_CfgPullupDis(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; + } +} + static void help(void) { DEBUGPCR("r: iso uart Rx mode\r\n" @@ -69,10 +113,10 @@ int _main_dbgu(char key) switch (key) { case 's': - sim_switch_mode(0, 0); + simtrace_set_mode(SIMTRACE_MD_MITM); break; case 'S': - sim_switch_mode(1, 1); + simtrace_set_mode(SIMTRACE_MD_SNIFFER); case 'r': iso_uart_rx_mode(); break; diff --git a/firmware/src/simtrace/sim_switch.c b/firmware/src/simtrace/sim_switch.c index 4f5621c..118437a 100644 --- a/firmware/src/simtrace/sim_switch.c +++ b/firmware/src/simtrace/sim_switch.c @@ -38,14 +38,14 @@ void sim_switch_mode(int connect_io, int connect_misc) { if (connect_io) - AT91F_PIO_SetOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_IO_SW); - else 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_SetOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_SC_SW); - else 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) -- cgit v1.2.3 From 08c8f4beb59c273be8b573747076bb583983a7ea Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 21 Jun 2011 09:30:46 +0200 Subject: simtrace: use better names for GPIO lines --- firmware/src/simtrace.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/firmware/src/simtrace.h b/firmware/src/simtrace.h index 6b8f753..40ed3ab 100644 --- a/firmware/src/simtrace.h +++ b/firmware/src/simtrace.h @@ -31,10 +31,11 @@ #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_PIO_PA14 -#define PIO_SPIF_MOSI AT91C_PIO_PA13 -#define PIO_SPIF_MISO AT91C_PIO_PA12 -#define PIO_SPIF_nCS AT91C_PIO_PA11 +#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 -- cgit v1.2.3 From db3dca00622c1c390e46315c0caaf93e3ed7bded Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 21 Jun 2011 09:32:28 +0200 Subject: simtrace: add VCC_PHINE IRQ detection --- firmware/src/simtrace/sim_switch.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/firmware/src/simtrace/sim_switch.c b/firmware/src/simtrace/sim_switch.c index 118437a..f83290f 100644 --- a/firmware/src/simtrace/sim_switch.c +++ b/firmware/src/simtrace/sim_switch.c @@ -57,6 +57,14 @@ static void sw_sim_irq(u_int32_t pio) 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"); @@ -73,4 +81,15 @@ void sim_switch_init(void) 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 } -- cgit v1.2.3 From e95ccd8f1db1f43d729153a30f3b5cf84cbc6606 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 21 Jun 2011 09:32:48 +0200 Subject: simtrace: switch VCC_SIM into output mode, as we use it to supply Vcc This is just a temp rework in the 1st generation prototype, as the bus switch has too high resistance for passing throuhg Vcc from the phone to the SIM. --- firmware/src/simtrace/main_simtrace.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/firmware/src/simtrace/main_simtrace.c b/firmware/src/simtrace/main_simtrace.c index 8945a56..ed2921c 100644 --- a/firmware/src/simtrace/main_simtrace.c +++ b/firmware/src/simtrace/main_simtrace.c @@ -75,11 +75,17 @@ 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); - AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_SIM); - AT91F_PIO_CfgPullupDis(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_SIM); + + /* 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); -- cgit v1.2.3 From 30cb576ca5ed5281e997333fd522440faa595565 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 30 Jun 2011 13:55:00 +0200 Subject: simtrace: initialize sniffer mode right after start-up --- firmware/src/simtrace/main_simtrace.c | 40 +++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/firmware/src/simtrace/main_simtrace.c b/firmware/src/simtrace/main_simtrace.c index ed2921c..f919690 100644 --- a/firmware/src/simtrace/main_simtrace.c +++ b/firmware/src/simtrace/main_simtrace.c @@ -34,24 +34,6 @@ #include #include -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(); -} - enum simtrace_md { SIMTRACE_MD_OFF, SIMTRACE_MD_SNIFFER, @@ -101,6 +83,26 @@ static void simtrace_set_mode(enum simtrace_md mode) } } +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" @@ -108,6 +110,7 @@ static void help(void) "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"); } @@ -123,6 +126,7 @@ int _main_dbgu(char key) break; case 'S': simtrace_set_mode(SIMTRACE_MD_SNIFFER); + break; case 'r': iso_uart_rx_mode(); break; -- cgit v1.2.3 From fe88b83e80df8be0351ff38ee6a77b855b0cd0a9 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 7 Jul 2011 17:39:32 +0200 Subject: dfu: fix EP0 IN trasnfers that are even multiple of 8 We have to send a ZLP at the end of such transfers, otherwise the host will time out at the end of the transfer. This resulted in multi-second delays for recognizing the SIMtrace hardware by the USB host. --- firmware/src/dfu/dfu.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/firmware/src/dfu/dfu.c b/firmware/src/dfu/dfu.c index f740800..8425c28 100644 --- a/firmware/src/dfu/dfu.c +++ b/firmware/src/dfu/dfu.c @@ -86,18 +86,20 @@ static void __dfufunc udp_init(void) AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4); } +static void __dfufunc udp_ep0_send_zlp(void); + /* 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; + u_int32_t cpt = 0, len_remain = length; AT91_REG csr; DEBUGE("send_data: %u bytes ", length); do { - cpt = MIN(length, 8); - length -= cpt; + cpt = MIN(len_remain, 8); + len_remain -= cpt; while (cpt--) pUdp->UDP_FDR[0] = *pData++; @@ -119,12 +121,20 @@ static void __dfufunc udp_ep0_send_data(const char *pData, u_int32_t length) } } while (!(csr & AT91C_UDP_TXCOMP)); - } while (length); + } while (len_remain); if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) { pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) ; } + + if ((length % 8) == 0) { + /* if the length is a multiple of the EP size, we need + * to send another ZLP (zero-length packet) to tell the + * host the transfer has completed. */ + DEBUGE("set_txpktrdy_zlp "); + udp_ep0_send_zlp(); + } } static void udp_ep0_recv_clean(void) -- cgit v1.2.3 From a23eefc6dc5f45498116f69125f6e12f53a81130 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 7 Jul 2011 17:43:55 +0200 Subject: USB driver: use the DFU-provided function to send EP0 data There is no point in replicating the functionality that already exists in the DFU section of the flash --- firmware/src/os/pcd_enumerate.c | 49 +---------------------------------------- 1 file changed, 1 insertion(+), 48 deletions(-) diff --git a/firmware/src/os/pcd_enumerate.c b/firmware/src/os/pcd_enumerate.c index b4392c0..a195267 100644 --- a/firmware/src/os/pcd_enumerate.c +++ b/firmware/src/os/pcd_enumerate.c @@ -78,7 +78,7 @@ #ifdef CONFIG_DFU static const struct dfuapi *dfu = DFU_API_LOCATION; #define udp_init dfu->udp_init -//#define udp_ep0_send_data dfu->ep0_send_data +#define udp_ep0_send_data dfu->ep0_send_data #define udp_ep0_send_zlp dfu->ep0_send_zlp #define udp_ep0_send_stall dfu->ep0_send_stall #else @@ -107,53 +107,6 @@ static const struct epstate epstate[] = { .state_pending = RCTX_STATE_UDP_EP3_PENDING }, }; -/* Send Data through the control endpoint */ -static void 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; - - DEBUGE("fifo_fill "); - while (cpt--) - pUdp->UDP_FDR[0] = *pData++; - - if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) { - DEBUGE("wait_txcomp_clear "); - pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP); - while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) ; - } - - DEBUGE("set_txpktrdy "); - pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY; - DEBUGE("wait_txcomp "); - 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); - - DEBUGE("clear_txcomp "); - if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) { - pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP); - while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) ; - } - DEBUGE("done "); -} - static void reset_ep(unsigned int ep) { AT91PS_UDP pUDP = upcd.pUdp; -- cgit v1.2.3 From d56bb35e907e2d7c4507b7240e36d8b69d272bce Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 29 Jul 2011 23:30:00 +0200 Subject: sam7dfu: make sure we can use USB reset to get from DFU -> APP When we went through a Download -> Manifest cycle, we can switch back to dfuIDLE. However, we need to memorize that manifest had already happened and thus should treat a host-initiated bus reset as trigger to switch back into application mode. --- firmware/src/dfu/dfu.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/firmware/src/dfu/dfu.c b/firmware/src/dfu/dfu.c index 8425c28..e126539 100644 --- a/firmware/src/dfu/dfu.c +++ b/firmware/src/dfu/dfu.c @@ -69,6 +69,8 @@ #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 void __dfufunc udp_init(void) { /* Set the PLL USB Divider */ @@ -486,7 +488,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: @@ -858,12 +869,13 @@ static __dfufunc void dfu_udp_irq(void) cur_config = 0; if (dfu_state == DFU_STATE_dfuMANIFEST_WAIT_RST || - dfu_state == DFU_STATE_dfuMANIFEST) { + dfu_state == DFU_STATE_dfuMANIFEST || + past_manifest) { + /* reset back into the main application */ AT91F_RSTSoftReset(AT91C_BASE_RSTC, AT91C_RSTC_PROCRST| AT91C_RSTC_PERRST| AT91C_RSTC_EXTRST); } - } if (isr & AT91C_UDP_EPINT0) -- cgit v1.2.3 From a1e7c0c5efba4eebdb1ed178b5e3604226a1421a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 29 Jul 2011 23:33:20 +0200 Subject: sam7dfu: update copyright years --- firmware/src/dfu/dfu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/src/dfu/dfu.c b/firmware/src/dfu/dfu.c index e126539..6a2f59c 100644 --- a/firmware/src/dfu/dfu.c +++ b/firmware/src/dfu/dfu.c @@ -914,7 +914,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 \n\r" + "(C) 2006-2011 by Harald Welte \n\r" "This software is FREE SOFTWARE licensed under GNU GPL\n\r"); AT91F_DBGU_Printk("Version " COMPILE_SVNREV " compiled " COMPILE_DATE -- cgit v1.2.3 From dda0896d875ec2d33b6de94df818a2f94526272b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 30 Jul 2011 00:34:59 +0200 Subject: use gcc/ld flags -ffunction-sections and --gc-sections This will discard unused functions from the resulting binary --- firmware/Makefile | 4 ++-- firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld | 10 +++++----- firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld | 10 +++++----- firmware/link/AT91SAM7S64-ROM-sam7dfu-app.ld | 10 +++++----- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/firmware/Makefile b/firmware/Makefile index 9a95d44..b085c33 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -249,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 @@ -315,7 +315,7 @@ 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) 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 -- cgit v1.2.3 From 5a8cd9feca7d0d09aee736ff804be4967828aefd Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 30 Jul 2011 00:37:04 +0200 Subject: add new RUN_FROM_RAM run-mode for direct DFU-to-RAM support --- firmware/Makefile | 4 +- firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld | 94 +++++++++++++++++++++++++++ firmware/src/os/req_ctx.c | 2 +- firmware/src/start/Cstartup_app.S | 2 + 4 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld diff --git a/firmware/Makefile b/firmware/Makefile index b085c33..68ff85f 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -49,7 +49,7 @@ 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 @@ -319,7 +319,7 @@ 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/link/AT91SAM7S128-RAM-sam7dfu-app.ld b/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld new file mode 100644 index 0000000..674ee00 --- /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 = 0x00200400, LENGTH = (0x00008000 - 0x400) + STACK (rw) : ORIGIN = 0x00208000, LENGTH = 0x00000000 +} + + +/* Section Definitions */ + +SECTIONS +{ + . = 0x00000000; + /* first section is .text which is used for code */ + .text 0x00200400: 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/src/os/req_ctx.c b/firmware/src/os/req_ctx.c index 0e4816e..cc8d57b 100644 --- a/firmware/src/os/req_ctx.c +++ b/firmware/src/os/req_ctx.c @@ -28,7 +28,7 @@ /* FIXME: locking, FIFO order processing */ -#ifdef __AT91SAM7S64__ +#if defined(__AT91SAM7S64__) || defined(RUN_FROM_RAM) #define NUM_RCTX_SMALL 16 #define NUM_RCTX_LARGE 1 #else 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 -- cgit v1.2.3 From 9f120cdf57b9dc2ca8112cbb89587f77df4facd2 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 30 Jul 2011 00:38:20 +0200 Subject: Makefile: SIMtrace uses SAM7S128, not 256 --- firmware/Makefile | 2 +- firmware/Makefile.dfu | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/Makefile b/firmware/Makefile index 68ff85f..1f2f7ed 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -113,7 +113,7 @@ SRCARM += src/picc/$(TARGET).c endif ifeq ($(BOARD), SIMTRACE) -SUBMDL = AT91SAM7S256 +SUBMDL = AT91SAM7S128 TARGET := main_simtrace SRCARM += src/simtrace/iso7816_uart.c src/simtrace/tc_etu.c \ src/simtrace/sim_switch.c diff --git a/firmware/Makefile.dfu b/firmware/Makefile.dfu index dbe9b35..3c797ef 100644 --- a/firmware/Makefile.dfu +++ b/firmware/Makefile.dfu @@ -175,7 +175,7 @@ CINCS = -Isrc/pcd endif ifeq ($(BOARD),SIMTRACE) -SUBMDL = AT91SAM7S256 +SUBMDL = AT91SAM7S128 CDEFS += -DSIMTRACE ADEFS += -DSIMTRACE CINCS = -Isrc/simtrace -- cgit v1.2.3 From de0d7e35eed67bab478fda9eee7cb9edb1f34f04 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 30 Jul 2011 00:39:22 +0200 Subject: simtrace: add some early spi flash utility routines This also adds a new 'main_factory' target for simtrace --- firmware/Makefile | 2 +- firmware/src/simtrace/main_factory.c | 80 +++++++++++++++++++ firmware/src/simtrace/spi_flash.c | 144 +++++++++++++++++++++++++++++++++++ 3 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 firmware/src/simtrace/main_factory.c create mode 100644 firmware/src/simtrace/spi_flash.c diff --git a/firmware/Makefile b/firmware/Makefile index 1f2f7ed..3f7a2e9 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -116,7 +116,7 @@ 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/sim_switch.c src/simtrace/spi_flash.c SRCARM += src/simtrace/$(TARGET).c endif 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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include "../openpcd.h" +#include "../simtrace.h" +#include +#include + +#include +#include +#include + +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/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 + * + * 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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#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]); +} -- cgit v1.2.3 From e3d1fd9bbdb789196c25bdd5eb7536cda5ba39f3 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 30 Jul 2011 02:08:36 +0200 Subject: DFU: add third 'alternate configuration' for RAM load This will allow us to load code directly into RAM without going through flash. --- firmware/src/dfu/dfu.h | 26 +++++++++++++++++++++++--- firmware/src/os/usb_descriptors_openpcd.h | 14 +++++++------- firmware/src/pcd/usb_strings_app.txt | 1 + firmware/src/pcd/usb_strings_dfu.txt | 1 + firmware/src/picc/usb_strings_app.txt | 1 + firmware/src/picc/usb_strings_dfu.txt | 1 + firmware/src/simtrace/usb_strings_app.txt | 1 + firmware/src/simtrace/usb_strings_dfu.txt | 1 + 8 files changed, 36 insertions(+), 10 deletions(-) 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/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/usb_strings_app.txt b/firmware/src/simtrace/usb_strings_app.txt index ba24b2b..02cf326 100644 --- a/firmware/src/simtrace/usb_strings_app.txt +++ b/firmware/src/simtrace/usb_strings_app.txt @@ -1,5 +1,6 @@ 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 diff --git a/firmware/src/simtrace/usb_strings_dfu.txt b/firmware/src/simtrace/usb_strings_dfu.txt index ae2ff6a..2f65684 100644 --- a/firmware/src/simtrace/usb_strings_dfu.txt +++ b/firmware/src/simtrace/usb_strings_dfu.txt @@ -3,3 +3,4 @@ SimTrace SIM Sniffer - DFU Mode SimTrace DFU Configuration SimTrace DFU Interface - Application Partition SimTrace DFU Interface - Bootloader Partition +SimTrace DFU Interface - RAM -- cgit v1.2.3 From 58d958e60c429bd7a2b2d114a4f7a86a65bdacef Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 30 Jul 2011 02:56:36 +0200 Subject: DFU: Support re-flashing of DFU via DFU As we re-locate the entire sam7dfu program into RAM, we don't need to execute from flash and can thus re-program the DFU partition via the DFU protocol itself (alternate setting '1'). We also implement downloading executable code into RAM using alternate setting '2'. The latter part is not properly executed yet. --- firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld | 4 +- firmware/src/dfu/dfu.c | 148 +++++++++++++++++++++++--- 2 files changed, 134 insertions(+), 18 deletions(-) diff --git a/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld b/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld index 674ee00..ad02776 100644 --- a/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld +++ b/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld @@ -5,7 +5,7 @@ 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 = 0x00200400, LENGTH = (0x00008000 - 0x400) + DATA (rw) : ORIGIN = 0x00202000, LENGTH = (0x00008000 - 0x2000) STACK (rw) : ORIGIN = 0x00208000, LENGTH = 0x00000000 } @@ -16,7 +16,7 @@ SECTIONS { . = 0x00000000; /* first section is .text which is used for code */ - .text 0x00200400: AT ( 0x00000000 ) { + .text 0x00202000: AT ( 0x00000000 ) { src/start/Cstartup_app.o (.text) * (.text) * (.rodata*) diff --git a/firmware/src/dfu/dfu.c b/firmware/src/dfu/dfu.c index 6a2f59c..f65b00d 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 + * (C) 2006-2011 by Harald Welte * * 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 #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 */ @@ -70,6 +71,8 @@ #define led2off() AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2) static int past_manifest = 0; +static u_int16_t usb_if_nr = 0; +static u_int16_t usb_if_alt_nr = 0; static void __dfufunc udp_init(void) { @@ -212,14 +215,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; @@ -240,13 +266,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; @@ -258,10 +291,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 */ @@ -276,6 +309,56 @@ 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) +{ + 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) { @@ -287,9 +370,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; @@ -606,7 +692,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, @@ -648,6 +734,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, }; @@ -831,9 +932,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: @@ -849,6 +952,8 @@ static __dfufunc void dfu_udp_ep0_handler(void) DEBUGE("\r\n"); } +const void (*ram_app_entry)(void) = AT91C_ISRAM + SAM7DFU_RAM_SIZE; + /* minimal USB IRQ handler in DFU mode */ static __dfufunc void dfu_udp_irq(void) { @@ -871,10 +976,21 @@ static __dfufunc void dfu_udp_irq(void) if (dfu_state == DFU_STATE_dfuMANIFEST_WAIT_RST || dfu_state == DFU_STATE_dfuMANIFEST || past_manifest) { - /* reset back into the main application */ - AT91F_RSTSoftReset(AT91C_BASE_RSTC, AT91C_RSTC_PROCRST| - AT91C_RSTC_PERRST| - AT91C_RSTC_EXTRST); + AT91F_DBGU_Printk("sam7dfu: switching to APP mode\r\n"); + switch (usb_if_alt_nr) { + case 2: + /* jump into RAM */ + DEBUGP("JUMP TO RAM ENTRY %p\r\n", ram_app_entry); + ram_app_entry(); + break; + default: + /* reset back into the main application */ + AT91F_RSTSoftReset(AT91C_BASE_RSTC, + AT91C_RSTC_PROCRST| + AT91C_RSTC_PERRST| + AT91C_RSTC_EXTRST); + break; + } } } -- cgit v1.2.3 From 1acaecb4cb1de370a4fee692baaf6b41b8d8ec8c Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 30 Jul 2011 18:53:43 +0200 Subject: DFU: Fix execution of software that was loaded to RAM via DFU --- firmware/src/dfu/dfu.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/firmware/src/dfu/dfu.c b/firmware/src/dfu/dfu.c index f65b00d..0e22256 100644 --- a/firmware/src/dfu/dfu.c +++ b/firmware/src/dfu/dfu.c @@ -71,8 +71,10 @@ #define led2off() AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2) static int past_manifest = 0; -static u_int16_t usb_if_nr = 0; -static u_int16_t usb_if_alt_nr = 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) { @@ -351,6 +353,7 @@ static int __dfufunc handle_dnload_ram(u_int16_t val, u_int16_t len) 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); @@ -952,8 +955,6 @@ static __dfufunc void dfu_udp_ep0_handler(void) DEBUGE("\r\n"); } -const void (*ram_app_entry)(void) = AT91C_ISRAM + SAM7DFU_RAM_SIZE; - /* minimal USB IRQ handler in DFU mode */ static __dfufunc void dfu_udp_irq(void) { @@ -977,11 +978,9 @@ static __dfufunc void dfu_udp_irq(void) dfu_state == DFU_STATE_dfuMANIFEST || past_manifest) { AT91F_DBGU_Printk("sam7dfu: switching to APP mode\r\n"); - switch (usb_if_alt_nr) { + switch (usb_if_alt_nr_dnload) { case 2: - /* jump into RAM */ - DEBUGP("JUMP TO RAM ENTRY %p\r\n", ram_app_entry); - ram_app_entry(); + switch_to_ram = 1; break; default: /* reset back into the main application */ @@ -1073,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(); + } } } -- cgit v1.2.3 From ffbce3ea2cda51214be0bb7a107954f890f99b0d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 30 Jul 2011 19:01:57 +0200 Subject: update mkcompile_h to work with git repository --- firmware/scripts/git-version-gen | 151 +++++++++++++++++++++++++++++++++++++++ firmware/scripts/mkcompile_h | 8 +-- 2 files changed, 155 insertions(+), 4 deletions(-) create mode 100755 firmware/scripts/git-version-gen 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 . + +# 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" -- cgit v1.2.3