Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: counter: Add user_data to alarm callback #11572

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion drivers/counter/counter_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ COUNTER_HANDLER(get_pending_int)
COUNTER_HANDLER(read)
COUNTER_HANDLER(stop)
COUNTER_HANDLER(start)
COUNTER_HANDLER(get_wrap)
COUNTER_HANDLER(get_top_value)
COUNTER_HANDLER(get_max_relative_alarm)
101 changes: 55 additions & 46 deletions drivers/counter/counter_nrfx_rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,28 @@
LOG_MODULE_REGISTER();

#define RTC_CLOCK 32768
#define COUNTER_MAX_WRAP RTC_COUNTER_COUNTER_Msk
#define COUNTER_MAX_TOP_VALUE RTC_COUNTER_COUNTER_Msk

#define CC_TO_ID(cc) ((cc) - 1)
#define ID_TO_CC(id) ((id) + 1)

#define WRAP_CH 0
#define COUNTER_WRAP_INT NRFX_RTC_INT_COMPARE0
#define TOP_CH 0
#define COUNTER_TOP_INT NRFX_RTC_INT_COMPARE0

struct counter_nrfx_data {
counter_wrap_callback_t wrap_cb;
void *wrap_user_data;
u32_t wrap;
counter_top_callback_t top_cb;
void *top_user_data;
u32_t top;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer this be top_value, but I won't block for that.

};

struct counter_nrfx_ch_data {
counter_alarm_callback_t callback;
void *user_data;
};

struct counter_nrfx_config {
struct counter_config_info info;
const struct counter_alarm_cfg **alarm_cfgs;
struct counter_nrfx_ch_data *ch_data;
nrfx_rtc_t rtc;

LOG_INSTANCE_PTR_DECLARE(log);
Expand Down Expand Up @@ -67,28 +72,29 @@ static u32_t counter_nrfx_read(struct device *dev)
return nrfx_rtc_counter_get(&get_nrfx_config(dev)->rtc);
}

static int counter_nrfx_set_alarm(struct device *dev,
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)->wrap) {
if (alarm_cfg->ticks > get_dev_data(dev)->top) {
return -EINVAL;
}

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

cc_val = alarm_cfg->ticks + (alarm_cfg->absolute ?
0 : nrfx_rtc_counter_get(rtc));
cc_val = (cc_val > get_dev_data(dev)->wrap) ?
(cc_val - get_dev_data(dev)->wrap) : cc_val;
nrfx_config->alarm_cfgs[alarm_cfg->channel_id] = alarm_cfg;
cc_val = (cc_val > get_dev_data(dev)->top) ?
(cc_val - get_dev_data(dev)->top) : cc_val;
nrfx_config->ch_data[chan_id].callback = alarm_cfg->callback;
nrfx_config->ch_data[chan_id].user_data = alarm_cfg->user_data;

nrfx_rtc_cc_set(rtc, ID_TO_CC(alarm_cfg->channel_id), cc_val, true);
nrfx_rtc_cc_set(rtc, ID_TO_CC(chan_id), cc_val, true);

return 0;
}
Expand All @@ -98,20 +104,19 @@ 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->alarm_cfgs[id] = NULL;
config->ch_data[id].callback = NULL;
}

static int counter_nrfx_disable_alarm(struct device *dev,
const struct counter_alarm_cfg *alarm_cfg)
static int counter_nrfx_disable_alarm(struct device *dev, u8_t chan_id)
{
_disable(dev, alarm_cfg->channel_id);
_disable(dev, chan_id);

return 0;
}

static int counter_nrfx_set_wrap(struct device *dev, u32_t ticks,
counter_wrap_callback_t callback,
void *user_data)
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;
Expand All @@ -121,18 +126,18 @@ static int counter_nrfx_set_wrap(struct device *dev, u32_t ticks,
/* Overflow can be changed only when all alarms are
* disables.
*/
if (nrfx_config->alarm_cfgs[i]) {
if (nrfx_config->ch_data[i].callback) {
return -EBUSY;
}
}

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

dev_data->wrap_cb = callback;
dev_data->wrap_user_data = user_data;
dev_data->wrap = ticks;
nrfx_rtc_cc_set(rtc, WRAP_CH, ticks, callback ? true : false);
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;
}
Expand All @@ -145,32 +150,36 @@ static u32_t counter_nrfx_get_pending_int(struct device *dev)
static void alarm_event_handler(struct device *dev, u32_t id)
{
const struct counter_nrfx_config *config = get_nrfx_config(dev);
const struct counter_alarm_cfg *alarm_cfg = config->alarm_cfgs[id];
counter_alarm_callback_t clbk = config->ch_data[id].callback;
u32_t cc_val;

if (!clbk) {
return;
}

cc_val = nrf_rtc_cc_get(config->rtc.p_reg, ID_TO_CC(id));

_disable(dev, id);
alarm_cfg->handler(dev, alarm_cfg, cc_val);
clbk(dev, id, cc_val, config->ch_data[id].user_data);
}

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_WRAP_INT) {
/* Manually reset counter when wrap is different than max wrap*/
if (data->wrap != COUNTER_MAX_WRAP) {
if (int_type == COUNTER_TOP_INT) {
/* Manually reset counter if top value is different than max. */
if (data->top != COUNTER_MAX_TOP_VALUE) {
nrfx_rtc_counter_clear(&get_nrfx_config(dev)->rtc);
nrfx_rtc_cc_set(&get_nrfx_config(dev)->rtc,
WRAP_CH, data->wrap, true);
TOP_CH, data->top, true);
}

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

}
Expand Down Expand Up @@ -198,21 +207,21 @@ static int init_rtc(struct device *dev,
return -EBUSY;
}

get_dev_data(dev)->wrap = COUNTER_MAX_WRAP;
get_dev_data(dev)->top = COUNTER_MAX_TOP_VALUE;

LOG_INST_DBG(nrfx_config->log, "Initialized");
return 0;
}

static u32_t counter_nrfx_get_wrap(struct device *dev)
static u32_t counter_nrfx_get_top_value(struct device *dev)
{
return get_dev_data(dev)->wrap;
return get_dev_data(dev)->top;
}

static u32_t counter_nrfx_get_max_relative_alarm(struct device *dev)
{
/* Maybe decreased. */
return get_dev_data(dev)->wrap;
return get_dev_data(dev)->top;
}

static const struct counter_driver_api counter_nrfx_driver_api = {
Expand All @@ -221,9 +230,9 @@ static const struct counter_driver_api counter_nrfx_driver_api = {
.read = counter_nrfx_read,
.set_alarm = counter_nrfx_set_alarm,
.disable_alarm = counter_nrfx_disable_alarm,
.set_wrap = counter_nrfx_set_wrap,
.set_top_value = counter_nrfx_set_top_value,
.get_pending_int = counter_nrfx_get_pending_int,
.get_wrap = counter_nrfx_get_wrap,
.get_top_value = counter_nrfx_get_top_value,
.get_max_relative_alarm = counter_nrfx_get_max_relative_alarm,
};

Expand All @@ -244,18 +253,18 @@ static const struct counter_driver_api counter_nrfx_driver_api = {
return init_rtc(dev, &config, rtc_##idx##_handler); \
} \
static struct counter_nrfx_data counter_##idx##_data; \
static const struct counter_alarm_cfg \
*counter##idx##_alarm_cfgs[CC_TO_ID(RTC##idx##_CC_NUM)]; \
static struct counter_nrfx_ch_data \
counter##idx##_ch_data[CC_TO_ID(RTC##idx##_CC_NUM)]; \
LOG_INSTANCE_REGISTER(LOG_MODULE_NAME, idx, CONFIG_COUNTER_LOG_LEVEL); \
static const struct counter_nrfx_config nrfx_counter_##idx##_config = {\
.info = { \
.max_wrap = COUNTER_MAX_WRAP, \
.max_top_value = COUNTER_MAX_TOP_VALUE, \
.freq = RTC_CLOCK / \
(CONFIG_COUNTER_RTC##idx##_PRESCALER + 1), \
.count_up = true, \
.channels = CC_TO_ID(RTC##idx##_CC_NUM) \
}, \
.alarm_cfgs = counter##idx##_alarm_cfgs, \
.ch_data = counter##idx##_ch_data, \
.rtc = NRFX_RTC_INSTANCE(idx), \
LOG_INSTANCE_PTR_INIT(log, LOG_MODULE_NAME, idx) \
}; \
Expand Down
Loading