drivers: entropy: Add nRF5 entropy generator driver
Origin: Original Signed-off-by: Thiago Silveira <thiago@exati.com.br> Signed-off-by: Andrzej Głąbek <andrzej.glabek@nordicsemi.no>
This commit is contained in:
parent
acd10bf7a0
commit
912a51957e
4 changed files with 129 additions and 0 deletions
|
@ -1,5 +1,6 @@
|
||||||
zephyr_sources_ifdef(CONFIG_ENTROPY_ESP32_RNG entropy_esp32.c)
|
zephyr_sources_ifdef(CONFIG_ENTROPY_ESP32_RNG entropy_esp32.c)
|
||||||
zephyr_sources_ifdef(CONFIG_ENTROPY_MCUX_RNGA entropy_mcux_rnga.c)
|
zephyr_sources_ifdef(CONFIG_ENTROPY_MCUX_RNGA entropy_mcux_rnga.c)
|
||||||
zephyr_sources_ifdef(CONFIG_ENTROPY_MCUX_TRNG entropy_mcux_trng.c)
|
zephyr_sources_ifdef(CONFIG_ENTROPY_MCUX_TRNG entropy_mcux_trng.c)
|
||||||
|
zephyr_sources_ifdef(CONFIG_ENTROPY_NRF5_RNG entropy_nrf5.c)
|
||||||
zephyr_sources_ifdef(CONFIG_ENTROPY_STM32_RNG entropy_stm32_rng.c)
|
zephyr_sources_ifdef(CONFIG_ENTROPY_STM32_RNG entropy_stm32_rng.c)
|
||||||
zephyr_sources_ifdef(CONFIG_USERSPACE entropy_handlers.c)
|
zephyr_sources_ifdef(CONFIG_USERSPACE entropy_handlers.c)
|
||||||
|
|
|
@ -18,6 +18,7 @@ if ENTROPY_GENERATOR
|
||||||
source "drivers/entropy/Kconfig.mcux"
|
source "drivers/entropy/Kconfig.mcux"
|
||||||
source "drivers/entropy/Kconfig.stm32"
|
source "drivers/entropy/Kconfig.stm32"
|
||||||
source "drivers/entropy/Kconfig.esp32"
|
source "drivers/entropy/Kconfig.esp32"
|
||||||
|
source "drivers/entropy/Kconfig.nrf5"
|
||||||
|
|
||||||
config ENTROPY_HAS_DRIVER
|
config ENTROPY_HAS_DRIVER
|
||||||
bool
|
bool
|
||||||
|
|
25
drivers/entropy/Kconfig.nrf5
Normal file
25
drivers/entropy/Kconfig.nrf5
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# Kconfig.nrf5 - nRF5 entropy generator driver configuration
|
||||||
|
#
|
||||||
|
# Copyright (c) 2017 Nordic Semiconductor ASA
|
||||||
|
# Copyright (c) 2017 Exati Tecnologia Ltda.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
menuconfig ENTROPY_NRF5_RNG
|
||||||
|
bool "nRF5 RNG driver"
|
||||||
|
# FIXME: nRF5 RNG driver can't co-exist with Bluetooth's HAL
|
||||||
|
# implementation yet
|
||||||
|
depends on ENTROPY_GENERATOR && !BT
|
||||||
|
select ENTROPY_HAS_DRIVER
|
||||||
|
help
|
||||||
|
This option enables the RNG peripheral, which is a random number
|
||||||
|
generator, based on internal thermal noise, that provides a
|
||||||
|
random 8-bit value to the host when read.
|
||||||
|
|
||||||
|
config ENTROPY_NRF5_BIAS_CORRECTION
|
||||||
|
bool "Enable bias correction (uniform distribution)"
|
||||||
|
depends on ENTROPY_NRF5_RNG
|
||||||
|
help
|
||||||
|
This option enables the RNG bias correction, which guarantees a
|
||||||
|
uniform distribution of 0 and 1. When this option is enabled, the time
|
||||||
|
to generate a byte cannot be guaranteed.
|
102
drivers/entropy/entropy_nrf5.c
Normal file
102
drivers/entropy/entropy_nrf5.c
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Nordic Semiconductor ASA
|
||||||
|
* Copyright (c) 2017 Exati Tecnologia Ltda.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <entropy.h>
|
||||||
|
#include <atomic.h>
|
||||||
|
#include <nrf_rng.h>
|
||||||
|
|
||||||
|
struct entropy_nrf5_dev_data {
|
||||||
|
atomic_t user_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEV_DATA(dev) \
|
||||||
|
((struct entropy_nrf5_dev_data *)(dev)->driver_data)
|
||||||
|
|
||||||
|
static inline u8_t entropy_nrf5_get_u8(void)
|
||||||
|
{
|
||||||
|
while (!nrf_rng_event_get(NRF_RNG_EVENT_VALRDY)) {
|
||||||
|
__WFE();
|
||||||
|
__SEV();
|
||||||
|
__WFE();
|
||||||
|
}
|
||||||
|
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
|
||||||
|
|
||||||
|
/* Clear the Pending status of the RNG interrupt so that it could
|
||||||
|
* wake up the core when the VALRDY event occurs again. */
|
||||||
|
NVIC_ClearPendingIRQ(RNG_IRQn);
|
||||||
|
|
||||||
|
return nrf_rng_random_value_get();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int entropy_nrf5_get_entropy(struct device *device, u8_t *buf, u16_t len)
|
||||||
|
{
|
||||||
|
/* Mark the peripheral as being used */
|
||||||
|
atomic_inc(&DEV_DATA(device)->user_count);
|
||||||
|
|
||||||
|
/* Disable the shortcut that stops the task after a byte is generated */
|
||||||
|
nrf_rng_shorts_disable(NRF_RNG_SHORT_VALRDY_STOP_MASK);
|
||||||
|
|
||||||
|
/* Start the RNG generator peripheral */
|
||||||
|
nrf_rng_task_trigger(NRF_RNG_TASK_START);
|
||||||
|
|
||||||
|
while (len) {
|
||||||
|
*buf = entropy_nrf5_get_u8();
|
||||||
|
buf++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only stop the RNG generator peripheral if we're the last user */
|
||||||
|
if (atomic_dec(&DEV_DATA(device)->user_count) == 1) {
|
||||||
|
/* Disable the peripheral on the next VALRDY event */
|
||||||
|
nrf_rng_shorts_enable(NRF_RNG_SHORT_VALRDY_STOP_MASK);
|
||||||
|
|
||||||
|
if (atomic_get(&DEV_DATA(device)->user_count) != 0) {
|
||||||
|
/* Race condition: another thread started to use
|
||||||
|
* the peripheral while we were disabling it.
|
||||||
|
* Enable the peripheral again
|
||||||
|
*/
|
||||||
|
nrf_rng_shorts_disable(NRF_RNG_SHORT_VALRDY_STOP_MASK);
|
||||||
|
nrf_rng_task_trigger(NRF_RNG_TASK_START);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int entropy_nrf5_init(struct device *device)
|
||||||
|
{
|
||||||
|
/* Enable the RNG interrupt to be generated on the VALRDY event,
|
||||||
|
* but do not enable this interrupt in NVIC to be serviced.
|
||||||
|
* When the interrupt enters the Pending state it will set internal
|
||||||
|
* event (SEVONPEND is activated by kernel) and wake up the core
|
||||||
|
* if it was suspended by WFE. And that's enough. */
|
||||||
|
nrf_rng_int_enable(NRF_RNG_INT_VALRDY_MASK);
|
||||||
|
NVIC_ClearPendingIRQ(RNG_IRQn);
|
||||||
|
|
||||||
|
/* Enable or disable bias correction */
|
||||||
|
if (IS_ENABLED(CONFIG_ENTROPY_NRF5_BIAS_CORRECTION)) {
|
||||||
|
nrf_rng_error_correction_enable();
|
||||||
|
} else {
|
||||||
|
nrf_rng_error_correction_disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the user count with zero */
|
||||||
|
atomic_clear(&DEV_DATA(device)->user_count);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct entropy_nrf5_dev_data entropy_nrf5_data;
|
||||||
|
|
||||||
|
static const struct entropy_driver_api entropy_nrf5_api_funcs = {
|
||||||
|
.get_entropy = entropy_nrf5_get_entropy
|
||||||
|
};
|
||||||
|
|
||||||
|
DEVICE_AND_API_INIT(entropy_nrf5, CONFIG_ENTROPY_NAME,
|
||||||
|
entropy_nrf5_init, &entropy_nrf5_data, NULL,
|
||||||
|
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||||
|
&entropy_nrf5_api_funcs);
|
Loading…
Add table
Add a link
Reference in a new issue