aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/crypto/rand/rand_baremetal.go4
-rw-r--r--src/machine/machine_nrf52840_rng.go60
2 files changed, 62 insertions, 2 deletions
diff --git a/src/crypto/rand/rand_baremetal.go b/src/crypto/rand/rand_baremetal.go
index c7a205222..6f3370e96 100644
--- a/src/crypto/rand/rand_baremetal.go
+++ b/src/crypto/rand/rand_baremetal.go
@@ -1,5 +1,5 @@
-//go:build stm32 || (sam && atsamd51) || (sam && atsame5x) || rp2040
-// +build stm32 sam,atsamd51 sam,atsame5x rp2040
+//go:build nrf52840 || stm32 || (sam && atsamd51) || (sam && atsame5x) || rp2040
+// +build nrf52840 stm32 sam,atsamd51 sam,atsame5x rp2040
package rand
diff --git a/src/machine/machine_nrf52840_rng.go b/src/machine/machine_nrf52840_rng.go
new file mode 100644
index 000000000..1d4eba040
--- /dev/null
+++ b/src/machine/machine_nrf52840_rng.go
@@ -0,0 +1,60 @@
+//go:build nrf52840
+// +build nrf52840
+
+package machine
+
+import (
+ "device/nrf"
+)
+
+// Implementation based on Nordic Semiconductor's nRF52840 documentation version 1.7 found here:
+// https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.7.pdf
+
+// SetRNGBiasCorrection configures the RNG peripheral's bias correction mechanism. Note that when
+// bias correction is enabled, the peripheral is slower to produce random values.
+func SetRNGBiasCorrection(enabled bool) {
+ var val uint32
+ if enabled {
+ val = nrf.RNG_CONFIG_DERCEN_Enabled
+ }
+ nrf.RNG.SetCONFIG_DERCEN(val)
+}
+
+// RNGBiasCorrectionEnabled determines whether the RNG peripheral's bias correction mechanism is
+// enabled or not.
+func RNGBiasCorrectionEnabled() bool {
+ return nrf.RNG.GetCONFIG_DERCEN() == nrf.RNG_CONFIG_DERCEN_Enabled
+}
+
+// StartRNG starts the RNG peripheral core. This is automatically called by GetRNG, but can be
+// manually called for interacting with the RNG peripheral directly.
+func StartRNG() {
+ nrf.RNG.SetTASKS_START(nrf.RNG_TASKS_START_TASKS_START_Trigger)
+}
+
+// StopRNG stops the RNG peripheral core. This is not called automatically. It may make sense to
+// manually disable RNG peripheral for power conservation.
+func StopRNG() {
+ nrf.RNG.SetTASKS_STOP(nrf.RNG_TASKS_STOP_TASKS_STOP_Trigger)
+}
+
+// GetRNG returns 32 bits of non-deterministic random data based on internal thermal noise.
+// According to Nordic's documentation, the random output is suitable for cryptographic purposes.
+func GetRNG() (ret uint32, err error) {
+ // There's no apparent way to check the status of the RNG peripheral's task, so simply start it
+ // to avoid deadlocking while waiting for output.
+ StartRNG()
+
+ // The RNG returns one byte at a time, so stack up four bytes into a single uint32 for return.
+ for i := 0; i < 4; i++ {
+ // Wait for data to be ready.
+ for nrf.RNG.GetEVENTS_VALRDY() == nrf.RNG_EVENTS_VALRDY_EVENTS_VALRDY_NotGenerated {
+ }
+ // Append random byte to output.
+ ret = (ret << 8) ^ nrf.RNG.GetVALUE()
+ // Unset the EVENTS_VALRDY register to avoid reading the same random output twice.
+ nrf.RNG.SetEVENTS_VALRDY(nrf.RNG_EVENTS_VALRDY_EVENTS_VALRDY_NotGenerated)
+ }
+
+ return ret, nil
+}