summaryrefslogtreecommitdiff
path: root/firmware
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 /firmware
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.
Diffstat (limited to 'firmware')
-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;
personal git repositories of Harald Welte. Your mileage may vary