BeRTOS
random_stm32.c
Go to the documentation of this file.
00001 
00038 #include <sec/random_p.h>
00039 
00040 #include <cpu/power.h>
00041 
00042 #include <drv/clock_cm3.h>
00043 
00044 #include <io/cm3.h>
00045 
00046 struct stm32_adc *adc = (struct stm32_adc *)ADC1_BASE;
00047 
00048 /*
00049  * Return the cpu core temperature in raw format
00050  */
00051 INLINE uint16_t hw_readRawTemp(void)
00052 {
00053     /* We sample only from one channel */
00054     adc->SQR1 |= BV(SQR1_SQ_LEN_SHIFT);
00055     adc->SQR3 = (ADC_TEMP_CH & SQR3_SQ_MASK);
00056 
00057     /* Start convertion */
00058     adc->CR2 |= CR2_EXTTRIG_SWSTRT_SET;
00059 
00060     /* Wait in polling until conversion is done */
00061     while (!(adc->SR & BV(SR_EOC)))
00062         cpu_relax();
00063 
00064     /* Return the last converted data */
00065     return (uint16_t)adc->DR;
00066 }
00067 
00068 INLINE void hw_initIntTemp(void)
00069 {
00070     RCC->APB2ENR |= RCC_APB2_ADC1;
00071 
00072     /* Reset registry */
00073     adc->CR1 = 0;
00074     adc->CR2 = 0;
00075     adc->SQR1 = 0;
00076     adc->SQR2 = 0;
00077     adc->SQR3 = 0;
00078 
00079     /*
00080      * Configure ADC
00081      *  - Regular mode
00082      *  - Wake up adc
00083      *  - Wake up temperature and Vrefint
00084      */
00085     adc->CR2 |= BV(CR2_ADON) | ADC_EXTERNALTRIGCONV_NONE | BV(CR2_TSVREFE);
00086 
00087     /* Set 17.1usec sampling time*/
00088     adc->SMPR1 |= ((ADC_SAMPLETIME_239CYCLES5 << SMPR1_CH17) | (ADC_SAMPLETIME_239CYCLES5 << SMPR1_CH16));
00089 }
00090 
00091 
00092 void random_pull_entropy(uint8_t *entropy, size_t len)
00093 {
00094     // We use the internal temperature sensor of LM3S as a source of entropy.
00095     // The last bit of the acquisition is very variable and with a decent distribution
00096     // to consider it "entropic". It does not really matter because it will
00097     // go through a randomness extractor anyway.
00098     hw_initIntTemp();
00099 
00100     for (size_t j=0; j<len; j++)
00101     {
00102         uint8_t accum = 0;
00103         for (int b=0; b<8; ++b)
00104             if (hw_readRawTemp() & 1)
00105                 accum |= 1<<b;
00106 
00107         *entropy++ = accum;
00108     }
00109 }