.. index:: random number generator, serial, stm32f407 discovery board .. _f407-8mhz-rng: Random Number Generator ======================= For the STM32F407 Discovery Board with a default Mecrisp-Stellaris binary, 8 MHz HSE clock. Operation --------- The RNG requires a special clock, and it can only be obtained from the PLL. In this project I use the default Mecrisp-Stellaris settings with the only special hardware config being: "pll-on" (below) tells the MCU to use the HSE clock for the PLL and to wait until the PLL is ready and stable. The HSE clock is set up by the Mecrisp-Stellaris Kernel and is running by the time you see "Mecrisp-Stellaris x.x.x for STM32F407 by Matthias Koch" greeting message. The PLL is all that the RNG is waiting for now. Once the PLL is running, the RNG is happy with the power up defaults and can begin generating random numbers. .. note:: If the MCU was using the default MCI clock, all one need to do is enable the PLL and the RNG will run nicely using the RCC_PLLCFGR power up default config of $24003010. :: print-random 1647364344 ok. print-random 749262874 ok. print-random 2962038891 ok. Source Code ----------- :: \ Program Name: rnd-f407.fs \ Project: f407 rng 8mhz HSE clock \ Created: Sun 14 Mar 2021 20:53:47 AEDT \ Author Copyright 2021 by t.j.porter \ Purpose: Demonstrate the RNG \ Intended Audience: \ MCU: STM32F407 \ Board: F4 Disco \ Core: Mecrisp-Stellaris RA 2.5.4 for STM32F407 by Matthias Koch \ For use with a default Mecrisp-Stellaris with a serial terminal \ license: MIT, please see COPYING \ \ print-random 4141816465 ok. \ print-random 3956190172 ok. \ print-random 2788497613 ok. \ compiletoram \ comment out any of these previously loaded $40023800 constant RCC ( Reset and clock control ) RCC $34 + constant RCC_AHB2ENR ( read-write ) \ AHB2 peripheral clock enable register RCC $0 + constant RCC_CR ( ) \ clock control register RCC $4 + constant RCC_PLLCFGR ( read-write ) \ PLL configuration register $50060800 constant RNG ( Random number generator ) RNG $0 + constant RNG_CR ( read-write ) \ control register RNG $4 + constant RNG_SR ( ) \ status register RNG $8 + constant RNG_DR ( read-only ) \ data register : bit ( u -- u ) 1 swap lshift 1-foldable ; : RCC_CR_PLLON ( -- x addr ) 24 bit RCC_CR ; \ Main PLL PLL enable : RCC_CR_PLLRDY? ( -- 1|0 ) 25 bit RCC_CR bit@ ; \ Main PLL PLL clock ready flag : RCC_PLLCFGR_PLLSRC ( -- x addr ) 22 bit RCC_PLLCFGR ; \ 0: HSI clock selected as PLL, 1: HSE oscillator clock selected as PLL : PLLCFGR-CNF ( -- ) 1 RCC_PLLCFGR_PLLSRC bis! \ HSI clock selected as PLL clock source ; : pll-on ( -- ) PLLCFGR-CNF RCC_CR_PLLON bis! begin RCC_CR_PLLRDY? until ; 0 variable rnd-sample 0 variable rnd-flag : RCC_AHB2ENR_RNGEN ( -- x addr ) 6 bit RCC_AHB2ENR ; \ RCC_AHB2ENR_RNGEN, Random number generator clock enable : RNG_CR_RNGEN ( -- x addr ) 2 bit RNG_CR ; \ RNG_CR_RNGEN, Random number generator enable : RNG_SR_DRDY? ( -- x addr ) 0 bit RNG_SR bit@ ; \ RNG_SR_DRDY, Random data ready yet ? : RNG_SR_SECS? ( -- 1|0 ) 2 bit RNG_SR bit@ ; \ RNG_SR_SECS, Seed error current status : RNG_SR_CECS? ( -- 1|0 ) 1 bit RNG_SR bit@ ; \ RNG_SR_CECS, Clock error current status : RNG_DR_RNDATA? ( -- x ) RNG_DR @ ; \ RNG_DR_RNDATA, Random data output register : init.rng ( -- ) pll-on RCC_AHB2ENR_RNGEN bis! \ Enable Random number generator clock RNG_CR_RNGEN bis! \ Enable Random number generator ; : rng-check-errors ( -- ) RNG_SR_SECS? if ." There has been a seed error, reinitializing the RNG " cr RNG_CR_RNGEN bic! RNG_CR_RNGEN bis! 0 rnd-flag ! then RNG_SR_CECS? if ." There is a RNG CLOCK problem, see page 768 of RM0090 Rev 18" cr exit then ; : print-random ( -- ) \ but check it's valid first. rng-check-errors RNG_DR_RNDATA? \ get the new random number rnd-flag @ 0= if \ is this the first random number generated since RNG_CR_RNGEN ? RNG_DR_RNDATA? rnd-sample ! \ yes, save it then \ no, proceed to testing the new number against the old begin begin RNG_SR_DRDY? until \ Is a new random number ready ? RNG_DR_RNDATA? dup rnd-sample @ - 0= if \ compare old and new random numbers rnd-sample ! \ same! save new as old, delete new else drop then \ different, drop the copy dup \ valid RN on the stack, make a copy for final printing 0<> \ is it greater than zero ? ( question: will the RNG generate 0 as a valid RN ?) until u. \ yes, Print it ; init.rng print-random print-random print-random