示例#1
0
static void event_handler(nrfx_rtc_int_type_t int_type, void *p_context)
{
	struct device *dev = p_context;
	struct counter_nrfx_data *data = get_dev_data(dev);

	if (int_type == COUNTER_TOP_INT) {
		/* Manually reset counter if top value is different than max. */
		if ((data->top != COUNTER_MAX_TOP_VALUE)
#if CONFIG_COUNTER_RTC_WITH_PPI_WRAP
		    && !get_nrfx_config(dev)->use_ppi
#endif
		    ) {
			nrfx_rtc_counter_clear(&get_nrfx_config(dev)->rtc);
		}

		nrfx_rtc_cc_set(&get_nrfx_config(dev)->rtc,
				TOP_CH, data->top, true);

		if (data->top_cb) {
			data->top_cb(dev, data->top_user_data);
		}
	} else if (int_type > COUNTER_TOP_INT) {
		alarm_event_handler(dev, CC_TO_ID(int_type));

	}
}
static int counter_nrfx_set_top_value(struct device *dev, u32_t ticks,
				      counter_top_callback_t callback,
				      void *user_data)
{
	const struct counter_nrfx_config *nrfx_config = get_nrfx_config(dev);
	const nrfx_rtc_t *rtc = &nrfx_config->rtc;
	struct counter_nrfx_data *dev_data = get_dev_data(dev);

	for (int i = 0; i < counter_get_num_of_channels(dev); i++) {
		/* Overflow can be changed only when all alarms are
		 * disables.
		 */
		if (nrfx_config->ch_data[i].callback) {
			return -EBUSY;
		}
	}

	nrfx_rtc_cc_disable(rtc, TOP_CH);
	nrfx_rtc_counter_clear(rtc);

	dev_data->top_cb = callback;
	dev_data->top_user_data = user_data;
	dev_data->top = ticks;
	nrfx_rtc_cc_set(rtc, TOP_CH, ticks, callback ? true : false);

	return 0;
}
static int init_rtc(struct device *dev,
		    const nrfx_rtc_config_t *config,
		    nrfx_rtc_handler_t handler)
{
	struct device *clock;
	const struct counter_nrfx_config *nrfx_config = get_nrfx_config(dev);
	const nrfx_rtc_t *rtc = &nrfx_config->rtc;

	clock = device_get_binding(DT_NORDIC_NRF_CLOCK_0_LABEL "_32K");
	if (!clock) {
		return -ENODEV;
	}

	clock_control_on(clock, (void *)CLOCK_CONTROL_NRF_K32SRC);

	nrfx_err_t result = nrfx_rtc_init(rtc, config, handler);

	if (result != NRFX_SUCCESS) {
		LOG_INST_ERR(nrfx_config->log, "Failed to initialize device.");
		return -EBUSY;
	}

	get_dev_data(dev)->top = COUNTER_MAX_TOP_VALUE;

	LOG_INST_DBG(nrfx_config->log, "Initialized");
	return 0;
}
示例#4
0
static int counter_nrfx_set_top_value(struct device *dev, u32_t ticks,
				      counter_top_callback_t callback,
				      void *user_data)
{
	const struct counter_nrfx_config *nrfx_config = get_nrfx_config(dev);
	const nrfx_timer_t *timer = &nrfx_config->timer;
	struct counter_nrfx_data *data = get_dev_data(dev);

	for (int i = 0; i < counter_get_num_of_channels(dev); i++) {
		/* Overflow can be changed only when all alarms are
		 * disables.
		 */
		if (nrfx_config->ch_data[i].callback) {
			return -EBUSY;
		}
	}

	nrfx_timer_compare_int_disable(timer, TOP_CH);
	nrfx_timer_clear(timer);

	data->top_cb = callback;
	data->top_user_data = user_data;
	nrfx_timer_extended_compare(timer, TOP_CH,
				    ticks, COUNTER_OVERFLOW_SHORT,
				    callback ? true : false);

	return 0;
}
示例#5
0
static void _disable(struct device *dev, u8_t id)
{
	const struct counter_nrfx_config *config = get_nrfx_config(dev);

	nrfx_timer_compare_int_disable(&config->timer, ID_TO_CC(id));
	config->ch_data[id].callback = NULL;
}
static void disable(struct device *dev, u8_t id)
{
	const struct counter_nrfx_config *config = get_nrfx_config(dev);

	nrfx_rtc_cc_disable(&config->rtc, ID_TO_CC(id));
	config->ch_data[id].callback = NULL;
}
示例#7
0
static void alarm_event_handler(struct device *dev, u32_t id)
{
	const struct counter_nrfx_config *config = get_nrfx_config(dev);
	counter_alarm_callback_t clbk = config->ch_data[id].callback;
	u32_t cc_val;

	if (!clbk) {
		return;
	}

	cc_val = nrfx_timer_capture_get(&config->timer, ID_TO_CC(id));
	_disable(dev, id);
	clbk(dev, id, cc_val, config->ch_data[id].user_data);
}
示例#8
0
static int init_timer(struct device *dev, const nrfx_timer_config_t *config)
{
	const struct counter_nrfx_config *nrfx_config = get_nrfx_config(dev);
	const nrfx_timer_t *timer = &nrfx_config->timer;

	nrfx_err_t result = nrfx_timer_init(timer, config, event_handler);

	if (result != NRFX_SUCCESS) {
		LOG_INST_ERR(nrfx_config->log, "Failed to initialize device.");
		return -EBUSY;
	}

	nrfx_timer_compare(timer, TOP_CH, UINT32_MAX, false);

	LOG_INST_DBG(nrfx_config->log, "Initialized");

	return 0;
}
示例#9
0
static int ppi_setup(struct device *dev)
{
#if CONFIG_COUNTER_RTC_WITH_PPI_WRAP
	const struct counter_nrfx_config *nrfx_config = get_nrfx_config(dev);
	struct counter_nrfx_data *data = get_dev_data(dev);
	const nrfx_rtc_t *rtc = &nrfx_config->rtc;
	nrfx_err_t result;

	if (!nrfx_config->use_ppi) {
		return 0;
	}

#ifdef DPPI_PRESENT
	result = nrfx_dppi_channel_alloc(&data->ppi_ch);
	if (result != NRFX_SUCCESS) {
		LOG_INST_ERR(nrfx_config->log,
			     "Failed to allocate PPI channel.");
		return -ENODEV;
	}

	nrf_rtc_subscribe_set(rtc->p_reg, NRF_RTC_TASK_CLEAR, data->ppi_ch);
	nrf_rtc_publish_set(rtc->p_reg, NRF_RTC_EVENT_COMPARE_0, data->ppi_ch);
	(void)nrfx_dppi_channel_enable(data->ppi_ch);
#else /* DPPI_PRESENT */
	u32_t evt;
	u32_t task;

	evt = nrfx_rtc_event_address_get(rtc, NRF_RTC_EVENT_COMPARE_0);
	task = nrfx_rtc_task_address_get(rtc, NRF_RTC_TASK_CLEAR);

	result = nrfx_ppi_channel_alloc(&data->ppi_ch);
	if (result != NRFX_SUCCESS) {
		LOG_INST_ERR(nrfx_config->log,
			     "Failed to allocate PPI channel.");
		return -ENODEV;
	}

	(void)nrfx_ppi_channel_assign(data->ppi_ch, evt, task);
	(void)nrfx_ppi_channel_enable(data->ppi_ch);
#endif
#endif /* CONFIG_COUNTER_RTC_WITH_PPI_WRAP */
	return 0;
}
static int counter_nrfx_set_alarm(struct device *dev, u8_t chan_id,
				  const struct counter_alarm_cfg *alarm_cfg)
{
	const struct counter_nrfx_config *nrfx_config = get_nrfx_config(dev);
	const nrfx_rtc_t *rtc = &nrfx_config->rtc;
	u32_t cc_val;

	if (alarm_cfg->ticks > get_dev_data(dev)->top) {
		return -EINVAL;
	}

	if (nrfx_config->ch_data[chan_id].callback) {
		return -EBUSY;
	}

	if (alarm_cfg->absolute) {
		cc_val = alarm_cfg->ticks;
	} else {
		/* As RTC is 24 bit there is no risk of overflow. */
		cc_val = alarm_cfg->ticks + nrfx_rtc_counter_get(rtc);
		cc_val -= (cc_val > get_dev_data(dev)->top) ?
				get_dev_data(dev)->top : 0;
	}

	nrfx_config->ch_data[chan_id].callback = alarm_cfg->callback;
	nrfx_config->ch_data[chan_id].user_data = alarm_cfg->user_data;

	if ((cc_val == 0) &&
	    (get_dev_data(dev)->top != counter_get_max_top_value(dev))) {
		/* From Product Specification: If a CC register value is 0 when
		 * a CLEAR task is set, this will not trigger a COMPARE event.
		 */
		LOG_INST_INF(nrfx_config->log,
				"Attempt to set CC to 0, delayed to 1.");
		cc_val++;
	}
	nrfx_rtc_cc_set(rtc, ID_TO_CC(chan_id), cc_val, true);

	return 0;
}
示例#11
0
static int counter_nrfx_set_alarm(struct device *dev, u8_t chan_id,
				  const struct counter_alarm_cfg *alarm_cfg)
{
	const struct counter_nrfx_config *nrfx_config = get_nrfx_config(dev);
	const nrfx_timer_t *timer = &nrfx_config->timer;
	u32_t cc_val;

	if (alarm_cfg->ticks > nrfx_timer_capture_get(timer, TOP_CH)) {
		return -EINVAL;
	}

	if (nrfx_config->ch_data[chan_id].callback) {
		return -EBUSY;
	}

	cc_val = alarm_cfg->ticks + (alarm_cfg->absolute ?
				0 : nrfx_timer_capture(timer, COUNTER_READ_CC));
	nrfx_config->ch_data[chan_id].callback = alarm_cfg->callback;
	nrfx_config->ch_data[chan_id].user_data = alarm_cfg->user_data;

	nrfx_timer_compare(timer, ID_TO_CC(chan_id), cc_val, true);

	return 0;
}
示例#12
0
static int counter_nrfx_start(struct device *dev)
{
	nrfx_timer_enable(&get_nrfx_config(dev)->timer);

	return 0;
}
static u32_t counter_nrfx_read(struct device *dev)
{
	return nrfx_rtc_counter_get(&get_nrfx_config(dev)->rtc);
}
static int counter_nrfx_stop(struct device *dev)
{
	nrfx_rtc_disable(&get_nrfx_config(dev)->rtc);

	return 0;
}
示例#15
0
static u32_t counter_nrfx_get_top_value(struct device *dev)
{
	return nrfx_timer_capture_get(&get_nrfx_config(dev)->timer, TOP_CH);
}
示例#16
0
static u32_t counter_nrfx_get_max_relative_alarm(struct device *dev)
{
	return nrfx_timer_capture_get(&get_nrfx_config(dev)->timer, TOP_CH);
}
示例#17
0
static u32_t counter_nrfx_read(struct device *dev)
{
	return nrfx_timer_capture(&get_nrfx_config(dev)->timer,
				  COUNTER_READ_CC);
}