diff --git a/include/libopencm3/stm32/common/rng_common_v1.h b/include/libopencm3/stm32/common/rng_common_v1.h index e0c26a81..1f226d77 100644 --- a/include/libopencm3/stm32/common/rng_common_v1.h +++ b/include/libopencm3/stm32/common/rng_common_v1.h @@ -28,6 +28,9 @@ specific memorymap.h header before including this header file.*/ #ifndef LIBOPENCM3_RNG_V1_H #define LIBOPENCM3_RNG_V1_H +#include +#include + /**@{*/ /* --- Random number generator registers ----------------------------------- */ @@ -72,6 +75,8 @@ BEGIN_DECLS void rng_enable(void); void rng_disable(void); +bool rng_get_random(uint32_t *rand_nr); +uint32_t rng_get_random_blocking(void); END_DECLS diff --git a/lib/stm32/common/rng_common_v1.c b/lib/stm32/common/rng_common_v1.c index 6808b683..7ed1e635 100644 --- a/lib/stm32/common/rng_common_v1.c +++ b/lib/stm32/common/rng_common_v1.c @@ -41,4 +41,51 @@ void rng_enable(void) RNG_CR |= RNG_CR_RNGEN; } +/** Randomizes a number (non-blocking). + * Can fail if a clock error or seed error is detected. Consult the Reference + * Manual, but "try again", potentially after resetting the peripheral + * @param pointer to a uint32_t that will be randomized. + * @returns true on success, pointer is only written to on success + * @sa rng_get_random_blocking + */ +bool rng_get_random(uint32_t *rand_nr) +{ + /* data ready */ + if (!(RNG_SR & RNG_SR_DRDY)) { + return false; + } + + /* Check for errors */ + if (RNG_SR & (RNG_SR_CECS | RNG_SR_SECS)) { + return false; + } + + *rand_nr = RNG_DR; + + return true; +} + + +/** + * Get a random number and block until it works. + * Unless you have a clock problem, this should always return "promptly" + * If you have a clock problem, you will wait here forever! + * @returns a random 32bit number + */ +uint32_t rng_get_random_blocking(void) +{ + uint32_t rv; + bool done; + do { + if (RNG_SR & RNG_SR_SECS) { + rng_disable(); + rng_enable(); + } + done = rng_get_random(&rv); + } while (!done); + + return rv; +} + + /**@}*/