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; }
void nrfx_rng_start(void) { NRFX_ASSERT(m_rng_state == NRFX_DRV_STATE_INITIALIZED); 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 int entropy_nrf5_init(struct device *device) { /* Check if this API is called on correct driver instance. */ __ASSERT_NO_MSG(&entropy_nrf5_data == DEV_DATA(device)); /* Locking semaphore initialized to 1 (unlocked) */ k_sem_init(&entropy_nrf5_data.sem_lock, 1, 1); /* Synching semaphore */ k_sem_init(&entropy_nrf5_data.sem_sync, 0, 1); rng_pool_init((struct rng_pool *)(entropy_nrf5_data.thr), CONFIG_ENTROPY_NRF5_THR_POOL_SIZE, CONFIG_ENTROPY_NRF5_THR_THRESHOLD); rng_pool_init((struct rng_pool *)(entropy_nrf5_data.isr), CONFIG_ENTROPY_NRF5_ISR_POOL_SIZE, CONFIG_ENTROPY_NRF5_ISR_THRESHOLD); /* Enable or disable bias correction */ if (IS_ENABLED(CONFIG_ENTROPY_NRF5_BIAS_CORRECTION)) { nrf_rng_error_correction_enable(); } else { nrf_rng_error_correction_disable(); } 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); IRQ_CONNECT(RNG_IRQn, CONFIG_ENTROPY_NRF5_PRI, isr, &entropy_nrf5_data, 0); irq_enable(RNG_IRQn); return 0; }
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 u16_t rng_pool_get(struct rng_pool *rngp, u8_t *buf, u16_t len) { u32_t last = rngp->last; u32_t mask = rngp->mask; u8_t *dst = buf; u32_t first, available; u32_t other_read_in_progress; unsigned int key; key = irq_lock(); first = rngp->first_alloc; /* * The other_read_in_progress is non-zero if rngp->first_read != first, * which means that lower-priority code (which was interrupted by this * call) already allocated area for read. */ other_read_in_progress = (rngp->first_read ^ first); available = (last - first) & mask; if (available < len) { len = available; } /* * Move alloc index forward to signal, that part of the buffer is * now reserved for this call. */ rngp->first_alloc = (first + len) & mask; irq_unlock(key); while (likely(len--)) { *dst++ = rngp->buffer[first]; first = (first + 1) & mask; } /* * If this call is the last one accessing the pool, move read index * to signal that all allocated regions are now read and could be * overwritten. */ if (likely(!other_read_in_progress)) { key = irq_lock(); rngp->first_read = rngp->first_alloc; irq_unlock(key); } len = dst - buf; available = available - len; if (available <= rngp->threshold) { nrf_rng_task_trigger(NRF_RNG_TASK_START); } return len; }
void nrfx_rng_uninit(void) { NRFX_ASSERT(m_rng_state == NRFX_DRV_STATE_INITIALIZED); nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK); nrf_rng_task_trigger(NRF_RNG_TASK_STOP); NRFX_IRQ_DISABLE(RNG_IRQn); m_rng_state = NRFX_DRV_STATE_UNINITIALIZED; NRFX_LOG_INFO("Uninitialized."); }
static int entropy_nrf5_get_entropy_isr(struct device *dev, u8_t *buf, u16_t len, u32_t flags) { u16_t cnt = len; /* Check if this API is called on correct driver instance. */ __ASSERT_NO_MSG(&entropy_nrf5_data == DEV_DATA(dev)); if (likely((flags & ENTROPY_BUSYWAIT) == 0)) { return rng_pool_get((struct rng_pool *)(entropy_nrf5_data.isr), buf, len); } if (len) { unsigned int key; int irq_enabled; key = irq_lock(); irq_enabled = irq_is_enabled(RNG_IRQn); irq_disable(RNG_IRQn); irq_unlock(key); nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY); nrf_rng_task_trigger(NRF_RNG_TASK_START); do { int byte; while (!nrf_rng_event_get(NRF_RNG_EVENT_VALRDY)) { __WFE(); __SEV(); __WFE(); } byte = random_byte_get(); NVIC_ClearPendingIRQ(RNG_IRQn); if (byte < 0) { continue; } buf[--len] = byte; } while (len); if (irq_enabled) { irq_enable(RNG_IRQn); } } return cnt; }
static void isr(void *arg) { int byte, ret; ARG_UNUSED(arg); byte = random_byte_get(); if (byte < 0) { return; } ret = rng_pool_put((struct rng_pool *)(entropy_nrf5_data.isr), byte); if (ret < 0) { ret = rng_pool_put((struct rng_pool *)(entropy_nrf5_data.thr), byte); if (ret < 0) { nrf_rng_task_trigger(NRF_RNG_TASK_STOP); } k_sem_give(&entropy_nrf5_data.sem_sync); } }
void nrfx_rng_stop(void) { NRFX_ASSERT(m_rng_state == NRFX_DRV_STATE_INITIALIZED); nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK); nrf_rng_task_trigger(NRF_RNG_TASK_STOP); }
static void rng_stop(void) { nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK); nrf_rng_task_trigger(NRF_RNG_TASK_STOP); }
static void generatorStart(void) { 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); }