OK I figured it out. There is a mistake in the STM32F4xx_spi.c Peripheral Driver file
that doesn't allow the use of the HSI(internal clock) value needed for calculating the appropriate divider and odd values for the I2SPR register. (see the last line)
I changed it to:
i2sclk = (uint32_t)(((HSI_VALUE / pllm) * plln) / pllr);
and now it works. Hours wasted as usual!!
The clock configuration tool is also wrong as it creates a message in the system_stm32F4xx.c file that states
* To achieve the following I2S config: |
* - Master clock output (MCKO): ON |
* - Frame wide : 16bit |
* - Audio sampling freq (KHz) : 48 |
* - Error % : 0.0186 |
* - Prescaler Odd factor (ODD): 0 |
* - Linear prescaler (DIV) : 2 |
which conflicts with the programmers reference that ODD=1 and DIV=3 for 48kHz sample rate, which is correct.
/* Get the PLLI2SN value */
plln = (uint32_t)(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6) & \
(RCC_PLLI2SCFGR_PLLI2SN >> 6));
/* Get the PLLI2SR value */
pllr = (uint32_t)(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28) & \
(RCC_PLLI2SCFGR_PLLI2SR >> 28));
/* Get the PLLM value */
pllm = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM);
/* Get the I2S source clock value */
i2sclk = (uint32_t)(((HSE_VALUE / pllm) * plln) / pllr);
Dave's answer quite nicely resume it, but to clarify a little bit more on the second option:
a real hardware random number generator uses a physical entropy source. Such an entropy source could be cosmic radiation, electrical noise, avanlanche effect from a reverse-biased diode (or BJT transistor), chua circuit, etc. The less deterministic the entropy source, the better the quality of the random output. An ideal entropy source would be to use a quantum physics effect, or something that cannot possibly modeled with deterministic equations.
Another important factor with random number generators is that the entropy source may generate only a limited amount of entropy per unit of time. A good example is the chua circuit: while it is quite random, it has very poor speed and cannot possibly be used for real-life application.
In many processor/microcontrollers with built-in RNGs, the clock drift from 2 to 4 clocks which are deliberatly incorrectly synchronized is used. Then, they use both analog and digital filters to randomize even more the pattern and shift-in the result in a register. Performing such filtering requires a few cycles, which explains the minimum amount of cycles required on a given clock before the newer value is available.
The clock drifting is not quite a quantum effect, so it could be modeled, but it is random enough, because it is dependent on a lot of parameters, such as temperature, silicon process, frequency of operation, electrical noise, background radiations, etc.
In applications where the hardware RNG do not have sufficient throughtput (such as in highly demanding cryptographic applications), it is quite common to use the hardware RNG as a seed for a pseudo random number generator such as the rand() function in the sdtlib. However, such application usually provide a better implementation of rand() which is specifically design to run from a seed which may be discarded very often with true random values. In newer Intel processor with integrated hardware RNGs, the pseudo-random algorithm part is directly integrated in the silicon, so it is performed by hardware, yielding very high random throughtput.
If you mind about the rand() method itself, it is only a methematical expression which is designed to generate a large enough amount of entropy. Large enough being dependant on the application: for cryptographic keys generations, the randomness is required to be of higher quality that the randomness required for a simple random shuffle in your favorite music player. It is obvious that the higher the quality of the random output, the higher the computational cost of the random number.
The operations involved in a random number are quite similar to the one involved in computing the MD5 hash of a file: they try to use a kind of bit avalanche effect so that a single bit change in a seed value changes the whole generating pattern. As a side note, I do NOT recommand using MD5 as a pseudo-random number generator; it was only an example. It would be both inefficient and not so random, but the point is there: if you feed the same file to an MD5 hasing algorithm, you will always get the same deterministic output, pretty much the same way you would always get the same output from the rand() function if you input the same seed unless your implementation depends on some arbitrary elements such as current time.
Best Answer
If you need an int use int bla = RNG_DR % 14 + 1 (yields a number between 0 and 15 (not including 0 and 15)); RNG_DR is the Data register of the RNG. You will need to check for the data ready flag to get valid values.
If you need something else, please specify :)