From 868b6d0c68f52385f7924e7d63eb1a5e92642f3a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 23 Mar 2012 00:03:45 +0100 Subject: simtrace: introduce statistics the statistics count various events like overruns, parity errors, missing rctx and can dump those stats via USB as well as on the serial console. --- firmware/include/simtrace_usb.h | 12 ++++++++++++ firmware/src/simtrace/iso7816_uart.c | 33 ++++++++++++++++++++++++++++++++- firmware/src/simtrace/iso7816_uart.h | 2 ++ firmware/src/simtrace/main_simtrace.c | 25 ++++++++++++++++++++++++- 4 files changed, 70 insertions(+), 2 deletions(-) diff --git a/firmware/include/simtrace_usb.h b/firmware/include/simtrace_usb.h index b8b62d3..08e4523 100644 --- a/firmware/include/simtrace_usb.h +++ b/firmware/include/simtrace_usb.h @@ -15,6 +15,7 @@ enum simtrace_usb_msgt { SIMTRACE_MSGT_NULL, SIMTRACE_MSGT_DATA, SIMTRACE_MSGT_RESET, /* reset was asserted, no more data */ + SIMTRACE_MSGT_STATS, /* statistics */ }; /* flags for MSGT_DATA */ @@ -22,4 +23,15 @@ enum simtrace_usb_msgt { #define SIMTRACE_FLAG_WTIME_EXP 0x04 /* work waiting time expired */ #define SIMTRACE_FLAG_PPS_FIDI 0x08 /* Fi/Di values in res[2] */ +struct simtrace_stats { + u_int32_t no_rctx; + u_int32_t rctx_sent; + u_int32_t rst; + u_int32_t pps; + u_int32_t bytes; + u_int32_t parity_err; + u_int32_t frame_err; + u_int32_t overrun; +} stats; + #endif /* SIMTRACE_USB_H */ diff --git a/firmware/src/simtrace/iso7816_uart.c b/firmware/src/simtrace/iso7816_uart.c index 09a7aa0..4169ab9 100644 --- a/firmware/src/simtrace/iso7816_uart.c +++ b/firmware/src/simtrace/iso7816_uart.c @@ -106,6 +106,8 @@ struct iso7816_3_handle { int rctx_must_be_sent; struct req_ctx *rctx; + + struct simtrace_stats stats; }; struct iso7816_3_handle isoh; @@ -123,6 +125,20 @@ static const u_int8_t di_table[] = { 12, 20, 2, 4, 8, 16, 32, 64, }; +void iso_uart_stats_dump(void) +{ + DEBUGPCRF("no_rctx: %u, rctx_sent: %u, rst: %u, pps: %u, bytes: %u, " + "parity_err: %u, frame_err: %u, overrun:%u", + isoh.stats.no_rctx, isoh.stats.rctx_sent, isoh.stats.rst, + isoh.stats.pps, isoh.stats.bytes, isoh.stats.parity_err, + isoh.stats.frame_err, isoh.stats.overrun); +} + +struct simtrace_stats *iso_uart_stats_get(void) +{ + return &isoh.stats; +} + /* compute the F/D ratio based on Fi and Di values */ static int compute_fidi_ratio(u_int8_t fi, u_int8_t di) { @@ -186,6 +202,8 @@ static void send_rctx(struct iso7816_3_handle *ih) memset(&ih->sh, 0, sizeof(ih->sh)); ih->rctx = NULL; + + ih->stats.rctx_sent++; } @@ -476,6 +494,8 @@ static void process_byte(struct iso7816_3_handle *ih, u_int8_t byte) int new_state = -1; struct req_ctx *rctx; + ih->stats.bytes++; + if (!ih->rctx) refill_rctx(ih); @@ -489,6 +509,7 @@ static void process_byte(struct iso7816_3_handle *ih, u_int8_t byte) case ISO7816_S_WAIT_APDU: if (byte == 0xff) { new_state = process_byte_pts(ih, byte); + ih->stats.pps++; goto out_silent; } case ISO7816_S_IN_APDU: @@ -506,7 +527,8 @@ static void process_byte(struct iso7816_3_handle *ih, u_int8_t byte) rctx = ih->rctx; if (!rctx) { - DEBUGPCR("==> Lost byte, missing rctx"); + //DEBUGPCR("==> Lost byte, missing rctx"); + ih->stats.no_rctx++; return; } @@ -562,6 +584,13 @@ static __ramfunc void usart_irq(void) //DEBUGP("NER=%02x ", nb_err); /* clear the status */ usart->US_CR |= AT91C_US_RSTSTA; + + if (csr & AT91C_US_PARE) + isoh.stats.parity_err++; + if (csr & AT91C_US_FRAME) + isoh.stats.frame_err++; + if (csr & AT91C_US_OVRE) + isoh.stats.overrun++; } if (csr & AT91C_US_INACK) { @@ -579,6 +608,7 @@ static void reset_pin_irq(u_int32_t pio) } else { DEBUGPCR("RST"); set_state(&isoh, ISO7816_S_WAIT_ATR); + isoh.stats.rst++; } } @@ -647,6 +677,7 @@ void iso_uart_init(void) AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, SIMTRACE_PIO_IO, SIMTRACE_PIO_CLK); AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SIMTRACE_PIO_nRST); + /* Configure Interrupt */ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_US0, OPENPCD_IRQ_PRIO_USART, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &usart_irq); diff --git a/firmware/src/simtrace/iso7816_uart.h b/firmware/src/simtrace/iso7816_uart.h index ed1c898..beb0b23 100644 --- a/firmware/src/simtrace/iso7816_uart.h +++ b/firmware/src/simtrace/iso7816_uart.h @@ -1,4 +1,6 @@ +struct simtrace_stats *iso_uart_stats_get(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); diff --git a/firmware/src/simtrace/main_simtrace.c b/firmware/src/simtrace/main_simtrace.c index 0f2bfc5..6f82d96 100644 --- a/firmware/src/simtrace/main_simtrace.c +++ b/firmware/src/simtrace/main_simtrace.c @@ -33,6 +33,7 @@ #include #include #include +#include enum simtrace_md { SIMTRACE_MD_OFF, @@ -117,6 +118,24 @@ static void simtrace_set_mode(enum simtrace_md mode) } } +static int simtrace_usb_in(struct req_ctx *rctx) +{ + struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->data[0]; + struct simtrace_stats *stats_in; + struct simtrace_stats *stats = (struct simtrace_stats *) poh->data; + + switch (poh->cmd) { + case SIMTRACE_MSGT_STATS: + stats_in = iso_uart_stats_get(); + memcpy(stats, stats_in, sizeof(*stats)); + req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING); + break; + default: + req_ctx_set_state(rctx, RCTX_STATE_FREE); + break; + } +} + void _init_func(void) { /* low-level hardware initialization */ @@ -126,6 +145,7 @@ void _init_func(void) sim_switch_init(); usbtest_init(); + usb_hdlr_register(&simtrace_usb_in, OPENPCD_CMD_CLS_ADC); /* high-level protocol */ //opicc_usbapi_init(); @@ -150,7 +170,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" + "t: ISO UART statistics\r\n" "s: disconnect SIM bus switch\r\n" "S: connect SIM bus switch\r\n"); } @@ -167,6 +187,9 @@ int _main_dbgu(char key) case 'S': simtrace_set_mode(SIMTRACE_MD_SNIFFER); break; + case 't': + iso_uart_stats_dump(); + break; case 'r': iso_uart_rx_mode(); break; -- cgit v1.2.3