-
Notifications
You must be signed in to change notification settings - Fork 7.7k
drivers: timer: nrf_rtc_timer: Allow use of custom bit width #92025
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -17,11 +17,21 @@ | |||||
#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."); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
If |
||||||
|
||||||
#if (CONFIG_NRF_RTC_COUNTER_BIT_WIDTH < 24) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
#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) | ||||||
|
||||||
#define RTC NRF_RTC1 | ||||||
#define RTC_IRQn NRFX_IRQ_NUMBER_GET(RTC) | ||||||
|
@@ -33,7 +43,7 @@ BUILD_ASSERT(CHAN_COUNT <= CHAN_COUNT_MAX, "Not enough compare channels"); | |||||
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 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would be good to have |
||||||
#define COUNTER_SPAN BIT(COUNTER_BIT_WIDTH) | ||||||
#define COUNTER_MAX (COUNTER_SPAN - 1U) | ||||||
#define COUNTER_HALF_SPAN (COUNTER_SPAN / 2U) | ||||||
|
@@ -259,6 +269,15 @@ static int set_alarm(int32_t chan, uint32_t req_cc, bool exact) | |||||
*/ | ||||||
enum { MIN_CYCLES_FROM_NOW = 3 }; | ||||||
uint32_t cc_val = req_cc; | ||||||
|
||||||
#if CUSTOM_COUNTER_BIT_WIDTH | ||||||
/* If a CC value is 0 when a CLEAR task is set, this will not | ||||||
* trigger a COMAPRE event. Need to use 1 instead. | ||||||
*/ | ||||||
if (cc_val % COUNTER_MAX == 0) { | ||||||
cc_val = 1; | ||||||
} | ||||||
#endif | ||||||
uint32_t cc_inc = MIN_CYCLES_FROM_NOW; | ||||||
|
||||||
/* Disable event routing for the channel to avoid getting a COMPARE | ||||||
|
@@ -422,6 +441,17 @@ uint64_t z_nrf_rtc_timer_read(void) | |||||
|
||||||
uint32_t cntr = counter(); | ||||||
|
||||||
#if CUSTOM_COUNTER_BIT_WIDTH | ||||||
/* If counter is equal to it maximum value while val is greater | ||||||
* than anchor, then we can assume that overflow has been recorded | ||||||
* in the overflow_cnt, but clear task has not been triggered yet. | ||||||
* Treat counter as if it has been cleared. | ||||||
*/ | ||||||
if ((cntr == COUNTER_MAX) && (val > anchor)) { | ||||||
cntr = 0; | ||||||
} | ||||||
#endif | ||||||
|
||||||
val += cntr; | ||||||
|
||||||
if (cntr < OVERFLOW_RISK_RANGE_END) { | ||||||
|
@@ -560,8 +590,13 @@ void rtc_nrf_isr(const void *arg) | |||||
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) && | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no need to check OVERFLOW event if custom bit width is used. |
||||||
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++; | ||||||
} | ||||||
|
||||||
|
@@ -697,7 +732,9 @@ uint32_t sys_clock_cycle_get_32(void) | |||||
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 | | ||||||
|
@@ -729,7 +766,9 @@ static int sys_clock_driver_init(void) | |||||
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); | ||||||
|
||||||
|
@@ -742,7 +781,7 @@ static int sys_clock_driver_init(void) | |||||
|
||||||
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); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With potentially 2 internal channels It would be good to define
And use it here and in places where 0 and 1 are used explicitly now. |
||||||
} | ||||||
|
||||||
uint32_t initial_timeout = IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? | ||||||
|
@@ -761,6 +800,28 @@ static int sys_clock_driver_init(void) | |||||
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; | ||||||
} | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
&rtc0 { | ||
status = "okay"; | ||
fixed-top; | ||
}; | ||
&rtc2 { | ||
status = "okay"; | ||
fixed-top; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
range x 24