Having real randomness on a deterministic machine is a pretty interesting topic, while one can easily achieve pseudo-randomness by creating a complex algorithm with unpredictable outputs(such as a chaotic system). However, for a microcontroller with the same code whenever it boots up, the above solution will give you the same number every time. So it would be nice to introduce some external chaotic sources, the most commonly used one might be heat noises, which require some kind of temperature sensor. I also heard Lava Lamps are being used as a chaotic source in some real applications - Cloudflare uses 100 such lamps for their random generator - how bizarre!

Ring Oscillator

Though on the RP2040s, there is something nice to have called ring oscillators. They are a bunch of NOT gates connected in series with the total number of them to be an odd number.

ring oscillator

And such a simple construction gives an unpredictable/unstable system, which benefits us in building a true random number generator(TRNG)

Ring Oscillator Based TRNG

As we look at the datasheet for the RP2040s, we can see there is a register we can directly access to get the Ring Oscillator(ROSC) output.

We can have an unsigned int type variable and each bit be the ROSC random bit value to create a rather large random value like this:

#define ROSC_RANDOMBIT_OFFSET _u(0x0000001c)
#define ROSC_BASE _u(0x40060000)

// return random number by ROSC between 0-2^N
// N should be in [0,32]
unsigned int ROrand(int N)
  static volatile uint32_t *randbit_reg = (uint32_t *)(ROSC_BASE + ROSC_RANDOMBIT_OFFSET);
  unsigned int random = 0;
  for (int i = 0; i < N; i++)
    unsigned int random_bit = 0x1 & (*randbit_reg);
    random = random << 1 | random_bit;
  return random;

For the input N being 32, we should be able to get a random number between 0-2^32

Pretty cool stuff! There is definitely space for optimization.