diff options
-rw-r--r-- | openpicc/Makefile | 5 | ||||
-rw-r--r-- | openpicc/application/cmd.c | 2 | ||||
-rw-r--r-- | openpicc/application/cmd.h | 2 | ||||
-rw-r--r-- | openpicc/application/iso14443a_diffmiller.c | 19 | ||||
-rw-r--r-- | openpicc/application/iso14443a_manchester.c | 2 | ||||
-rw-r--r-- | openpicc/application/main.c | 2 | ||||
-rw-r--r-- | openpicc/application/performance.c | 145 | ||||
-rw-r--r-- | openpicc/application/performance.h | 25 | ||||
-rw-r--r-- | openpicc/application/tc_sniffer.c | 139 |
9 files changed, 276 insertions, 65 deletions
diff --git a/openpicc/Makefile b/openpicc/Makefile index 927aa22..e70eab7 100644 --- a/openpicc/Makefile +++ b/openpicc/Makefile @@ -98,7 +98,7 @@ ARM_SRC= \ application/decoder_miller.c \ application/decoder_nrzl.c \ application/decoder.c \ - application/tc_sniffer.c \ + application/performance.c \ os/boot/Cstartup_SAM7.c \ os/core/list.c \ os/core/queue.c \ @@ -109,7 +109,8 @@ ARM_SRC= \ os/core/MemMang/heap_2.c \ os/usb/USB-CDC.c \ os/usb/USBIsr.c \ - application/iso14443a_pretender.c \ + application/tc_sniffer.c \ +# application/iso14443a_pretender.c \ # application/iso14443_sniffer.c \ # application/iso14443_layer3a.c diff --git a/openpicc/application/cmd.c b/openpicc/application/cmd.c index 58b341d..4d7d6b2 100644 --- a/openpicc/application/cmd.c +++ b/openpicc/application/cmd.c @@ -68,7 +68,7 @@ void DumpUIntToUSB(unsigned int data) } /**********************************************************************/ -void DumpStringToUSB(char* text) +void DumpStringToUSB(const char* text) { usb_print_string(text); } diff --git a/openpicc/application/cmd.h b/openpicc/application/cmd.h index a93d8f0..aec4fd9 100644 --- a/openpicc/application/cmd.h +++ b/openpicc/application/cmd.h @@ -12,7 +12,7 @@ typedef struct { portBASE_TYPE vCmdInit(void); extern void DumpUIntToUSB(unsigned int data); -extern void DumpStringToUSB(char *string); +extern void DumpStringToUSB(const char *string); extern void DumpBufferToUSB(char* buffer, int len); extern void DumpTimeToUSB(long ticks); extern xQueueHandle xCmdQueue; diff --git a/openpicc/application/iso14443a_diffmiller.c b/openpicc/application/iso14443a_diffmiller.c index 85f9518..020760f 100644 --- a/openpicc/application/iso14443a_diffmiller.c +++ b/openpicc/application/iso14443a_diffmiller.c @@ -31,6 +31,8 @@ #include "iso14443a_diffmiller.h" #include "usb_print.h" +#include "performance.h" + #define DEBUGP (void) #define printf usb_print_string @@ -125,7 +127,7 @@ const struct decoder_table_entry decoder_table[][5] = { [sym_z] = {NIENTE, {sym_z, NO_SYM}, {sym_x, NO_SYM}, {sym_y, NO_SYM}, {sym_y, NO_SYM}, }, }; -int print_bits = 1; +int print_bits = 0; inline void start_frame(struct diffmiller_state * const state) { @@ -134,10 +136,14 @@ inline void start_frame(struct diffmiller_state * const state) state->parity=0; state->crc=0x6363; + performance_set_checkpoint("start_frame before memset"); memset(&state->flags, 0, sizeof(state->flags)); state->flags.in_frame = 1; - memset(state->frame, 0, sizeof(*state->frame)); + //memset(state->frame, 0, sizeof(*state->frame)); + //memset(state->frame, 0, (u_int32_t)&(((iso14443_frame*)0)->data) ); + memset(state->frame, 0, 26 ); + performance_set_checkpoint("start_frame after memset"); } static inline void append_to_frame(struct diffmiller_state *const state, @@ -165,7 +171,7 @@ static inline void append_to_frame(struct diffmiller_state *const state, } -static void end_frame(struct diffmiller_state * const state) +static inline void end_frame(struct diffmiller_state * const state) { if(state->frame != NULL) { if(state->counter > 0) { @@ -181,7 +187,7 @@ static void end_frame(struct diffmiller_state * const state) } } -static void Miller_Bit(struct diffmiller_state * const state, const enum bit bit) +static inline void Miller_Bit(struct diffmiller_state * const state, const enum bit bit) { switch(bit) { case BIT_SOF: @@ -233,7 +239,7 @@ static void Miller_Bit(struct diffmiller_state * const state, const enum bit bit } } -static void Miller_Symbol(struct diffmiller_state * const state, const enum symbol symbol) +static inline void Miller_Symbol(struct diffmiller_state * const state, const enum symbol symbol) { static enum bit last_bit = BIT_ERROR; static int in_frame = 0; @@ -279,7 +285,7 @@ static void Miller_Symbol(struct diffmiller_state * const state, const enum symb } -static void Miller_Edge(struct diffmiller_state * const state, const unsigned int delta) +static inline void Miller_Edge(struct diffmiller_state * const state, const unsigned int delta) { static enum symbol old_state = NO_SYM; enum bit_length length = out_of_range; @@ -326,6 +332,7 @@ int iso14443a_decode_diffmiller(struct diffmiller_state * const state, iso14443_ if(state->flags.frame_finished) { state->flags.frame_finished = 0; + performance_set_checkpoint("frame finished"); return 0; } } diff --git a/openpicc/application/iso14443a_manchester.c b/openpicc/application/iso14443a_manchester.c index e8640fa..9822c60 100644 --- a/openpicc/application/iso14443a_manchester.c +++ b/openpicc/application/iso14443a_manchester.c @@ -59,7 +59,7 @@ enum parity { PARITY_0, PARITY_1 /* Set fixed parity */ }; -static void manchester_enc_byte(u_int16_t **s16, u_int8_t data, enum parity parity) +static inline void manchester_enc_byte(u_int16_t **s16, const u_int8_t data, const enum parity parity) { int i; u_int8_t sum_1 = 0; diff --git a/openpicc/application/main.c b/openpicc/application/main.c index 9b81aea..8babafe 100644 --- a/openpicc/application/main.c +++ b/openpicc/application/main.c @@ -52,6 +52,7 @@ #include "iso14443a_pretender.h" #include "decoder.h" #include "tc_sniffer.h" +#include "performance.h" static inline int detect_board(void) { @@ -197,6 +198,7 @@ int main (void) prvSetupHardware (); usb_print_init(); decoder_init(); + performance_init(); pio_irq_init(); diff --git a/openpicc/application/performance.c b/openpicc/application/performance.c new file mode 100644 index 0000000..cffd094 --- /dev/null +++ b/openpicc/application/performance.c @@ -0,0 +1,145 @@ +/* T/C driver for performance measurements + * + * Copyright 2008 Henryk Plötz <henryk@ploetzli.ch> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <FreeRTOS.h> +#include <AT91SAM7.h> +#include <openpicc.h> + +#include <string.h> + +#include "performance.h" +#include "cmd.h" + +static AT91PS_TC tc_perf = AT91C_BASE_TC1; +static u_int32_t overruns = 0; + +#define NUMBER_OF_CHECKPOINTS 20 +static struct performance_checkpoint checkpoints[NUMBER_OF_CHECKPOINTS]; +static int current_checkpoint; + +static void __ramfunc tc_perf_irq(void) __attribute__ ((naked)); +static void __ramfunc tc_perf_irq(void) +{ + portSAVE_CONTEXT(); + u_int32_t sr = tc_perf->TC_SR; + if(sr & AT91C_TC_COVFS) overruns++; + AT91F_AIC_AcknowledgeIt(); + portRESTORE_CONTEXT(); +} + +void performance_init(void) +{ + AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, ((u_int32_t) 1 << AT91C_ID_TC1)); + /* clock is MCK/2, TIOA/B unconfigured, reset only on SWTRG, ignore Compare C */ + tc_perf->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + tc_perf->TC_CCR = AT91C_TC_CLKDIS; + + AT91F_AIC_ConfigureIt(AT91C_ID_TC1, AT91C_AIC_PRIOR_HIGHEST-1, + AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, (THandler)&tc_perf_irq); + tc_perf->TC_IER = AT91C_TC_COVFS; + AT91F_AIC_ClearIt(AT91C_ID_TC1); + AT91F_AIC_EnableIt(AT91C_ID_TC1); + + memset(checkpoints, 0, sizeof(checkpoints)); +} + +inline void performance_start(void) +{ + memset(checkpoints, 0, sizeof(checkpoints)); + current_checkpoint = 0; + overruns = 0; + tc_perf->TC_CCR = AT91C_TC_SWTRG | AT91C_TC_CLKEN; +} + +inline perf_time_t performance_get(void) +{ + u_int32_t cv = tc_perf->TC_CV; + perf_time_t result = { + .high = overruns, + .low = cv, + }; + return result; +} + +inline perf_time_t performance_stop(void) +{ + perf_time_t result = performance_get(); + tc_perf->TC_CCR = AT91C_TC_CLKDIS; + return result; +} + +void performance_print(perf_time_t time) +{ + DumpUIntToUSB(time.high); + DumpStringToUSB(":"); + DumpUIntToUSB(time.low); +} + +perf_time_t performance_diff(perf_time_t a, perf_time_t b) +{ + // assert that a <= b + if( (a.high > b.high) || (a.high == b.high && a.low > b.low) ) return performance_diff(b, a); + perf_time_t result = { b.high - a.high, 0 }; + if(b.high == a.high) result.low = b.low - a.low; + + return result; +} + +void performance_set_checkpoint(const char * const description) +{ + if(current_checkpoint < NUMBER_OF_CHECKPOINTS) { + perf_time_t time = performance_get(); + checkpoints[current_checkpoint++] = (struct performance_checkpoint){ + .time = time, + .description = description, + }; + } +} + +void performance_stop_report(void) +{ + perf_time_t _now = performance_stop(); + struct performance_checkpoint now = { + .time = _now, + .description = "end of data collection", + }; + perf_time_t last = {0,0}; + int i; + DumpStringToUSB("Performance report: \n\r"); + for(i = 0; i <= current_checkpoint; i++) { + struct performance_checkpoint current = (i<current_checkpoint ? checkpoints[i] : now); + + DumpStringToUSB("\t"); + performance_print(current.time); + DumpStringToUSB(" \t"); + + if(last.high == 0 && last.low == 0) + DumpStringToUSB(" "); + else + performance_print(performance_diff(last, current.time)); + last = current.time; + DumpStringToUSB(" \t"); + + if(current.description) + DumpStringToUSB(current.description); + DumpStringToUSB("\n\r"); + } +} diff --git a/openpicc/application/performance.h b/openpicc/application/performance.h new file mode 100644 index 0000000..fddd9d9 --- /dev/null +++ b/openpicc/application/performance.h @@ -0,0 +1,25 @@ +#ifndef PERFORMANCE_H_ +#define PERFORMANCE_H_ + +extern void performance_start(void); +extern void performance_init(void); + +typedef struct { + u_int32_t high; /* 32 bit count of overruns */ + u_int32_t low; /* 16 bit from T/C running at MCK/2 */ +} perf_time_t; + +extern perf_time_t performance_get(void); +extern perf_time_t performance_stop(void); + +extern void performance_print(perf_time_t time); + +struct performance_checkpoint { + perf_time_t time; + const char * description; +}; + +extern void performance_set_checkpoint(const char * const description); +extern void performance_stop_report(void); + +#endif /*PERFORMANCE_H_*/ diff --git a/openpicc/application/tc_sniffer.c b/openpicc/application/tc_sniffer.c index a77d790..cc21a2f 100644 --- a/openpicc/application/tc_sniffer.c +++ b/openpicc/application/tc_sniffer.c @@ -30,6 +30,7 @@ #include <FreeRTOS.h> #include <openpicc.h> #include <task.h> +#include <semphr.h> #include <string.h> #include <USB-CDC.h> @@ -43,6 +44,7 @@ #include "pio_irq.h" #include "led.h" #include "clock_switch.h" +#include "performance.h" #include "iso14443a_diffmiller.h" @@ -50,6 +52,7 @@ * Strategy: Double buffering. */ +static xSemaphoreHandle data_semaphore; struct diffmiller_state *decoder; iso14443_frame rx_frame; @@ -71,32 +74,26 @@ enum { NONE, REQUEST_START, REQUEST_STOP } request_change = REQUEST_START; #define MIN(a, b) ((a)>(b)?(b):(a)) static int overruns = 0; -void flush_buffer(fiq_buffer_t *buffer) +static void handle_buffer(u_int32_t data[], unsigned int count) { - /* Write all data from the given buffer out, then zero the count */ - if(buffer->count > 0) { - if(buffer->count >= BUFSIZE) { - DumpStringToUSB("Warning: Possible buffer overrun detected\n\r"); - overruns++; - } - buffer->count = MIN(buffer->count, BUFSIZE); #ifdef USE_BINARY_PROTOCOL - vUSBSendBuffer_blocking((unsigned char*)(&(buffer->data[0])), 0, MIN(buffer->count,BUFSIZE)*4, WAIT_TICKS); - if(buffer->count >= BUFSIZE) + vUSBSendBuffer_blocking((unsigned char*)(&data[0]), 0, MIN(count,BUFSIZE)*4, WAIT_TICKS); + if(count >= BUFSIZE) vUSBSendBuffer_blocking((unsigned char*)"////", 0, 4, WAIT_TICKS); else vUSBSendBuffer_blocking((unsigned char*)"____", 0, 4, WAIT_TICKS); #elif defined(PRINT_TIMES) unsigned int i=0; - for(i=0; i<buffer->count; i++) { - DumpUIntToUSB(buffer->data[i]); + for(i=0; i<count; i++) { + DumpUIntToUSB(data[i]); DumpStringToUSB(" "); } DumpStringToUSB("\n\r"); #else unsigned int offset = 0; - while(offset < buffer->count) { - int ret = iso14443a_decode_diffmiller(decoder, &rx_frame, buffer->data, &offset, buffer->count); + while(offset < count) { + int ret = iso14443a_decode_diffmiller(decoder, &rx_frame, data, &offset, count); + /* DumpStringToUSB("\n\r"); if(ret < 0) { DumpStringToUSB("-"); @@ -105,7 +102,7 @@ void flush_buffer(fiq_buffer_t *buffer) DumpUIntToUSB(ret); } DumpStringToUSB(" "); - DumpUIntToUSB(offset); DumpStringToUSB(" "); DumpUIntToUSB(buffer->count); DumpStringToUSB(" "); DumpUIntToUSB(overruns); + DumpUIntToUSB(offset); DumpStringToUSB(" "); DumpUIntToUSB(count); DumpStringToUSB(" "); DumpUIntToUSB(overruns); DumpStringToUSB("\n\r"); if(ret >= 0) { DumpStringToUSB("Frame finished, "); @@ -118,9 +115,22 @@ void flush_buffer(fiq_buffer_t *buffer) case CRC_ERROR: DumpStringToUSB("CRC ERROR\n\r"); break; case CRC_UNCALCULATED: DumpStringToUSB("CRC UNCALCULATED\n\r"); break; } - } + }*/ + (void)ret; } #endif +} + +void flush_buffer(fiq_buffer_t *buffer) +{ + /* Write all data from the given buffer out, then zero the count */ + if(buffer->count > 0) { + if(buffer->count >= BUFSIZE) { + DumpStringToUSB("Warning: Possible buffer overrun detected\n\r"); + overruns++; + } + buffer->count = MIN(buffer->count, BUFSIZE); + handle_buffer(buffer->data, buffer->count); buffer->count = 0; } } @@ -133,10 +143,60 @@ void start_stop_sniffing(void) request_change = REQUEST_START; } +static portBASE_TYPE tc_sniffer_irq(u_int32_t pio, portBASE_TYPE xTaskWoken) +{ + (void)pio; + usb_print_string_f("?", 0); + xTaskWoken = xSemaphoreGiveFromISR(data_semaphore, xTaskWoken); + return xTaskWoken; +} + +static void main_loop(void) +{ + int current = 0; + + while(1) { + /* Main loop of the sniffer */ + //vTaskDelay(1000 * portTICK_RATE_MS); + + u_int32_t start = *AT91C_TC2_CV; + int next = (current+1)%(sizeof(fiq_buffers)/sizeof(fiq_buffers[0])); + flush_buffer( &fiq_buffers[next] ); + /* The buffer designated by next is now empty, give it to the fiq, + * we'll just guess that this write is atomic */ + tc_sniffer_next_buffer_for_fiq = &fiq_buffers[current=next]; + u_int32_t stop = *AT91C_TC2_CV; + + DumpStringToUSB("{"); DumpUIntToUSB(start); DumpStringToUSB(":"); DumpUIntToUSB(stop); DumpStringToUSB("}"); + if(*AT91C_TC2_CV > 2*128) { + u_int32_t dummybuf[1] = {*AT91C_TC2_CV}; + handle_buffer(dummybuf, 1); + + usb_print_string_f("[", 0); + while(xSemaphoreTake(data_semaphore, portMAX_DELAY) == pdFALSE) ; + usb_print_string_f("]", 0); + } + } +} + +static u_int32_t testdata[] = {65535, 75, 138, 75, 138, 139, 139, 300}; +static u_int32_t testdata2[] = {65535, 80, 144, 208, 208, 208, 80, 80, 208, 208, 208, 208, 80, 144, 80, 144, 144, 80, 144, 208, 81, 80, 80, 81, 80, 81, 209, 209, 209, 80, 81, 145, 81, 300}; + +static void timing_loop(void) +{ + while(1) { + vTaskDelay(5000*portTICK_RATE_MS); + performance_start(); + handle_buffer(testdata, sizeof(testdata)/sizeof(testdata[0])); + performance_set_checkpoint("end of first buffer"); + handle_buffer(testdata2, sizeof(testdata2)/sizeof(testdata2[0])); + performance_stop_report(); + } +} + void tc_sniffer (void *pvParameters) { (void)pvParameters; - /* Disable load modulation circuitry * (Must be done explicitly, because the default state is pull-up high, leading * to a constant modulation output which prevents reception. I've been bitten by @@ -172,46 +232,17 @@ void tc_sniffer (void *pvParameters) } if(!decoder) vLedHaltBlinking(1); + vSemaphoreCreateBinary(data_semaphore); + if(data_semaphore == NULL) vLedHaltBlinking(3); // The change interrupt is going to be handled by the FIQ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPICC_SSC_DATA); + if( pio_irq_register(OPENPICC_SSC_DATA, &tc_sniffer_irq) < 0) + vLedHaltBlinking(2); pio_irq_enable(OPENPICC_SSC_DATA); - - int current = 0; - while(1) { - /* Main loop of the sniffer */ - - if(currently_sniffing) { - int next = (current+1)%(sizeof(fiq_buffers)/sizeof(fiq_buffers[0])); - flush_buffer( &fiq_buffers[next] ); - /* The buffer designated by next is now empty, give it to the fiq, - * we'll just guess that this write is atomic */ - tc_sniffer_next_buffer_for_fiq = &fiq_buffers[current=next]; - if(request_change == REQUEST_STOP) { - currently_sniffing = 0; - request_change = NONE; - - tc_sniffer_next_buffer_for_fiq = 0; - memset(fiq_buffers, 0, sizeof(fiq_buffers)); - current = 0; -#ifdef USE_BINARY_PROTOCOL - vUSBSendBuffer_blocking((unsigned char *)"----", 0, 4, WAIT_TICKS); - usb_print_set_force_silence(0); -#endif - } else vTaskDelay(2* portTICK_RATE_MS); - } else { - // Do nothing, wait longer - - if(request_change == REQUEST_START) { - // Prevent usb_print code from barging in -#ifdef USE_BINARY_PROTOCOL - usb_print_set_force_silence(1); - vUSBSendBuffer_blocking((unsigned char *)"----", 0, 4, WAIT_TICKS); -#endif - currently_sniffing = 1; - request_change = NONE; - } else vTaskDelay(100 * portTICK_RATE_MS); - } - } + //main_loop(); + timing_loop(); + + (void)main_loop; (void)timing_loop; } |