From e22f23efcbe54ab8aabfd54f8b55a5d01a15a487 Mon Sep 17 00:00:00 2001 From: henryk Date: Mon, 3 Dec 2007 04:55:57 +0000 Subject: * Reduce leaking of TX buffers * Found the problem that when switching between receiving and sending tc_cdiv would most of the time not generate an SSC_CLOCK for approx. 5ms: The issue is that after setting the divisor (which stored in RC) CV might be greater than RC. Thus no compare will happen until CV overflows (at 0xffff carrier cycles) and therefore the clock will appear to be stopped for that time. A good fix would have been TC_CV = TC_CV % TC_RC but unfortunately TC_CV is read-only. Instead use SWTRG to reset TC_CV to zero and then try to use the phase-shift code to have the phase stay correct. * Measured the transmit start delay that is introduced by the SSC TF emulation through FIQ and adjusted ISO14443A_FDT accordingly git-svn-id: https://svn.openpcd.org:2342/trunk@366 6dc7ffe9-61d6-0310-9af1-9938baff3ed1 --- openpicc/application/iso14443_layer3a.h | 6 ++++-- openpicc/application/ssc_picc.c | 12 +++++++++++- openpicc/application/tc_cdiv.c | 4 ++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/openpicc/application/iso14443_layer3a.h b/openpicc/application/iso14443_layer3a.h index 142128e..d398d1f 100644 --- a/openpicc/application/iso14443_layer3a.h +++ b/openpicc/application/iso14443_layer3a.h @@ -16,9 +16,11 @@ enum ISO14443_STATES { }; /******************** RX ************************************/ +/* measured TF->FIQ->SSC TX start delay (~3.480us) in carrier cycles */ +#define TF_FIQ_SSC_DELAY 47 /* standard derived magic values */ -#define ISO14443A_FDT_SHORT_1 1236 -#define ISO14443A_FDT_SHORT_0 1172 +#define ISO14443A_FDT_SHORT_1 (1236-TF_FIQ_SSC_DELAY) +#define ISO14443A_FDT_SHORT_0 (1172-TF_FIQ_SSC_DELAY) #ifdef FOUR_TIMES_OVERSAMPLING /* definitions for four-times oversampling */ diff --git a/openpicc/application/ssc_picc.c b/openpicc/application/ssc_picc.c index a5f1075..02d87d1 100644 --- a/openpicc/application/ssc_picc.c +++ b/openpicc/application/ssc_picc.c @@ -205,6 +205,7 @@ void ssc_tx_start(ssc_dma_tx_buffer_t *buf) ssc->SSC_TCMR = 0x01 | AT91C_SSC_CKO_NONE | start_cond; AT91F_PDC_SetTx(tx_pdc, buf->data, num_data); + buf->state = PENDING; #ifdef TEST_WHETHER_NOT_ENABLING_IT_HELPS AT91F_SSC_EnableIt(ssc, AT91C_SSC_TXSYN | AT91C_SSC_ENDTX | AT91C_SSC_TXBUFE); @@ -227,6 +228,7 @@ void ssc_tx_start(ssc_dma_tx_buffer_t *buf) #ifdef USE_SSC_TX_TF_WORKAROUND void ssc_tf_irq(u_int32_t pio) { (void)pio; + if(!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, OPENPICC_SSC_TF)) return; pio_irq_disable(OPENPICC_SSC_TF); if(ssc_tx_pending) { /* Transmit has not yet been started by the FIQ */ AT91F_SSC_EnableTx(AT91C_BASE_SSC); @@ -397,7 +399,15 @@ static void __ramfunc ssc_irq(void) DEBUGP("CP0 "); if (ssc_sr & AT91C_SSC_TXSYN) - usb_print_string_f("TXSYN ", 0); + DEBUGP("TXSYN "); + + if(ssc_sr & AT91C_SSC_ENDTX) { + if(ssc_tx_buffer.state == PENDING) + ssc_tx_buffer.state = FREE; + } + + if(ssc_sr & AT91C_SSC_TXBUFE) + DEBUGP("TXBUFE "); if(irq_extension != NULL) irq_extension(ssc_sr, ssc_state.mode, inbuf?inbuf->data:NULL); diff --git a/openpicc/application/tc_cdiv.c b/openpicc/application/tc_cdiv.c index 638586d..3bbfe77 100644 --- a/openpicc/application/tc_cdiv.c +++ b/openpicc/application/tc_cdiv.c @@ -38,6 +38,10 @@ void tc_cdiv_set_divider(u_int16_t div) /* set to 50% duty cycle */ tcb->TCB_TC0.TC_RA = 1; tcb->TCB_TC0.TC_RB = 1 + (div >> 1); + + /* Save current CV as phase, then reset to 0 (might otherwise be greater than RC) */ + tc_cdiv_phase_add(tcb->TCB_TC0.TC_RC-(tcb->TCB_TC0.TC_CV%tcb->TCB_TC0.TC_RC)); + tcb->TCB_TC0.TC_CCR = AT91C_TC_SWTRG; } void tc_cdiv_phase_add(int16_t inc) -- cgit v1.2.3