nrf_drv_rng.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #include <stdint.h>
  13. #include <stddef.h>
  14. #include "nrf_drv_rng.h"
  15. #include "nrf_assert.h"
  16. #include "nrf_drv_common.h"
  17. #include "nordic_common.h"
  18. #include "nrf_error.h"
  19. #include "nrf_assert.h"
  20. #ifdef SOFTDEVICE_PRESENT
  21. #include "nrf_sdm.h"
  22. #include "nrf_soc.h"
  23. #else
  24. #include "app_fifo.h"
  25. #include "app_util_platform.h"
  26. static __INLINE uint32_t fifo_length(app_fifo_t * p_fifo)
  27. {
  28. uint32_t tmp = p_fifo->read_pos;
  29. return p_fifo->write_pos - tmp;
  30. }
  31. #define FIFO_LENGTH(fifo) fifo_length(&(fifo)) /**< Macro for calculating the FIFO length. */
  32. #endif // SOFTDEVICE_PRESENT
  33. typedef struct
  34. {
  35. nrf_drv_state_t state;
  36. #ifndef SOFTDEVICE_PRESENT
  37. app_fifo_t rand_pool;
  38. uint8_t buffer[RNG_CONFIG_POOL_SIZE];
  39. #endif // SOFTDEVICE_PRESENT
  40. } nrf_drv_rng_cb_t;
  41. static nrf_drv_rng_cb_t m_rng_cb;
  42. #ifndef SOFTDEVICE_PRESENT
  43. static const nrf_drv_rng_config_t m_default_config = NRF_DRV_RNG_DEFAULT_CONFIG;
  44. static void rng_start(void)
  45. {
  46. if (FIFO_LENGTH(m_rng_cb.rand_pool) <= m_rng_cb.rand_pool.buf_size_mask)
  47. {
  48. nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
  49. nrf_rng_int_enable(NRF_RNG_INT_VALRDY_MASK);
  50. nrf_rng_task_trigger(NRF_RNG_TASK_START);
  51. }
  52. }
  53. static void rng_stop(void)
  54. {
  55. nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK);
  56. nrf_rng_task_trigger(NRF_RNG_TASK_STOP);
  57. }
  58. #endif // SOFTDEVICE_PRESENT
  59. ret_code_t nrf_drv_rng_init(nrf_drv_rng_config_t const * p_config)
  60. {
  61. uint32_t result;
  62. if (m_rng_cb.state == NRF_DRV_STATE_UNINITIALIZED)
  63. {
  64. #ifndef SOFTDEVICE_PRESENT
  65. result = app_fifo_init(&m_rng_cb.rand_pool, m_rng_cb.buffer, RNG_CONFIG_POOL_SIZE);
  66. if (p_config == NULL)
  67. {
  68. p_config = &m_default_config;
  69. }
  70. if (result == NRF_SUCCESS)
  71. {
  72. if (p_config->error_correction)
  73. {
  74. nrf_rng_error_correction_enable();
  75. }
  76. nrf_drv_common_irq_enable(RNG_IRQn, p_config->interrupt_priority);
  77. nrf_rng_shorts_disable(NRF_RNG_SHORT_VALRDY_STOP_MASK);
  78. rng_start();
  79. m_rng_cb.state = NRF_DRV_STATE_INITIALIZED;
  80. }
  81. #else
  82. UNUSED_VARIABLE(p_config);
  83. uint8_t softdevice_is_enabled;
  84. result = sd_softdevice_is_enabled(&softdevice_is_enabled);
  85. if (softdevice_is_enabled)
  86. {
  87. m_rng_cb.state = NRF_DRV_STATE_INITIALIZED;
  88. }
  89. else
  90. {
  91. result = NRF_ERROR_SOFTDEVICE_NOT_ENABLED;
  92. }
  93. #endif // SOFTDEVICE_PRESENT
  94. }
  95. else
  96. {
  97. result = NRF_ERROR_INVALID_STATE;
  98. }
  99. return result;
  100. }
  101. void nrf_drv_rng_uninit(void)
  102. {
  103. ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
  104. m_rng_cb.state = NRF_DRV_STATE_UNINITIALIZED;
  105. #ifndef SOFTDEVICE_PRESENT
  106. rng_stop();
  107. nrf_drv_common_irq_disable(RNG_IRQn);
  108. #endif // SOFTDEVICE_PRESENT
  109. }
  110. ret_code_t nrf_drv_rng_bytes_available(uint8_t * p_bytes_available)
  111. {
  112. ret_code_t result;
  113. ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
  114. #ifndef SOFTDEVICE_PRESENT
  115. result = NRF_SUCCESS;
  116. *p_bytes_available = FIFO_LENGTH(m_rng_cb.rand_pool);
  117. #else
  118. result = sd_rand_application_bytes_available_get(p_bytes_available);
  119. #endif // SOFTDEVICE_PRESENT
  120. return result;
  121. }
  122. ret_code_t nrf_drv_rng_pool_capacity(uint8_t * p_pool_capacity)
  123. {
  124. ret_code_t result;
  125. ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
  126. #ifndef SOFTDEVICE_PRESENT
  127. result = NRF_SUCCESS;
  128. *p_pool_capacity = RNG_CONFIG_POOL_SIZE;
  129. #else
  130. result = sd_rand_application_pool_capacity_get(p_pool_capacity);
  131. #endif // SOFTDEVICE_PRESENT
  132. return result;
  133. }
  134. ret_code_t nrf_drv_rng_rand(uint8_t * p_buff, uint8_t length)
  135. {
  136. ret_code_t result;
  137. ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
  138. #ifndef SOFTDEVICE_PRESENT
  139. if (FIFO_LENGTH(m_rng_cb.rand_pool) >= length)
  140. {
  141. result = NRF_SUCCESS;
  142. for (uint32_t i = 0; (i < length) && (result == NRF_SUCCESS); i++)
  143. {
  144. result = app_fifo_get(&(m_rng_cb.rand_pool), &p_buff[i]);
  145. }
  146. rng_start();
  147. }
  148. else
  149. {
  150. result = NRF_ERROR_NO_MEM;
  151. }
  152. #else
  153. result = sd_rand_application_vector_get(p_buff, length);
  154. #endif // SOFTDEVICE_PRESENT
  155. return result;
  156. }
  157. ret_code_t nrf_drv_rng_block_rand(uint8_t * p_buff, uint32_t length)
  158. {
  159. uint32_t count = 0, poolsz = 0;
  160. ret_code_t result;
  161. ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
  162. result = nrf_drv_rng_pool_capacity((uint8_t *) &poolsz);
  163. if(result != NRF_SUCCESS)
  164. {
  165. return result;
  166. }
  167. while(length)
  168. {
  169. uint32_t len = length >= poolsz ? poolsz : length;
  170. while((result = nrf_drv_rng_rand(&p_buff[count], len)) != NRF_SUCCESS)
  171. {
  172. #ifndef SOFTDEVICE_PRESENT
  173. ASSERT(result == NRF_ERROR_NO_MEM);
  174. #else
  175. ASSERT(result == NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES);
  176. #endif
  177. }
  178. length -= len;
  179. count += len;
  180. }
  181. return result;
  182. }
  183. #ifndef SOFTDEVICE_PRESENT
  184. void RNG_IRQHandler(void)
  185. {
  186. if (nrf_rng_event_get(NRF_RNG_EVENT_VALRDY) &&
  187. nrf_rng_int_get(NRF_RNG_INT_VALRDY_MASK))
  188. {
  189. nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
  190. uint32_t nrf_error = app_fifo_put(&m_rng_cb.rand_pool, nrf_rng_random_value_get());
  191. if ((FIFO_LENGTH(m_rng_cb.rand_pool) > m_rng_cb.rand_pool.buf_size_mask) || (nrf_error == NRF_ERROR_NO_MEM))
  192. {
  193. rng_stop();
  194. }
  195. }
  196. }
  197. #endif // SOFTDEVICE_PRESENT