summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--watch-library/watch/watch_private.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/watch-library/watch/watch_private.c b/watch-library/watch/watch_private.c
index 270208dc..e652b271 100644
--- a/watch-library/watch/watch_private.c
+++ b/watch-library/watch/watch_private.c
@@ -65,6 +65,38 @@ void _watch_init() {
a4_callback = NULL;
}
+static inline void _watch_wait_for_entropy() {
+ while (!hri_trng_get_INTFLAG_reg(TRNG, TRNG_INTFLAG_DATARDY));
+}
+
+// this function is called by arc4random to get entropy for random number generation.
+// let's use the SAM L22's true random number generator to seed the PRNG!
+int getentropy(void *buf, size_t buflen) {
+ hri_mclk_set_APBCMASK_TRNG_bit(MCLK);
+ hri_trng_set_CTRLA_ENABLE_bit(TRNG);
+
+ size_t i = 0;
+ while(i < buflen / 4) {
+ _watch_wait_for_entropy();
+ ((uint32_t *)buf)[i++] = hri_trng_read_DATA_reg(TRNG);
+ }
+
+ // but what if they asked for an awkward number of bytes?
+ if (buflen % 4) {
+ // all good: let's fill in one, two or three bytes at the end of the buffer.
+ _watch_wait_for_entropy();
+ uint32_t last_little_bit = hri_trng_read_DATA_reg(TRNG);
+ for(size_t j = 0; j <= (buflen % 4); j++) {
+ ((uint8_t *)buf)[i * 4 + j] = (last_little_bit >> (j * 8)) & 0xFF;
+ }
+ }
+
+ hri_trng_clear_CTRLA_ENABLE_bit(TRNG);
+ hri_mclk_clear_APBCMASK_TRNG_bit(MCLK);
+
+ return 0;
+}
+
void _watch_enable_tcc() {
// clock TCC0 with the main clock (8 MHz) and enable the peripheral clock.
hri_gclk_write_PCHCTRL_reg(GCLK, TCC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK0_Val | GCLK_PCHCTRL_CHEN);