MFRC522 Driver

Driver for the MFRC522 module.

This is a driver for the MFRC522 Mifare and NTAG frontend. It supports the MFRC522 chip connected over various interfaces. It exports an Pcd object for use by other layers.

Note: This driver requires the EXT driver to be enabled and configured with non-const EXTConfig strcture (as opposed to one documented by function extStart)!

This driver invokes the extSetChannelMode function, see its docs for explanation.

Defines

MFRC522_USE_SPI

Enables SPI support.

Note
Disabling this option saves both code and data space.

MFRC522_USE_I2C

Enables I2C support.

Note
Disabling this option saves both code and data space.

MFRC522_USE_UART

Enables UART support.

Note
Disabling this option saves both code and data space.

MFRC522_MAX_DEVICES

Maximum number of simultaneously active devices this driver should handle.

Note
Lowering this value saves data space and increases driver performance.

Functions

void mfrc522Init(void)

Initializes the MFRC522 driver.

Note
This function is called implicitly by halCustomInit, no need to call it explicitly.

void mfrc522ObjectInitSPI(Mfrc522Driver *mdp, SPIDriver *spip)

Initializes the driver object for a MFRC522 module connected over the SPI.

Parameters
  • mdp: Uninitialized driver object.
  • spip: Initialized and started SPI driver object.

void mfrc522ObjectInitI2C(Mfrc522Driver *mdp, I2CDriver *i2cp)

Initializes the driver object for a MFRC522 module connected over the I2C.

Note
Not yet implemented!
Parameters
  • mdp: Uninitialized driver object.
  • i2cp: Initialized and started I2C driver object

void mfrc522ObjectInitSerial(Mfrc522Driver *mdp, SerialDriver *sdp)

Initializes the driver object for a MFRC522 module connected over the Serial.

Note
Not yet implemented!
Parameters
  • mdp: Uninitialized driver object.
  • sdp: Initialized and started Serial driver object

void mfrc522Start(Mfrc522Driver *mdp, const Mfrc522Config *config)

Starts the MFRC522 module.

This function powers up, soft-resets the MFRC522 module, initializes, configures it and register is for use with this driver. It also reconfigures the provided Ext driver and register its own interrupt handler to handle interrupts on channel config->interrupt_channel.

Parameters
  • mdp: Initialized driver object
  • config: Configuration to apply

void mfrc522Reconfig(Mfrc522Driver *mdp, const Mfrc522Config *config)

Reconfigures the MFRC522 module without resetting it.

This function reprograms control registers of the MFRC522 module without resetting it, which is useful for hot-swapping MFRC522-specific config options during the module run-time.

This function won’t reconfig the following options:

  • EXTDriver *extp
  • expchannel_t interrupt_channel
  • void *reset_line

The only way to change these is to stop and restart the module.

Parameters
  • mdp: Started driver object
  • config: Configuration to apply

void mfrc522Stop(Mfrc522Driver *mdp)

Stops the MFRC522 module.

Unregisters this module from this driver and powers it down.

Parameters
  • mdp: Started driver object

struct Mfrc522Config
#include <hal_mfrc522.h>

Config options for the MFRC522 module.

In order for the driver to function properly you have to specify:

  • EXTDriver *extp
  • expchannel_t interrupt_channel
  • void *reset_line

Rest of these options are intended for advanced configuration of the module if you have special needs, otherwise default values are just fine.

If you need to modify something consult the MFRC522 Datasheet.

Public Types

enum driver_input_select_t

Selects the input of drivers TX1 and TX2.

Default: MFRC522_DRSEL_MPE

MFRC522 Datasheet page 51

Values:

MFRC522_DRSEL_3STATE = 0b00

3-state mode during soft powerdown

MFRC522_DRSEL_MPE = 0b01

modulation signal (envelope) from the internal encoder, Miller pulse encoded

MFRC522_DRSEL_MFIN = 0b10

modulation signal (envelope) from pin MFIN

MFRC522_DRSEL_HIGH = 0b11

HIGH; the HIGH level depends on the setting of bits InvTx1RFOn/InvTx1RFOff and InvTx2RFOn/InvTx2RFOff

enum mfout_select_t

Selects the input for pin MFOUT.

Default: MFRC522_MFSEL_3STATE

MFRC522 Datasheet page 52

Values:

MFRC522_MFSEL_3STATE = 0b0000

3-state

MFRC522_MFSEL_LOW = 0b0001

LOW.

MFRC522_MFSEL_HIGH = 0b0010

HIGH.

MFRC522_MFSEL_TBUS = 0b0011

test bus signal as defined by the test_bus_bit_sel

MFRC522_MFSEL_MPE = 0b0100

modulation signal (envelope) from the internal encoder, Miller pulse encoded

MFRC522_MFSEL_SSTRT = 0b0101

serial data stream to be transmitted, data stream before Miller encoder

MFRC522_MFSEL_SSTRR = 0b0111

serial data stream received, data stream after Manchester decoder

enum cl_uart_in_sel_t

Selects the input of the contactless UART.

Default: MFRC522_UINSEL_ANALOG

MFRC522 Datasheet page 52

Values:

MFRC522_UINSEL_LOW = 0b00

constant LOW

MFRC522_UINSEL_MAN_MFIN = 0b01

Manchester with subcarrier from pin MFIN

MFRC522_UINSEL_ANALOG = 0b10

modulated signal from the internal analog module, default

MFRC522_UINSEL_NRZ_MFIN = 0b11

NRZ coding without subcarrier from pin MFIN which is only valid for transfer speeds above 106 kBd

enum receiver_gain_t

Gain of the receiver.

Default: MFRC522_GAIN_33

MFRC522 Datasheet page 59

Values:

MFRC522_GAIN_18 = 0b000

18 dB

MFRC522_GAIN_23 = 0b001

23 dB

MFRC522_GAIN_33 = 0b100

33 dB

MFRC522_GAIN_38 = 0b101

38 dB

MFRC522_GAIN_43 = 0b110

43 dB

MFRC522_GAIN_48 = 0b111

48 dB

Public Members

EXTDriver *extp

EXT driver to use for handling MFRC522-issued interrupts

expchannel_t interrupt_channel

EXT channel to which the IRQ pin (and only the IRQ pin) of the MFRC522 is connected.

void *reset_line

PAL line, which when set low resets the connected MFRC522

bool MFIN_polarity

Defines polarity of pin MFIN.

true: MFIN is active HIGH false: MFIN is active LOW

Default: true

MFRC522 Datasheet page 48

bool inverse_modulation

Modulation of transmitted data should be inverted.

Default: false

MFRC522 Datasheet page 49

uint8_t tx_control_reg

Value of the transmission control register.

Default: 0x80

MFRC522 Datasheet page 50

Mfrc522Config::driver_input_select_t driver_input_select
Mfrc522Config::mfout_select_t mfout_select
Mfrc522Config::cl_uart_in_sel_t cl_uart_in_sel
uint8_t min_rx_signal_strength

Minimum signal strength which will be accepted by the decoder.

Only 4 lowest bits are taken into account.

Default: 8

MFRC522 Datasheet page 53

uint8_t min_rx_collision_level

Minimum collision signal strength.

Minimum signal strength at the decoder input that must be reached by the weaker half-bit of the Manchester encoded signal to generate a bit-collision relative to the amplitude of the stronger half-bit.

Only 3 lowest bits are taken into account.

Default: 4

MFRC522 Datasheet page 53

uint8_t demod_reg

Demodulator settings.

Default: 0x4D

MFRC522 Datasheet page 53

Mfrc522Config::receiver_gain_t receiver_gain
uint8_t transmit_power_n

Conductance of the output n-driver (CWGsN) which can be used to regulate the output power.

Default: 8

MFRC522 Datasheet page 59

uint8_t modulation_index_n

Conductance of the output n-driver (ModGsN) which can be used to regulate the modulation index.

Default: 8

MFRC522 Datasheet page 59

uint8_t transmit_power_p

Conductance of the output p-driver (CWGsP) which can be used to regulate the output power.

Default: 32

MFRC522 Datasheet page 60

uint8_t modulation_index_p

Conductance of the output n-driver (ModGsP) which can be used to regulate the modulation index.

Default: 32

MFRC522 Datasheet page 60

struct Mfrc522Driver
#include <hal_mfrc522.h>

Structure representing a MFRC522 driver.

For functions expecting a Pcd object use the pcd memeber of this structure. Otherwise don’t modify any of these values.

Public Types

enum mfrc522_conntype_t

How is the MFRC522 connected.

Values:

MFRC522_CONN_SPI
MFRC522_CONN_I2C
MFRC522_CONN_SERIAL

Public Members

Pcd pcd

Abstract Pcd structure to be used with other parts of this stack

pcdstate_t state

Driver state

Mfrc522Driver::mfrc522_conntype_t connection_type
union Mfrc522Driver::iface_u iface
EXTDriver *extp

EXT driver to use for handling MFRC522-issued interrupts

expchannel_t interrupt_channel

EXT channel to which the IRQ pin is connected

void *reset_line

PAL line, which when set low resets the connected MFRC522

const Mfrc522Config *current_config

Lastly applied config

volatile bool interrupt_pending

Interrupt is pending for this reader

thread_reference_t tr

Thread reference the reader will sleep on

uint8_t response[64]

Response buffer

uint8_t resp_last_valid_bits

Number of last valid bits in the response

uint8_t resp_length

Response length

uint8_t resp_read_bytes

Number of already retreived response bytes

mutex_t mutex

Mutex for mutual access

union iface_u
#include <hal_mfrc522.h>

Pointer to a given interface driver.

Public Members

SPIDriver *spip
I2CDriver *i2cp
SerialDriver *sdp

Internal functioning of the driver

Although most of the drivers in the HAL are contained in one file, the MFRC522 driver was becoming unreadable, so I’ve split it between several files.

  • src/hal_mfrc522/hal_mfrc522_internal.h header contains internal constants and internal documentation. It is not supposed to be used by application using this driver.
  • src/hal_mfrc522/hal_mfrc522.c is the main driver file. It contains MFRC522-specific initialization and configuration functions. It also contains the interrupt handler only purpose of which is to wake up a sleeping thread.
  • src/hal_mfrc522/hal_mfrc522_ext_api.c contains implementation of extended features. See hal_abstract_iso14443_pcd_ext.h.
  • src/hal_mfrc522/hal_mfrc522_llcom.c contains low-level communication routines for reading and writing registers of the MFRC522 over various connection interfaces.
  • src/hal_mfrc552/hal_mfrc522_pcd_api.c contains implementation of Pcd API functions for MFRC522.

Primary goals

This driver should provide easy-to-use synchronous API to drivers of higher protocol layers while being efficient and friendly to other threads (it suspends the calling thread while it’s waiting for data).

Initialization and configuration functions handling global objects of this driver must be thread-safe.

This driver does not guarantee thread safety if single Mfrc522Driver file is used simultaneously by multiple threads. Those threads should call pcdAcquireBus and pcdReleaseBus to achiveve mutual exclusion. However, it is safe to use different Mfrc522Driver objects from different threads simultaneously.

This driver should be as universal as possible. This is the reason for (over?)complicated configuration structure. It allows you to, when you know what are you doing, configure the MFRC522 modulee for your specific use-case (like using an external modulator with the chip). It is also easy to use, since default values work out-of-the box with the typical use-case (like the RFID-RC522 chinese module).

Thread suspend and interrupt handling

Each time this driver waits for the action of the reader it suspends the calling thread, to allow other threads to run.

MFRC522 has a mechanism of waking up the host using its IRQ pin. Host can conigure which interrupts propagate to the interrupt pin, and later figure out which interrupt occured by reading a specific register.

This driver uses the Ext driver provided by ChibiOS to handle these interrupts. It registers its own interrupt handler, the same for each interrupt channel. However, in the current version the Ext driver doesn’t allow passing custom parameters to the handler function, therefore when an interrupt occurs we only know which channel it came from. Then we may wake up all sleeping driver threads and let every thread check whether the interrupt is intended for it. This is problemating due to race conditions, necessity of events buffering, etc. Instead, we have imposed limitation that each interrupt channel can have only one reader (and nothing else than the reader) attached to it. Therefore when an interrupt occures by knowing the interrupt channel we can wake up the proper thread.

In addition this wake-up is buffered if the thread couldn’t be suspended in time.

Anticollision detection

TODO