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
@@ -259,6 +270,15 @@ static int set_alarm(int32_t chan, uint32_t req_cc, bool exact)
259270 */
260271 enum { MIN_CYCLES_FROM_NOW = 3 };
261272 uint32_t cc_val = req_cc ;
273+
274+ #if CUSTOM_COUNTER_BIT_WIDTH
275+ /* If a CC value is 0 when a CLEAR task is set, this will not
276+ * trigger a COMAPRE event. Need to use 1 instead.
277+ */
278+ if (cc_val % COUNTER_MAX == 0 ) {
279+ cc_val = 1 ;
280+ }
281+ #endif
262282 uint32_t cc_inc = MIN_CYCLES_FROM_NOW ;
263283
264284 /* Disable event routing for the channel to avoid getting a COMPARE
@@ -422,6 +442,17 @@ uint64_t z_nrf_rtc_timer_read(void)
422442
423443 uint32_t cntr = counter ();
424444
445+ #if CUSTOM_COUNTER_BIT_WIDTH
446+ /* If counter is equal to it maximum value while val is greater
447+ * than anchor, then we can assume that overflow has been recorded
448+ * in the overflow_cnt, but clear task has not been triggered yet.
449+ * Treat counter as if it has been cleared.
450+ */
451+ if ((cntr == COUNTER_MAX ) && (val > anchor )) {
452+ cntr = 0 ;
453+ }
454+ #endif
455+
425456 val += cntr ;
426457
427458 if (cntr < OVERFLOW_RISK_RANGE_END ) {
@@ -560,8 +591,13 @@ void rtc_nrf_isr(const void *arg)
560591 rtc_pretick_rtc1_isr_hook ();
561592 }
562593
594+ #if CUSTOM_COUNTER_BIT_WIDTH
595+ if (nrfy_rtc_int_enable_check (RTC , NRF_RTC_INT_COMPARE1_MASK ) &&
596+ nrfy_rtc_events_process (RTC , NRF_RTC_INT_COMPARE1_MASK )) {
597+ #else
563598 if (nrfy_rtc_int_enable_check (RTC , NRF_RTC_INT_OVERFLOW_MASK ) &&
564599 nrfy_rtc_events_process (RTC , NRF_RTC_INT_OVERFLOW_MASK )) {
600+ #endif
565601 overflow_cnt ++ ;
566602 }
567603
@@ -620,7 +656,7 @@ int z_nrf_rtc_timer_trigger_overflow(void)
620656 uint64_t now = z_nrf_rtc_timer_read ();
621657
622658 if (err == 0 ) {
623- sys_clock_timeout_handler (0 , now , NULL );
659+ sys_clock_timeout_handler (SYS_CLOCK_CH , now , NULL );
624660 }
625661bail :
626662 full_int_unlock (mcu_critical_state );
@@ -677,7 +713,7 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
677713
678714 uint64_t target_time = cyc + last_count ;
679715
680- compare_set (0 , target_time , sys_clock_timeout_handler , NULL , false);
716+ compare_set (SYS_CLOCK_CH , target_time , sys_clock_timeout_handler , NULL , false);
681717}
682718
683719uint32_t sys_clock_elapsed (void )
@@ -697,7 +733,9 @@ uint32_t sys_clock_cycle_get_32(void)
697733static void int_event_disable_rtc (void )
698734{
699735 uint32_t mask = NRF_RTC_INT_TICK_MASK |
736+ #if !CUSTOM_COUNTER_BIT_WIDTH
700737 NRF_RTC_INT_OVERFLOW_MASK |
738+ #endif
701739 NRF_RTC_INT_COMPARE0_MASK |
702740 NRF_RTC_INT_COMPARE1_MASK |
703741 NRF_RTC_INT_COMPARE2_MASK |
@@ -729,7 +767,9 @@ static int sys_clock_driver_init(void)
729767 nrfy_rtc_int_enable (RTC , NRF_RTC_CHANNEL_INT_MASK (chan ));
730768 }
731769
770+ #if !CUSTOM_COUNTER_BIT_WIDTH
732771 nrfy_rtc_int_enable (RTC , NRF_RTC_INT_OVERFLOW_MASK );
772+ #endif
733773
734774 NVIC_ClearPendingIRQ (RTC_IRQn );
735775
@@ -742,13 +782,13 @@ static int sys_clock_driver_init(void)
742782
743783 int_mask = BIT_MASK (CHAN_COUNT );
744784 if (CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT ) {
745- alloc_mask = BIT_MASK (EXT_CHAN_COUNT ) << 1 ;
785+ alloc_mask = BIT_MASK (CHAN_COUNT ) & ~ BIT ( SYS_CLOCK_CH ) ;
746786 }
747787
748788 uint32_t initial_timeout = IS_ENABLED (CONFIG_TICKLESS_KERNEL ) ?
749789 MAX_CYCLES : CYC_PER_TICK ;
750790
751- compare_set (0 , initial_timeout , sys_clock_timeout_handler , NULL , false);
791+ compare_set (SYS_CLOCK_CH , initial_timeout , sys_clock_timeout_handler , NULL , false);
752792
753793#if defined(CONFIG_CLOCK_CONTROL_NRF )
754794 static const enum nrf_lfclk_start_mode mode =
@@ -761,6 +801,29 @@ static int sys_clock_driver_init(void)
761801 z_nrf_clock_control_lf_on (mode );
762802#endif
763803
804+ #if CUSTOM_COUNTER_BIT_WIDTH
805+ /* WRAP_CH reserved for wrapping. */
806+ alloc_mask &= ~BIT (WRAP_CH );
807+
808+ nrf_rtc_event_t evt = NRF_RTC_CHANNEL_EVENT_ADDR (WRAP_CH );
809+ nrfx_err_t result ;
810+ nrf_ppi_channel_t ch ;
811+
812+ nrfy_rtc_event_enable (RTC , NRF_RTC_CHANNEL_INT_MASK (WRAP_CH ));
813+ nrfy_rtc_cc_set (RTC , WRAP_CH , COUNTER_MAX );
814+ uint32_t evt_addr ;
815+ uint32_t task_addr ;
816+
817+ evt_addr = nrfy_rtc_event_address_get (RTC , evt );
818+ task_addr = nrfy_rtc_task_address_get (RTC , NRF_RTC_TASK_CLEAR );
819+
820+ result = nrfx_ppi_channel_alloc (& ch );
821+ if (result != NRFX_SUCCESS ) {
822+ return - ENODEV ;
823+ }
824+ (void )nrfx_ppi_channel_assign (ch , evt_addr , task_addr );
825+ (void )nrfx_ppi_channel_enable (ch );
826+ #endif
764827 return 0 ;
765828}
766829
0 commit comments