cancel
Showing results for 
Search instead for 
Did you mean: 

[ST25DV] Restore RFSwitchOn (RF disabled)

pa0grg
Associate II

Hello everyone,

before introducing you to the issue I am experiencing, let me share my setup:

  • uC: STM32U585
  • I2C: Fast Mode Plus
  • Ide: STM32CubeIde
  • Power Source: 3.6VDC (laboratory power supply)
  • st25dvxxkc package: GitHub st25dvxxkc 
  • RF Reader: ST25 App (Google Play Store)
  • Before sending any I2C command to protected area an I2C security session is opened with ST25DVxxKC_PresentI2CPassword() function;

 

My RF Interface is NOT working anymore after sending ST25DVxxKC_SetI2CCFG_RFSWITCHOFF(&(pObj->Ctx), &reg_value) I2C command. I'm trying to restore it but until now I have not succeed. In order to restore it I've tried to apply some I2C command such ST25DVxxKC_ResetRFOff_Dyn() from st25dvxxkc package I pasted beforehand, but it's not working since it writes NULL data:

ret = pObj->IO.Write((pObj->IO.DeviceAddress | ST25DVXXKC_ADDR_RFSWITCH_BIT_I2C) & ~ST25DVXXKC_ADDR_MODE_BIT_I2C, ST25DVXXKC_ICREF_REG, NULL, 0);

which is of course denied from HAL_I2C_Mem_Write() function. I've read the following thread but I have still not found anything helpful: Solved: ST25DV64KC RF SWITCH ON/OFF - STMicroelectronics Community

Therefore, I made some changes in source code, as it follows (i have commented the beforehand expression and added ST25DVxxKC_SetRF_MNGT_DYN_RFOFF function):

pa0grg_0-1709915423432.png

but it's not working either; in that case HAL_I2C_Mem_Write() works fine, but when I read the register value it does not change its value (RF_MNGT_DYN is equal to 0). According to ST25DV datasheet RF should be enabled but actually it isn't.

1 ACCEPTED SOLUTION

Accepted Solutions
Cedric Dalban
ST Employee

Hello,

I am coming back to you about this issue with HAL_I2C_Mem_Write().


On our side, using the API HAL_I2C_Master_Transmit() perfectly works.


I assume you have the following code for BSP_I2C2_WriteReg16():
int32_t BSP_I2C2_WriteReg16(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t len)
{
  int32_t ret = BSP_ERROR_BUS_FAILURE;

  if(HAL_I2C_Mem_Write(&hi2c2, (uint8_t) DevAddr, (uint16_t) Reg, I2C_MEMADD_SIZE_16BIT, (uint8_t*) pData, len, TIMEOUT_DURATION) == HAL_OK)
  {
  ret = BSP_ERROR_NONE;
  }

  return ret;
}

Could you please replace it with the following:
int32_t BSP_I2C2_WriteReg16(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t len)
{
  int32_t ret = BSP_ERROR_BUS_FAILURE;
  HAL_StatusTypeDef halRet = HAL_ERROR;

  if ((pData == NULL) && (len == 0U)) {
halRet = HAL_I2C_Master_Transmit(&hi2c2, (uint8_t)DevAddr, (uint8_t *)pData, len, TIMEOUT_DURATION);
}
  else {
    halRet = HAL_I2C_Mem_Write(&hi2c2, (uint8_t) DevAddr, (uint16_t) Reg, I2C_MEMADD_SIZE_16BIT, (uint8_t*) pData, len, TIMEOUT_DURATION);
  }

  if (halRet == HAL_OK)
  {
    ret = BSP_ERROR_NONE;
  }

  return ret;
}

Please also ensure you have the appropriate SlaveMode setter API (considering you reverted the modifications you did in ST25DVxxKC_WriteI2CSlaveMode() and kept the IO.Write(...., NULL, 0) 🙂 :(
int32_t BSP_NFCTAG_WriteI2CSlaveMode(uint32_t Instance, const ST25DVxxKC_SLAVE_MODE_E slaveMode)
{
  UNUSED(Instance);
  return ST25DVxxKC_WriteI2CSlaveMode(&NfcTagObj, slaveMode);
}

Finally:
BSP_NFCTAG_WriteI2CSlaveMode(<your instance>, ST25DVXXKC_SLAVE_MODE_RFOFF); => sets the RF OFF
BSP_NFCTAG_WriteI2CSlaveMode(<your instance>, ST25DVXXKC_SLAVE_MODE_RFON); => sets the RF back to ON
BSP_NFCTAG_WriteI2CSlaveMode(<your instance>, ST25DVXXKC_SLAVE_MODE_NORMAL); => sets the RF back to ON

Hoping this helps,
best regards,
Cedric.

 

View solution in original post

6 REPLIES 6
JL. Lebon
ST Employee

Hello, 

You probably set your RF OFF, that's why you can't use RF anymore.

In order to set RF on again, you should call ST25DVxxKC_WriteI2CSlaveMode with salveMode parameter set to ST25DVXXKC_SLAVE_MODE_RFON. That's all. The modification you did in this function is not right.

What this function will do, is set the I2C_CFG configuration with bit I2C_RF_SWITCHOFF_EN=1, which means that the special I2C command to switch RF ON or OFF is authorized.
Then it sends the special I2C command to switch the RF ON. This special I2C command is just a special I2C device address with no data. That is why the number of data sent is 0 (please see chapter "5.3.1 I²C priority" of the datasheet, it explains those I2C special command that have no data).

The ST25DVxxKC_GetRFOff_Dyn() gives you the current status of the RF interface, to know if it is OFF or ON.
The ST25DVxxKC_SetRFOff_Dyn() is of no use since the bit RF_OFF of the RF_MNGT_Dyn register is read only.

Best regards.

Hello,

okay, it's clear. But I do not understand how to write null data to ST25 register since HAL_I2C_Mem_Write() does not accept null pointer as input argument; I've tried also HAL_I2C_Master_Transmit() but it's not working either.

Cedric Dalban
ST Employee

Hello,

there is in our provided BSP a special trick to be able to pass NULL pointer as argument: combine NULL pointer + size=0.

Indeed, in provided BSP (File: .../Drivers/BSP/Linux/bsp_nfctag.c), the function BSP_NFCTAG_Init() called at init phase, sets  IO.Write to NFC_IO_WriteReg16() (File: .../Drivers/BSP/Linux/st25dv-i2c_linux.c). This function handles the trick referred to above.

More precisely, NFC_IO_WriteReg16() sets the ioctl parameters for the I2C_RDWR as follows:

struct i2c_msg messages[1] = {
{
.addr = DevAddr >>1,
.buf = NULL,
.len = 0,
.flags = 0,
}
};

struct i2c_rdwr_ioctl_data payload = {
.msgs = messages,
.nmsgs = 1,
};

ret = ioctl(filehandle, I2C_RDWR, &payload);

The ioctl used with these parameters generate the I2C command with special I2C device address with no data mentioned above by JL. Lebon.

I can only recommend that if you are using your own implementation of I2C_write, you ensure the combination NULL+size=0 is handled.

 

best regards,

Cedric.

 

Cedric Dalban
ST Employee

Hello,

I just realized my answer is only applicable to Linux which has different ways to access the I2C.

I will check how to generate the I2C command with special I2C device address with no data in other configurations.

Best regards,

Cedric.

Okay, fine. I'll wait. Thank you..

Cedric Dalban
ST Employee

Hello,

I am coming back to you about this issue with HAL_I2C_Mem_Write().


On our side, using the API HAL_I2C_Master_Transmit() perfectly works.


I assume you have the following code for BSP_I2C2_WriteReg16():
int32_t BSP_I2C2_WriteReg16(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t len)
{
  int32_t ret = BSP_ERROR_BUS_FAILURE;

  if(HAL_I2C_Mem_Write(&hi2c2, (uint8_t) DevAddr, (uint16_t) Reg, I2C_MEMADD_SIZE_16BIT, (uint8_t*) pData, len, TIMEOUT_DURATION) == HAL_OK)
  {
  ret = BSP_ERROR_NONE;
  }

  return ret;
}

Could you please replace it with the following:
int32_t BSP_I2C2_WriteReg16(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t len)
{
  int32_t ret = BSP_ERROR_BUS_FAILURE;
  HAL_StatusTypeDef halRet = HAL_ERROR;

  if ((pData == NULL) && (len == 0U)) {
halRet = HAL_I2C_Master_Transmit(&hi2c2, (uint8_t)DevAddr, (uint8_t *)pData, len, TIMEOUT_DURATION);
}
  else {
    halRet = HAL_I2C_Mem_Write(&hi2c2, (uint8_t) DevAddr, (uint16_t) Reg, I2C_MEMADD_SIZE_16BIT, (uint8_t*) pData, len, TIMEOUT_DURATION);
  }

  if (halRet == HAL_OK)
  {
    ret = BSP_ERROR_NONE;
  }

  return ret;
}

Please also ensure you have the appropriate SlaveMode setter API (considering you reverted the modifications you did in ST25DVxxKC_WriteI2CSlaveMode() and kept the IO.Write(...., NULL, 0) 🙂 :(
int32_t BSP_NFCTAG_WriteI2CSlaveMode(uint32_t Instance, const ST25DVxxKC_SLAVE_MODE_E slaveMode)
{
  UNUSED(Instance);
  return ST25DVxxKC_WriteI2CSlaveMode(&NfcTagObj, slaveMode);
}

Finally:
BSP_NFCTAG_WriteI2CSlaveMode(<your instance>, ST25DVXXKC_SLAVE_MODE_RFOFF); => sets the RF OFF
BSP_NFCTAG_WriteI2CSlaveMode(<your instance>, ST25DVXXKC_SLAVE_MODE_RFON); => sets the RF back to ON
BSP_NFCTAG_WriteI2CSlaveMode(<your instance>, ST25DVXXKC_SLAVE_MODE_NORMAL); => sets the RF back to ON

Hoping this helps,
best regards,
Cedric.