machine/nrf52840: implement RNG peripheral operation

Этот коммит содержится в:
Matt Schultz 2022-09-11 15:08:04 -05:00 коммит произвёл Ron Evans
родитель ea1e08f53f
коммит 4ba76a5df9
2 изменённых файлов: 62 добавлений и 2 удалений

Просмотреть файл

@ -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

60
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
}