Skip to content
Draft
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
62 changes: 62 additions & 0 deletions drivers/timer/nrf_grtc_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,23 @@
return (int32_t)chan;
}

int32_t z_nrf_grtc_timer_special_chan_alloc(void)
{
uint8_t chan;
int err_code;

/* Prevent allocating all available channels - one must be left for system purposes. */
if (ext_channels_allocated >= EXT_CHAN_COUNT) {
return -ENOMEM;
}
err_code = nrfx_grtc_extended_channel_alloc(&chan);
if (err_code < 0) {
return -ENOMEM;
}
ext_channels_allocated++;
return (int32_t)chan;
}

void z_nrf_grtc_timer_chan_free(int32_t chan)
{
IS_CHANNEL_ALLOWED_ASSERT(chan);
Expand Down Expand Up @@ -262,6 +279,51 @@
return ret;
}

static void interval_set_nolocks(int32_t chan, uint32_t interval_value,
z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
{

Check notice on line 284 in drivers/timer/nrf_grtc_timer.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/timer/nrf_grtc_timer.c:284 - z_nrf_grtc_timer_compare_handler_t handler, void *user_data) + z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
nrfx_grtc_channel_t user_channel_data = {
.handler = handler,
.p_context = user_data,
.channel = chan,
};

nrfx_grtc_syscounter_cc_interval_set(chan, interval_value, interval_value);
nrfx_grtc_channel_callback_set(chan, user_channel_data.handler,
user_channel_data.p_context);

}

static void interval_set(int32_t chan, uint32_t interval_value,
z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
{

Check notice on line 299 in drivers/timer/nrf_grtc_timer.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/timer/nrf_grtc_timer.c:299 - user_channel_data.p_context); - + user_channel_data.p_context); } static void interval_set(int32_t chan, uint32_t interval_value, - z_nrf_grtc_timer_compare_handler_t handler, void *user_data) + z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
bool key = compare_int_lock(chan);

interval_set_nolocks(chan, interval_value, handler, user_data);

compare_int_unlock(chan, key);
}

int z_nrf_grtc_timer_interval_set(int32_t chan, uint32_t interval_value,
z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
{

Check notice on line 309 in drivers/timer/nrf_grtc_timer.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/timer/nrf_grtc_timer.c:309 - z_nrf_grtc_timer_compare_handler_t handler, void *user_data) + z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
if (NRFX_BIT((uint32_t)chan) && NRFX_GRTC_CONFIG_EXTENDED_CC_CHANNELS_MASK == 0) {
return -ENOMEM;
}
if (handler == NULL) {
return -EINVAL;
}
interval_set(chan, interval_value, (nrfx_grtc_cc_handler_t)handler, user_data);

return 0;
}

int z_nrf_grtc_timer_interval_stop(int32_t chan)
{
nrfx_grtc_syscounter_cc_interval_reset(chan);
return 0;
}

int z_nrf_grtc_timer_set(int32_t chan, uint64_t target_time,
z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
{
Expand Down
6 changes: 6 additions & 0 deletions dts/bindings/timer/nordic,nrf-grtc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,9 @@ properties:
description: |
Clock frequency information for tick increment operations, this default value comes from
the nRF54L15 datasheet.
extended-channels:
type: array
description: |
List of channels in a split-ownership peripheral that are to be owned
for use by the compiled CPU.
1 change: 1 addition & 0 deletions dts/vendor/nordic/nrf54h20.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,7 @@
cc-num = <16>;
clocks = <&lfclk>, <&fll16m>;
clock-names = "lfclock", "hfclock";
extended-channels = <0>;
};

dppic133: dppic@9a1000 {
Expand Down
1 change: 1 addition & 0 deletions dts/vendor/nordic/nrf54l_05_10_15.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@
clocks = <&lfxo>, <&pclk>;
clock-names = "lfclock", "hfclock";
status = "disabled";
extended-channels = <0>;
};

dppic30: dppic@102000 {
Expand Down
1 change: 1 addition & 0 deletions dts/vendor/nordic/nrf54lm20a.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@
clocks = <&lfxo>, <&pclk>;
clock-names = "lfclock", "hfclock";
status = "disabled";
extended-channels = <0>;
};

tdm: tdm@e8000 {
Expand Down
1 change: 1 addition & 0 deletions dts/vendor/nordic/nrf9280.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,7 @@
reg = <0x99c000 0x1000>;
status = "disabled";
cc-num = <16>;
extended-channels = <0>;
};

dppic133: dppic@9a1000 {
Expand Down
9 changes: 8 additions & 1 deletion include/zephyr/drivers/timer/nrf_grtc_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
*/
int32_t z_nrf_grtc_timer_chan_alloc(void);

int32_t z_nrf_grtc_timer_special_chan_alloc(void);

/** @brief Free GRTC capture/compare channel.
*
* @param chan Previously allocated channel ID.
Expand Down Expand Up @@ -123,7 +125,12 @@
* @retval -EPERM if either channel is unavailable or SYSCOUNTER is not running.
*/
int z_nrf_grtc_timer_set(int32_t chan, uint64_t target_time,
z_nrf_grtc_timer_compare_handler_t handler, void *user_data);
z_nrf_grtc_timer_compare_handler_t handler, void *user_data);

int z_nrf_grtc_timer_interval_set(int32_t chan, uint32_t interval_value,
z_nrf_grtc_timer_compare_handler_t handler, void *user_data);

Check notice on line 132 in include/zephyr/drivers/timer/nrf_grtc_timer.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

include/zephyr/drivers/timer/nrf_grtc_timer.h:132 - z_nrf_grtc_timer_compare_handler_t handler, void *user_data); + z_nrf_grtc_timer_compare_handler_t handler, void *user_data); int z_nrf_grtc_timer_interval_set(int32_t chan, uint32_t interval_value, - z_nrf_grtc_timer_compare_handler_t handler, void *user_data); + z_nrf_grtc_timer_compare_handler_t handler, void *user_data);
int z_nrf_grtc_timer_interval_stop(int32_t chan);

/** @brief Abort a timer requested with z_nrf_grtc_timer_set().
*
Expand Down
3 changes: 3 additions & 0 deletions modules/hal_nordic/nrfx/nrfx_reserved_resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
#define NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS \
(DT_PROP_LEN_OR(DT_INST(0, nordic_nrf_grtc), owned_channels, 0) - \
DT_PROP_LEN_OR(DT_INST(0, nordic_nrf_grtc), child_owned_channels, 0))
#define NRFX_GRTC_CONFIG_EXTENDED_CC_CHANNELS_MASK \
(NRFX_CONFIG_MASK_DT(DT_INST(0, nordic_nrf_grtc), extended_channels) & \
~NRFX_CONFIG_MASK_DT(DT_INST(0, nordic_nrf_grtc), child_owned_channels))

Check notice on line 47 in modules/hal_nordic/nrfx/nrfx_reserved_resources.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

modules/hal_nordic/nrfx/nrfx_reserved_resources.h:47 -#define NRFX_GRTC_CONFIG_EXTENDED_CC_CHANNELS_MASK \ - (NRFX_CONFIG_MASK_DT(DT_INST(0, nordic_nrf_grtc), extended_channels) & \ +#define NRFX_GRTC_CONFIG_EXTENDED_CC_CHANNELS_MASK \ + (NRFX_CONFIG_MASK_DT(DT_INST(0, nordic_nrf_grtc), extended_channels) & \
#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_grtc) */

/*
Expand Down
47 changes: 47 additions & 0 deletions tests/drivers/timer/nrf_grtc_timer/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@

#define GRTC_SLEW_TICKS 10
#define NUMBER_OF_TRIES 2000
#define NUMBER_OF_INTERVAL_EVENTS 10
#define CYC_PER_TICK \
((uint64_t)sys_clock_hw_cycles_per_sec() / (uint64_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC)
#define TIMER_COUNT_TIME_MS 10
#define INTERVAL_COUNT_TIME_MS 50
#define WAIT_FOR_TIMER_EVENT_TIME_MS TIMER_COUNT_TIME_MS + 5

Check notice on line 25 in tests/drivers/timer/nrf_grtc_timer/src/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

tests/drivers/timer/nrf_grtc_timer/src/main.c:25 -#define INTERVAL_COUNT_TIME_MS 50 +#define INTERVAL_COUNT_TIME_MS 50

static volatile uint8_t compare_isr_call_counter;

Expand All @@ -32,6 +34,16 @@
TC_PRINT("Call counter: %d\n", compare_isr_call_counter);
}

/* GRTC timer interval interrupt handler */
static void timer_interval_interrupt_handler(int32_t id, uint64_t expire_time, void *user_data)
{
(void)id;
(void)expire_time;
(void)user_data;

compare_isr_call_counter++;
}

ZTEST(nrf_grtc_timer, test_get_ticks)
{
k_timeout_t t = K_MSEC(1);
Expand Down Expand Up @@ -161,6 +173,41 @@
z_nrf_grtc_timer_chan_free(channel);
}

ZTEST(nrf_grtc_timer, test_timer_interval_mode)
{
int err;
uint64_t test_ticks = 0;
char user_data[] = "test_timer_interval_mode\n";
int32_t channel = z_nrf_grtc_timer_special_chan_alloc();

if (channel < 0) {
if ((NRFX_GRTC_CONFIG_EXTENDED_CC_CHANNELS_MASK &
NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK) == 0) {
ztest_test_pass();
}
TC_PRINT("Failed to allocate GRTC channel, chan=%d\n", channel);
ztest_test_fail();
}
TC_PRINT("Allocated GRTC channel %d\n", channel);

compare_isr_call_counter = 0;
test_ticks = INTERVAL_COUNT_TIME_MS * 1000;
err = z_nrf_grtc_timer_interval_set(channel, test_ticks, timer_interval_interrupt_handler,
(void *)user_data);
zassert_equal(err, 0, "z_nrf_grtc_timer_set raised an error: %d", err);

Check notice on line 197 in tests/drivers/timer/nrf_grtc_timer/src/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

tests/drivers/timer/nrf_grtc_timer/src/main.c:197 - (void *)user_data); + (void *)user_data);

k_busy_wait(NUMBER_OF_INTERVAL_EVENTS * test_ticks + test_ticks / 2);

z_nrf_grtc_timer_interval_stop(channel);
TC_PRINT("Interval events count: %d\n", compare_isr_call_counter);
TC_PRINT("Compare event register address: %X\n",
z_nrf_grtc_timer_compare_evt_address_get(channel));

zassert_equal(compare_isr_call_counter, NUMBER_OF_INTERVAL_EVENTS,
"Compare isr call counter: %d", compare_isr_call_counter);
z_nrf_grtc_timer_chan_free(channel);

Check notice on line 208 in tests/drivers/timer/nrf_grtc_timer/src/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

tests/drivers/timer/nrf_grtc_timer/src/main.c:208 - "Compare isr call counter: %d", compare_isr_call_counter); + "Compare isr call counter: %d", compare_isr_call_counter);
}

enum test_timer_state {
TIMER_IDLE,
TIMER_PREPARE,
Expand Down
Loading