aboutsummaryrefslogtreecommitdiffstats
path: root/firmware/src/simtrace
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/src/simtrace')
-rw-r--r--firmware/src/simtrace/iso7816_uart.c40
-rw-r--r--firmware/src/simtrace/iso7816_uart.h7
-rw-r--r--firmware/src/simtrace/main_simtrace.c43
-rw-r--r--firmware/src/simtrace/sim_switch.c7
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");
}