Commit a first version of an iso 14443 layer 2 and a passive sniffer. Works for short frames, and sometimes even for long frames. Pending some major cleanup
git-svn-id: https://svn.openpcd.org:2342/trunk@408 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
This commit is contained in:
parent
f44e839dcc
commit
6be69f0de0
|
@ -88,7 +88,9 @@ ARM_SRC= \
|
|||
application/tc_fdt.c \
|
||||
application/tc_cdiv.c \
|
||||
application/usb_print.c \
|
||||
application/iso14443_layer2a.c \
|
||||
application/iso14443_layer3a.c \
|
||||
application/iso14443_sniffer.c \
|
||||
application/iso14443a_manchester.c \
|
||||
application/iso14443a_miller.c \
|
||||
application/load_modulation.c \
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/***************************************************************
|
||||
*
|
||||
* OpenPICC - ISO 14443 Layer 2 Type A PICC transceiver code
|
||||
* Manages receiving, sending and parts of framing
|
||||
*
|
||||
* This does not fully implement layer 2 in that it won't
|
||||
* automatically call the Miller decoder or Manchester encoder
|
||||
* for you. Instead you'll be given ssc rx buffer pointers and
|
||||
* are expected to hand in ssc tx buffer pointers. You've got
|
||||
* to call iso14443a_manchester and iso14443a_miller yourself.
|
||||
* The reason is that this makes it possible for the layer 3
|
||||
* implementation to work on raw samples without en/de-coding
|
||||
* time to enable fast responses during anticollision.
|
||||
*
|
||||
* 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; 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 <errno.h>
|
||||
|
||||
#include "openpicc.h"
|
||||
#include "iso14443_layer2a.h"
|
||||
#include "ssc_picc.h"
|
||||
#include "pll.h"
|
||||
#include "tc_fdt.h"
|
||||
#include "tc_cdiv.h"
|
||||
#include "tc_cdiv_sync.h"
|
||||
#include "load_modulation.h"
|
||||
|
||||
static u_int8_t fast_receive;
|
||||
static volatile u_int8_t receiving = 0;
|
||||
|
||||
#ifdef FOUR_TIMES_OVERSAMPLING
|
||||
#define RX_DIVIDER 32
|
||||
#else
|
||||
#define RX_DIVIDER 64
|
||||
#endif
|
||||
|
||||
int iso14443_receive(iso14443_receive_callback_t callback, ssc_dma_rx_buffer_t **buffer, unsigned int timeout)
|
||||
{
|
||||
int was_receiving = receiving;
|
||||
(void)callback;
|
||||
ssc_dma_rx_buffer_t* _buffer = NULL;
|
||||
int len;
|
||||
|
||||
|
||||
if(!was_receiving) {
|
||||
iso14443_l2a_rx_start();
|
||||
} else {
|
||||
/*
|
||||
* handled by _iso14443_ssc_irq_ext below
|
||||
tc_fdt_set(0xff00);
|
||||
tc_cdiv_set_divider(RX_DIVIDER);
|
||||
tc_cdiv_sync_reset();
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
if(xQueueReceive(ssc_rx_queue, &_buffer, timeout)) {
|
||||
if(!was_receiving) {
|
||||
iso14443_l2a_rx_stop();
|
||||
}
|
||||
|
||||
if(_buffer == NULL) {
|
||||
/* Can this happen? */
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
portENTER_CRITICAL();
|
||||
_buffer->state = PROCESSING;
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
len = _buffer->len_transfers;
|
||||
|
||||
if(buffer != NULL) *buffer = _buffer;
|
||||
else {
|
||||
portENTER_CRITICAL();
|
||||
_buffer->state = FREE;
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
if(!was_receiving)
|
||||
iso14443_l2a_rx_stop();
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
int iso14443_wait_for_carrier(unsigned int timeout)
|
||||
{
|
||||
(void)timeout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iso14443_l2a_rx_start(void)
|
||||
{
|
||||
receiving = 1;
|
||||
tc_fdt_set(0xff00);
|
||||
tc_cdiv_set_divider(RX_DIVIDER);
|
||||
ssc_rx_start();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iso14443_l2a_rx_stop(void)
|
||||
{
|
||||
ssc_rx_stop();
|
||||
receiving = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u_int8_t iso14443_set_fast_receive(u_int8_t enable_fast_receive)
|
||||
{
|
||||
u_int8_t old_value = fast_receive;
|
||||
fast_receive = enable_fast_receive;
|
||||
return old_value;
|
||||
}
|
||||
|
||||
u_int8_t iso14443_get_fast_receive(void)
|
||||
{
|
||||
return fast_receive;
|
||||
}
|
||||
|
||||
void _iso14443_ssc_irq_ext(u_int32_t ssc_sr, enum ssc_mode ssc_mode, u_int8_t* samples)
|
||||
{
|
||||
(void) ssc_mode; (void) samples;
|
||||
if( (ssc_sr & AT91C_SSC_CP1) && receiving) {
|
||||
tc_fdt_set(0xff00);
|
||||
tc_cdiv_set_divider(RX_DIVIDER);
|
||||
tc_cdiv_sync_reset();
|
||||
}
|
||||
}
|
||||
|
||||
int iso14443_layer2a_init(u_int8_t enable_fast_receive)
|
||||
{
|
||||
pll_init();
|
||||
|
||||
tc_cdiv_init();
|
||||
tc_fdt_init();
|
||||
//ssc_set_irq_extension((ssc_irq_ext_t)iso14443_layer3a_irq_ext);
|
||||
ssc_rx_init();
|
||||
ssc_tx_init();
|
||||
|
||||
load_mod_init();
|
||||
load_mod_level(3);
|
||||
|
||||
ssc_rx_mode_set(SSC_MODE_14443A);
|
||||
ssc_set_irq_extension(_iso14443_ssc_irq_ext);
|
||||
|
||||
iso14443_set_fast_receive(enable_fast_receive);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
#ifndef ISO14443_LAYER2A_H_
|
||||
#define ISO14443_LAYER2A_H_
|
||||
|
||||
#include "ssc_picc.h"
|
||||
|
||||
/* Callback type for iso14443_receive().
|
||||
* Parameter buffer is being passed a pointer to an SSC Rx buffer structure that this receive happened
|
||||
* on. You might want to pass this into iso14443a_decode_miller().
|
||||
* Parameter in_irq is true if the callback has been called while still in IRQ mode. It must then *NOT*
|
||||
* perform any calls that might upset the IRQ processing. Especially it may not call into FreeRTOS or
|
||||
* any parts of the applications that do.
|
||||
*/
|
||||
typedef void (*iso14443_receive_callback_t)(ssc_dma_rx_buffer_t *buffer, u_int8_t in_irq);
|
||||
|
||||
/* Wait for and receive a frame. Parameters callback and buffer are optional. If you omit them you'll lose
|
||||
* the received frame, obviously.
|
||||
* Parameter callback is a callback function that will be called for each received frame and might
|
||||
* then trigger a response.
|
||||
* Parameter buffer is an output pointer to a pointer to an SSC Rx buffer structure containing the
|
||||
* received frame.
|
||||
* Parameter timeout gives an optional timeout for the receive operation after which the receive will
|
||||
* be aborted. When timeout is 0 the receive will not time out.
|
||||
* This call will block until a frame is received or an exception happens. Obviously it must not be run
|
||||
* from IRQ context.
|
||||
*
|
||||
* Warning: When you get a buffer from the function then it's state is set to PROCESSING and you must
|
||||
* FREE it yourself.
|
||||
*
|
||||
* Return values:
|
||||
* >= 0 Frame received, return value is buffer length (yes, 0 is a valid buffer length)
|
||||
* -ENETDOWN PLL is not locked or PLL lock lost
|
||||
* -ETIMEDOUT Receive timed out without receiving anything (usually not regarded an error condition)
|
||||
* -EBUSY A Tx is currently running or pending; can't receive
|
||||
* -EALREADY There's already an iso14443_receive() invocation running
|
||||
*/
|
||||
extern int iso14443_receive(iso14443_receive_callback_t callback, ssc_dma_rx_buffer_t **buffer, unsigned int timeout);
|
||||
|
||||
/*
|
||||
* Transmit a frame. Starts transmitting fdt carrier cycles after the end of the received frame.
|
||||
* Parameters buffer and fdt specify the SSC Tx buffer to be sent and the frame delay time in carrier cycles.
|
||||
* When parameter async is set then this call will only schedule the buffer for sending and return immediately,
|
||||
* otherwise the call will block until the buffer has been sent completely, until the specified timeout is reached
|
||||
* or an error occurs.
|
||||
* This function may be run from IRQ context, especially from within the iso14443_receive callback, with the async
|
||||
* parameter set.
|
||||
*
|
||||
* Note: When your callback calls iso14443_transmit() from IRQ context it must set the async parameter to have transmit
|
||||
* return immediately and then not block within the callback. When the scheduled transmission has not happened by the next
|
||||
* time you call iso14443_receive() it will abort with -EBUSY and you can then either decide to wait for the transmission
|
||||
* to go through, or abort the scheduled transmission with iso14443_tx_abort(). You can check for whether a Tx is currently
|
||||
* pending or running with iso14443_tx_busy().
|
||||
*/
|
||||
extern int iso14443_transmit(ssc_dma_tx_buffer_t *buffer, unsigned int fdt, u_int8_t async, unsigned int timeout);
|
||||
|
||||
extern int iso14443_tx_abort(void);
|
||||
extern int iso14443_tx_busy(void);
|
||||
|
||||
extern int iso14443_l2a_rx_start(void);
|
||||
extern int iso14443_l2a_rx_stop(void);
|
||||
|
||||
/*
|
||||
* Wait for the presence of a reader to be detected.
|
||||
* Returns 0 when the PLL is locked.
|
||||
*/
|
||||
extern int iso14443_wait_for_carrier(unsigned int timeout);
|
||||
|
||||
/* Initialize the layer 2 transceiver code.
|
||||
* Parameter enable_fast_receive, when set, will enable special code to guarantee fast response times
|
||||
* for frames shorter than or equal to 56 data bits (bit oriented anticollision frame length). This
|
||||
* generally involves running the callback from an IRQ handler.
|
||||
*/
|
||||
extern int iso14443_layer2a_init(u_int8_t enable_fast_receive);
|
||||
|
||||
extern u_int8_t iso14443_set_fast_receive(u_int8_t enable_fast_receive);
|
||||
extern u_int8_t iso14443_get_fast_receive(void);
|
||||
|
||||
#endif /*ISO14443_LAYER2A_H_*/
|
|
@ -78,7 +78,7 @@ const u_int8_t ISO14443A_SHORT_FRAME_WUPA[ISO14443A_SHORT_FRAME_COMPARE_LENGTH]
|
|||
#define INITIAL_FRAME NULL_FRAME
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
#define SHORT_MODE SSC_MODE_14443A_SHORT
|
||||
#define STANDARD_MODE SSC_MODE_14443A_STANDARD
|
||||
#else
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/***************************************************************
|
||||
*
|
||||
* OpenPICC - ISO 14443 Layer 2 Type A Sniffer
|
||||
* Also serves as PoC code for iso14443_layer2a usage
|
||||
*
|
||||
* 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; 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 <errno.h>
|
||||
|
||||
#include "openpicc.h"
|
||||
#include "iso14443_sniffer.h"
|
||||
#include "iso14443_layer2a.h"
|
||||
#include "iso14443a_miller.h"
|
||||
#include "usb_print.h"
|
||||
#include "cmd.h"
|
||||
|
||||
static iso14443_frame rx_frame;
|
||||
|
||||
void iso14443_sniffer (void *pvParameters)
|
||||
{
|
||||
(void)pvParameters;
|
||||
int res;
|
||||
|
||||
/* Delay until USB print etc. are ready */
|
||||
vTaskDelay(1000 * portTICK_RATE_MS);
|
||||
|
||||
do {
|
||||
res = iso14443_layer2a_init(0);
|
||||
if(res < 0) {
|
||||
usb_print_string("Sniffer: Initialization failed\n\r");
|
||||
vTaskDelay(10000 * portTICK_RATE_MS);
|
||||
}
|
||||
} while(res < 0);
|
||||
|
||||
usb_print_string("Waiting for carrier. ");
|
||||
while(iso14443_wait_for_carrier(1000 * portTICK_RATE_MS) != 0) {
|
||||
}
|
||||
usb_print_string("Carrier detected.\n\r");
|
||||
|
||||
iso14443_l2a_rx_start();
|
||||
while(true) {
|
||||
ssc_dma_rx_buffer_t *buffer = 0;
|
||||
res = iso14443_receive(NULL, &buffer, 20000 * portTICK_RATE_MS);
|
||||
if(res >= 0) {
|
||||
DumpStringToUSB("\n\r");
|
||||
DumpTimeToUSB(xTaskGetTickCount());
|
||||
usb_print_string(": Frame received, consists of ");
|
||||
DumpUIntToUSB(res);
|
||||
usb_print_string(" transfers (");
|
||||
DumpUIntToUSB(buffer->reception_mode->transfersize_ssc);
|
||||
usb_print_string(" bits from SSC each)\n\r ");
|
||||
if(buffer->len_transfers < 200)
|
||||
DumpBufferToUSB((char*)buffer->data, (buffer->len_transfers * buffer->reception_mode->transfersize_pdc)/8);
|
||||
else {
|
||||
DumpBufferToUSB((char*)buffer->data, (200 * buffer->reception_mode->transfersize_pdc)/8);
|
||||
usb_print_string("...");
|
||||
}
|
||||
usb_print_string("\n\r ");
|
||||
|
||||
iso14443a_decode_miller(&rx_frame, buffer);
|
||||
|
||||
usb_print_string("Decodes to ");
|
||||
DumpUIntToUSB(rx_frame.numbytes);
|
||||
usb_print_string(" bytes and ");
|
||||
DumpUIntToUSB(rx_frame.numbits);
|
||||
usb_print_string(" bits: ");
|
||||
DumpBufferToUSB((char*)rx_frame.data, rx_frame.numbytes + (rx_frame.numbits+7)/8 );
|
||||
usb_print_string("\n\r");
|
||||
|
||||
portENTER_CRITICAL();
|
||||
buffer->state = FREE;
|
||||
portEXIT_CRITICAL();
|
||||
} else {
|
||||
if(res != -ETIMEDOUT) {
|
||||
usb_print_string("Receive error: ");
|
||||
switch(res) {
|
||||
case -ENETDOWN: usb_print_string("PLL is not locked or PLL lock lost\n\r"); break;
|
||||
case -EBUSY: usb_print_string("A Tx is currently running or pending, can't receive\n\r"); break;
|
||||
case -EALREADY: usb_print_string("There's already an iso14443_receive() invocation running\n\r"); break;
|
||||
}
|
||||
vTaskDelay(1000 * portTICK_RATE_MS); // FIXME Proper error handling, e.g. wait for Tx end in case of EBUSY
|
||||
} else if(0) {
|
||||
DumpStringToUSB("\n\r");
|
||||
DumpTimeToUSB(xTaskGetTickCount());
|
||||
usb_print_string(": -- Mark --");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef ISO14443_SNIFFER_H_
|
||||
#define ISO14443_SNIFFER_H_
|
||||
|
||||
extern void iso14443_sniffer (void *pvParameters);
|
||||
|
||||
#endif /*ISO14443_SNIFFER_H_*/
|
|
@ -48,6 +48,7 @@
|
|||
#include "tc_fdt.h"
|
||||
#include "usb_print.h"
|
||||
#include "iso14443_layer3a.h"
|
||||
#include "iso14443_sniffer.h"
|
||||
#include "decoder.h"
|
||||
|
||||
/**********************************************************************/
|
||||
|
@ -173,7 +174,9 @@ int main (void)
|
|||
|
||||
/*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,
|
||||
/*xTaskCreate (iso14443_layer3a_state_machine, (signed portCHAR *) "ISO14443A-3", TASK_ISO_STACK,
|
||||
NULL, TASK_ISO_PRIORITY, NULL);*/
|
||||
xTaskCreate (iso14443_sniffer, (signed portCHAR *) "ISO14443-SNIFF", TASK_ISO_STACK,
|
||||
NULL, TASK_ISO_PRIORITY, NULL);
|
||||
|
||||
xTaskCreate (vUSBCDCTask, (signed portCHAR *) "USB", TASK_USB_STACK,
|
||||
|
|
|
@ -167,6 +167,7 @@ static int __ramfunc __ssc_rx_load(int secondary)
|
|||
* of some sort. However, instead of leaking buffers we'll just pretend it to
|
||||
* be free again. */
|
||||
ssc_buffer_errors++;
|
||||
usb_print_buffer_f("^", 0, 1, 0);
|
||||
if(ssc_state.buffer[secondary]->state == PENDING) {
|
||||
ssc_state.buffer[secondary]->state = FREE;
|
||||
}
|
||||
|
@ -260,6 +261,7 @@ static ssc_dma_rx_buffer_t* __ramfunc __ssc_rx_unload(int secondary)
|
|||
DumpUIntToUSB(elapsed_size); DumpStringToUSB(" "); DumpUIntToUSB((int)buffer->data); DumpStringToUSB(" ");
|
||||
usb_print_set_default_flush(i);
|
||||
ssc_buffer_errors++;
|
||||
usb_print_buffer_f("°", 0, 1, 0);
|
||||
if(buffer->state == PENDING) buffer->state = FREE;
|
||||
ssc_state.buffer[secondary] = NULL;
|
||||
return NULL;
|
||||
|
@ -370,7 +372,7 @@ void ssc_rx_mode_set(enum ssc_mode ssc_mode)
|
|||
//| AT91C_SSC_MSBF
|
||||
;
|
||||
ssc->SSC_RCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE |
|
||||
clock_gating | AT91C_SSC_CKI | start_cond | (stop << 12);
|
||||
clock_gating | (0&AT91C_SSC_CKI) | start_cond | (stop << 12);
|
||||
|
||||
/* Enable Rx DMA */
|
||||
AT91F_PDC_EnableRx(rx_pdc);
|
||||
|
@ -488,8 +490,6 @@ static void __ramfunc ssc_irq(void)
|
|||
|
||||
u_int32_t ssc_sr = ssc->SSC_SR;
|
||||
u_int32_t orig_ssc_sr = ssc_sr;
|
||||
int i, emptyframe = 0;
|
||||
u_int32_t *tmp;
|
||||
ssc_dma_rx_buffer_t *inbuf=NULL;
|
||||
DEBUGP("ssc_sr=0x%08x, mode=%u: ", ssc_sr, ssc_state.mode);
|
||||
|
||||
|
@ -499,7 +499,7 @@ static void __ramfunc ssc_irq(void)
|
|||
* irq is raised. (The scheduler masks interrupts for about 56us,
|
||||
* which is too much for anticollision.) */
|
||||
int i = 0;
|
||||
vLedBlinkRed();
|
||||
//vLedBlinkRed();
|
||||
while( ! ((ssc_sr=ssc->SSC_SR) & (AT91C_SSC_ENDRX | AT91C_SSC_CP1)) ) {
|
||||
i++;
|
||||
if(i > 9600) break; /* Break out, clearly this is not a short frame or a reception error happened */
|
||||
|
@ -508,55 +508,29 @@ static void __ramfunc ssc_irq(void)
|
|||
vLedSetRed(1);
|
||||
}
|
||||
|
||||
if(orig_ssc_sr & AT91C_SSC_CP1) {usb_print_string_f("oCP1 ", 0); vLedBlinkRed();}
|
||||
if(ssc_sr & AT91C_SSC_CP1) usb_print_string_f("CP1 ", 0);
|
||||
|
||||
if (ssc_sr & (AT91C_SSC_ENDRX | AT91C_SSC_CP1)) {
|
||||
#if 0
|
||||
// Bitrotten
|
||||
/* Ignore empty frames */
|
||||
if (ssc_state.mode == SSC_MODE_CONTINUOUS) {
|
||||
/* This code section is probably bitrotten by now. */
|
||||
tmp = (u_int32_t*)ssc_state.buffer[0]->data;
|
||||
emptyframe = 1;
|
||||
for(i = (ssc_state.buffer[0]->len) / 4 - 8/*WTF?*/; i > 0; i--) {
|
||||
if( *tmp++ != 0x0 ) {
|
||||
DEBUGPCR("NONEMPTY(%08x, %i): %08x", tmp, i, *(tmp-1));
|
||||
emptyframe = 0;
|
||||
break;
|
||||
} else {
|
||||
//DEBUGPCR("DUNNO(%08x, %i): %08x", tmp, i, tmp[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)i;
|
||||
(void)tmp;
|
||||
#endif
|
||||
//DEBUGP("Sending primary RCTX(%u, len=%u) ", req_ctx_num(ssc_state.rx_ctx[0]), ssc_state.rx_ctx[0]->tot_len);
|
||||
/* Mark primary RCTX as ready to send for usb */
|
||||
if(!emptyframe) {
|
||||
//unsigned int i;
|
||||
DEBUGP("NONEMPTY");
|
||||
//gaportENTER_CRITICAL();
|
||||
ssc_state.buffer[0]->state = FULL;
|
||||
//gaportEXIT_CRITICAL();
|
||||
task_woken = xQueueSendFromISR(ssc_rx_queue, &ssc_state.buffer[0], task_woken);
|
||||
} else {
|
||||
DEBUGP("EMPTY");
|
||||
//gaportENTER_CRITICAL();
|
||||
ssc_state.buffer[0]->state = FREE;
|
||||
//gaportEXIT_CRITICAL();
|
||||
}
|
||||
vLedSetGreen(1);
|
||||
|
||||
inbuf = ssc_state.buffer[0];
|
||||
if(ssc_sr & AT91C_SSC_CP1 && !(ssc_sr & AT91C_SSC_ENDRX)) {
|
||||
/* Manually unload buffer 0, since only the SSC has stopped, not the PDC */
|
||||
__ssc_rx_unload(0);
|
||||
__ssc_rx_load(0);
|
||||
}
|
||||
|
||||
inbuf->state = FULL;
|
||||
task_woken = xQueueSendFromISR(ssc_rx_queue, &inbuf, task_woken);
|
||||
vLedSetGreen(1);
|
||||
|
||||
if(ssc_sr & AT91C_SSC_ENDRX) {
|
||||
/* second buffer gets propagated to primary */
|
||||
/* second buffer got propagated to primary */
|
||||
ssc_state.buffer[0] = ssc_state.buffer[1];
|
||||
ssc_state.buffer[1] = NULL;
|
||||
}
|
||||
|
||||
if(ssc_state.mode == SSC_MODE_EDGE_ONE_SHOT || ssc_state.mode == SSC_MODE_14443A_SHORT
|
||||
|| ssc_state.mode == SSC_MODE_14443A_STANDARD || (ssc_state.mode == SSC_MODE_14443A && ssc_sr & AT91C_SSC_CP1)) {
|
||||
|| ssc_state.mode == SSC_MODE_14443A_STANDARD) {
|
||||
// Stop sampling here
|
||||
ssc_rx_stop();
|
||||
} else {
|
||||
|
@ -576,7 +550,7 @@ static void __ramfunc ssc_irq(void)
|
|||
AT91C_SSC_OVRUN);
|
||||
}
|
||||
|
||||
if(ssc_sr & AT91C_SSC_RXENA) if (__ssc_rx_load(1) == -1)
|
||||
if(ssc_sr & AT91C_SSC_RXENA && ssc_state.buffer[1] == NULL) if (__ssc_rx_load(1) == -1)
|
||||
AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX |
|
||||
AT91C_SSC_RXBUFF |
|
||||
AT91C_SSC_OVRUN);
|
||||
|
|
Loading…
Reference in New Issue