How to use the RNG on the STMF32F429

Hello. I created a usRand() function to use the RNG in the STMF32429. According to the manual, this generates a random number once it’s enabled. I would expect that after enabling the RNG, i can just read the register. Using HALRNGGenerateRandomNumber from stm32f4xxhalrng.c, it does just read the register. ~~~ HALStatusTypeDef HALRNGGenerateRandomNumber(RNGHandleTypeDef *hrng, uint32_t *random32bit) { uint32_t tickstart = 0U;
HAL_StatusTypeDef status = HAL_OK; /* Process Locked */ __HAL_LOCK(hrng); /* Check RNG peripheral state / if(hrng->State == HAL_RNG_STATE_READY) { / Change RNG peripheral state */
hrng->State = HAL_RNG_STATE_BUSY;
/* Get tick */
tickstart = HAL_GetTick();

/* Check if data register contains valid random data */
  if((HAL_GetTick() - tickstart ) > RNG_TIMEOUT_VALUE)
    hrng->State = HAL_RNG_STATE_ERROR;

    /* Process Unlocked */

    return HAL_TIMEOUT;

/* Get a 32bit Random number */
hrng->RandomNumber = hrng->Instance->DR;
*random32bit = hrng->RandomNumber;

hrng->State = HAL_RNG_STATE_READY;
} else { status = HAL_ERROR; } /* Process Unlocked */ __HAL_UNLOCK(hrng); return status; } ~~~ But, when I get a random number using this, I keep getting the same number, as if the RNG isn’t running. Seeing how it’s used in the sample, the value from the RNG seems to be being used as a seed, rather than a random number. This seems wrong, but it’s not working as I expect, so I’m missing something. Can anyone explain how uxRand should be written for an STMF32 with an RNG? ~~~ UBaseTypet uxRand( void ) { const uint32t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL; static BaseType_t xInitialised = pdFALSE;
/* Don't initialise until the scheduler is running, as the timeout in the
random number generator uses the tick count. */
if( xInitialised == pdFALSE )
    if( xTaskGetSchedulerState() !=  taskSCHEDULER_NOT_STARTED )
    RNG_HandleTypeDef xRND;
    uint32_t ulSeed;

        /* Generate a random number with which to seed the local pseudo random
        number generating function. */
        HAL_RNG_Init( &xRND );
        HAL_RNG_GenerateRandomNumber( &xRND, &ulSeed );
        prvSRand( ulSeed );
        xInitialised = pdTRUE;

/* Utility function to generate a pseudo random number. */

ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );
} ~~~

How to use the RNG on the STMF32F429

Hi Robert, I generally don’t use the STM32 HAL (bad experiences with strange bugs going back many years) so I generally write to the hardware registers myself. Most likely I’m guessing you haven’t enabled the clock into the RNG. In my code, this is: ~~~ RCCAHB2PeriphClockCmd(RCCAHB2Periph_RNG, ENABLE); // Enable RNG clock ~~~ Hopefully you can find this function and trace through it. Then you have to enable the RNG peripheral by setting the third bit (bit 2, zero-based), e.g. ~~~ TheRNG.CR = (1UL << 2); ~~~ Now you “just” have to read the data register, once the status register (bit 0) indicates the DR has a new random number. The manual explains how to do this at a higher level (throw away first value, and check for repeated values back-to-back), but essentially it’s: ~~~ while (!(TheRNG.SR & 1UL)) { } // wait for data // read error bits in SR – not shown here uint32t newdata = TheRNG.DR; ~~~ BTW, normally hardware RNGs are used to seed a cryptographically secure PRNG (software algorithm like AES in CTR mode or BlumBlumShub or…) This is because hardware RNGs could have strange failure modes that are hard to detect. I’m going to cut myself off there — I teach a 4-day class on embedded systems security, and random numbers are half a day of material, so it’s a big topic with lots of nuances, but I think you at least have an answer to your question (I hope?)