Merge pull request #6116 from marcuschangarm/fix_trng_nrf52

Add TRNG for NRF52832
pull/6119/merge
Cruz Monrreal 2018-02-26 12:09:43 -06:00 committed by GitHub
commit c9cefccbdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 761 additions and 23 deletions

View File

@ -171,7 +171,7 @@
#define NRF_MAXIMUM_LATENCY_US 2000
/* RNG */
#define RNG_ENABLED 0
#define RNG_ENABLED 1
#if (RNG_ENABLED == 1)
#define RNG_CONFIG_ERROR_CORRECTION true

View File

@ -0,0 +1,281 @@
/*
* Copyright (c) 2014 Nordic Semiconductor ASA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
* integrated circuit in a product or a software update for such product, must reproduce
* the above copyright notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific prior
* written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @file
* @brief RNG HAL API.
*/
#ifndef NRF_RNG_H__
#define NRF_RNG_H__
/**
* @defgroup nrf_rng_hal RNG HAL
* @{
* @ingroup nrf_rng
* @brief Hardware access layer for managing the random number generator (RNG).
*/
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "nrf.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NRF_RNG_TASK_SET (1UL)
#define NRF_RNG_EVENT_CLEAR (0UL)
/**
* @enum nrf_rng_task_t
* @brief RNG tasks.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_RNG_TASK_START = offsetof(NRF_RNG_Type, TASKS_START), /**< Start the random number generator. */
NRF_RNG_TASK_STOP = offsetof(NRF_RNG_Type, TASKS_STOP) /**< Stop the random number generator. */
} nrf_rng_task_t; /*lint -restore */
/**
* @enum nrf_rng_event_t
* @brief RNG events.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_RNG_EVENT_VALRDY = offsetof(NRF_RNG_Type, EVENTS_VALRDY) /**< New random number generated event. */
} nrf_rng_event_t; /*lint -restore */
/**
* @enum nrf_rng_int_mask_t
* @brief RNG interrupts.
*/
typedef enum
{
NRF_RNG_INT_VALRDY_MASK = RNG_INTENSET_VALRDY_Msk /**< Mask for enabling or disabling an interrupt on VALRDY event. */
} nrf_rng_int_mask_t;
/**
* @enum nrf_rng_short_mask_t
* @brief Types of RNG shortcuts.
*/
typedef enum
{
NRF_RNG_SHORT_VALRDY_STOP_MASK = RNG_SHORTS_VALRDY_STOP_Msk /**< Mask for setting shortcut between EVENT_VALRDY and TASK_STOP. */
} nrf_rng_short_mask_t;
/**
* @brief Function for enabling interrupts.
*
* @param[in] rng_int_mask Mask of interrupts.
*/
__STATIC_INLINE void nrf_rng_int_enable(uint32_t rng_int_mask);
/**
* @brief Function for disabling interrupts.
*
* @param[in] rng_int_mask Mask of interrupts.
*/
__STATIC_INLINE void nrf_rng_int_disable(uint32_t rng_int_mask);
/**
* @brief Function for getting the state of a specific interrupt.
*
* @param[in] rng_int_mask Interrupt.
*
* @retval true If the interrupt is not enabled.
* @retval false If the interrupt is enabled.
*/
__STATIC_INLINE bool nrf_rng_int_get(nrf_rng_int_mask_t rng_int_mask);
/**
* @brief Function for getting the address of a specific task.
*
* This function can be used by the PPI module.
*
* @param[in] rng_task Task.
*/
__STATIC_INLINE uint32_t * nrf_rng_task_address_get(nrf_rng_task_t rng_task);
/**
* @brief Function for setting a specific task.
*
* @param[in] rng_task Task.
*/
__STATIC_INLINE void nrf_rng_task_trigger(nrf_rng_task_t rng_task);
/**
* @brief Function for getting address of a specific event.
*
* This function can be used by the PPI module.
*
* @param[in] rng_event Event.
*/
__STATIC_INLINE uint32_t * nrf_rng_event_address_get(nrf_rng_event_t rng_event);
/**
* @brief Function for clearing a specific event.
*
* @param[in] rng_event Event.
*/
__STATIC_INLINE void nrf_rng_event_clear(nrf_rng_event_t rng_event);
/**
* @brief Function for getting the state of a specific event.
*
* @param[in] rng_event Event.
*
* @retval true If the event is not set.
* @retval false If the event is set.
*/
__STATIC_INLINE bool nrf_rng_event_get(nrf_rng_event_t rng_event);
/**
* @brief Function for setting shortcuts.
*
* @param[in] rng_short_mask Mask of shortcuts.
*
*/
__STATIC_INLINE void nrf_rng_shorts_enable(uint32_t rng_short_mask);
/**
* @brief Function for clearing shortcuts.
*
* @param[in] rng_short_mask Mask of shortcuts.
*
*/
__STATIC_INLINE void nrf_rng_shorts_disable(uint32_t rng_short_mask);
/**
* @brief Function for getting the previously generated random value.
*
* @return Previously generated random value.
*/
__STATIC_INLINE uint8_t nrf_rng_random_value_get(void);
/**
* @brief Function for enabling digital error correction.
*/
__STATIC_INLINE void nrf_rng_error_correction_enable(void);
/**
* @brief Function for disabling digital error correction.
*/
__STATIC_INLINE void nrf_rng_error_correction_disable(void);
/**
*@}
**/
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_rng_int_enable(uint32_t rng_int_mask)
{
NRF_RNG->INTENSET = rng_int_mask;
}
__STATIC_INLINE void nrf_rng_int_disable(uint32_t rng_int_mask)
{
NRF_RNG->INTENCLR = rng_int_mask;
}
__STATIC_INLINE bool nrf_rng_int_get(nrf_rng_int_mask_t rng_int_mask)
{
return (bool)(NRF_RNG->INTENCLR & rng_int_mask);
}
__STATIC_INLINE uint32_t * nrf_rng_task_address_get(nrf_rng_task_t rng_task)
{
return (uint32_t *)((uint8_t *)NRF_RNG + rng_task);
}
__STATIC_INLINE void nrf_rng_task_trigger(nrf_rng_task_t rng_task)
{
*((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_task)) = NRF_RNG_TASK_SET;
}
__STATIC_INLINE uint32_t * nrf_rng_event_address_get(nrf_rng_event_t rng_event)
{
return (uint32_t *)((uint8_t *)NRF_RNG + rng_event);
}
__STATIC_INLINE void nrf_rng_event_clear(nrf_rng_event_t rng_event)
{
*((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_event)) = NRF_RNG_EVENT_CLEAR;
#if __CORTEX_M == 0x04
volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_event));
(void)dummy;
#endif
}
__STATIC_INLINE bool nrf_rng_event_get(nrf_rng_event_t rng_event)
{
return (bool) * ((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_event));
}
__STATIC_INLINE void nrf_rng_shorts_enable(uint32_t rng_short_mask)
{
NRF_RNG->SHORTS |= rng_short_mask;
}
__STATIC_INLINE void nrf_rng_shorts_disable(uint32_t rng_short_mask)
{
NRF_RNG->SHORTS &= ~rng_short_mask;
}
__STATIC_INLINE uint8_t nrf_rng_random_value_get(void)
{
return (uint8_t)(NRF_RNG->VALUE & RNG_VALUE_VALUE_Msk);
}
__STATIC_INLINE void nrf_rng_error_correction_enable(void)
{
NRF_RNG->CONFIG |= RNG_CONFIG_DERCEN_Msk;
}
__STATIC_INLINE void nrf_rng_error_correction_disable(void)
{
NRF_RNG->CONFIG &= ~RNG_CONFIG_DERCEN_Msk;
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* NRF_RNG_H__ */

View File

@ -0,0 +1,250 @@
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
#include <stdint.h>
#include <stddef.h>
#include "nrf_drv_rng.h"
#include "nrf_assert.h"
#include "nrf_drv_common.h"
#include "nordic_common.h"
#include "nrf_error.h"
#include "nrf_assert.h"
#ifdef SOFTDEVICE_PRESENT
#include "nrf_sdm.h"
#include "nrf_soc.h"
#else
#include "app_fifo.h"
#include "app_util_platform.h"
static __INLINE uint32_t fifo_length(app_fifo_t * p_fifo)
{
uint32_t tmp = p_fifo->read_pos;
return p_fifo->write_pos - tmp;
}
#define FIFO_LENGTH(fifo) fifo_length(&(fifo)) /**< Macro for calculating the FIFO length. */
#endif // SOFTDEVICE_PRESENT
typedef struct
{
nrf_drv_state_t state;
#ifndef SOFTDEVICE_PRESENT
app_fifo_t rand_pool;
uint8_t buffer[RNG_CONFIG_POOL_SIZE];
#endif // SOFTDEVICE_PRESENT
} nrf_drv_rng_cb_t;
static nrf_drv_rng_cb_t m_rng_cb;
#ifndef SOFTDEVICE_PRESENT
static const nrf_drv_rng_config_t m_default_config = NRF_DRV_RNG_DEFAULT_CONFIG;
static void rng_start(void)
{
if (FIFO_LENGTH(m_rng_cb.rand_pool) <= m_rng_cb.rand_pool.buf_size_mask)
{
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
nrf_rng_int_enable(NRF_RNG_INT_VALRDY_MASK);
nrf_rng_task_trigger(NRF_RNG_TASK_START);
}
}
static void rng_stop(void)
{
nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK);
nrf_rng_task_trigger(NRF_RNG_TASK_STOP);
}
#endif // SOFTDEVICE_PRESENT
ret_code_t nrf_drv_rng_init(nrf_drv_rng_config_t const * p_config)
{
uint32_t result;
if (m_rng_cb.state == NRF_DRV_STATE_UNINITIALIZED)
{
#ifndef SOFTDEVICE_PRESENT
result = app_fifo_init(&m_rng_cb.rand_pool, m_rng_cb.buffer, RNG_CONFIG_POOL_SIZE);
if (p_config == NULL)
{
p_config = &m_default_config;
}
if (result == NRF_SUCCESS)
{
if (p_config->error_correction)
{
nrf_rng_error_correction_enable();
}
nrf_drv_common_irq_enable(RNG_IRQn, p_config->interrupt_priority);
nrf_rng_shorts_disable(NRF_RNG_SHORT_VALRDY_STOP_MASK);
rng_start();
m_rng_cb.state = NRF_DRV_STATE_INITIALIZED;
}
#else
UNUSED_VARIABLE(p_config);
uint8_t softdevice_is_enabled;
result = sd_softdevice_is_enabled(&softdevice_is_enabled);
if (softdevice_is_enabled)
{
m_rng_cb.state = NRF_DRV_STATE_INITIALIZED;
}
else
{
result = NRF_ERROR_SOFTDEVICE_NOT_ENABLED;
}
#endif // SOFTDEVICE_PRESENT
}
else
{
result = NRF_ERROR_INVALID_STATE;
}
return result;
}
void nrf_drv_rng_uninit(void)
{
ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
m_rng_cb.state = NRF_DRV_STATE_UNINITIALIZED;
#ifndef SOFTDEVICE_PRESENT
rng_stop();
nrf_drv_common_irq_disable(RNG_IRQn);
#endif // SOFTDEVICE_PRESENT
}
ret_code_t nrf_drv_rng_bytes_available(uint8_t * p_bytes_available)
{
ret_code_t result;
ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
#ifndef SOFTDEVICE_PRESENT
result = NRF_SUCCESS;
*p_bytes_available = FIFO_LENGTH(m_rng_cb.rand_pool);
#else
result = sd_rand_application_bytes_available_get(p_bytes_available);
#endif // SOFTDEVICE_PRESENT
return result;
}
ret_code_t nrf_drv_rng_pool_capacity(uint8_t * p_pool_capacity)
{
ret_code_t result;
ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
#ifndef SOFTDEVICE_PRESENT
result = NRF_SUCCESS;
*p_pool_capacity = RNG_CONFIG_POOL_SIZE;
#else
result = sd_rand_application_pool_capacity_get(p_pool_capacity);
#endif // SOFTDEVICE_PRESENT
return result;
}
ret_code_t nrf_drv_rng_rand(uint8_t * p_buff, uint8_t length)
{
ret_code_t result;
ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
#ifndef SOFTDEVICE_PRESENT
if (FIFO_LENGTH(m_rng_cb.rand_pool) >= length)
{
result = NRF_SUCCESS;
for (uint32_t i = 0; (i < length) && (result == NRF_SUCCESS); i++)
{
result = app_fifo_get(&(m_rng_cb.rand_pool), &p_buff[i]);
}
rng_start();
}
else
{
result = NRF_ERROR_NO_MEM;
}
#else
result = sd_rand_application_vector_get(p_buff, length);
#endif // SOFTDEVICE_PRESENT
return result;
}
ret_code_t nrf_drv_rng_block_rand(uint8_t * p_buff, uint32_t length)
{
uint32_t count = 0, poolsz = 0;
ret_code_t result;
ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
result = nrf_drv_rng_pool_capacity((uint8_t *) &poolsz);
if(result != NRF_SUCCESS)
{
return result;
}
while(length)
{
uint32_t len = length >= poolsz ? poolsz : length;
while((result = nrf_drv_rng_rand(&p_buff[count], len)) != NRF_SUCCESS)
{
#ifndef SOFTDEVICE_PRESENT
ASSERT(result == NRF_ERROR_NO_MEM);
#else
ASSERT(result == NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES);
#endif
}
length -= len;
count += len;
}
return result;
}
#ifndef SOFTDEVICE_PRESENT
void RNG_IRQHandler(void)
{
if (nrf_rng_event_get(NRF_RNG_EVENT_VALRDY) &&
nrf_rng_int_get(NRF_RNG_INT_VALRDY_MASK))
{
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
uint32_t nrf_error = app_fifo_put(&m_rng_cb.rand_pool, nrf_rng_random_value_get());
if ((FIFO_LENGTH(m_rng_cb.rand_pool) > m_rng_cb.rand_pool.buf_size_mask) || (nrf_error == NRF_ERROR_NO_MEM))
{
rng_stop();
}
}
}
#endif // SOFTDEVICE_PRESENT

View File

@ -0,0 +1,115 @@
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
#ifndef NRF_DRV_RNG_H__
#define NRF_DRV_RNG_H__
#include <stdbool.h>
#include <stdint.h>
#include "nrf_rng.h"
#include "sdk_errors.h"
#include "nrf_drv_config.h"
/**
* @addtogroup nrf_rng RNG HAL and driver
* @ingroup nrf_drivers
* @brief Random number generator (RNG) APIs.
* @details The RNG HAL provides basic APIs for accessing the registers of the random number generator.
* The RNG driver provides APIs on a higher level.
*
* @defgroup nrf_drv_rng RNG driver
* @{
* @ingroup nrf_rng
* @brief Driver for managing the random number generator (RNG).
*/
/**@brief Struct for RNG configuration. */
typedef struct
{
bool error_correction; /**< Error correction flag. */
uint8_t interrupt_priority; /**< interrupt priority */
} nrf_drv_rng_config_t;
/**@brief RNG default configuration. */
#define NRF_DRV_RNG_DEFAULT_CONFIG \
{ \
.error_correction = RNG_CONFIG_ERROR_CORRECTION, \
.interrupt_priority = RNG_CONFIG_IRQ_PRIORITY, \
}
/**
* @brief Function for initializing the nrf_drv_rng module.
*
* @param[in] p_config Initial configuration. Default configuration used if NULL.
*
* @retval NRF_SUCCESS Driver was successfully initialized.
* @retval NRF_ERROR_INVALID_STATE Driver was already initialized.
* @retval NRF_ERROR_INVALID_LENGTH Pool size have to be a power of 2.
* @retval NRF_ERROR_SOFTDEVICE_NOT_ENABLED SoftDevice is present, but not enabled.
*/
ret_code_t nrf_drv_rng_init(nrf_drv_rng_config_t const * p_config);
/**
* @brief Function for uninitializing the nrf_drv_rng module.
*/
void nrf_drv_rng_uninit(void);
/**
* @brief Function for getting the number of currently available random bytes.
*
* @param[out] p_bytes_available The number of bytes currently available in the pool.
*
* @retval NRF_SUCCESS If the number of available random bytes was written to p_bytes_available.
*/
ret_code_t nrf_drv_rng_bytes_available(uint8_t * p_bytes_available);
/**
* @brief Function for querying the capacity of the application random pool.
*
* @param[out] p_pool_capacity The capacity of the pool.
*
* @retval NRF_SUCCESS If the capacity of the pool was written to p_pool_capacity.
*/
ret_code_t nrf_drv_rng_pool_capacity(uint8_t * p_pool_capacity);
/**
* @brief Function for getting the vector of random numbers.
*
* @param[out] p_buff Pointer to uint8_t buffer for storing the bytes.
* @param[in] length Number of bytes to take from the pool and place in p_buff.
*
* @retval NRF_SUCCESS If the requested bytes were written to p_buff.
* @retval NRF_ERROR_NO_MEM If no bytes were written to the buffer
* because there were not enough bytes available in p_buff.
* @retval NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES If no bytes were written to the buffer
* because there were not enough bytes available in the pool.
*/
ret_code_t nrf_drv_rng_rand(uint8_t * p_buff, uint8_t length);
/**
* @brief Blocking function for getting an arbitrary array of random numbers.
*
* @note This function may execute for a substantial amount of time depending on the length of the buffer
* required and on the state of the current internal pool of random numbers.
*
* @param[out] p_buff Pointer to uint8_t buffer for storing the bytes.
* @param[in] length Number of bytes place in p_buff.
*
* @retval NRF_SUCCESS If the requested bytes were written to p_buff.
*/
ret_code_t nrf_drv_rng_block_rand(uint8_t * p_buff, uint32_t length);
/**
*@}
**/
#endif // NRF_DRV_RNG_H__

View File

@ -37,54 +37,146 @@
*/
#if defined(DEVICE_TRNG)
#include "trng_api.h"
#include "hal/trng_api.h"
#include "hal/lp_ticker_api.h"
#include "nrf_drv_rng.h"
#define DEFAULT_TIMEOUT_US (1000*1000)
/* Macro for testing if the SoftDevice is active, regardless of whether the
* application is build with the SoftDevice or not.
*/
#if defined(SOFTDEVICE_PRESENT)
#include "nrf_sdm.h"
static uint8_t wrapper(void) {
uint8_t softdevice_is_enabled;
ret_code_t result = sd_softdevice_is_enabled(&softdevice_is_enabled);
return ((result == NRF_SUCCESS) && (softdevice_is_enabled == 1));
}
#define NRF_HAL_SD_IS_ENABLED() wrapper()
#else
#define NRF_HAL_SD_IS_ENABLED() 0
#endif
/** Initialize the TRNG peripheral
*
* @param obj The TRNG object
*/
void trng_init(trng_t *obj)
{
(void) obj;
(void)nrf_drv_rng_init(NULL);
/* Initialize low power ticker. Used for timeouts. */
static bool first_init = true;
if (first_init) {
first_init = false;
lp_ticker_init();
}
}
/** Deinitialize the TRNG peripheral
*
* @param obj The TRNG object
*/
void trng_free(trng_t *obj)
{
(void) obj;
nrf_drv_rng_uninit();
}
/* Get random data from NRF5x TRNG peripheral.
/** Get random data from TRNG peripheral
*
* This implementation returns num of random bytes in range <1, length>.
* For parameters description see trng_api.h file.
* @param obj The TRNG object
* @param output The pointer to an output array
* @param length The size of output data, to avoid buffer overwrite
* @param output_length The length of generated data
* @return 0 success, -1 fail
*/
int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length)
{
uint8_t bytes_available;
(void) obj;
nrf_drv_rng_bytes_available(&bytes_available);
/* Use SDK RNG driver if SoftDevice is enabled. */
if (NRF_HAL_SD_IS_ENABLED()) {
if (bytes_available == 0) {
nrf_drv_rng_block_rand(output, 1);
*output_length = 1;
/* Initialize driver once. */
static bool nordic_driver_init = true;
if (nordic_driver_init) {
nordic_driver_init = false;
nrf_drv_rng_init(NULL);
}
/* Query how many bytes are available. */
uint8_t bytes_available;
nrf_drv_rng_bytes_available(&bytes_available);
/* If no bytes are cached, block until at least 1 byte is available. */
if (bytes_available == 0) {
nrf_drv_rng_block_rand(output, 1);
*output_length = 1;
} else {
/* Get up to the requested number of bytes. */
if (bytes_available > length) {
bytes_available = length;
}
ret_code_t result = nrf_drv_rng_rand(output, bytes_available);
/* Set output length with available bytes. */
if (result == NRF_SUCCESS) {
*output_length = bytes_available;
} else {
*output_length = 0;
}
}
} else {
if (bytes_available > length) {
bytes_available = length;
/* Initialize low-level registers once. */
static bool nordic_register_init = true;
if (nordic_register_init) {
nordic_register_init = false;
/* Enable RNG */
nrf_rng_error_correction_enable();
nrf_rng_task_trigger(NRF_RNG_TASK_START);
}
if (nrf_drv_rng_rand(output, bytes_available) != NRF_SUCCESS) {
*output_length = 0;
return -1;
} else {
*output_length = bytes_available;
/* Copy out one byte at a time. */
size_t index = 0;
for ( ; index < length; index++) {
/* Setup stop watch for timeout. */
uint32_t start_us = lp_ticker_read();
uint32_t now_us = start_us;
/* Block until timeout or random numer is ready. */
while (((now_us - start_us) < DEFAULT_TIMEOUT_US) &&
!nrf_rng_event_get(NRF_RNG_EVENT_VALRDY)) {
now_us = lp_ticker_read();
}
/* Abort if timeout was reached. */
if ((now_us - start_us) >= DEFAULT_TIMEOUT_US) {
break;
} else {
/* Read random byte and clear event in preparation for the next byte. */
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
output[index] = nrf_rng_random_value_get();
}
}
/* Set output length with available bytes. */
*output_length = index;
}
return 0;
/* Set return value based on how many bytes was read. */
return (*output_length == 0) ? -1 : 0;
}
#endif

View File

@ -3433,7 +3433,7 @@
"inherits": ["Target"],
"core": "Cortex-M4F",
"macros": ["NRF52", "TARGET_NRF52832", "BLE_STACK_SUPPORT_REQD", "SOFTDEVICE_PRESENT", "S132", "CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\"", "MBED_TICKLESS"],
"device_has": ["STCLK_OFF_DURING_SLEEP", "ITM"],
"device_has": ["STCLK_OFF_DURING_SLEEP", "ITM", "TRNG"],
"extra_labels": ["NORDIC", "MCU_NRF52", "MCU_NRF52832", "NRF5", "SDK11", "NRF52_COMMON"],
"OUTPUT_EXT": "hex",
"is_disk_virtual": true,