Skip to content

Commit d8232f6

Browse files
committed
counter: Update counter API in order to provide more flexibility
This commit introduces new "reset" parameter to the set_top_value() making resetting counter optional during change of top value. Such change allows for zephyrproject-rtos#12068 implementation on hardware which does not provide alarms. Signed-off-by: Piotr Zięcik <[email protected]> Signed-off-by: Krzysztof Chruscinski <[email protected]>
1 parent e523c73 commit d8232f6

13 files changed

+175
-105
lines changed

drivers/counter/counter_imx_epit.c

+9-9
Original file line numberDiff line numberDiff line change
@@ -96,24 +96,24 @@ static u32_t imx_epit_read(struct device *dev)
9696
return value;
9797
}
9898

99-
static int imx_epit_set_top_value(struct device *dev, u32_t ticks,
100-
counter_top_callback_t callback,
101-
void *user_data)
99+
static int imx_epit_set_top_value(struct device *dev,
100+
const struct counter_top_cfg *cfg)
102101
{
103102
EPIT_Type *base = get_epit_config(dev)->base;
104103
struct imx_epit_data *driver_data = dev->driver_data;
105104

106105
/* Disable EPIT Output Compare interrupt for consistency */
107106
EPIT_SetIntCmd(base, false);
108107

109-
driver_data->callback = callback;
110-
driver_data->user_data = user_data;
108+
driver_data->callback = cfg->callback;
109+
driver_data->user_data = cfg->user_data;
111110

112-
/* Set both reload and counter values to "ticks" */
113-
EPIT_SetOverwriteCounter(base, true);
114-
EPIT_SetCounterLoadValue(base, ticks);
111+
/* Set reload value and optionally counter to "ticks" */
112+
EPIT_SetOverwriteCounter(base,
113+
!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET));
114+
EPIT_SetCounterLoadValue(base, cfg->ticks);
115115

116-
if (callback != NULL) {
116+
if (cfg->callback != NULL) {
117117
/* (Re)enable EPIT Output Compare interrupt */
118118
EPIT_SetIntCmd(base, true);
119119
}

drivers/counter/counter_ll_stm32_rtc.c

+4-8
Original file line numberDiff line numberDiff line change
@@ -197,17 +197,13 @@ static u32_t rtc_stm32_get_top_value(struct device *dev)
197197
}
198198

199199

200-
static int rtc_stm32_set_top_value(struct device *dev, u32_t ticks,
201-
counter_top_callback_t callback,
202-
void *user_data)
200+
static int rtc_stm32_set_top_value(struct device *dev,
201+
const struct counter_top_cfg *cfg)
203202
{
204203
const struct counter_config_info *info = dev->config->config_info;
205204

206-
ARG_UNUSED(dev);
207-
ARG_UNUSED(callback);
208-
ARG_UNUSED(user_data);
209-
210-
if (ticks != info->max_top_value) {
205+
if ((cfg->ticks != info->max_top_value) ||
206+
!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
211207
return -ENOTSUP;
212208
} else {
213209
return 0;

drivers/counter/counter_mcux_rtc.c

+8-7
Original file line numberDiff line numberDiff line change
@@ -133,20 +133,21 @@ static int mcux_rtc_cancel_alarm(struct device *dev, u8_t chan_id)
133133
return 0;
134134
}
135135

136-
static int mcux_rtc_set_top_value(struct device *dev, u32_t ticks,
137-
counter_top_callback_t callback,
138-
void *user_data)
136+
static int mcux_rtc_set_top_value(struct device *dev,
137+
const struct counter_top_cfg *cfg)
139138
{
140139
const struct counter_config_info *info = dev->config->config_info;
141140
struct mcux_rtc_data *data = dev->driver_data;
142141

143-
if (ticks != info->max_top_value) {
144-
LOG_ERR("Wrap can only be set to 0x%x", info->max_top_value);
142+
if ((cfg->ticks != info->max_top_value) ||
143+
!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
144+
LOG_ERR("Wrap can only be set to 0x%x. "
145+
"Counter reset is not supported.", info->max_top_value);
145146
return -ENOTSUP;
146147
}
147148

148-
data->top_callback = callback;
149-
data->top_user_data = user_data;
149+
data->top_callback = cfg->callback;
150+
data->top_user_data = cfg->user_data;
150151

151152
return 0;
152153
}

drivers/counter/counter_nrfx_rtc.c

+9-8
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,8 @@ static int counter_nrfx_cancel_alarm(struct device *dev, u8_t chan_id)
137137
return 0;
138138
}
139139

140-
static int counter_nrfx_set_top_value(struct device *dev, u32_t ticks,
141-
counter_top_callback_t callback,
142-
void *user_data)
140+
static int counter_nrfx_set_top_value(struct device *dev,
141+
const struct counter_top_cfg *cfg)
143142
{
144143
const struct counter_nrfx_config *nrfx_config = get_nrfx_config(dev);
145144
const nrfx_rtc_t *rtc = &nrfx_config->rtc;
@@ -155,12 +154,14 @@ static int counter_nrfx_set_top_value(struct device *dev, u32_t ticks,
155154
}
156155

157156
nrfx_rtc_cc_disable(rtc, TOP_CH);
158-
nrfx_rtc_counter_clear(rtc);
157+
if (!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
158+
nrfx_rtc_counter_clear(rtc);
159+
}
159160

160-
dev_data->top_cb = callback;
161-
dev_data->top_user_data = user_data;
162-
dev_data->top = ticks;
163-
nrfx_rtc_cc_set(rtc, TOP_CH, ticks, callback ? true : false);
161+
dev_data->top_cb = cfg->callback;
162+
dev_data->top_user_data = cfg->user_data;
163+
dev_data->top = cfg->ticks;
164+
nrfx_rtc_cc_set(rtc, TOP_CH, cfg->ticks, cfg->callback ? true : false);
164165

165166
return 0;
166167
}

drivers/counter/counter_nrfx_timer.c

+9-8
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,8 @@ static int counter_nrfx_cancel_alarm(struct device *dev, u8_t chan_id)
156156
}
157157

158158

159-
static int counter_nrfx_set_top_value(struct device *dev, u32_t ticks,
160-
counter_top_callback_t callback,
161-
void *user_data)
159+
static int counter_nrfx_set_top_value(struct device *dev,
160+
const struct counter_top_cfg *cfg)
162161
{
163162
const struct counter_nrfx_config *nrfx_config = get_nrfx_config(dev);
164163
const nrfx_timer_t *timer = &nrfx_config->timer;
@@ -174,13 +173,15 @@ static int counter_nrfx_set_top_value(struct device *dev, u32_t ticks,
174173
}
175174

176175
nrfx_timer_compare_int_disable(timer, TOP_CH);
177-
nrfx_timer_clear(timer);
176+
if (!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
177+
nrfx_timer_clear(timer);
178+
}
178179

179-
data->top_cb = callback;
180-
data->top_user_data = user_data;
180+
data->top_cb = cfg->callback;
181+
data->top_user_data = cfg->user_data;
181182
nrfx_timer_extended_compare(timer, TOP_CH,
182-
ticks, COUNTER_OVERFLOW_SHORT,
183-
callback ? true : false);
183+
cfg->ticks, COUNTER_OVERFLOW_SHORT,
184+
cfg->callback ? true : false);
184185

185186
return 0;
186187
}

drivers/counter/counter_qmsi_aon.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ static u32_t aon_counter_qmsi_read(struct device *dev)
3939
}
4040

4141
static int aon_counter_qmsi_set_top(struct device *dev,
42-
u32_t ticks,
43-
counter_top_callback_t callback,
44-
void *user_data)
42+
const struct counter_top_cfg *cfg)
4543

4644
{
4745
return -ENODEV;

drivers/counter/counter_qmsi_aonpt.c

+9-6
Original file line numberDiff line numberDiff line change
@@ -113,19 +113,22 @@ static u32_t aon_timer_qmsi_read(struct device *dev)
113113
}
114114

115115
static int aon_timer_qmsi_set_top(struct device *dev,
116-
u32_t ticks,
117-
counter_top_callback_t callback,
118-
void *user_data)
116+
const struct counter_top_cfg *cfg)
119117
{
120118
qm_aonpt_config_t qmsi_cfg;
121119
int result = 0;
122120

123-
user_cb = callback;
121+
/* Counter is always reset when top value is updated. */
122+
if (cfg->flags & COUNTER_TOP_CFG_DONT_RESET) {
123+
return -ENOTSUP;
124+
}
125+
126+
user_cb = cfg->callback;
124127

125128
qmsi_cfg.callback = aonpt_int_callback;
126129
qmsi_cfg.int_en = true;
127-
qmsi_cfg.count = ticks;
128-
qmsi_cfg.callback_data = user_data;
130+
qmsi_cfg.count = cfg->ticks;
131+
qmsi_cfg.callback_data = cfg->user_data;
129132

130133
if (IS_ENABLED(CONFIG_AON_API_REENTRANCY)) {
131134
k_sem_take(RP_GET(dev), K_FOREVER);

drivers/counter/counter_rtc_qmsi.c

+4-8
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,13 @@ static int rtc_qmsi_cancel_alarm(struct device *dev, u8_t chan_id)
9090
return 0;
9191
}
9292

93-
static int rtc_qmsi_set_top(struct device *dev, u32_t ticks,
94-
counter_top_callback_t callback,
95-
void *user_data)
93+
static int rtc_qmsi_set_top(struct device *dev,
94+
const struct counter_top_cfg *cfg)
9695
{
9796
const struct counter_config_info *info = dev->config->config_info;
9897

99-
ARG_UNUSED(dev);
100-
ARG_UNUSED(callback);
101-
ARG_UNUSED(user_data);
102-
103-
if (ticks != info->max_top_value) {
98+
if ((cfg->ticks != info->max_top_value) ||
99+
!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
104100
return -ENOTSUP;
105101
} else {
106102
return 0;

drivers/counter/counter_sam0_tc32.c

+11-8
Original file line numberDiff line numberDiff line change
@@ -226,30 +226,33 @@ static int counter_sam0_tc32_cancel_alarm(struct device *dev, u8_t chan_id)
226226
return 0;
227227
}
228228

229-
static int counter_sam0_tc32_set_top_value(struct device *dev, u32_t ticks,
230-
counter_top_callback_t callback,
231-
void *user_data)
229+
static int counter_sam0_tc32_set_top_value(struct device *dev,
230+
const struct counter_top_cfg *top_cfg)
232231
{
233232
bool reset = true;
234233
struct counter_sam0_tc32_data *data = DEV_DATA(dev);
235234
const struct counter_sam0_tc32_config *const cfg = DEV_CFG(dev);
236235
TcCount32 *tc = cfg->regs;
237236
int key = irq_lock();
238237

238+
if (top_cfg->flags & COUNTER_TOP_CFG_DONT_RESET) {
239+
return -ENOTSUP;
240+
}
241+
239242
if (data->ch.callback) {
240243
irq_unlock(key);
241244
return -EBUSY;
242245
}
243246

244-
if (callback) {
245-
data->top_cb = callback;
246-
data->top_user_data = user_data;
247+
if (top_cfg->callback) {
248+
data->top_cb = top_cfg->callback;
249+
data->top_user_data = top_cfg->user_data;
247250
tc->INTENSET.reg = TC_INTFLAG_MC0;
248251
} else {
249252
tc->INTENCLR.reg = TC_INTFLAG_MC0;
250253
}
251254

252-
tc->CC[0].reg = ticks;
255+
tc->CC[0].reg = top_cfg->ticks;
253256

254257
if (reset) {
255258
tc->CTRLBSET.reg = TC_CTRLBSET_CMD_RETRIGGER;
@@ -258,7 +261,7 @@ static int counter_sam0_tc32_set_top_value(struct device *dev, u32_t ticks,
258261
* Top trigger is on equality of the rising edge only, so
259262
* manually reset it if the counter has missed the new top.
260263
*/
261-
if (counter_sam0_tc32_read(dev) >= ticks) {
264+
if (counter_sam0_tc32_read(dev) >= top_cfg->ticks) {
262265
tc->CTRLBSET.reg = TC_CTRLBSET_CMD_RETRIGGER;
263266
}
264267
}

drivers/counter/timer_dtmr_cmsdk_apb.c

+17-7
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,32 @@ static u32_t dtmr_cmsdk_apb_read(struct device *dev)
6969
}
7070

7171
static int dtmr_cmsdk_apb_set_top_value(struct device *dev,
72-
u32_t ticks,
73-
counter_top_callback_t callback,
74-
void *user_data)
72+
const struct counter_top_cfg *top_cfg)
7573
{
7674
const struct dtmr_cmsdk_apb_cfg * const cfg =
7775
dev->config->config_info;
7876
struct dtmr_cmsdk_apb_dev_data *data = dev->driver_data;
7977

80-
data->top_callback = callback;
81-
data->top_user_data = user_data;
78+
data->top_callback = top_cfg->callback;
79+
data->top_user_data = top_cfg->user_data;
8280

8381
/* Store the reload value */
84-
data->load = ticks;
82+
data->load = top_cfg->ticks;
8583

8684
/* Set the timer to count */
87-
cfg->dtimer->timer1load = ticks;
85+
if (top_cfg->flags & COUNTER_TOP_CFG_DONT_RESET) {
86+
/*
87+
* Write to background load register will not affect
88+
* the current value of the counter.
89+
*/
90+
cfg->dtimer->timer1bgload = top_cfg->ticks;
91+
} else {
92+
/*
93+
* Write to load register will also set
94+
* the current value of the counter.
95+
*/
96+
cfg->dtimer->timer1load = top_cfg->ticks;
97+
}
8898

8999
/* Enable IRQ */
90100
cfg->dtimer->timer1ctrl |= (DUALTIMER_CTRL_INTEN

drivers/counter/timer_tmr_cmsdk_apb.c

+11-8
Original file line numberDiff line numberDiff line change
@@ -69,25 +69,28 @@ static u32_t tmr_cmsdk_apb_read(struct device *dev)
6969
}
7070

7171
static int tmr_cmsdk_apb_set_top_value(struct device *dev,
72-
u32_t ticks,
73-
counter_top_callback_t callback,
74-
void *user_data)
72+
const struct counter_top_cfg *top_cfg)
7573
{
7674
const struct tmr_cmsdk_apb_cfg * const cfg =
7775
dev->config->config_info;
7876
struct tmr_cmsdk_apb_dev_data *data = dev->driver_data;
7977

80-
data->top_callback = callback;
81-
data->top_user_data = user_data;
78+
/* Counter is always reset when top value is updated. */
79+
if (top_cfg->flags & COUNTER_TOP_CFG_DONT_RESET) {
80+
return -ENOTSUP;
81+
}
82+
83+
data->top_callback = top_cfg->callback;
84+
data->top_user_data = top_cfg->user_data;
8285

8386
/* Store the reload value */
84-
data->load = ticks;
87+
data->load = top_cfg->ticks;
8588

8689
/* Set value register to count */
87-
cfg->timer->value = ticks;
90+
cfg->timer->value = top_cfg->ticks;
8891

8992
/* Set the timer reload to count */
90-
cfg->timer->reload = ticks;
93+
cfg->timer->reload = top_cfg->ticks;
9194

9295
/* Enable IRQ */
9396
cfg->timer->ctrl |= TIMER_CTRL_IRQ_EN;

0 commit comments

Comments
 (0)