From 616746c2e01a0425a9fc62d24153d88079f0daac Mon Sep 17 00:00:00 2001 From: henryk Date: Wed, 21 Nov 2007 04:45:15 +0000 Subject: Commit status quo: Start adding iso 14443 layer 3a code Currently working on fiq for pio data change to reset tc0 via swtrg git-svn-id: https://svn.openpcd.org:2342/trunk@336 6dc7ffe9-61d6-0310-9af1-9938baff3ed1 --- openpicc/Makefile | 1 + openpicc/application/cmd.c | 3 - openpicc/application/iso14443_layer3a.c | 143 ++++++++++++++++++++++++++++++++ openpicc/application/iso14443_layer3a.h | 18 ++++ openpicc/application/main.c | 22 ++--- openpicc/application/pio_irq.c | 10 +++ openpicc/application/ssc_picc.c | 1 + openpicc/application/ssc_picc.h | 1 + openpicc/application/tc_cdiv_sync.c | 4 +- openpicc/config/atmel-rom.ld | 2 +- openpicc/config/board.h | 3 + openpicc/os/boot/Cstartup_SAM7.c | 6 ++ openpicc/os/boot/boot.s | 93 ++++++++++++++++++++- 13 files changed, 282 insertions(+), 25 deletions(-) create mode 100644 openpicc/application/iso14443_layer3a.c create mode 100644 openpicc/application/iso14443_layer3a.h diff --git a/openpicc/Makefile b/openpicc/Makefile index f88f052..bea0f40 100644 --- a/openpicc/Makefile +++ b/openpicc/Makefile @@ -83,6 +83,7 @@ ARM_SRC= \ application/tc_fdt.c \ application/tc_cdiv.c \ application/usb_print.c \ + application/iso14443_layer3a.c \ os/boot/Cstartup_SAM7.c \ os/core/list.c \ os/core/queue.c \ diff --git a/openpicc/application/cmd.c b/openpicc/application/cmd.c index 1e7b552..7b370db 100644 --- a/openpicc/application/cmd.c +++ b/openpicc/application/cmd.c @@ -422,8 +422,5 @@ portBASE_TYPE vCmdInit(void) { return 0; } - ssc_rx_mode_set(SSC_MODE_CONTINUOUS); - DumpStringToUSB("SSC mode set to continuous\n\r"); - return 1; } diff --git a/openpicc/application/iso14443_layer3a.c b/openpicc/application/iso14443_layer3a.c new file mode 100644 index 0000000..26a6115 --- /dev/null +++ b/openpicc/application/iso14443_layer3a.c @@ -0,0 +1,143 @@ +/*************************************************************** + * + * OpenPICC - ISO 14443 Layer 3 Type A state machine + * + * Copyright 2007 Henryk Plötz + * + *************************************************************** + + 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; version 2. + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +*/ + +#include +#include +#include + +#include "openpicc.h" +#include "iso14443_layer3a.h" +#include "ssc_picc.h" +#include "pll.h" +#include "tc_fdt.h" +#include "tc_cdiv.h" +#include "tc_cdiv_sync.h" +#include "usb_print.h" +#include "cmd.h" + +static enum ISO14443_STATES state = STARTING_UP; +#define PLL_LOCK_HYSTERESIS portTICK_RATE_MS*5 + +#define LAYER3_DEBUG usb_print_string + +void iso14443_layer3a_state_machine (void *pvParameters) +{ + unsigned long int last_pll_lock = ~0; + (void)pvParameters; + while(1) { + ssc_dma_buffer_t* buffer = NULL; + portBASE_TYPE need_receive = 0, switch_on = 0; + + /* First let's see whether there is a reader */ + switch(state) { + case STARTING_UP: /* Fall through */ + case ERROR: + // do nothing here + break; + case POWERED_OFF: + if(pll_is_locked()) { + unsigned long int now = xTaskGetTickCount(); + if(now - last_pll_lock > PLL_LOCK_HYSTERESIS) { + /* Go to idle when in POWERED_OFF and pll + * was locked for at least + * PLL_LOCK_HYSTERESIS ticks */ + switch_on = 1; + last_pll_lock = ~0; + LAYER3_DEBUG("PLL locked, switching on \n\r"); + } else last_pll_lock = now; + } else last_pll_lock = ~0; + break; + default: + if(!pll_is_locked()) { + unsigned long int now = xTaskGetTickCount(); + if(now - last_pll_lock > PLL_LOCK_HYSTERESIS) { + /* Power off when not powered off and pll + * was unlocked for at least PLL_LOCK_HYSTERESIS + * ticks */ + state = POWERED_OFF; + ssc_rx_stop(); + last_pll_lock = ~0; + LAYER3_DEBUG("PLL lost lock, switching off \n\r"); + continue; + } else last_pll_lock = now; + } else last_pll_lock = ~0; + break; + } + + switch(state) { + case STARTING_UP: + pll_init(); + + tc_cdiv_init(); + tc_cdiv_set_divider(32); + tc_fdt_init(); +#if 0 + ssc_tx_init(); +#else + AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPICC_MOD_PWM); + AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, OPENPICC_MOD_SSC | + OPENPICC_SSC_DATA | OPENPICC_SSC_DATA | + AT91C_PIO_PA15, 0); +#endif + ssc_rx_init(); + + state = POWERED_OFF; + break; + case POWERED_OFF: + if(switch_on == 1) { + state=IDLE; + continue; + } + break; + case IDLE: + case HALT: + /* Wait for REQA or WUPA (HALT: only WUPA) */ + ssc_rx_mode_set(SSC_MODE_14443A_SHORT); + ssc_rx_start(); + need_receive = 1; + default: + break; + } + + if(need_receive) { + if(xQueueReceive(ssc_rx_queue, &buffer, portTICK_RATE_MS)) { + portENTER_CRITICAL(); + buffer->state = PROCESSING; + portEXIT_CRITICAL(); + + switch(state) { + case IDLE: + case HALT: + + break; + default: + break; + } + + portENTER_CRITICAL(); + buffer->state = FREE; + portEXIT_CRITICAL(); + } + } else vTaskDelay(portTICK_RATE_MS); + } +} diff --git a/openpicc/application/iso14443_layer3a.h b/openpicc/application/iso14443_layer3a.h new file mode 100644 index 0000000..396ebe9 --- /dev/null +++ b/openpicc/application/iso14443_layer3a.h @@ -0,0 +1,18 @@ +#ifndef ISO14443_LAYER3A_H_ +#define ISO14443_LAYER3A_H_ + +extern void iso14443_layer3a_state_machine (void *pvParameters); + +enum ISO14443_STATES { + STARTING_UP, /* Hardware has not been initialized, initialize hardware, go to power-off */ + POWERED_OFF, /* Card not in field, wait for PLL lock */ + IDLE, /* Card in field and powered, wait for REQA or WUPA */ + READY, /* Perform anticollision, wait for select */ + ACTIVE, /* Selected */ + HALT, /* Card halted and powered, wait for WUPA */ + READY_STAR, /* Perform anticollision, wait for select */ + ACTIVE_STAR, /* Selected */ + ERROR, /* Some unrecoverable error has occured */ +}; + +#endif /*ISO14443_LAYER3A_H_*/ diff --git a/openpicc/application/main.c b/openpicc/application/main.c index e13c793..0756d10 100644 --- a/openpicc/application/main.c +++ b/openpicc/application/main.c @@ -47,6 +47,7 @@ #include "tc_cdiv_sync.h" #include "tc_fdt.h" #include "usb_print.h" +#include "iso14443_layer3a.h" /**********************************************************************/ static inline void prvSetupHardware (void) @@ -149,23 +150,10 @@ int main (void) da_init(); adc_init(); - pll_init(); - - tc_cdiv_init(); - tc_cdiv_set_divider(16); - tc_fdt_init(); -#if 0 - ssc_tx_init(); -#else - AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPICC_MOD_PWM); - AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, OPENPICC_MOD_SSC | - OPENPICC_SSC_DATA | OPENPICC_SSC_DATA | - AT91C_PIO_PA15, 0); -#endif - ssc_rx_init(); - - xTaskCreate (vMainTestSSCRXConsumer, (signed portCHAR *) "SSC_CONSUMER", TASK_USB_STACK, - NULL, TASK_USB_PRIORITY, NULL); + /*xTaskCreate (vMainTestSSCRXConsumer, (signed portCHAR *) "SSC_CONSUMER", TASK_USB_STACK, + NULL, TASK_USB_PRIORITY, NULL);*/ + xTaskCreate (iso14443_layer3a_state_machine, (signed portCHAR *) "ISO14443A-3", TASK_ISO_STACK, + NULL, TASK_ISO_PRIORITY, NULL); xTaskCreate (vUSBCDCTask, (signed portCHAR *) "USB", TASK_USB_STACK, NULL, TASK_USB_PRIORITY, NULL); diff --git a/openpicc/application/pio_irq.c b/openpicc/application/pio_irq.c index 648a561..73dbae5 100644 --- a/openpicc/application/pio_irq.c +++ b/openpicc/application/pio_irq.c @@ -147,13 +147,23 @@ void pio_irq_init_once(void) if(!initialized) pio_irq_init(); } +#define USE_FIQ +extern void fiq_handler(void); void pio_irq_init(void) { initialized = 1; AT91F_PIOA_CfgPMC(); +#ifdef USE_FIQ + AT91F_AIC_ConfigureIt(AT91C_ID_FIQ, + //0, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &cdsync_cb); + 0, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &fiq_handler); + /* enable fast forcing for PIOA interrupt */ + *AT91C_AIC_FFER = (1 << AT91C_ID_PIOA); +#else AT91F_AIC_ConfigureIt(AT91C_ID_PIOA, OPENPICC_IRQ_PRIO_PIO, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &pio_irq_demux); +#endif AT91F_AIC_EnableIt(AT91C_ID_PIOA); (void)pio_irq_demux; // FIXME NO IRQ } diff --git a/openpicc/application/ssc_picc.c b/openpicc/application/ssc_picc.c index 176af88..ac3b70f 100644 --- a/openpicc/application/ssc_picc.c +++ b/openpicc/application/ssc_picc.c @@ -315,6 +315,7 @@ static void __ramfunc ssc_irq_short_inner(void) }*/ ssc_state.buffer[0]->state = FULL; + ssc_state.buffer[0]->reception_mode = ssc_state.mode; vLedSetGreen(1); task_woken = xQueueSendFromISR(ssc_rx_queue, &ssc_state.buffer[0], task_woken); DumpStringToUSB("Sent "); diff --git a/openpicc/application/ssc_picc.h b/openpicc/application/ssc_picc.h index 34bdc18..813ef33 100644 --- a/openpicc/application/ssc_picc.h +++ b/openpicc/application/ssc_picc.h @@ -41,6 +41,7 @@ typedef enum { typedef struct { volatile ssc_dma_buffer_state_t state; u_int32_t len; /* Length of the content */ + enum ssc_mode reception_mode; u_int8_t data[SSC_DMA_BUFFER_SIZE]; } ssc_dma_buffer_t; diff --git a/openpicc/application/tc_cdiv_sync.c b/openpicc/application/tc_cdiv_sync.c index 422fe44..0486f90 100644 --- a/openpicc/application/tc_cdiv_sync.c +++ b/openpicc/application/tc_cdiv_sync.c @@ -19,9 +19,11 @@ static void pio_data_change(u_int32_t pio) * change the level is high, then it must have been a rising * edge */ if (*AT91C_PIOA_PDSR & OPENPICC_PIO_FRAME) { + vLedSetGreen(1); *AT91C_TC0_CCR = AT91C_TC_SWTRG; DEBUGPCR("CDIV_SYNC_FLIP SWTRG CV=0x%08x", *AT91C_TC0_CV); + vLedSetGreen(0); } else DEBUGPCR(""); //vLedSetGreen(0); @@ -60,7 +62,6 @@ void tc_cdiv_sync_enable(void) *AT91C_PIOA_IER = OPENPICC_PIO_FRAME; } -extern void (*fiq_handler)(void); void tc_cdiv_sync_init(void) { pio_irq_init_once(); @@ -69,7 +70,6 @@ void tc_cdiv_sync_init(void) enabled = 0; AT91F_PIOA_CfgPMC(); - AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPICC_PIO_SSC_DATA_CONTROL); pio_irq_register(OPENPICC_PIO_FRAME, &pio_data_change); diff --git a/openpicc/config/atmel-rom.ld b/openpicc/config/atmel-rom.ld index 0a9a04d..8ea6c68 100644 --- a/openpicc/config/atmel-rom.ld +++ b/openpicc/config/atmel-rom.ld @@ -1,7 +1,7 @@ MEMORY { flash : ORIGIN = 0x00100000, LENGTH = 256K - 1K /* save 1K for environment on top of flash */ - ram : ORIGIN = 0x00200000, LENGTH = 64K + ram : ORIGIN = 0x00200028, LENGTH = 64K-28 } __stack_end__ = 0x00200000 + 64K - 4; diff --git a/openpicc/config/board.h b/openpicc/config/board.h index c2f0e2e..18cfe9e 100644 --- a/openpicc/config/board.h +++ b/openpicc/config/board.h @@ -95,6 +95,9 @@ #define TASK_USB_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define TASK_USB_STACK ( 512 ) +#define TASK_ISO_PRIORITY ( tskIDLE_PRIORITY + 3 ) +#define TASK_ISO_STACK ( 512 ) + #define TASK_NRF_PRIORITY ( tskIDLE_PRIORITY + 3 ) #define TASK_NRF_STACK ( 512 ) diff --git a/openpicc/os/boot/Cstartup_SAM7.c b/openpicc/os/boot/Cstartup_SAM7.c index 72c9917..fdcafd3 100644 --- a/openpicc/os/boot/Cstartup_SAM7.c +++ b/openpicc/os/boot/Cstartup_SAM7.c @@ -26,6 +26,7 @@ //*---------------------------------------------------------------------------- void AT91F_LowLevelInit (void) { + char i=0; AT91PS_PMC pPMC = AT91C_BASE_PMC; //* Set flash wait state @@ -65,4 +66,9 @@ void AT91F_LowLevelInit (void) pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK; while (!(pPMC->PMC_SR & AT91C_PMC_MCKRDY)); + + /* Copy IRQ vector table to RAM */ + for(i=0; i<0x24; i++) *((char*)(0x00200000)+i) = *((char*)(0x00100000)+i); + /* Perform remap FIXME doesn't work*/ + // AT91C_BASE_MC->MC_RCR = AT91C_MC_RCB; } diff --git a/openpicc/os/boot/boot.s b/openpicc/os/boot/boot.s index 6bd5db2..cbd9be7 100644 --- a/openpicc/os/boot/boot.s +++ b/openpicc/os/boot/boot.s @@ -23,7 +23,7 @@ /* Stack Sizes */ .set UND_STACK_SIZE, 0x00000004 .set ABT_STACK_SIZE, 0x00000004 - .set FIQ_STACK_SIZE, 0x00000004 + .set FIQ_STACK_SIZE, 0x00000400 .set IRQ_STACK_SIZE, 0X00000400 .set SVC_STACK_SIZE, 0x00000400 @@ -39,6 +39,20 @@ .equ I_BIT, 0x80 /* when I bit is set, IRQ is disabled */ .equ F_BIT, 0x40 /* when F bit is set, FIQ is disabled */ +.equ AT91C_BASE_AIC, (0xFFFFF000) +.equ AT91C_BASE_PIOA, 0xFFFFF400 +.equ AT91C_BASE_TC0, 0xFFFA0000 +.equ AT91C_TC_SWTRG, (1 << 2) +.equ PIO_DATA, (1 << 27) +.equ PIOA_SODR, 0x30 +.equ PIOA_CODR, 0x34 +.equ PIOA_PDSR, 0x3c +.equ PIOA_IDR, 0x44 +.equ PIOA_ISR, 0x4c +.equ TC_CCR, 0x00 +.equ AIC_EOICR, (304) +/*.equ PIO_LED1, (1 << 25)*/ +.equ PIO_LED1, (1 << 12) start: _start: @@ -55,6 +69,11 @@ _mainCRTStartup: mov sp, r0 sub r0, r0, #ABT_STACK_SIZE msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */ + /* Preload registers for FIQ handler */ + ldr r10, =AT91C_BASE_PIOA + ldr r12, =AT91C_BASE_TC0 + ldr r8, =AT91C_BASE_AIC + mov r9, #AT91C_TC_SWTRG mov sp, r0 sub r0, r0, #FIQ_STACK_SIZE msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */ @@ -147,7 +166,7 @@ endless_loop: ldr pc, _dabt /* data abort - _dabt */ nop /* reserved */ ldr pc, [pc,#-0xF20] /* IRQ - read the AIC */ - ldr pc, _fiq /* FIQ - _fiq */ + ldr pc, [pc,#-0xF20] /* FIQ - read the AIC */ _undf: .word __undf /* undefined */ _swi: .word swi_handler /* SWI */ @@ -159,3 +178,73 @@ __undf: b . /* undefined */ __pabt: b . /* program abort */ __dabt: b . /* data abort */ __fiq: b . /* FIQ */ + +/* Following is from openpcd/firmware/src/start/Cstartup_app.S */ +#define LED_TRIGGER +/*#define CALL_PIO_IRQ_DEMUX*/ + + .text + .arm + .section .fastrun, "ax" + + .global fiq_handler + .func fiq_handler +fiq_handler: + /* code that uses pre-initialized FIQ reg */ + /* r8 AT91C_BASE_AIC (dfu init) + r9 AT91C_TC_SWTRG + r10 AT91C_BASE_PIOA + r11 tmp + r12 AT91C_BASE_TC0 + r13 stack + r14 lr + */ + + ldr r8, [r10, #PIOA_ISR] + tst r8, #PIO_DATA /* check for PIO_DATA change */ + ldrne r11, [r10, #PIOA_PDSR] + tstne r11, #PIO_DATA /* check for PIO_DATA == 1 */ + strne r9, [r12, #TC_CCR] /* software trigger */ +#ifdef LED_TRIGGER + movne r11, #PIO_LED1 + strne r11, [r10, #PIOA_CODR] /* enable LED */ +#endif + +#if 1 + movne r11, #PIO_DATA + strne r11, [r10, #PIOA_IDR] /* disable further PIO_DATA FIQ */ +#endif + + /*- Mark the End of Interrupt on the AIC */ + ldr r11, =AT91C_BASE_AIC + str r11, [r11, #AIC_EOICR] + +#ifdef LED_TRIGGER + mov r11, #PIO_LED1 + str r11, [r10, #PIOA_SODR] /* disable LED */ +#endif + +#ifdef CALL_PIO_IRQ_DEMUX + /* push r0, r1-r3, r12, r14 onto FIQ stack */ + /*stmfd sp!, { r0-r3, r12, lr} + mov r0, r8*/ + + /* enable interrupts while handling demux */ + /* enable interrupts while handling demux */ + /* msr CPSR_c, #F_BIT | ARM_MODE_SVC */ + + /* Call C function, give PIOA_ISR as argument */ + /*ldr r11, =__pio_irq_demux + mov r14, pc + bx r11*/ + + /* msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ */ + /*ldmia sp!, { r0-r3, r12, lr }*/ +#endif + + /*- Restore the Program Counter using the LR_fiq directly in the PC */ + subs pc, lr, #4 + + .size fiq_handler, . - fiq_handler + .endfunc + .end -- cgit v1.2.3