2024-03-08 08:43 AM
Hello everyone,
before introducing you to the issue I am experiencing, let me share my setup:
My RF Interface is NOT working anymore after sending ST25DVxxKC_SetI2CCFG_RFSWITCHOFF(&(pObj->Ctx), ®_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):
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.
Solved! Go to Solution.
2024-03-13 09:33 AM
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.
2024-03-11 10:33 AM
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.
2024-03-12 12:46 AM
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.
2024-03-12 06:15 AM
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.
2024-03-12 07:36 AM
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.
2024-03-13 09:04 AM
Okay, fine. I'll wait. Thank you..
2024-03-13 09:33 AM
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.