Skip to content

[nrf fromlist] drivers: timer: nrf_rtc_timer: Allow use of custom bit width #2976

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
8 changes: 8 additions & 0 deletions drivers/timer/Kconfig.nrf_rtc
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,12 @@ config NRF_RTC_TIMER_TRIGGER_OVERFLOW
When enabled, a function can be used to trigger RTC overflow and
effectively shift time into the future.

config NRF_RTC_COUNTER_BIT_WIDTH
int "Bit width of RTC counter"
default 24
help
Use custom bit width of RTC counter. If bit width other than 24 bits
is used then one RTC channel will be reserved to control wrapping via
PPI connections.

endif # NRF_RTC_TIMER
51 changes: 46 additions & 5 deletions drivers/timer/nrf_rtc_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,22 @@
#include <haly/nrfy_rtc.h>
#include <zephyr/irq.h>

/* Ensure that selected counter bit width is within its maximum hardware width. */
BUILD_ASSERT(CONFIG_NRF_RTC_COUNTER_BIT_WIDTH <= 24, "Counter bit width exceeds maximum width.");

#if (CONFIG_NRF_RTC_COUNTER_BIT_WIDTH < 24)
#define CUSTOM_COUNTER_BIT_WIDTH 1
#include "nrfx_ppi.h"
#else
#define CUSTOM_COUNTER_BIT_WIDTH 0
#endif

#define RTC_PRETICK (IS_ENABLED(CONFIG_SOC_NRF53_RTC_PRETICK) && \
IS_ENABLED(CONFIG_SOC_NRF5340_CPUNET))

#define EXT_CHAN_COUNT CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT
#define CHAN_COUNT (EXT_CHAN_COUNT + 1)
#define CHAN_COUNT (EXT_CHAN_COUNT + 1 + CUSTOM_COUNTER_BIT_WIDTH)

Check notice on line 35 in drivers/timer/nrf_rtc_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_rtc_timer.c:35 -#define CHAN_COUNT (EXT_CHAN_COUNT + 1 + CUSTOM_COUNTER_BIT_WIDTH) +#define CHAN_COUNT (EXT_CHAN_COUNT + 1 + CUSTOM_COUNTER_BIT_WIDTH)
#define RTC NRF_RTC1
#define RTC_IRQn NRFX_IRQ_NUMBER_GET(RTC)
#define RTC_LABEL rtc1
Expand All @@ -33,7 +43,7 @@
BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_NODELABEL(RTC_LABEL), disabled),
"Counter for RTC1 must be disabled");

#define COUNTER_BIT_WIDTH 24U
#define COUNTER_BIT_WIDTH CONFIG_NRF_RTC_COUNTER_BIT_WIDTH
#define COUNTER_SPAN BIT(COUNTER_BIT_WIDTH)
#define COUNTER_MAX (COUNTER_SPAN - 1U)
#define COUNTER_HALF_SPAN (COUNTER_SPAN / 2U)
Expand Down Expand Up @@ -565,9 +575,14 @@
rtc_pretick_rtc1_isr_hook();
}

if (nrfy_rtc_int_enable_check(RTC, NRF_RTC_INT_OVERFLOW_MASK) &&
nrfy_rtc_events_process(RTC, NRF_RTC_INT_OVERFLOW_MASK)) {
if ((nrfy_rtc_int_enable_check(RTC, NRF_RTC_INT_OVERFLOW_MASK) &&
nrfy_rtc_events_process(RTC, NRF_RTC_INT_OVERFLOW_MASK)) ||
#if CUSTOM_COUNTER_BIT_WIDTH
(nrfy_rtc_int_enable_check(RTC, NRF_RTC_INT_COMPARE1_MASK) &&
nrfy_rtc_events_process(RTC, NRF_RTC_INT_COMPARE1_MASK)) ||
#endif
0) {
overflow_cnt++;

Check notice on line 585 in drivers/timer/nrf_rtc_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_rtc_timer.c:585 - nrfy_rtc_events_process(RTC, NRF_RTC_INT_OVERFLOW_MASK)) || + nrfy_rtc_events_process(RTC, NRF_RTC_INT_OVERFLOW_MASK)) || #if CUSTOM_COUNTER_BIT_WIDTH (nrfy_rtc_int_enable_check(RTC, NRF_RTC_INT_COMPARE1_MASK) && - nrfy_rtc_events_process(RTC, NRF_RTC_INT_COMPARE1_MASK)) || + nrfy_rtc_events_process(RTC, NRF_RTC_INT_COMPARE1_MASK)) || #endif - 0) { + 0) {
}

for (int32_t chan = 0; chan < CHAN_COUNT; chan++) {
Expand Down Expand Up @@ -702,12 +717,14 @@
static void int_event_disable_rtc(void)
{
uint32_t mask = NRF_RTC_INT_TICK_MASK |
#if !CUSTOM_COUNTER_BIT_WIDTH
NRF_RTC_INT_OVERFLOW_MASK |
#endif
NRF_RTC_INT_COMPARE0_MASK |
NRF_RTC_INT_COMPARE1_MASK |
NRF_RTC_INT_COMPARE2_MASK |
NRF_RTC_INT_COMPARE3_MASK;

Check notice on line 727 in drivers/timer/nrf_rtc_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_rtc_timer.c:727 - uint32_t mask = NRF_RTC_INT_TICK_MASK | + uint32_t mask = NRF_RTC_INT_TICK_MASK | #if !CUSTOM_COUNTER_BIT_WIDTH NRF_RTC_INT_OVERFLOW_MASK | #endif - NRF_RTC_INT_COMPARE0_MASK | - NRF_RTC_INT_COMPARE1_MASK | - NRF_RTC_INT_COMPARE2_MASK | - NRF_RTC_INT_COMPARE3_MASK; + NRF_RTC_INT_COMPARE0_MASK | NRF_RTC_INT_COMPARE1_MASK | + NRF_RTC_INT_COMPARE2_MASK | NRF_RTC_INT_COMPARE3_MASK;
/* Reset interrupt enabling to expected reset values */
nrfy_rtc_int_disable(RTC, mask);

Expand All @@ -734,7 +751,9 @@
nrfy_rtc_int_enable(RTC, NRF_RTC_CHANNEL_INT_MASK(chan));
}

#if !CUSTOM_COUNTER_BIT_WIDTH
nrfy_rtc_int_enable(RTC, NRF_RTC_INT_OVERFLOW_MASK);
#endif

NVIC_ClearPendingIRQ(RTC_IRQn);

Expand All @@ -747,7 +766,7 @@

int_mask = BIT_MASK(CHAN_COUNT);
if (CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT) {
alloc_mask = BIT_MASK(EXT_CHAN_COUNT) << 1;
alloc_mask = BIT_MASK(EXT_CHAN_COUNT) << (1 + CUSTOM_COUNTER_BIT_WIDTH);
}

uint32_t initial_timeout = IS_ENABLED(CONFIG_TICKLESS_KERNEL) ?
Expand All @@ -766,6 +785,28 @@
z_nrf_clock_control_lf_on(mode);
#endif

#if CUSTOM_COUNTER_BIT_WIDTH
/* Use channel 1 for wrapping. */
uint8_t chan = 1;
nrf_rtc_event_t evt = NRF_RTC_CHANNEL_EVENT_ADDR(chan);
nrfx_err_t result;
nrf_ppi_channel_t ch;

nrfy_rtc_event_enable(RTC, NRF_RTC_CHANNEL_INT_MASK(chan));
nrfy_rtc_cc_set(RTC, chan, COUNTER_MAX);
uint32_t evt_addr;
uint32_t task_addr;

evt_addr = nrfy_rtc_event_address_get(RTC, evt);
task_addr = nrfy_rtc_task_address_get(RTC, NRF_RTC_TASK_CLEAR);

result = nrfx_ppi_channel_alloc(&ch);
if (result != NRFX_SUCCESS) {
return -ENODEV;
}
(void)nrfx_ppi_channel_assign(ch, evt_addr, task_addr);
(void)nrfx_ppi_channel_enable(ch);
#endif
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion include/zephyr/drivers/timer/nrf_rtc_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ extern "C" {

/** @brief Maximum allowed time span that is considered to be in the future.
*/
#define NRF_RTC_TIMER_MAX_SCHEDULE_SPAN BIT(23)
#define NRF_RTC_TIMER_MAX_SCHEDULE_SPAN BIT(CONFIG_NRF_RTC_COUNTER_BIT_WIDTH - 1)

/** @brief RTC timer compare event handler.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
&rtc0 {
status = "okay";
fixed-top;
};
&rtc2 {
status = "okay";
fixed-top;
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ tests:
- counter
depends_on: counter
platform_allow:
- nrf52dk/nrf52832
- nrf52840dk/nrf52840
- nrf52_bsim
- nrf54h20dk/nrf54h20/cpuapp
Expand Down
5 changes: 5 additions & 0 deletions tests/drivers/timer/nrf_rtc_timer/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,11 @@ static void overflow_sched_handler(int32_t id, uint64_t expire_time,
*/
ZTEST(nrf_rtc_timer, test_overflow)
{
/* For bit width lower than default 24, overflow injection is not possible. */
if (CONFIG_NRF_RTC_COUNTER_BIT_WIDTH < 24) {
ztest_test_skip();
}

PRINT("RTC ticks before overflow injection: %u\r\n",
(uint32_t)z_nrf_rtc_timer_read());

Expand Down
12 changes: 12 additions & 0 deletions tests/drivers/timer/nrf_rtc_timer/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,15 @@ tests:
- nrf5340bsim/nrf5340/cpunet
integration_platforms:
- nrf52dk/nrf52832

drivers.timer.nrf_rtc_timer_16_bits:
tags:
- drivers
- timer
platform_allow:
- nrf52dk/nrf52832
integration_platforms:
- nrf52dk/nrf52832
extra_configs:
- CONFIG_ZERO_LATENCY_IRQS=y
- CONFIG_NRF_RTC_COUNTER_BIT_WIDTH=16
Loading