fix(nfc): separate ATS transmit and receive

This commit is contained in:
chenjintao
2026-09-22 15:53:06 +08:00
parent 768ad0e47f
commit 14c0065bb1
@@ -45,19 +45,27 @@ static volatile int g_nfc_irq_trigger = 0;
#if (NFC_WORK_MODE == NFC_WORK_MODE_CARD_EMULATION) #if (NFC_WORK_MODE == NFC_WORK_MODE_CARD_EMULATION)
#define NFC_CARD_FRAME_MAX 64 #define NFC_CARD_FRAME_MAX 64
#define NFC_CARD_SESSION_POLLS 200 #define NFC_CARD_TX_POLLS 20
#define NFC_CARD_RX_POLLS 200
#define NFC_CARD_SESSION_POLL_MS 1 #define NFC_CARD_SESSION_POLL_MS 1
#define NFC_IRQ_TX 0x40
#define NFC_IRQ_RX 0x20
#define NFC_IRQ_ERR 0x02
static void nfc_card_emulation_log_status(const char *reason) static void nfc_card_emulation_log_status(const char *reason)
{ {
printf("NFC card emulation %s: cmd=%02X irq=%02X err=%02X status1=%02X status2=%02X fifo=%02X\r\n", printf("NFC card emulation %s: cmd=%02X irq=%02X err=%02X status1=%02X status2=%02X fifo=%02X txm=%02X rxm=%02X framing=%02X\r\n",
reason, reason,
DP1312EA_ReadRawRC(CommandReg), DP1312EA_ReadRawRC(CommandReg),
DP1312EA_ReadRawRC(ComIrqReg), DP1312EA_ReadRawRC(ComIrqReg),
DP1312EA_ReadRawRC(ErrorReg), DP1312EA_ReadRawRC(ErrorReg),
DP1312EA_ReadRawRC(Status1Reg), DP1312EA_ReadRawRC(Status1Reg),
DP1312EA_ReadRawRC(Status2Reg), DP1312EA_ReadRawRC(Status2Reg),
DP1312EA_ReadRawRC(FIFOLevelReg)); DP1312EA_ReadRawRC(FIFOLevelReg),
DP1312EA_ReadRawRC(TxModeReg),
DP1312EA_ReadRawRC(RxModeReg),
DP1312EA_ReadRawRC(BitFramingReg));
} }
static u8 nfc_card_emulation_read_frame(u8 *frame, u8 capacity) static u8 nfc_card_emulation_read_frame(u8 *frame, u8 capacity)
@@ -94,16 +102,46 @@ static void nfc_card_emulation_log_frame(const char *prefix,
printf("\r\n"); printf("\r\n");
} }
static void nfc_card_emulation_send_frame(const u8 *frame, u8 length) static u8 nfc_card_emulation_send_frame(const u8 *frame, u8 length)
{ {
u16 poll_count;
u8 irq;
/* Stop the AutoColl-created Transceive before starting a clean TX. */
DP1312EA_WriteRawRC(CommandReg, DP1312EA_IDLE);
DP1312EA_WriteRawRC(ComIrqReg, 0x7F); DP1312EA_WriteRawRC(ComIrqReg, 0x7F);
DP1312EA_SetBitMask(FIFOLevelReg, 0x80); DP1312EA_SetBitMask(FIFOLevelReg, 0x80);
DP1312EA_WriteFIFO((u8 *)frame, length);
/* AutoColl leaves Transceive active and waiting for StartSend. */
DP1312EA_SetBitMask(TxModeReg, 0x80); DP1312EA_SetBitMask(TxModeReg, 0x80);
DP1312EA_SetBitMask(RxModeReg, 0x80); DP1312EA_SetBitMask(RxModeReg, 0x80);
DP1312EA_WriteRawRC(BitFramingReg, 0x80); DP1312EA_WriteRawRC(BitFramingReg, 0x00);
DP1312EA_WriteFIFO((u8 *)frame, length);
DP1312EA_WriteRawRC(CommandReg, DP1312EA_TRANSMIT);
DP1312EA_SetBitMask(BitFramingReg, 0x80);
for (poll_count = 0; poll_count < NFC_CARD_TX_POLLS; poll_count++) {
irq = DP1312EA_ReadRawRC(ComIrqReg);
if ((irq & NFC_IRQ_TX) != 0) {
DP1312EA_WriteRawRC(BitFramingReg, 0x00);
return 1;
}
if ((irq & NFC_IRQ_ERR) != 0) {
break;
}
ql_rtos_task_sleep_ms(NFC_CARD_SESSION_POLL_MS);
}
DP1312EA_WriteRawRC(BitFramingReg, 0x00);
nfc_card_emulation_log_status("ATS transmit failed");
return 0;
}
static void nfc_card_emulation_start_receive(void)
{
DP1312EA_WriteRawRC(CommandReg, DP1312EA_IDLE);
DP1312EA_WriteRawRC(ComIrqReg, 0x7F);
DP1312EA_SetBitMask(FIFOLevelReg, 0x80);
DP1312EA_WriteRawRC(BitFramingReg, 0x00);
DP1312EA_WriteRawRC(CommandReg, DP1312EA_RECEIVE);
} }
static void nfc_card_emulation_configure_iso_dep(void) static void nfc_card_emulation_configure_iso_dep(void)
@@ -166,21 +204,28 @@ static void nfc_card_emulation_task(void)
nfc_card_emulation_log_frame("activation RX", frame, frame_len); nfc_card_emulation_log_frame("activation RX", frame, frame_len);
if (frame_len == 2 && frame[0] == 0xE0) { if (frame_len == 2 && frame[0] == 0xE0) {
nfc_card_emulation_send_frame(ats, sizeof(ats)); if (!nfc_card_emulation_send_frame(ats, sizeof(ats))) {
nfc_card_emulation_log_frame("ATS TX", ats, sizeof(ats)); nfc_card_emulation_log_status("session complete");
nfc_card_emulation_start();
last_command = DP1312EA_AUTOCOLL;
ql_rtos_task_sleep_ms(1);
continue;
}
nfc_card_emulation_log_frame("ATS TX complete", ats,
sizeof(ats));
nfc_card_emulation_start_receive();
for (poll_count = 0; for (poll_count = 0;
poll_count < NFC_CARD_SESSION_POLLS; poll_count < NFC_CARD_RX_POLLS;
poll_count++) { poll_count++) {
u8 irq = DP1312EA_ReadRawRC(ComIrqReg); u8 irq = DP1312EA_ReadRawRC(ComIrqReg);
u8 error = DP1312EA_ReadRawRC(ErrorReg);
if (error != 0) { if ((irq & NFC_IRQ_ERR) != 0) {
nfc_card_emulation_log_status("ISO-DEP error"); nfc_card_emulation_log_status("ISO-DEP receive error");
break; break;
} }
if ((irq & 0x20) != 0 && if ((irq & NFC_IRQ_RX) != 0 &&
(DP1312EA_ReadRawRC(FIFOLevelReg) & 0x7F) != 0) { (DP1312EA_ReadRawRC(FIFOLevelReg) & 0x7F) != 0) {
frame_len = nfc_card_emulation_read_frame( frame_len = nfc_card_emulation_read_frame(
frame, sizeof(frame)); frame, sizeof(frame));
@@ -191,6 +236,10 @@ static void nfc_card_emulation_task(void)
ql_rtos_task_sleep_ms(NFC_CARD_SESSION_POLL_MS); ql_rtos_task_sleep_ms(NFC_CARD_SESSION_POLL_MS);
} }
if (poll_count == NFC_CARD_RX_POLLS) {
nfc_card_emulation_log_status("ISO-DEP receive timeout");
}
} else { } else {
printf("NFC activation frame is not RATS\r\n"); printf("NFC activation frame is not RATS\r\n");
} }