Skip to content

Commit 10329ce

Browse files
pizi-nordicnordic-krch
authored andcommitted
counter: Update counter API in order to provide more flexibility
This commit introduces new top_value setting configuration structure with flag for controlling resetting of the counter 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]> Signed-off-by: Benjamin Valentin <[email protected]>
1 parent a30162b commit 10329ce

14 files changed

+248
-125
lines changed

drivers/counter/counter_gecko_rtcc.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,13 @@ static u32_t counter_gecko_read(struct device *dev)
9090
return RTCC_CounterGet();
9191
}
9292

93-
static int counter_gecko_set_top_value(struct device *dev, u32_t ticks,
94-
counter_top_callback_t callback,
95-
void *user_data)
93+
static int counter_gecko_set_top_value(struct device *dev,
94+
const struct counter_top_cfg *cfg)
9695
{
9796
struct counter_gecko_data *const dev_data = DEV_DATA(dev);
97+
u32_t ticks;
98+
u32_t flags;
99+
int err = 0;
98100

99101
#ifdef CONFIG_SOC_GECKO_HAS_ERRATA_RTCC_E201
100102
const struct counter_gecko_config *const dev_cfg = DEV_CFG(dev);
@@ -114,18 +116,31 @@ static int counter_gecko_set_top_value(struct device *dev, u32_t ticks,
114116

115117
RTCC_IntClear(RTCC_IF_CC1);
116118

117-
dev_data->top_callback = callback;
118-
dev_data->top_user_data = user_data;
119+
dev_data->top_callback = cfg->callback;
120+
dev_data->top_user_data = cfg->user_data;
121+
ticks = cfg->ticks;
122+
flags = cfg->flags;
123+
124+
if (!(flags & COUNTER_TOP_CFG_DONT_RESET)) {
125+
RTCC_CounterSet(0);
126+
}
119127

120-
RTCC_CounterSet(0);
121128
RTCC_ChannelCCVSet(1, ticks);
122129

123130
LOG_DBG("set top value: %u", ticks);
124131

132+
if ((flags & COUNTER_TOP_CFG_DONT_RESET) &&
133+
RTCC_CounterGet() > ticks) {
134+
err = -ETIME;
135+
if (flags & COUNTER_TOP_CFG_RESET_WHEN_LATE) {
136+
RTCC_CounterSet(0);
137+
}
138+
}
139+
125140
/* Enable the compare interrupt */
126141
RTCC_IntEnable(RTCC_IF_CC1);
127142

128-
return 0;
143+
return err;
129144
}
130145

131146
static u32_t counter_gecko_get_top_value(struct device *dev)

drivers/counter/counter_imx_epit.c

Lines changed: 9 additions & 9 deletions
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

Lines changed: 4 additions & 8 deletions
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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,20 +133,27 @@ 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;
140+
const struct mcux_rtc_config *config =
141+
CONTAINER_OF(info, struct mcux_rtc_config, info);
141142
struct mcux_rtc_data *data = dev->driver_data;
142143

143-
if (ticks != info->max_top_value) {
144-
LOG_ERR("Wrap can only be set to 0x%x", info->max_top_value);
144+
if (cfg->ticks != info->max_top_value) {
145+
LOG_ERR("Wrap can only be set to 0x%x.", info->max_top_value);
145146
return -ENOTSUP;
146147
}
147148

148-
data->top_callback = callback;
149-
data->top_user_data = user_data;
149+
if (!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
150+
RTC_StopTimer(config->base);
151+
config->base->TSR = 0;
152+
RTC_StartTimer(config->base);
153+
}
154+
155+
data->top_callback = cfg->callback;
156+
data->top_user_data = cfg->user_data;
150157

151158
return 0;
152159
}

drivers/counter/counter_nrfx_rtc.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,13 @@ static int counter_nrfx_cancel_alarm(struct device *dev, u8_t chan_id)
141141
return 0;
142142
}
143143

144-
static int counter_nrfx_set_top_value(struct device *dev, u32_t ticks,
145-
counter_top_callback_t callback,
146-
void *user_data)
144+
static int counter_nrfx_set_top_value(struct device *dev,
145+
const struct counter_top_cfg *cfg)
147146
{
148147
const struct counter_nrfx_config *nrfx_config = get_nrfx_config(dev);
149148
const nrfx_rtc_t *rtc = &nrfx_config->rtc;
150149
struct counter_nrfx_data *dev_data = get_dev_data(dev);
150+
int err = 0;
151151

152152
for (int i = 0; i < counter_get_num_of_channels(dev); i++) {
153153
/* Overflow can be changed only when all alarms are
@@ -159,14 +159,26 @@ static int counter_nrfx_set_top_value(struct device *dev, u32_t ticks,
159159
}
160160

161161
nrfx_rtc_cc_disable(rtc, TOP_CH);
162-
nrfx_rtc_counter_clear(rtc);
163162

164-
dev_data->top_cb = callback;
165-
dev_data->top_user_data = user_data;
166-
dev_data->top = ticks;
167-
nrfx_rtc_cc_set(rtc, TOP_CH, ticks, callback ? true : false);
163+
dev_data->top_cb = cfg->callback;
164+
dev_data->top_user_data = cfg->user_data;
165+
dev_data->top = cfg->ticks;
166+
nrfx_rtc_cc_set(rtc, TOP_CH, cfg->ticks, false);
167+
168+
if (!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
169+
nrfx_rtc_counter_clear(rtc);
170+
} else if (counter_nrfx_read(dev) >= cfg->ticks) {
171+
err = -ETIME;
172+
if (cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE) {
173+
nrfx_rtc_counter_clear(rtc);
174+
}
175+
}
168176

169-
return 0;
177+
if (cfg->callback) {
178+
nrfx_rtc_int_enable(rtc, COUNTER_TOP_INT);
179+
}
180+
181+
return err;
170182
}
171183

172184
static u32_t counter_nrfx_get_pending_int(struct device *dev)

drivers/counter/counter_nrfx_timer.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,13 @@ 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;
165164
struct counter_nrfx_data *data = get_dev_data(dev);
165+
int err = 0;
166166

167167
for (int i = 0; i < counter_get_num_of_channels(dev); i++) {
168168
/* Overflow can be changed only when all alarms are
@@ -174,15 +174,27 @@ static int counter_nrfx_set_top_value(struct device *dev, u32_t ticks,
174174
}
175175

176176
nrfx_timer_compare_int_disable(timer, TOP_CH);
177-
nrfx_timer_clear(timer);
178177

179-
data->top_cb = callback;
180-
data->top_user_data = user_data;
178+
data->top_cb = cfg->callback;
179+
data->top_user_data = cfg->user_data;
181180
nrfx_timer_extended_compare(timer, TOP_CH,
182-
ticks, COUNTER_OVERFLOW_SHORT,
183-
callback ? true : false);
181+
cfg->ticks, COUNTER_OVERFLOW_SHORT,
182+
false);
183+
184+
if (!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
185+
nrfx_timer_clear(timer);
186+
} else if (counter_nrfx_read(dev) >= cfg->ticks) {
187+
err = -ETIME;
188+
if (cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE) {
189+
nrfx_timer_clear(timer);
190+
}
191+
}
184192

185-
return 0;
193+
if (cfg->callback) {
194+
nrfx_timer_compare_int_enable(timer, TOP_CH);
195+
}
196+
197+
return err;
186198
}
187199

188200
static u32_t counter_nrfx_get_pending_int(struct device *dev)

drivers/counter/counter_qmsi_aon.c

Lines changed: 1 addition & 3 deletions
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

Lines changed: 9 additions & 6 deletions
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

Lines changed: 4 additions & 8 deletions
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

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -226,48 +226,50 @@ 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
{
233-
bool reset = true;
234232
struct counter_sam0_tc32_data *data = DEV_DATA(dev);
235233
const struct counter_sam0_tc32_config *const cfg = DEV_CFG(dev);
236234
TcCount32 *tc = cfg->regs;
235+
int err = 0;
237236
int key = irq_lock();
238237

239238
if (data->ch.callback) {
240239
irq_unlock(key);
241240
return -EBUSY;
242241
}
243242

244-
if (callback) {
245-
data->top_cb = callback;
246-
data->top_user_data = user_data;
243+
if (top_cfg->callback) {
244+
data->top_cb = top_cfg->callback;
245+
data->top_user_data = top_cfg->user_data;
247246
tc->INTENSET.reg = TC_INTFLAG_MC0;
248247
} else {
249248
tc->INTENCLR.reg = TC_INTFLAG_MC0;
250249
}
251250

252-
tc->CC[0].reg = ticks;
251+
tc->CC[0].reg = top_cfg->ticks;
253252

254-
if (reset) {
255-
tc->CTRLBSET.reg = TC_CTRLBSET_CMD_RETRIGGER;
256-
} else {
253+
if (top_cfg->flags & COUNTER_TOP_CFG_DONT_RESET) {
257254
/*
258255
* Top trigger is on equality of the rising edge only, so
259256
* manually reset it if the counter has missed the new top.
260257
*/
261-
if (counter_sam0_tc32_read(dev) >= ticks) {
262-
tc->CTRLBSET.reg = TC_CTRLBSET_CMD_RETRIGGER;
258+
if (counter_sam0_tc32_read(dev) >= top_cfg->ticks) {
259+
err = -ETIME;
260+
if (top_cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE) {
261+
tc->CTRLBSET.reg = TC_CTRLBSET_CMD_RETRIGGER;
262+
}
263263
}
264+
} else {
265+
tc->CTRLBSET.reg = TC_CTRLBSET_CMD_RETRIGGER;
264266
}
265267

266268
wait_synchronization(tc);
267269

268270
tc->INTFLAG.reg = TC_INTFLAG_MC0;
269271
irq_unlock(key);
270-
return 0;
272+
return err;
271273
}
272274

273275
static u32_t counter_sam0_tc32_get_pending_int(struct device *dev)

0 commit comments

Comments
 (0)