Skip to main content
Associate
April 28, 2025
Solved

RFAL Manual RX CRC

  • April 28, 2025
  • 1 reply
  • 345 views

I am working with an ST25R3916b, utilizing the RFAL library. I am trying to work with a card that does not always send back a CRC over NFC, so I need to be able to disable the CRC RX checks dynamically. My txrx function looks like:

static int st25r_nfca_rxtx_rf(const struct device *dev, uint8_t *tx_data, uint16_t tx_bitlen,
			 uint8_t *rx_data, uint16_t rx_size, uint16_t *rx_bitlen)
{
	LOG_DBG("Transmitting and receiving using RF interface");

	ReturnCode ret;
	rfalTransceiveContext ctx = {
		.txBuf = tx_data,
		.txBufLen = tx_bitlen,
		.rxBuf = rx_data,
		.rxBufLen = rx_size,
		.rxRcvdLen = rx_bitlen,
		.flags =
			(uint32_t)((NFC_ST25R_DATA(dev)->tx_crc) ? RFAL_TXRX_FLAGS_CRC_TX_AUTO
								 : RFAL_TXRX_FLAGS_CRC_TX_MANUAL) |
			(uint32_t)((NFC_ST25R_DATA(dev)->rx_crc_keep)
					 ? RFAL_TXRX_FLAGS_CRC_RX_KEEP
					 : RFAL_TXRX_FLAGS_CRC_RX_REMV) |
			(uint32_t)RFAL_TXRX_FLAGS_NFCIP1_OFF | (uint32_t)RFAL_TXRX_FLAGS_AGC_ON |
			(uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO |
			(uint32_t)((NFC_ST25R_DATA(dev)->tx_parity) ? RFAL_TXRX_FLAGS_PAR_TX_AUTO
								 : RFAL_TXRX_FLAGS_PAR_TX_NONE) |
			(uint32_t)((NFC_ST25R_DATA(dev)->rx_parity) ? RFAL_TXRX_FLAGS_PAR_RX_KEEP
								 : RFAL_TXRX_FLAGS_PAR_RX_REMV) |
			(uint32_t)((NFC_ST25R_DATA(dev)->rx_crc_check)
					 ? RFAL_TXRX_FLAGS_CRC_RX_AUTO
					 : RFAL_TXRX_FLAGS_CRC_RX_MANUAL),
		.fwt = rfalConvUsTo1fc(NFC_ST25R_DATA(dev)->timeout_us),
	};

	LOG_INF("Transceive flags: 0x%08X", ctx.flags);

	/* Start transceiving bits over NFC */
	ret = rfalStartTransceive(&ctx);
	if (ret) {
		LOG_ERR("Failed to start transceive (err %d)", ret);
		return -EIO;
	}

	do {
		rfalWorker();
		ret = rfalGetTransceiveStatus();
	} while (rfalIsTransceiveInTx() && (ret == ERR_BUSY));

	if (rfalIsTransceiveInRx()) {
		ret = RFAL_ERR_NONE;
	}

	if (ret) {
		LOG_ERR("Failed to transceive Tx Bits (err %d)", ret);
		return -EIO;
	}

	/* Block until Rx is complete */
	ret = rfalTransceiveBlockingRx();
	if (ret == RFAL_ERR_CRC) {
		LOG_ERR("CRC check failed");
		/* continue */
	} else if (ret) {
		LOG_ERR("Failed to transceive Rx Bits (err %d)", ret);
		return -ENOMSG;
	}

	/* Convert received bits to bytes */
	*rx_bitlen = rfalConvBitsToBytes(*rx_bitlen);

	return 0;
}

Before calling this function, I will set the property for NFC_ST25R_DATA(dev)->rx_crc_check to false: effectively producing the transceive flags 0x00000080. However, I will always receive an ERR_CRC from rfal_rfst25r3916.c:2515:

static void rfalTransceiveRx( void )
{
 ...
 switch( gRFAL.TxRx.state )
 {
 ...
 case RFAL_TXRX_STATE_RX_ERR_CHECK:
 ...
 else if( (irqs & ST25R3916_IRQ_MASK_CRC) != 0U )
 {
 gRFAL.TxRx.status = RFAL_ERR_CRC;
 gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA;
 
 /* Check if there's a specific error handling for this */
 rfalErrorHandling();
 break;
 }
 ...
}

Is how I am trying to disable the CRC check not the correct way or is there another way I should be doing this?

This topic has been closed for replies.
Best answer by Ulysses HERNIOSUS

Hi kwolff,

your procedure looks right. Do you get this ERR_CRC only for your special frames are also for frames with normal good CRC?

Also you probably want to receive the CRC, i.e. setting RFAL_TXRX_FLAGS_CRC_RX_KEEP. Which RFAL version are you using?

BR, Ulysses

1 reply

Ulysses HERNIOSUS
Technical Moderator
April 29, 2025

Hi kwolff,

your procedure looks right. Do you get this ERR_CRC only for your special frames are also for frames with normal good CRC?

Also you probably want to receive the CRC, i.e. setting RFAL_TXRX_FLAGS_CRC_RX_KEEP. Which RFAL version are you using?

BR, Ulysses