mirror of https://github.com/ARMmbed/mbed-os.git
commit
c9cefccbdc
|
@ -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
|
||||
|
|
|
@ -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__ */
|
|
@ -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
|
|
@ -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__
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue