cancel
Showing results for 
Search instead for 
Did you mean: 

M24SR04 Stops Responding During Intense Activity

MBrow.13
Associate II

Hi,

We have a bespoke board built around a STM3L4 and a M24SR04-Y.

We share data with a NFC reader, i.e. the NFC reader can write a command into the M24SR EEPROM, interrupt the STM32 via GPO and the STM32 will reply by writing something in the EEPROM.

Broadly speaking what we've done works. We can use the NFC reader to change the configuration of our device and retrieve data from the device. We finished this code some weeks ago and have been using it.

We have recently realised that if we abuse the process by continually exchanging information between the NFC reader and the STM32 it will eventually fail. Earlier I tried continually reading from the STM32 for 10 minutes, it failed on the 620th attempt.

In the STM32 code we're forcing the open session and our code gets stuck polling for this to be successful. After that the M24SR seems to be stuck because there is no response from the I2C or NFC sides.

The I2C bus is still working because we have another I2C device and it still responds. Restarting the STM32L4 doesn't help.

The only way to get the M24SR responding again is to remove power.

I have tried setting the I2C watchdog to 1 but it didn't make any difference.

It feels to me like the internal token passing mechanism has got locked up. This seems like a feasible explanation given that my testing is continually switching between NFC and I2C.

The STM32 application is based on Mbed OS and we're using ST's M24SR library, https://os.mbed.com/teams/ST/code/M24SR/.

Does any of this mean anything to anyone?

Is it likely to be a real problem or a problem with the software?

Thanks,

Matt

1 ACCEPTED SOLUTION

Accepted Solutions
Rene Lenerve
ST Employee

Hi matthew,

When you open a session in I²C, you then need to close it otherwise the RF could not open a new session with the M24SR and there is no KillSession on RF side. So in order to close your I²C session you need to perform the I²C token release sequence ( details are available in the Datasheet "https://www.st.com/resource/en/datasheet/m24sr04-y.pdf", section 7.4).

The description you give seems to be this kind of problem and looking quickly in the mbed code, it seems it is not using the correct process to close the I²C Session. sending Deselect command (as of RF functioning) instead of Token Release.

The sequence described in the Datasheet is to send the Device select code on the I2C line and then hold down the SCL during tSTART_OUT_max before releasing SCL and perform a stop.

Hope this can help you.

Regards.

View solution in original post

9 REPLIES 9
MBrow.13
Associate II

Searching for 'killrfsession' suggested found a post that suggested it can go wrong and that 'Deselect' followed by 'KillRFSession' might be the answer.

I shall give it a try.

https://community.st.com/s/global-search/killrfsession

MBrow.13
Associate II

I haven't managed to implement a test that follows a failed 'KillRFSession' with a deselect, at least in part, because of the complexity the Mbed OS M24SR library.

I now believe my problem is not restricted to polling for the completion of the 'KillRFSession' command. I've just seen it get stuck polling for completion of a normal write command.

I'm using the library in synchronous mode. So after writing some data to the M24SR using the I2C the library executes the polling sequence. In other words it does a 0 length writes until it gets an ACK. If the first 0 length write doesn't receive an ACK the library tries again, sometimes retrying works but sometimes it gets stuck in a infinite loop of retries.

MBrow.13
Associate II

I've double-posted in case this is a Mbed OS M24SR library problem.

https://os.mbed.com/questions/83076/M24SR-Gets-Stuck-in-Infinite-Loop/

Rene Lenerve
ST Employee

Hi matthew,

When you open a session in I²C, you then need to close it otherwise the RF could not open a new session with the M24SR and there is no KillSession on RF side. So in order to close your I²C session you need to perform the I²C token release sequence ( details are available in the Datasheet "https://www.st.com/resource/en/datasheet/m24sr04-y.pdf", section 7.4).

The description you give seems to be this kind of problem and looking quickly in the mbed code, it seems it is not using the correct process to close the I²C Session. sending Deselect command (as of RF functioning) instead of Token Release.

The sequence described in the Datasheet is to send the Device select code on the I2C line and then hold down the SCL during tSTART_OUT_max before releasing SCL and perform a stop.

Hope this can help you.

Regards.

Hi @Rene Lenerve​ ,

I've returned to this after some time doing other things!

> it seems it is not using the correct process to close the I²C Session. sending Deselect command (as of RF functioning) instead of Token Release.

I agree with and understand what saying but evidence and experimentation suggests that sending the deselect command via I2C releases the token.

I created a simple test, without using the ST M24SR library, and found that sending the deselect command via I2C followed by a 4 byte read released the token. In pseudo code:

    // get I2C session
    // select NDEF file
    // read binary
    // I2C has the token and RF not responding
 
    char deselect_cmd[] = { 0xC2, 0xE0, 0xB4 };
    i2c_write(&i2c_obj, address, deselect_cmd, sizeof(deselect_cmd), 1);
 
    char readout[4];
    i2c_read(&i2c_obj, address, readout, 0x4, 1);
 
    // RF responding again

Is this just working by luck?

I wonder if you know who wrote the ST M24SR library and if they know something we don't?

Thanks,

Matt

Rene Lenerve
ST Employee

Hi @MBrow.13​ ,

The Deselect command on I²C side is deprecated, and is no longer intended to be used.

The I²C Token Release is the strongest way to close the I²C session, as described in the Datasheet.

Hope this can help you.

Regards.

> The Deselect command on I²C side is deprecated

OK, I see.

The problem is that generating the I2C Token Release is difficult because the I2C writes are being done by the I2C peripheral.

As I understand it, creating this sequence would require toggling the SCL and SDA from program code. In order to do this, the GPIO pin functions would need changing, etc.

Is this correct? Or, is it possible to get the STM32L4 I2C peripheral to generate this kind of sequence?

Thanks,

Matt

Rene Lenerve
ST Employee

Hi @MBrow.13​,

Here after is the code from the X-CUBE-NFC1 software package showing the function which manage the token release :

/**
  * @brief  This functions implements I2C token release sequence used by M24SR
  * @retval M24SR_STATUS_SUCCESS : the function is succesful
  * @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured. 
  */
int8_t M24SR_I2CTokenRelease( void )
{
  uint32_t tmpreg = 0;
  uint32_t Timeout = 1;
  uint32_t tickstart;
  
    /* Process Locked */
  __HAL_LOCK(&hi2c1);
  
  hi2c1.State = HAL_I2C_STATE_BUSY_TX;
  hi2c1.ErrorCode   = HAL_I2C_ERROR_NONE;
  
  /* Get the CR2 register value */
  tmpreg = hi2c1.Instance->CR2;
  
  /* clear tmpreg specific bits */
  tmpreg &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP));
  
  /* update tmpreg */
  tmpreg |= (uint32_t)(((uint32_t)M24SR_ADDR & I2C_CR2_SADD) | \
            (uint32_t)I2C_SOFTEND_MODE | (uint32_t)I2C_GENERATE_START_WRITE);
  /* update CR2 register */
  hi2c1.Instance->CR2 = tmpreg;    
  
  M24SR_WaitMs(40);
 
  hi2c1.Instance->CR2 |= I2C_CR2_STOP;
  
  tickstart = HAL_GetTick();
  /* Wait until STOPF flag is set */
  while(__HAL_I2C_GET_FLAG(&hi2c1, I2C_FLAG_STOPF) == RESET)
  {
 
    /* Check for the Timeout */
    if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
    {
      hi2c1.ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
      hi2c1.State = HAL_I2C_STATE_READY;
 
      /* Process Unlocked */
      __HAL_UNLOCK(&hi2c1);
 
      return M24SR_ERROR_I2CTIMEOUT;
    }
  }
    
  /* Clear STOP Flag */
  __HAL_I2C_CLEAR_FLAG(&hi2c1, I2C_FLAG_STOPF);
 
    /* Clear Configuration Register 2 */
  I2C_RESET_CR2(&hi2c1);
 
  hi2c1.State = HAL_I2C_STATE_READY; 	  
 
  /* Process Unlocked */
  __HAL_UNLOCK(&hi2c1);
 
  return M24SR_STATUS_SUCCESS;
}

I do not know if you have the ability to easily drive the I²C with mbed, but the sequence is just send the device address and then wait 40 ms before raising a stop on I²C.

Let me know if you need more details on the above code.

Regards.

Hi @Rene Lenerve​ ,

Thanks for pointing that out!

I can see what's going on and how to drive the I2C peripheral to generate the I2C Token Release. I will try implementing this for myself and see whether or not it helps reliability of our app.

There's obviously a bit of a problem with the Mbed OS examples for driving the M24SR!

The Mbed OS examples are supposed to be MCU independent. Someone might be using a M24SR but another manufacture's MCU. Hence the Mbed OS libraries use the Mbed OS high-level I2C abstraction. This high-level abstraction only provides a basic I2C write function.

We're only ever going to use a STM32L4 with the M24SR so we can hack the library.

Thanks,

Matt