Skip to content

Commit 9b17fb1

Browse files
[draft] nrfx grtc interval
Signed-off-by: Adam Kondraciuk <[email protected]>
1 parent dd66b34 commit 9b17fb1

File tree

9 files changed

+130
-1
lines changed

9 files changed

+130
-1
lines changed

drivers/timer/nrf_grtc_timer.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,23 @@ int32_t z_nrf_grtc_timer_chan_alloc(void)
180180
return (int32_t)chan;
181181
}
182182

183+
int32_t z_nrf_grtc_timer_special_chan_alloc(void)
184+
{
185+
uint8_t chan;
186+
int err_code;
187+
188+
/* Prevent allocating all available channels - one must be left for system purposes. */
189+
if (ext_channels_allocated >= EXT_CHAN_COUNT) {
190+
return -ENOMEM;
191+
}
192+
err_code = nrfx_grtc_extended_channel_alloc(&chan);
193+
if (err_code < 0) {
194+
return -ENOMEM;
195+
}
196+
ext_channels_allocated++;
197+
return (int32_t)chan;
198+
}
199+
183200
void z_nrf_grtc_timer_chan_free(int32_t chan)
184201
{
185202
IS_CHANNEL_ALLOWED_ASSERT(chan);
@@ -262,6 +279,51 @@ static int compare_set(int32_t chan, uint64_t target_time,
262279
return ret;
263280
}
264281

282+
static void interval_set_nolocks(int32_t chan, uint32_t interval_value,
283+
z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
284+
{
285+
nrfx_grtc_channel_t user_channel_data = {
286+
.handler = handler,
287+
.p_context = user_data,
288+
.channel = chan,
289+
};
290+
291+
nrfx_grtc_syscounter_cc_interval_set(chan, interval_value, interval_value);
292+
nrfx_grtc_channel_callback_set(chan, user_channel_data.handler,
293+
user_channel_data.p_context);
294+
295+
}
296+
297+
static void interval_set(int32_t chan, uint32_t interval_value,
298+
z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
299+
{
300+
bool key = compare_int_lock(chan);
301+
302+
interval_set_nolocks(chan, interval_value, handler, user_data);
303+
304+
compare_int_unlock(chan, key);
305+
}
306+
307+
int z_nrf_grtc_timer_interval_set(int32_t chan, uint32_t interval_value,
308+
z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
309+
{
310+
if (NRFX_BIT((uint32_t)chan) && NRFX_GRTC_CONFIG_EXTENDED_CC_CHANNELS_MASK == 0) {
311+
return -ENOMEM;
312+
}
313+
if (handler == NULL) {
314+
return -EINVAL;
315+
}
316+
interval_set(chan, interval_value, (nrfx_grtc_cc_handler_t)handler, user_data);
317+
318+
return 0;
319+
}
320+
321+
int z_nrf_grtc_timer_interval_stop(int32_t chan)
322+
{
323+
nrfx_grtc_syscounter_cc_interval_reset(chan);
324+
return 0;
325+
}
326+
265327
int z_nrf_grtc_timer_set(int32_t chan, uint64_t target_time,
266328
z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
267329
{

dts/bindings/timer/nordic,nrf-grtc.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,9 @@ properties:
5252
description: |
5353
Clock frequency information for tick increment operations, this default value comes from
5454
the nRF54L15 datasheet.
55+
56+
extended-channels:
57+
type: array
58+
description: |
59+
List of channels in a split-ownership peripheral that are to be owned
60+
for use by the compiled CPU.

dts/vendor/nordic/nrf54h20.dtsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,7 @@
10731073
cc-num = <16>;
10741074
clocks = <&lfclk>, <&fll16m>;
10751075
clock-names = "lfclock", "hfclock";
1076+
extended-channels = <0>;
10761077
};
10771078

10781079
dppic133: dppic@9a1000 {

dts/vendor/nordic/nrf54l_05_10_15.dtsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@
574574
clocks = <&lfxo>, <&pclk>;
575575
clock-names = "lfclock", "hfclock";
576576
status = "disabled";
577+
extended-channels = <0>;
577578
};
578579

579580
dppic30: dppic@102000 {

dts/vendor/nordic/nrf54lm20a.dtsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,7 @@
612612
clocks = <&lfxo>, <&pclk>;
613613
clock-names = "lfclock", "hfclock";
614614
status = "disabled";
615+
extended-channels = <0>;
615616
};
616617

617618
tdm: tdm@e8000 {

dts/vendor/nordic/nrf9280.dtsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,7 @@
758758
reg = <0x99c000 0x1000>;
759759
status = "disabled";
760760
cc-num = <16>;
761+
extended-channels = <0>;
761762
};
762763

763764
dppic133: dppic@9a1000 {

include/zephyr/drivers/timer/nrf_grtc_timer.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ typedef void (*z_nrf_grtc_timer_compare_handler_t)(int32_t id, uint64_t expire_t
3636
*/
3737
int32_t z_nrf_grtc_timer_chan_alloc(void);
3838

39+
int32_t z_nrf_grtc_timer_special_chan_alloc(void);
40+
3941
/** @brief Free GRTC capture/compare channel.
4042
*
4143
* @param chan Previously allocated channel ID.
@@ -123,7 +125,12 @@ int z_nrf_grtc_timer_compare_read(int32_t chan, uint64_t *val);
123125
* @retval -EPERM if either channel is unavailable or SYSCOUNTER is not running.
124126
*/
125127
int z_nrf_grtc_timer_set(int32_t chan, uint64_t target_time,
126-
z_nrf_grtc_timer_compare_handler_t handler, void *user_data);
128+
z_nrf_grtc_timer_compare_handler_t handler, void *user_data);
129+
130+
int z_nrf_grtc_timer_interval_set(int32_t chan, uint32_t interval_value,
131+
z_nrf_grtc_timer_compare_handler_t handler, void *user_data);
132+
133+
int z_nrf_grtc_timer_interval_stop(int32_t chan);
127134

128135
/** @brief Abort a timer requested with z_nrf_grtc_timer_set().
129136
*

modules/hal_nordic/nrfx/nrfx_reserved_resources.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
#define NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS \
4343
(DT_PROP_LEN_OR(DT_INST(0, nordic_nrf_grtc), owned_channels, 0) - \
4444
DT_PROP_LEN_OR(DT_INST(0, nordic_nrf_grtc), child_owned_channels, 0))
45+
#define NRFX_GRTC_CONFIG_EXTENDED_CC_CHANNELS_MASK \
46+
(NRFX_CONFIG_MASK_DT(DT_INST(0, nordic_nrf_grtc), extended_channels) & \
47+
~NRFX_CONFIG_MASK_DT(DT_INST(0, nordic_nrf_grtc), child_owned_channels))
4548
#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_grtc) */
4649

4750
/*

tests/drivers/timer/nrf_grtc_timer/src/main.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ LOG_MODULE_REGISTER(test, 1);
1717

1818
#define GRTC_SLEW_TICKS 10
1919
#define NUMBER_OF_TRIES 2000
20+
#define NUMBER_OF_INTERVAL_EVENTS 10
2021
#define CYC_PER_TICK \
2122
((uint64_t)sys_clock_hw_cycles_per_sec() / (uint64_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC)
2223
#define TIMER_COUNT_TIME_MS 10
24+
#define INTERVAL_COUNT_TIME_MS 50
2325
#define WAIT_FOR_TIMER_EVENT_TIME_MS TIMER_COUNT_TIME_MS + 5
2426

2527
static volatile uint8_t compare_isr_call_counter;
@@ -32,6 +34,16 @@ static void timer_compare_interrupt_handler(int32_t id, uint64_t expire_time, vo
3234
TC_PRINT("Call counter: %d\n", compare_isr_call_counter);
3335
}
3436

37+
/* GRTC timer interval interrupt handler */
38+
static void timer_interval_interrupt_handler(int32_t id, uint64_t expire_time, void *user_data)
39+
{
40+
(void)id;
41+
(void)expire_time;
42+
(void)user_data;
43+
44+
compare_isr_call_counter++;
45+
}
46+
3547
ZTEST(nrf_grtc_timer, test_get_ticks)
3648
{
3749
k_timeout_t t = K_MSEC(1);
@@ -161,6 +173,41 @@ ZTEST(nrf_grtc_timer, test_timer_abort_in_compare_mode)
161173
z_nrf_grtc_timer_chan_free(channel);
162174
}
163175

176+
ZTEST(nrf_grtc_timer, test_timer_interval_mode)
177+
{
178+
int err;
179+
uint64_t test_ticks = 0;
180+
char user_data[] = "test_timer_interval_mode\n";
181+
int32_t channel = z_nrf_grtc_timer_special_chan_alloc();
182+
183+
if (channel < 0) {
184+
if ((NRFX_GRTC_CONFIG_EXTENDED_CC_CHANNELS_MASK &
185+
NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK) == 0) {
186+
ztest_test_pass();
187+
}
188+
TC_PRINT("Failed to allocate GRTC channel, chan=%d\n", channel);
189+
ztest_test_fail();
190+
}
191+
TC_PRINT("Allocated GRTC channel %d\n", channel);
192+
193+
compare_isr_call_counter = 0;
194+
test_ticks = INTERVAL_COUNT_TIME_MS * 1000;
195+
err = z_nrf_grtc_timer_interval_set(channel, test_ticks, timer_interval_interrupt_handler,
196+
(void *)user_data);
197+
zassert_equal(err, 0, "z_nrf_grtc_timer_set raised an error: %d", err);
198+
199+
k_busy_wait(NUMBER_OF_INTERVAL_EVENTS * test_ticks + test_ticks / 2);
200+
201+
z_nrf_grtc_timer_interval_stop(channel);
202+
TC_PRINT("Interval events count: %d\n", compare_isr_call_counter);
203+
TC_PRINT("Compare event register address: %X\n",
204+
z_nrf_grtc_timer_compare_evt_address_get(channel));
205+
206+
zassert_equal(compare_isr_call_counter, NUMBER_OF_INTERVAL_EVENTS,
207+
"Compare isr call counter: %d", compare_isr_call_counter);
208+
z_nrf_grtc_timer_chan_free(channel);
209+
}
210+
164211
enum test_timer_state {
165212
TIMER_IDLE,
166213
TIMER_PREPARE,

0 commit comments

Comments
 (0)