diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index d1692e2ac..8d2bdd1ba 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -314,6 +314,14 @@ uint32_t iso14a_get_timeout(void) { return iso14a_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 128 - 2; } +void iso14a_rebase_transfer_time(void) { + // NextTransferTime is expressed in absolute SSP-clock counts. A caller + // that restarts StartCountSspClk() resets that counter to zero; retaining + // the old value would make ReaderTransmit() wait for stale time from the + // preceding APDU. Do not reset PCB or ATS state here. + NextTransferTime = 2 * DELAY_ARM2AIR_AS_READER; +} + //----------------------------------------------------------------------------- // Generate the parity value for a byte sequence //----------------------------------------------------------------------------- diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 1f39be439..575a23184 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -129,6 +129,9 @@ void setHf14aConfig(const hf14a_config_t *hc); hf14a_config_t *getHf14aConfig(void); void iso14a_set_timeout(uint32_t timeout); uint32_t iso14a_get_timeout(void); +// Rebase the absolute reader-transfer schedule after a caller restarts the +// SSP clock counter. This preserves the active ISO14443-4 session. +void iso14a_rebase_transfer_time(void); void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); diff --git a/armsrc/sam_sc.c b/armsrc/sam_sc.c index 5bcd88395..cf7e7b73c 100644 --- a/armsrc/sam_sc.c +++ b/armsrc/sam_sc.c @@ -366,6 +366,12 @@ static int sam_sc_card_api_loop(uint8_t *response, uint16_t *response_len, } if (iso14a) { switch_clock_to_countsspclk(); + // This counter is reset for the RF exchange so the SAM + // path can return to millisecond ticks afterwards. Keep + // ISO14443A's absolute transfer scheduler in the same + // time base; otherwise it waits on a stale timestamp + // from the preceding Card-API APDU. + iso14a_rebase_transfer_time(); int apdu_len = iso14_apdu((uint8_t *)op_value, op_len, false, nfc_rx, sizeof(nfc_rx), NULL); switch_clock_to_ticks();