summaryrefslogtreecommitdiff
path: root/openpicc
diff options
context:
space:
mode:
Diffstat (limited to 'openpicc')
-rw-r--r--openpicc/Makefile1
-rw-r--r--openpicc/application/cmd.c3
-rw-r--r--openpicc/application/iso14443_layer3a.c143
-rw-r--r--openpicc/application/iso14443_layer3a.h18
-rw-r--r--openpicc/application/main.c22
-rw-r--r--openpicc/application/pio_irq.c10
-rw-r--r--openpicc/application/ssc_picc.c1
-rw-r--r--openpicc/application/ssc_picc.h1
-rw-r--r--openpicc/application/tc_cdiv_sync.c4
-rw-r--r--openpicc/config/atmel-rom.ld2
-rw-r--r--openpicc/config/board.h3
-rw-r--r--openpicc/os/boot/Cstartup_SAM7.c6
-rw-r--r--openpicc/os/boot/boot.s93
13 files changed, 282 insertions, 25 deletions
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 <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; 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 <FreeRTOS.h>
+#include <board.h>
+#include <task.h>
+
+#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
personal git repositories of Harald Welte. Your mileage may vary