PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3 vuotta sitten
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. // Entropy - A entropy (random number) generator for the Arduino
  2. // The latest version of this library will always be stored in the following
  3. // google code repository:
  4. // http://code.google.com/p/avr-hardware-random-number-generation/source/browse/#git%2FEntropy
  5. // with more information available on the libraries wiki page
  6. // http://code.google.com/p/avr-hardware-random-number-generation/wiki/WikiAVRentropy
  7. //
  8. // Copyright 2014 by Walter Anderson
  9. //
  10. // This file is part of Entropy, an Arduino library.
  11. // Entropy is free software: you can redistribute it and/or modify
  12. // it under the terms of the GNU General Public License as published by
  13. // the Free Software Foundation, either version 3 of the License, or
  14. // (at your option) any later version.
  15. //
  16. // Entropy is distributed in the hope that it will be useful,
  17. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. // GNU General Public License for more details.
  20. //
  21. // You should have received a copy of the GNU General Public License
  22. // along with Entropy. If not, see <http://www.gnu.org/licenses/>.
  23. #include <Arduino.h>
  24. #include <Entropy.h>
  25. const uint8_t WDT_MAX_8INT=0xFF;
  26. const uint16_t WDT_MAX_16INT=0xFFFF;
  27. const uint32_t WDT_MAX_32INT=0xFFFFFFFF;
  28. // Board-specific defines and variables
  29. // Arduino Due
  30. #if defined(ARDUINO_SAM_DUE)
  31. // Since the Due TRNG is so fast we don't need a circular buffer for it
  32. #define HAS_HARDWARE_RANDOM_NUMBER_GENERATOR
  33. // Teensy 3.5 & 3.6
  34. #elif defined(__MK66FX1M0__) || defined (__MK64FX512__)
  35. #define HAS_HARDWARE_RANDOM_NUMBER_GENERATOR
  36. #define RNG_CR_GO_MASK 0x1u
  37. #define RNG_CR_HA_MASK 0x2u
  38. #define RNG_CR_INTM_MASK 0x4u
  39. #define RNG_CR_CLRI_MASK 0x8u
  40. #define RNG_CR_SLP_MASK 0x10u
  41. #define RNG_SR_OREG_LVL_MASK 0xFF00u
  42. #define RNG_SR_OREG_LVL_SHIFT 8
  43. #define RNG_SR_OREG_LVL(x) (((uint32_t)(((uint32_t)(x))<<RNG_SR_OREG_LVL_SHIFT))&RNG_SR_OREG_LVL_MASK)
  44. // Teensy 4.0 & 4.1
  45. #elif defined(__IMXRT1062__)
  46. #define HAS_HARDWARE_RANDOM_NUMBER_GENERATOR
  47. uint32_t gWDT_trng_prior[16];
  48. uint8_t gWDT_trng_index=16;
  49. #endif
  50. // buffer and entropy pool used for boards without hardware random numbers
  51. #ifndef HAS_HARDWARE_RANDOM_NUMBER_GENERATOR
  52. const uint8_t gWDT_buffer_SIZE=32;
  53. const uint8_t WDT_POOL_SIZE=8;
  54. uint8_t gWDT_buffer[gWDT_buffer_SIZE];
  55. uint8_t gWDT_buffer_position;
  56. uint8_t gWDT_loop_counter;
  57. volatile uint8_t gWDT_pool_start;
  58. volatile uint8_t gWDT_pool_end;
  59. volatile uint8_t gWDT_pool_count;
  60. volatile uint32_t gWDT_entropy_pool[WDT_POOL_SIZE];
  61. #endif
  62. // This function initializes the global variables needed to implement the circular entropy pool and
  63. // the buffer that holds the raw Timer 1 values that are used to create the entropy pool. It then
  64. // Initializes the Watch Dog Timer (WDT) to perform an interrupt every 2048 clock cycles, (about
  65. // 16 ms) which is as fast as it can be set.
  66. void EntropyClass::Initialize(void)
  67. {
  68. #ifndef HAS_HARDWARE_RANDOM_NUMBER_GENERATOR
  69. gWDT_buffer_position=0;
  70. gWDT_pool_start = 0;
  71. gWDT_pool_end = 0;
  72. gWDT_pool_count = 0;
  73. #endif
  74. #if defined(__AVR__)
  75. cli(); // Temporarily turn off interrupts, until WDT configured
  76. MCUSR = 0; // Use the MCU status register to reset flags for WDR, BOR, EXTR, and POWR
  77. _WD_CONTROL_REG |= (1<<_WD_CHANGE_BIT) | (1<<WDE);
  78. // WDTCSR |= _BV(WDCE) | _BV(WDE);// WDT control register, This sets the Watchdog Change Enable (WDCE) flag, which is needed to set the
  79. _WD_CONTROL_REG = _BV(WDIE); // Watchdog system reset (WDE) enable and the Watchdog interrupt enable (WDIE)
  80. sei(); // Turn interupts on
  81. #elif defined(ARDUINO_SAM_DUE)
  82. pmc_enable_periph_clk(ID_TRNG);
  83. TRNG->TRNG_IDR = 0xFFFFFFFF;
  84. TRNG->TRNG_CR = TRNG_CR_KEY(0x524e47) | TRNG_CR_ENABLE;
  85. #elif defined(__MK66FX1M0__) || defined (__MK64FX512__)
  86. SIM_SCGC6 |= SIM_SCGC6_RNGA; // enable RNG T3.5/3.6
  87. RNG_CR &= ~RNG_CR_SLP_MASK;
  88. RNG_CR |= RNG_CR_HA_MASK; // high assurance
  89. RNG_CR |= RNG_CR_GO_MASK;
  90. #elif defined(__IMXRT1062__)
  91. CCM_CCGR6 |= CCM_CCGR6_TRNG(CCM_CCGR_ON);
  92. TRNG_MCTL = TRNG_MCTL_RST_DEF | TRNG_MCTL_PRGM; // reset to program mode
  93. TRNG_SCMISC = TRNG_SCMISC_RTY_CT(TRNG_DEFAULT_RETRY_COUNT) |
  94. TRNG_SCMISC_LRUN_MAX(TRNG_DEFAULT_RUN_MAX_LIMIT);
  95. TRNG_SCML = TRNG_SCML_MONO_MAX(TRNG_DEFAULT_MONOBIT_MAXIMUM) |
  96. TRNG_SCML_MONO_RNG(TRNG_DEFAULT_MONOBIT_MAXIMUM - TRNG_DEFAULT_MONOBIT_MINIMUM);
  97. TRNG_SCR1L = TRNG_SCR1L_RUN1_MAX(TRNG_DEFAULT_RUNBIT1_MAXIMUM) |
  98. TRNG_SCR1L_RUN1_RNG(TRNG_DEFAULT_RUNBIT1_MAXIMUM - TRNG_DEFAULT_RUNBIT1_MINIMUM);
  99. TRNG_SCR2L = TRNG_SCR2L_RUN2_MAX(TRNG_DEFAULT_RUNBIT2_MAXIMUM) |
  100. TRNG_SCR2L_RUN2_RNG(TRNG_DEFAULT_RUNBIT2_MAXIMUM - TRNG_DEFAULT_RUNBIT2_MINIMUM);
  101. TRNG_SCR3L = TRNG_SCR3L_RUN3_MAX(TRNG_DEFAULT_RUNBIT3_MAXIMUM) |
  102. TRNG_SCR3L_RUN3_RNG(TRNG_DEFAULT_RUNBIT3_MAXIMUM - TRNG_DEFAULT_RUNBIT3_MINIMUM);
  103. TRNG_SCR4L = TRNG_SCR4L_RUN4_MAX(TRNG_DEFAULT_RUNBIT4_MAXIMUM) |
  104. TRNG_SCR4L_RUN4_RNG(TRNG_DEFAULT_RUNBIT4_MAXIMUM - TRNG_DEFAULT_RUNBIT4_MINIMUM);
  105. TRNG_SCR5L = TRNG_SCR5L_RUN5_MAX(TRNG_DEFAULT_RUNBIT5_MAXIMUM) |
  106. TRNG_SCR5L_RUN5_RNG(TRNG_DEFAULT_RUNBIT5_MAXIMUM - TRNG_DEFAULT_RUNBIT5_MINIMUM);
  107. TRNG_SCR6PL = TRNG_SCR6PL_RUN6P_MAX(TRNG_DEFAULT_RUNBIT6PLUS_MAXIMUM) |
  108. TRNG_SCR6PL_RUN6P_RNG(TRNG_DEFAULT_RUNBIT6PLUS_MAXIMUM -
  109. TRNG_DEFAULT_RUNBIT6PLUS_MINIMUM);
  110. TRNG_PKRMAX = TRNG_DEFAULT_POKER_MAXIMUM;
  111. TRNG_PKRRNG = TRNG_DEFAULT_POKER_MAXIMUM - TRNG_DEFAULT_POKER_MINIMUM;
  112. TRNG_FRQMAX = TRNG_DEFAULT_FREQUENCY_MAXIMUM;
  113. TRNG_FRQMIN = TRNG_DEFAULT_FREQUENCY_MINIMUM;
  114. TRNG_SDCTL = TRNG_SDCTL_ENT_DLY(TRNG_DEFAULT_ENTROPY_DELAY) |
  115. TRNG_SDCTL_SAMP_SIZE(TRNG_DEFAULT_SAMPLE_SIZE);
  116. TRNG_SBLIM = TRNG_DEFAULT_SPARSE_BIT_LIMIT;
  117. TRNG_MCTL = TRNG_MCTL_SAMP_MODE(2); // start run mode
  118. TRNG_ENT15; // discard any stale data
  119. #elif defined(__arm__) && defined(TEENSYDUINO)
  120. SIM_SCGC5 |= SIM_SCGC5_LPTIMER;
  121. LPTMR0_CSR = 0b10000100;
  122. LPTMR0_PSR = 0b00000101; // PCS=01 : 1 kHz clock
  123. LPTMR0_CMR = 0x0006; // smaller number = faster random numbers...
  124. LPTMR0_CSR = 0b01000101;
  125. NVIC_ENABLE_IRQ(IRQ_LPTMR);
  126. #endif
  127. }
  128. // This function returns a uniformly distributed random integer in the range
  129. // of [0,0xFFFFFFFF] as long as some entropy exists in the pool and a 0
  130. // otherwise. To ensure a proper random return the available() function
  131. // should be called first to ensure that entropy exists.
  132. //
  133. // The pool is implemented as an 8 value circular buffer
  134. uint32_t EntropyClass::random(void)
  135. {
  136. #ifdef ARDUINO_SAM_DUE
  137. while (! (TRNG->TRNG_ISR & TRNG_ISR_DATRDY))
  138. ;
  139. retVal = TRNG->TRNG_ODATA;
  140. #elif defined(__MK66FX1M0__) || defined (__MK64FX512__)
  141. while ((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0); // wait
  142. retVal = RNG_OR;
  143. #elif defined(__IMXRT1062__)
  144. while (!available()) ; // wait
  145. return gWDT_trng_prior[gWDT_trng_index++];
  146. #else
  147. uint8_t waiting;
  148. while (gWDT_pool_count < 1)
  149. waiting += 1;
  150. ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
  151. {
  152. retVal = gWDT_entropy_pool[gWDT_pool_start];
  153. gWDT_pool_start = (gWDT_pool_start + 1) % WDT_POOL_SIZE;
  154. --gWDT_pool_count;
  155. }
  156. #endif
  157. return(retVal);
  158. }
  159. // This function returns one byte of a single 32-bit entropy value, while preserving the remaining bytes to
  160. // be returned upon successive calls to the method. This makes best use of the available entropy pool when
  161. // only bytes size chunks of entropy are needed. Not available to public use since there is a method of using
  162. // the default random method for the end-user to achieve the same results. This internal method is for providing
  163. // that capability to the random method, shown below
  164. uint8_t EntropyClass::random8(void)
  165. {
  166. static uint8_t byte_position=0;
  167. uint8_t retVal8;
  168. if (byte_position == 0)
  169. share_entropy.int32 = random();
  170. retVal8 = share_entropy.int8[byte_position++];
  171. byte_position = byte_position % 4;
  172. return(retVal8);
  173. }
  174. // This function returns one word of a single 32-bit entropy value, while preserving the remaining word to
  175. // be returned upon successive calls to the method. This makes best use of the available entropy pool when
  176. // only word sized chunks of entropy are needed. Not available to public use since there is a method of using
  177. // the default random method for the end-user to achieve the same results. This internal method is for providing
  178. // that capability to the random method, shown below
  179. uint16_t EntropyClass::random16(void)
  180. {
  181. static uint8_t word_position=0;
  182. uint16_t retVal16;
  183. if (word_position == 0)
  184. share_entropy.int32 = random();
  185. retVal16 = share_entropy.int16[word_position++];
  186. word_position = word_position % 2;
  187. return(retVal16);
  188. }
  189. // This function returns a uniformly distributed integer in the range of
  190. // of [0,max). The added complexity of this function is required to ensure
  191. // a uniform distribution since the naive modulus max (% max) introduces
  192. // bias for all values of max that are not powers of two.
  193. //
  194. // The loops below are needed, because there is a small and non-uniform chance
  195. // That the division below will yield an answer = max, so we just get
  196. // the next random value until answer < max. Which prevents the introduction
  197. // of bias caused by the division process. This is why we can't use the
  198. // simpler modulus operation which introduces significant bias for divisors
  199. // that aren't a power of two
  200. uint32_t EntropyClass::random(uint32_t max)
  201. {
  202. uint32_t slice;
  203. if (max < 2)
  204. retVal=0;
  205. else
  206. {
  207. retVal = WDT_MAX_32INT;
  208. if (max <= WDT_MAX_8INT) // If only byte values are needed, make best use of entropy
  209. { // by diving the long into four bytes and using individually
  210. slice = WDT_MAX_8INT / max;
  211. while (retVal >= max)
  212. retVal = random8() / slice;
  213. }
  214. else if (max <= WDT_MAX_16INT) // If only word values are need, make best use of entropy
  215. { // by diving the long into two words and using individually
  216. slice = WDT_MAX_16INT / max;
  217. while (retVal >= max)
  218. retVal = random16() / slice;
  219. }
  220. else
  221. {
  222. slice = WDT_MAX_32INT / max;
  223. while (retVal >= max)
  224. retVal = random() / slice;
  225. }
  226. }
  227. return(retVal);
  228. }
  229. // This function returns a uniformly distributed integer in the range of
  230. // of [min,max).
  231. uint32_t EntropyClass::random(uint32_t min, uint32_t max)
  232. {
  233. uint32_t tmp_random, tmax;
  234. tmax = max - min;
  235. if (tmax < 1)
  236. retVal=min;
  237. else
  238. {
  239. tmp_random = random(tmax);
  240. retVal = min + tmp_random;
  241. }
  242. return(retVal);
  243. }
  244. // This function returns a uniformly distributed single precision floating point
  245. // in the range of [0.0,1.0)
  246. float EntropyClass::randomf(void)
  247. {
  248. float fRetVal;
  249. // Since c++ doesn't allow bit manipulations of floating point types, we are
  250. // using integer type and arrange its bit pattern to follow the IEEE754 bit
  251. // pattern for single precision floating point value in the range of 1.0 - 2.0
  252. uint32_t tmp_random = random();
  253. tmp_random = (tmp_random & 0x007FFFFF) | 0x3F800000;
  254. // We then copy that binary representation from the temporary integer to the
  255. // returned floating point value
  256. memcpy((void *) &fRetVal, (void *) &tmp_random, sizeof(fRetVal));
  257. // Now translate the value back to its intended range by subtracting 1.0
  258. fRetVal = fRetVal - 1.0;
  259. return (fRetVal);
  260. }
  261. // This function returns a uniformly distributed single precision floating point
  262. // in the range of [0.0, max)
  263. float EntropyClass::randomf(float max)
  264. {
  265. float fRetVal;
  266. fRetVal = randomf() * max;
  267. return(fRetVal);
  268. }
  269. // This function returns a uniformly distributed single precision floating point
  270. // in the range of [min, max)
  271. float EntropyClass::randomf(float min,float max)
  272. {
  273. float fRetVal;
  274. float tmax;
  275. tmax = max - min;
  276. fRetVal = (randomf() * tmax) + min;
  277. return(fRetVal);
  278. }
  279. // This function implements the Marsaglia polar method of converting a uniformly
  280. // distributed random numbers to a normaly distributed (bell curve) with the
  281. // mean and standard deviation specified. This type of random number is useful
  282. // for a variety of purposes, like Monte Carlo simulations.
  283. float EntropyClass::rnorm(float mean, float stdDev)
  284. {
  285. static float spare;
  286. static float u1;
  287. static float u2;
  288. static float s;
  289. static bool isSpareReady = false;
  290. if (isSpareReady)
  291. {
  292. isSpareReady = false;
  293. return ((spare * stdDev) + mean);
  294. } else {
  295. do {
  296. u1 = (randomf() * 2) - 1;
  297. u2 = (randomf() * 2) - 1;
  298. s = (u1 * u1) + (u2 * u2);
  299. } while (s >= 1.0);
  300. s = sqrt(-2.0 * log(s) / s);
  301. spare = u2 * s;
  302. isSpareReady = true;
  303. return(mean + (stdDev * u1 * s));
  304. }
  305. }
  306. // This function returns a unsigned char (8-bit) with the number of unsigned long values
  307. // in the entropy pool
  308. uint8_t EntropyClass::available(void)
  309. {
  310. #ifdef ARDUINO_SAM_DUE
  311. return(TRNG->TRNG_ISR & TRNG_ISR_DATRDY);
  312. #elif defined(__MK66FX1M0__) || defined (__MK64FX512__)
  313. return (RNG_SR & RNG_SR_OREG_LVL(0xF));
  314. #elif defined(__IMXRT1062__)
  315. if (gWDT_trng_index < 16) return (16 - gWDT_trng_index);
  316. uint32_t m = TRNG_MCTL;
  317. if (m & TRNG_MCTL_ENT_VAL) {
  318. } else if (m & TRNG_MCTL_ERR) {
  319. TRNG_MCTL = m;
  320. } else {
  321. return 0;
  322. }
  323. for (int i=0; i < 16; i++) {
  324. gWDT_trng_prior[i] = *(&TRNG_ENT0 + i); // copy 512 bits from TRNG
  325. }
  326. gWDT_trng_index = 0;
  327. return 16;
  328. #else
  329. return(gWDT_pool_count);
  330. #endif
  331. }
  332. // Circular buffer is not needed with the speed of the Arduino Due trng hardware generator
  333. #ifndef HAS_HARDWARE_RANDOM_NUMBER_GENERATOR
  334. // This interrupt service routine is called every time the WDT interrupt is triggered.
  335. // With the default configuration that is approximately once every 16ms, producing
  336. // approximately two 32-bit integer values every second.
  337. //
  338. // The pool is implemented as an 8 value circular buffer
  339. static void isr_hardware_neutral(uint8_t val)
  340. {
  341. gWDT_buffer[gWDT_buffer_position] = val;
  342. gWDT_buffer_position++; // every time the WDT interrupt is triggered
  343. if (gWDT_buffer_position >= gWDT_buffer_SIZE)
  344. {
  345. gWDT_pool_end = (gWDT_pool_start + gWDT_pool_count) % WDT_POOL_SIZE;
  346. // The following code is an implementation of Jenkin's one at a time hash
  347. // This hash function has had preliminary testing to verify that it
  348. // produces reasonably uniform random results when using WDT jitter
  349. // on a variety of Arduino platforms
  350. for(gWDT_loop_counter = 0; gWDT_loop_counter < gWDT_buffer_SIZE; ++gWDT_loop_counter)
  351. {
  352. gWDT_entropy_pool[gWDT_pool_end] += gWDT_buffer[gWDT_loop_counter];
  353. gWDT_entropy_pool[gWDT_pool_end] += (gWDT_entropy_pool[gWDT_pool_end] << 10);
  354. gWDT_entropy_pool[gWDT_pool_end] ^= (gWDT_entropy_pool[gWDT_pool_end] >> 6);
  355. }
  356. gWDT_entropy_pool[gWDT_pool_end] += (gWDT_entropy_pool[gWDT_pool_end] << 3);
  357. gWDT_entropy_pool[gWDT_pool_end] ^= (gWDT_entropy_pool[gWDT_pool_end] >> 11);
  358. gWDT_entropy_pool[gWDT_pool_end] += (gWDT_entropy_pool[gWDT_pool_end] << 15);
  359. gWDT_entropy_pool[gWDT_pool_end] = gWDT_entropy_pool[gWDT_pool_end];
  360. gWDT_buffer_position = 0; // Start collecting the next 32 bytes of Timer 1 counts
  361. if (gWDT_pool_count == WDT_POOL_SIZE) // The entropy pool is full
  362. gWDT_pool_start = (gWDT_pool_start + 1) % WDT_POOL_SIZE;
  363. else // Add another unsigned long (32 bits) to the entropy pool
  364. ++gWDT_pool_count;
  365. }
  366. }
  367. #endif
  368. #if defined( __AVR_ATtiny25__ ) || defined( __AVR_ATtiny45__ ) || defined( __AVR_ATtiny85__ )
  369. ISR(WDT_vect)
  370. {
  371. isr_hardware_neutral(TCNT0);
  372. }
  373. #elif defined(__AVR__)
  374. ISR(WDT_vect)
  375. {
  376. isr_hardware_neutral(TCNT1L); // Record the Timer 1 low byte (only one needed)
  377. }
  378. #elif defined(__arm__) && defined(TEENSYDUINO) && !defined(HAS_HARDWARE_RANDOM_NUMBER_GENERATOR)
  379. void lptmr_isr(void)
  380. {
  381. LPTMR0_CSR = 0b10000100;
  382. LPTMR0_CSR = 0b01000101;
  383. isr_hardware_neutral(SYST_CVR);
  384. }
  385. #endif
  386. // The library implements a single global instance. There is no need, nor will the library
  387. // work properly if multiple instances are created.
  388. EntropyClass Entropy;