1717#include <haly/nrfy_rtc.h>
1818#include <zephyr/irq.h>
1919
20+ #define RTC_BIT_WIDTH 24
21+
22+ #if (CONFIG_NRF_RTC_COUNTER_BIT_WIDTH < RTC_BIT_WIDTH )
23+ #define CUSTOM_COUNTER_BIT_WIDTH 1
24+ #define WRAP_CH 1
25+ #include "nrfx_ppi.h"
26+ #else
27+ #define CUSTOM_COUNTER_BIT_WIDTH 0
28+ #endif
29+
2030#define RTC_PRETICK (IS_ENABLED(CONFIG_SOC_NRF53_RTC_PRETICK) && \
2131 IS_ENABLED(CONFIG_SOC_NRF5340_CPUNET))
2232
2333#define EXT_CHAN_COUNT CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT
24- #define CHAN_COUNT (EXT_CHAN_COUNT + 1)
34+ #define CHAN_COUNT (EXT_CHAN_COUNT + 1 + CUSTOM_COUNTER_BIT_WIDTH )
2535
2636#define RTC NRF_RTC1
2737#define RTC_IRQn NRFX_IRQ_NUMBER_GET(RTC)
2838#define RTC_LABEL rtc1
2939#define CHAN_COUNT_MAX (RTC1_CC_NUM - (RTC_PRETICK ? 1 : 0))
40+ #define SYS_CLOCK_CH 0
3041
3142BUILD_ASSERT (CHAN_COUNT <= CHAN_COUNT_MAX , "Not enough compare channels" );
3243/* Ensure that counter driver for RTC1 is not enabled. */
3344BUILD_ASSERT (DT_NODE_HAS_STATUS (DT_NODELABEL (RTC_LABEL ), disabled ),
3445 "Counter for RTC1 must be disabled" );
3546
36- #define COUNTER_BIT_WIDTH 24U
47+ #define COUNTER_BIT_WIDTH CONFIG_NRF_RTC_COUNTER_BIT_WIDTH
3748#define COUNTER_SPAN BIT(COUNTER_BIT_WIDTH)
3849#define COUNTER_MAX (COUNTER_SPAN - 1U)
3950#define COUNTER_HALF_SPAN (COUNTER_SPAN / 2U)
@@ -139,7 +150,7 @@ uint32_t z_nrf_rtc_timer_capture_task_address_get(int32_t chan)
139150{
140151#if defined(RTC_TASKS_CAPTURE_TASKS_CAPTURE_Msk )
141152 __ASSERT_NO_MSG (chan >= 0 && chan < CHAN_COUNT );
142- if (chan == 0 ) {
153+ if (chan == SYS_CLOCK_CH ) {
143154 return 0 ;
144155 }
145156
@@ -264,6 +275,15 @@ static int set_alarm(int32_t chan, uint32_t req_cc, bool exact)
264275 */
265276 enum { MIN_CYCLES_FROM_NOW = 3 };
266277 uint32_t cc_val = req_cc ;
278+
279+ #if CUSTOM_COUNTER_BIT_WIDTH
280+ /* If a CC value is 0 when a CLEAR task is set, this will not
281+ * trigger a COMAPRE event. Need to use 1 instead.
282+ */
283+ if (cc_val % COUNTER_MAX == 0 ) {
284+ cc_val = 1 ;
285+ }
286+ #endif
267287 uint32_t cc_inc = MIN_CYCLES_FROM_NOW ;
268288
269289 /* Disable event routing for the channel to avoid getting a COMPARE
@@ -427,6 +447,17 @@ uint64_t z_nrf_rtc_timer_read(void)
427447
428448 uint32_t cntr = counter ();
429449
450+ #if CUSTOM_COUNTER_BIT_WIDTH
451+ /* If counter is equal to it maximum value while val is greater
452+ * than anchor, then we can assume that overflow has been recorded
453+ * in the overflow_cnt, but clear task has not been triggered yet.
454+ * Treat counter as if it has been cleared.
455+ */
456+ if ((cntr == COUNTER_MAX ) && (val > anchor )) {
457+ cntr = 0 ;
458+ }
459+ #endif
460+
430461 val += cntr ;
431462
432463 if (cntr < OVERFLOW_RISK_RANGE_END ) {
@@ -565,8 +596,13 @@ void rtc_nrf_isr(const void *arg)
565596 rtc_pretick_rtc1_isr_hook ();
566597 }
567598
599+ #if CUSTOM_COUNTER_BIT_WIDTH
600+ if (nrfy_rtc_int_enable_check (RTC , NRF_RTC_INT_COMPARE1_MASK ) &&
601+ nrfy_rtc_events_process (RTC , NRF_RTC_INT_COMPARE1_MASK )) {
602+ #else
568603 if (nrfy_rtc_int_enable_check (RTC , NRF_RTC_INT_OVERFLOW_MASK ) &&
569604 nrfy_rtc_events_process (RTC , NRF_RTC_INT_OVERFLOW_MASK )) {
605+ #endif
570606 overflow_cnt ++ ;
571607 }
572608
@@ -625,7 +661,7 @@ int z_nrf_rtc_timer_trigger_overflow(void)
625661 uint64_t now = z_nrf_rtc_timer_read ();
626662
627663 if (err == 0 ) {
628- sys_clock_timeout_handler (0 , now , NULL );
664+ sys_clock_timeout_handler (SYS_CLOCK_CH , now , NULL );
629665 }
630666bail :
631667 full_int_unlock (mcu_critical_state );
@@ -682,7 +718,7 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
682718
683719 uint64_t target_time = cyc + last_count ;
684720
685- compare_set (0 , target_time , sys_clock_timeout_handler , NULL , false);
721+ compare_set (SYS_CLOCK_CH , target_time , sys_clock_timeout_handler , NULL , false);
686722}
687723
688724uint32_t sys_clock_elapsed (void )
@@ -702,7 +738,9 @@ uint32_t sys_clock_cycle_get_32(void)
702738static void int_event_disable_rtc (void )
703739{
704740 uint32_t mask = NRF_RTC_INT_TICK_MASK |
741+ #if !CUSTOM_COUNTER_BIT_WIDTH
705742 NRF_RTC_INT_OVERFLOW_MASK |
743+ #endif
706744 NRF_RTC_INT_COMPARE0_MASK |
707745 NRF_RTC_INT_COMPARE1_MASK |
708746 NRF_RTC_INT_COMPARE2_MASK |
@@ -734,7 +772,9 @@ static int sys_clock_driver_init(void)
734772 nrfy_rtc_int_enable (RTC , NRF_RTC_CHANNEL_INT_MASK (chan ));
735773 }
736774
775+ #if !CUSTOM_COUNTER_BIT_WIDTH
737776 nrfy_rtc_int_enable (RTC , NRF_RTC_INT_OVERFLOW_MASK );
777+ #endif
738778
739779 NVIC_ClearPendingIRQ (RTC_IRQn );
740780
@@ -747,13 +787,13 @@ static int sys_clock_driver_init(void)
747787
748788 int_mask = BIT_MASK (CHAN_COUNT );
749789 if (CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT ) {
750- alloc_mask = BIT_MASK (EXT_CHAN_COUNT ) << 1 ;
790+ alloc_mask = BIT_MASK (CHAN_COUNT ) & ~ BIT ( SYS_CLOCK_CH ) ;
751791 }
752792
753793 uint32_t initial_timeout = IS_ENABLED (CONFIG_TICKLESS_KERNEL ) ?
754794 MAX_CYCLES : CYC_PER_TICK ;
755795
756- compare_set (0 , initial_timeout , sys_clock_timeout_handler , NULL , false);
796+ compare_set (SYS_CLOCK_CH , initial_timeout , sys_clock_timeout_handler , NULL , false);
757797
758798#if defined(CONFIG_CLOCK_CONTROL_NRF )
759799 static const enum nrf_lfclk_start_mode mode =
@@ -766,6 +806,29 @@ static int sys_clock_driver_init(void)
766806 z_nrf_clock_control_lf_on (mode );
767807#endif
768808
809+ #if CUSTOM_COUNTER_BIT_WIDTH
810+ /* WRAP_CH reserved for wrapping. */
811+ alloc_mask &= ~BIT (WRAP_CH );
812+
813+ nrf_rtc_event_t evt = NRF_RTC_CHANNEL_EVENT_ADDR (WRAP_CH );
814+ nrfx_err_t result ;
815+ nrf_ppi_channel_t ch ;
816+
817+ nrfy_rtc_event_enable (RTC , NRF_RTC_CHANNEL_INT_MASK (WRAP_CH ));
818+ nrfy_rtc_cc_set (RTC , WRAP_CH , COUNTER_MAX );
819+ uint32_t evt_addr ;
820+ uint32_t task_addr ;
821+
822+ evt_addr = nrfy_rtc_event_address_get (RTC , evt );
823+ task_addr = nrfy_rtc_task_address_get (RTC , NRF_RTC_TASK_CLEAR );
824+
825+ result = nrfx_ppi_channel_alloc (& ch );
826+ if (result != NRFX_SUCCESS ) {
827+ return - ENODEV ;
828+ }
829+ (void )nrfx_ppi_channel_assign (ch , evt_addr , task_addr );
830+ (void )nrfx_ppi_channel_enable (ch );
831+ #endif
769832 return 0 ;
770833}
771834
0 commit comments