cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7B3I - Random Number Generator: Occasional SEED_ERROR

Garnett.Robert
Senior III

Hi

I'm using the Random Number Generator in interrupt mode and am getting HAL_RNG_ERROR_SEED errors. I'm not getting clock errors. I use HAL to drive the rng.

The errors are quite infrequent, I don't have stats but probably 1 in 100000.

Are these errors to be expected or am I potentially doing something wrong?

I am running the CPU at 280 MHz. The clock settings are implemented by HAL and I haven't changed these.

The problem I have is that to clear the error you have to restart the rng which take up to 200 ms.

The entropy of the numbers isn't critical in my app as I'm only using the rng to purterbate test data around a mean. So I am thinking that I could just let the rng run without resetting it.

Regards

Rob

10 REPLIES 10
Garnett.Robert
Senior III

Hi TDK

I made a test project similar to your code, but using interrupts as I am using interrupts in the Shortt clock project I am building. I don't thing using blocking or interrupts will make any difference to seed errors, but I wanted my test to be as close as possible to my application

Like you I got no errors. I used 64 bit counters to get more data, but still no errors.

The strange thing is I haven't had any more errors in my main project. I'm sure I wasn't imagining them as I put a breakpoints on the error code in the HAL RNG interrupt handler and the error happened twice.

I received an answer back on my service request. On the question of "true" randomness they said:

"The RNG output randomness is inherited from the randomness of the source.

To have a better feeling of the entropy of the RNG output, please refer to AN4320 "STM32 microcontroller random number generation validation using the NIST statistical test suite".

So I'm thinking that compared to algorithmic approximations of random number generation the numbers produced by the RNG are truly random by virtue of the fact they meet the NIST criteria.

On the question of recovering from a seed error there is a new HAL function: HAL_RNGEx_RecoverSeedError which was added in version 1.9 of the HAL Drivers. the code for this is:

/**
  * @brief  RNG sequence to recover from a seed error
  * @param  hrng: pointer to a RNG_HandleTypeDef structure.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RNGEx_RecoverSeedError(RNG_HandleTypeDef *hrng)
{
  HAL_StatusTypeDef status;
 
  /* Check the RNG handle allocation */
  if (hrng == NULL)
  {
    return HAL_ERROR;
  }
 
  /* Check RNG peripheral state */
  if (hrng->State == HAL_RNG_STATE_READY)
  {
    /* Change RNG peripheral state */
    hrng->State = HAL_RNG_STATE_BUSY;
 
    /* sequence to fully recover from a seed error */
    status = RNG_RecoverSeedError(hrng);
  }
  else
  {
    hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
    status = HAL_ERROR;
  }
 
  /* Return the function status */
  return status;
}
 
/**
  * @brief  RNG sequence to recover from a seed error
  * @param  hrng pointer to a RNG_HandleTypeDef structure.
  * @retval HAL status
  */
HAL_StatusTypeDef RNG_RecoverSeedError(RNG_HandleTypeDef *hrng)
{
  __IO uint32_t count = 0U;
 
  /*Check if seed error current status (SECS)is set */
  if (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_SECS) == RESET)
  {
    /* RNG performed the reset automatically (auto-reset) */
    /* Clear bit SEIS */
    CLEAR_BIT(hrng->Instance->SR, RNG_IT_SEI);
  }
  else  /* Sequence to fully recover from a seed error*/
  {
    /* Writing bit CONDRST=1*/
    SET_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
    /* Writing bit CONDRST=0*/
    CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
 
    /* Wait for conditioning reset process to be completed */
    count = RNG_TIMEOUT_VALUE;
    do
    {
      count-- ;
      if (count == 0U)
      {
        hrng->State = HAL_RNG_STATE_READY;
        hrng->ErrorCode |= HAL_RNG_ERROR_TIMEOUT;
        /* Process Unlocked */
        __HAL_UNLOCK(hrng);
#if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
        /* Call registered Error callback */
        hrng->ErrorCallback(hrng);
#else
        /* Call legacy weak Error callback */
        HAL_RNG_ErrorCallback(hrng);
#endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
        return HAL_ERROR;
      }
    } while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST));
 
    if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
    {
      /* Clear bit SEIS */
      CLEAR_BIT(hrng->Instance->SR, RNG_IT_SEI);
    }
 
    /* Wait for SECS to be cleared */
    count = RNG_TIMEOUT_VALUE;
    do
    {
      count-- ;
      if (count == 0U)
      {
        hrng->State = HAL_RNG_STATE_READY;
        hrng->ErrorCode |= HAL_RNG_ERROR_TIMEOUT;
        /* Process Unlocked */
        __HAL_UNLOCK(hrng);
#if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
        /* Call registered Error callback */
        hrng->ErrorCallback(hrng);
#else
        /* Call legacy weak Error callback */
        HAL_RNG_ErrorCallback(hrng);
#endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
        return HAL_ERROR;
      }
    } while (HAL_IS_BIT_SET(hrng->Instance->SR, RNG_FLAG_SECS));
  }
  /* Update the error code */
  hrng->ErrorCode &= ~ HAL_RNG_ERROR_SEED;
  return HAL_OK;
}

Regards

Rob