aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2012-03-23 00:03:45 +0100
committerHarald Welte <laforge@gnumonks.org>2012-03-23 00:03:45 +0100
commit868b6d0c68f52385f7924e7d63eb1a5e92642f3a (patch)
tree81ea5fc541c1ede08a8f5297399decdd921bc9fd
parent4c0cf591b03148b9450d4009d2a3e908ec0c87a8 (diff)
simtrace: introduce statisticsv0.5
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.
-rw-r--r--firmware/include/simtrace_usb.h12
-rw-r--r--firmware/src/simtrace/iso7816_uart.c33
-rw-r--r--firmware/src/simtrace/iso7816_uart.h2
-rw-r--r--firmware/src/simtrace/main_simtrace.c25
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 <simtrace/tc_etu.h>
#include <simtrace/iso7816_uart.h>
#include <simtrace/sim_switch.h>
+#include <simtrace_usb.h>
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;