Пример #1
0
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;
}
Пример #2
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);
}
Пример #3
0
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);
    }
}
Пример #5
0
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;
}
Пример #6
0
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.");
}
Пример #7
0
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;
}
Пример #8
0
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);
	}
}
Пример #9
0
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);
}
Пример #10
0
static void rng_stop(void)
{
    nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK);
    nrf_rng_task_trigger(NRF_RNG_TASK_STOP);
}
Пример #11
0
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);
}