diff options
author | Harald Welte <laforge@gnumonks.org> | 2014-11-11 22:31:27 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2014-11-11 22:31:27 +0100 |
commit | 5a40e2fed18ed75c7b8d62f52cf4a7c660a8e026 (patch) | |
tree | bce986dd5ab366dd141456f842c887868b73db7a /firmware/src/simtrace | |
parent | 3c85f8de8d394eaea5ed7f6e2675201d079e227b (diff) | |
parent | b6caca4b64a73d8d3ab4ce6b51cea71b8f1a54b0 (diff) |
Merge branch 'minxu-fixes'
Diffstat (limited to 'firmware/src/simtrace')
-rw-r--r-- | firmware/src/simtrace/iso7816_uart.c | 40 | ||||
-rw-r--r-- | firmware/src/simtrace/iso7816_uart.h | 7 | ||||
-rw-r--r-- | firmware/src/simtrace/main_simtrace.c | 43 | ||||
-rw-r--r-- | firmware/src/simtrace/sim_switch.c | 7 |
4 files changed, 95 insertions, 2 deletions
diff --git a/firmware/src/simtrace/iso7816_uart.c b/firmware/src/simtrace/iso7816_uart.c index 52522c0..9e8ace9 100644 --- a/firmware/src/simtrace/iso7816_uart.c +++ b/firmware/src/simtrace/iso7816_uart.c @@ -125,6 +125,20 @@ static const u_int8_t di_table[] = { 12, 20, 2, 4, 8, 16, 32, 64, }; +void iso_uart_report_errors(void) +{ + static unsigned lastOverrun = 0, lastParity = 0, lastFrame = 0; + if (isoh.stats.overrun != lastOverrun) { + DEBUGPCR("UART overrun: %u", lastOverrun = isoh.stats.overrun); + } + if (isoh.stats.frame_err != lastFrame) { + DEBUGPCR("UART frame error: %u", lastFrame = isoh.stats.frame_err); + } + if (isoh.stats.parity_err != lastParity) { + DEBUGPCR("UART parity error: %u", lastParity = isoh.stats.parity_err); + } +} + void iso_uart_stats_dump(void) { DEBUGPCRF("no_rctx: %u, rctx_sent: %u, rst: %u, pps: %u, bytes: %u, " @@ -567,6 +581,26 @@ void iso7816_wtime_expired(void) set_state(&isoh, ISO7816_S_WAIT_APDU); } +void iso_uart_flush(void) +{ + send_rctx(&isoh); +} + +void iso_uart_idleflush(void) +{ + static struct req_ctx *last_req = NULL; + static u_int16_t last_len = 0; + + if (last_req == isoh.rctx && + last_len == isoh.rctx->tot_len && + req_ctx_count(RCTX_STATE_UDP_EP2_PENDING) == 0 && + (isoh.sh.flags & SIMTRACE_FLAG_ATR) == 0) { + send_rctx(&isoh); + } + last_req = isoh.rctx; + last_len = isoh.rctx->tot_len; +} + static __ramfunc void usart_irq(void) { u_int32_t csr = usart->US_CSR; @@ -610,9 +644,13 @@ static __ramfunc void usart_irq(void) static void reset_pin_irq(u_int32_t pio) { if (!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, pio)) { + /* make sure to flush pending req_ctx */ + iso_uart_flush(); DEBUGPCR("nRST"); set_state(&isoh, ISO7816_S_RESET); } else { + /* make sure to flush pending req_ctx */ + iso_uart_flush(); DEBUGPCR("RST"); set_state(&isoh, ISO7816_S_WAIT_ATR); isoh.stats.rst++; @@ -675,6 +713,8 @@ void iso_uart_init(void) { DEBUGPCR("USART Initializing"); + memset(&isoh, 0, sizeof(isoh)); + refill_rctx(&isoh); /* make sure we get clock from the power management controller */ diff --git a/firmware/src/simtrace/iso7816_uart.h b/firmware/src/simtrace/iso7816_uart.h index beb0b23..969e6f9 100644 --- a/firmware/src/simtrace/iso7816_uart.h +++ b/firmware/src/simtrace/iso7816_uart.h @@ -1,8 +1,15 @@ +#ifndef SIMTRACE_ISO7816_UART_H +#define SIMTRACE_ISO7816_UART_H struct simtrace_stats *iso_uart_stats_get(void); +void iso_uart_report_errors(void); void iso_uart_stats_dump(void); 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); +void iso_uart_flush(void); +void iso_uart_idleflush(void); + +#endif diff --git a/firmware/src/simtrace/main_simtrace.c b/firmware/src/simtrace/main_simtrace.c index 6f82d96..8069349 100644 --- a/firmware/src/simtrace/main_simtrace.c +++ b/firmware/src/simtrace/main_simtrace.c @@ -134,10 +134,40 @@ static int simtrace_usb_in(struct req_ctx *rctx) req_ctx_set_state(rctx, RCTX_STATE_FREE); break; } + return 0; +} + +static volatile unsigned spuirq_pc, spuirq_count = 0; + +static void check_spurious_irq() +{ + static unsigned last_count = 0; + if (last_count != spuirq_count) { + DEBUGPCR("SPURRIOUS IRQ %i [Old PC = %08X]", spuirq_count, spuirq_pc); + last_count = spuirq_count; + } +} + +static void custom_spurious_handler(unsigned previous_pc) +{ + unsigned flags; + local_irq_save(flags); + spuirq_pc = previous_pc; + spuirq_count++; + local_irq_restore(flags); +} + +static void custom_spurious_entry(void) +{ + register unsigned *previous_pc asm("r0"); + asm("ADD R1, SP, #16; LDR R0, [R1]"); + custom_spurious_handler(previous_pc); } void _init_func(void) { + AT91C_BASE_AIC->AIC_SPU = (int)custom_spurious_entry; + /* low-level hardware initialization */ pio_irq_init(); iso_uart_init(); @@ -218,6 +248,8 @@ int _main_dbgu(char key) void _main_func(void) { + static unsigned loopLow = 0, loopHigh = 0; + /* first we try to get rid of pending to-be-sent stuff */ usb_out_process(); @@ -225,4 +257,15 @@ void _main_func(void) usb_in_process(); udp_unthrottle(); + + if ((loopLow & 0xFFFF) == 0) { + DEBUGPCR("Heart beat %08X", loopHigh++); + } + if ((loopLow & 0x3F) == 0) { + iso_uart_idleflush(); + } + loopLow++; + + iso_uart_report_errors(); + check_spurious_irq(); } diff --git a/firmware/src/simtrace/sim_switch.c b/firmware/src/simtrace/sim_switch.c index faf48f0..90067ac 100644 --- a/firmware/src/simtrace/sim_switch.c +++ b/firmware/src/simtrace/sim_switch.c @@ -59,9 +59,12 @@ static void sw_sim_irq(u_int32_t pio) static void vcc_phone_irq(u_int32_t pio) { - if (!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_PHONE)) + if (!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_PHONE)) { DEBUGPCR("VCC_PHONE off"); - else + /* flush any pending req_ctx to make sure the next ATR + * will be aligned to position 0 */ + iso_uart_flush(); + } else DEBUGPCR("VCC_PHONE on"); } |