Files
fromost 86373a2d33 Add read/write for felica
felica types refactor
2026-08-27 10:02:50 +08:00

16 KiB
Raw Permalink Blame History

PN532 — Byte-Level Communication Protocol

The PN532 is a "dumb" NFC front-end: the host drives it by writing command frames and reading back response frames. This document describes those bytes — the framing, checksums, acknowledgements, error codes and command set — independent of the physical transport (HSU/UART, I²C or SPI). The transport only changes how the bytes are clocked in/out; the frame content is identical everywhere.

Sources: NXP PN532 User Manual UM0701-02 (the host protocol) and NXP PN532_C1.pdf (the datasheet, for transport framing and the low-level CIU command set).


1. The Information Frame

Every command and every response is one information frame of bytes:

| Preamble | Start code | LEN | LCS | TFI | DATA ... | DCS | Postamble |
|    00    |   00 FF    |     |     |     |          |     |     00    |
Field Size Value / meaning
Preamble 1 0x00 (see §1.4 for length rules)
Start code 2 0x00 0xFF
LEN 1 Length of the data field = 1 (TFI) + N (payload bytes). 0x01..0xFF.
LCS 1 Length Checksum — (0x100 LEN) & 0xFF, i.e. LEN + LCS == 0 (mod 256).
TFI 1 Frame identifier: 0xD4 host→PN532, 0xD5 PN532→host.
DATA N Command code (PD0) followed by parameters (PD1…PDn).
DCS 1 Data Checksum — (0x100 (TFI + Σ DATA)) & 0xFF, i.e. TFI + Σ DATA + DCS == 0 (mod 256).
Postamble 1 0x00 (see §1.4)

Checksums in one line (two's complement):

LCS = (!LEN) + 1
DCS = (!(TFI + DATA0 + DATA1 + ...)) + 1

A frame is rejected (no ACK is returned) if LEN + LCS != 0 or the data checksum does not sum to zero.

1.1 Extended information frame (payload > 255 bytes)

The firmware supports up to 264 data bytes (265 including TFI). Beyond the normal frame's 255-byte limit it uses an extended frame:

00 00 FF FF FF LENM LENL LCS TFI PD0 ... PDn DCS 00
          └─┬─┘ └──┬──┘  │
     LEN = FF   LCS = FF │  ← both fixed to 0xFF (normally an "error" LEN/LCS pair)
                         LCS  ← lower byte of [LENM + LENL + LCS] = 0x00
  • LEN and LCS are fixed to 0xFF.
  • Real length: LENGTH = LENM × 256 + LENL = number of bytes in TFI + payload.
  • LCS satisfies LENM + LENL + LCS == 0 (mod 256).
  • The host may use the extended frame for short frames too; the PN532 always picks the right form (normal ≤ 255, extended > 255).

1.2 Frame Identifier (TFI)

TFI Direction
0xD4 Host → PN532
0xD5 PN532 → Host
0x7F Error frame (PN532 → host, §2)

1.3 Response command byte

The response echoes the command code + 1:

Command (host→PN532) Response (PN532→host)
GetFirmwareVersion 0x02 0x03
SAMConfiguration 0x14 0x15
InListPassiveTarget 0x4A 0x4B
InDataExchange 0x40 0x41
command + 1

1.4 Preamble / Postamble length rules

They are not always a single 0x00 byte:

  • Host → PN532 (HSU and I²C): preamble and postamble may be 0..n bytes; the value has no impact on frame processing. The PN532 only synchronises on the 0x00 0xFF start code.
  • Host → PN532 (SPI): preamble and postamble must be exactly one 0x00 byte.
  • PN532 → Host: always a single 0x00 byte. This can be disabled entirely with SetParameters flag fRemovePrePostAmble (bit 6) to save 2 bytes per frame.

2. Acknowledge / NACK / Error Frames

ACK  : 00 00 FF 00 FF 00          ← PN532 ↔ host: "frame received OK"
NACK : 00 00 FF FF 00 00          ← host → PN532 only: "resend your last response"
Error: 00 00 FF 01 FF 7F 81 00    ← PN532 → host: "syntax error at application level"
  • The ACK has two roles: acknowledging a received frame, and (when sent by the host during command processing) aborting the current process.
  • The NACK is used only by the host, to ask the PN532 to retransmit its last response (after a corrupt/absent response). The PN532 never sends NACK — it just stays silent on a data-link error.
  • The Error frame is returned when the PN532 sees an unknown command code or incorrect parameters in an otherwise valid frame.

2.1 Dialog structure

The host is always the master:

host ── command frame ──▶ PN532
host ◀── ACK ──────────── PN532      (must arrive within 15 ms; else host resends)
            ... PN532 executes ...
host ◀── response frame ─ PN532
host ── (optional ACK) ─▶ PN532
  • 15 ms rule (HSU): the ACK must follow the command within 15 ms. If the host sees no ACK, it resends the command.
  • Abort: a new command, or a bare ACK, aborts the current process; the PN532 then answers only the last command received.
  • Data-link errors that silence the PN532: LCS error, DCS error, framing error (HSU stop bit = 0), HSU timeout (frame not fully received within ~4× a 256-byte frame; e.g. 89 ms at 115200 baud, 44 ms at 230400, 8 ms at 1.288 M).

3. Status Byte and Error Codes

RF commands (InDataExchange, TgGetData, InListPassiveTarget, …) return a status byte as the first payload byte:

  7          6       5 .. 0
NADPresent  MI     Error code
  • bit 7 NADPresent — payload contains a NAD byte (DEP / ISO14443-4 PCD).
  • bit 6 MI — More Information (chaining) in progress.
  • bits 05 — error code (0x00 = success).

Error code list:

Code Cause
0x00 OK
0x01 Time out — target did not answer
0x02 CRC error detected by the CIU
0x03 Parity error detected by the CIU
0x04 Erroneous bit count during anticollision (14443-3 Type A / 18092 106 k)
0x05 Framing error during MIFARE operation
0x06 Abnormal bit-collision during bitwise anticollision at 106 k
0x07 Communication buffer size insufficient
0x09 RF buffer overflow (CIU_Error BufferOvfl)
0x0A RF field not switched on in time by counterpart (active mode)
0x0B RF protocol error
0x0D Temperature error — antenna drivers switched off
0x0E Internal buffer overflow
0x10 Invalid parameter (range / format)
0x12 DEP: unsupported command received from initiator
0x13 DEP / MIFARE / 14443-4: data format does not match spec
0x14 MIFARE: authentication error
0x23 ISO14443-3: UID check byte wrong
0x25 DEP: invalid device state
0x26 Operation not allowed in this configuration
0x27 Command not acceptable in current context (unknown target number, …)
0x29 Target released by its initiator
0x2A 14443-3B: card ID mismatch (wrong card)
0x2B 14443-3B: previously activated card disappeared
0x2C NFCID3 mismatch (initiator vs target) in DEP 212/424 passive
0x2D Over-current detected
0x2E NAD missing in DEP frame

4. Transport-Specific Bytes

4.1 HSU / UART

  • Full-duplex, up to 1.288 Mbaud (default 115200), 8 data bits, LSB first, 1 stop bit.
  • Frames are sent as-is (see §1), preamble/postamble may be 0..n bytes.
  • Hardware preamble filter strips 00 00 FF from incoming frames.

4.2 I²C

  • Address: 7-bit 0x24; 8-bit write 0x48, read 0x49 (SLV+W = 0x48, SLV+R = 0x49).

  • Fast mode up to 400 kHz.

  • The frame is "slightly modified": on reads, a status byte is prepended. On writes (commands) the frame is written verbatim (no status byte).

    RDY status byte:  bit 0 = RDY  (bits 7..1 reserved)
                      RDY = 0 → no frame available
                      RDY = 1 → frame follows
    

    Read sequence: START → read 1 status byte → if RDY == 0, STOP and retry; if RDY == 1, keep reading the whole frame before STOP. A STOP before the full frame discards the remaining bytes.

    RDY ... RDY RDY frame
    

4.3 SPI

  • Slave, SCK up to 5 MHz.

  • Every transfer starts with a direction byte (2 LSBs):

    First byte Operation
    xxxx xx01 (0x01) Data write (host → PN532)
    xxxx xx10 (0x02) Status read (PN532 → host)
    xxxx xx11 (0x03) Data read (PN532 → host)
  • Status register (1 byte): bit 0 = RDY. Poll 0x02 until RDY == 1, then read with 0x03.

  • SPI preamble/postamble must be exactly one 0x00 byte.

  • Optionally use the P70_IRQ pin (handshake) to skip status polling.


5. Host Command Set

Each command is the first payload byte (PD0) after the 0xD4 TFI. In = initiator, Tg = target.

Command Code Parameters
Diagnose 0x00 NumTst (1), [InParam…]
GetFirmwareVersion 0x02
GetGeneralStatus 0x04
ReadRegister 0x06 Address (2, big-endian)
WriteRegister 0x08 Address (2) + Value (1…n)
ReadGPIO 0x0C
WriteGPIO 0x0E P3, P7
SetSerialBaudRate 0x10 Baud rate (1)
SetParameters 0x12 Flags (1)
SAMConfiguration 0x14 Mode (1), Timeout (1), [IRQ (1)]
PowerDown 0x16 WakeUpEnable (1), GenerateIRQ (1)
RFConfiguration 0x32 CfgItem (1), …
RFRegulationTest 0x58 TxMode (1)
InJumpForPSL 0x46 ActPSL (1), …
InJumpForDEP 0x56 ActPass (1), …
InListPassiveTarget 0x4A MaxTg (1), BrTy (1), [InitiatorData]
InATR 0x50
InPSL 0x4E Tg (1)
InDataExchange 0x40 Tg (1), [DataOut…]
InCommunicateThru 0x42 DataOut…
InDeselect 0x44 Tg (1)
InRelease 0x52 Tg (1)
InSelect 0x54 Tg (1)
InAutoPoll 0x60 PollNr (1), …
TgInitAsTarget 0x8C Mode (1), …
TgGetData 0x86
TgSetData 0x8E DataIn…
TgGetInitiatorCommand 0x88
TgResponseToInitiator 0x90 Data…
TgGetTargetStatus 0x8A
TgSetGeneralBytes 0x92 Data…
TgSetMetaData 0x94 Data…

6. Worked Examples

6.1 GetFirmwareVersion (0x02)

Request:

00 00 FF 02 FE D4 02 2A 00
└─preamble+start─┘ │  │  │  │  └ postamble
     LEN=02 ───────┘  │  │  └ DCS=0x2A
     LCS=FE ──────────┘  └ command 0x02
     TFI=0xD4 ───────────┘

Response (IC=0x32 PN532, firmware 1.6, rev 0x06, support 0x07):

00 00 FF 06 FA D5 03 32 01 06 07 E8 00
                │  │  │  │  │  │  └ DCS
                │  │  │  │  │  └ support (0x07)
                │  │  │  │  └ rev
                │  │  │  └ firmware version (0x01 = 1.6)
                │  │  └ IC = 0x32 (PN532)
                │  └ cmd+1 = 0x03
                └ TFI = 0xD5

support bitmask: 0x01 ISO/IEC 14443A, 0x02 ISO/IEC 14443B, 0x04 ISO/IEC 18092 (NFCIP-1).

6.2 SAMConfiguration (0x14)

Params: Mode=0x01 (normal), Timeout=0x14 (20 × 50 ms = 1 s), IRQ=0x01 (drive P70_IRQ).

00 00 FF 05 FB D4 14 01 14 01 02 00
                │  │  │  │  │  └ DCS
                │  │  │  └ IRQ
                │  │  └ Timeout (LSB 50 ms; 0x00 = no timeout)
                │  └ Mode (0x01 normal, 0x02 virtual card, 0x03 wired card, 0x04 dual card)
                └ command 0x14

Response:

00 00 FF 02 FE D5 15 16 00

6.3 InListPassiveTarget (0x4A)

Params: MaxTg=0x01, BrTy=0x00 (106 kbps ISO/IEC 14443A):

00 00 FF 04 FC D4 4A 01 00 E1 00
                │  │  │  └ BrTy (0x00 A, 0x01/0x02 FeliCa 212/424, 0x03 B, 0x04 Jewel)
                │  │  └ MaxTg (max 2)
                │  └ command 0x4A

Response (0x4B) for a MIFARE card with 4-byte UID DE AD BE EF:

00 00 FF 0C F4 D5 4B 01 01 04 00 08 04 DE AD BE EF 96 00
                │  │  │  │  │  │  │  │  └── NFCID1 ──┘  └ DCS
                │  │  │  │  │  │  │  └ NFCID length (4)
                │  │  │  │  │  │  └ SEL_RES
                │  │  │  │  └── SENS_RES (04 00)
                │  │  └ target number (Tg = 0x01)
                │  └ NbTg = 0x01
                └ TFI 0xD5

6.4 InDataExchange (0x40)

Params: Tg=0x01, then the raw card command — MIFARE Classic READ block 4 (0x30 0x04):

00 00 FF 05 FB D4 40 01 30 04 B7 00
                │  │  │  └─────┘ └ DCS
                │  │  └ MIFARE READ (0x30) block 04
                │  └ target Tg = 0x01  (bit 6 = MI for DEP chaining)
                └ command 0x40

Success response (0x41): Status=0x00, then 16 data bytes (00..0F):

00 00 FF 13 ED D5 41 00 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 72 00
                │  │  └ status 0x00 = success
                │  └ cmd+1 = 0x41
                └ TFI 0xD5

6.5 ReadRegister (0x06)

Params: register address (2 bytes, big-endian). Reading CIU_RxSel (0x6307):

00 00 FF 04 FC D4 06 63 07 BC 00

Response (0x07) with value 0x84:

00 00 FF 03 FD D5 07 84 A0 00

7. MIFARE / ISO/IEC 14443A Card Bytes

These are the payload bytes passed inside InDataExchange / InCommunicateThru.

Operation Card command
Authenticate key A / B 0x60 / 0x61 + block + UID + key (6)
Read block 0x30 + block
Write block 0xA0 + block + 16 data bytes
Write (Ultralight) 0xA2 + page + 4 data bytes
Transfer (write commit) 0xB0 + block
Decrement 0xC0 + block + 4-byte value
Increment 0xC1 + block + 4-byte value
Restore 0xC2 + block

FeliCa payload codes: Polling 0x00, Request Service 0x02, Request Response 0x04, Read Without Encryption 0x06, Write Without Encryption 0x08, Request System Code 0x0C.


8. SetParameters (0x12) flags

D4 12 Flags
Bit Flag Meaning
0 fNADUsed Use NAD in DEP / 14443-4 PCD
1 fDIDUsed Use DID (DEP) / CID (14443-4 PCD)
2 fAutomaticATR_RES Auto-generate ATR_RES in target mode
4 fAutomaticRATS Auto-send RATS after selecting 14443-4 card
5 fISO14443-4_PICC Emulate ISO14443-4 PICC
6 fRemovePrePostAmble Omit preamble + postamble in frames sent to host

9. CIU Command Set (low-level, from datasheet §8.6.20)

The firmware drives a Contactless Interface Unit (CIU) whose commands live in the CIU_Command register. These are not host commands — they surface only via WriteRegister/ReadRegister. Listed for completeness:

Command Code Action
Idle 0000 No action; cancel current command
Config 0001 Configure CIU for FeliCa / MIFARE / NFCIP-1
GenerateRandomID 0010 Generate 10-byte random ID
CalcCRC 0011 Run CRC coprocessor (or self-test)
Transmit 0100 Transmit data from FIFO
NoCmdChange 0111 Modify CIU_Command bits without changing command
Receive 1000 Activate receiver
SelfTest 1001 Activate self-test
Transceive 1100 Transmit then auto-receive (initiator) or vice-versa
AutoColl 1101 FeliCa polling / MIFARE anticollision (card mode)
MFAuthent 1110 MIFARE Classic authentication
SoftReset 1111 Reset the CIU

10. Minimum Startup Sequence

  1. Reset — pulse RSTPD_N (high → low → wait ~400 ms → high), let the PN532 boot.
  2. GetFirmwareVersion (0x02) — sanity-check the link and chip.
  3. SAMConfiguration (0x14, mode 0x01) — enable the SAM in normal (reader) mode; required before any RF command.
  4. Poll with InListPassiveTarget (0x4A), then transact with InDataExchange (0x40).