17
17
#include <haly/nrfy_rtc.h>
18
18
#include <zephyr/irq.h>
19
19
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
+
20
30
#define RTC_PRETICK (IS_ENABLED(CONFIG_SOC_NRF53_RTC_PRETICK) && \
21
31
IS_ENABLED(CONFIG_SOC_NRF5340_CPUNET))
22
32
23
33
#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 )
25
35
26
36
#define RTC NRF_RTC1
27
37
#define RTC_IRQn NRFX_IRQ_NUMBER_GET(RTC)
28
38
#define RTC_LABEL rtc1
29
39
#define CHAN_COUNT_MAX (RTC1_CC_NUM - (RTC_PRETICK ? 1 : 0))
40
+ #define SYS_CLOCK_CH 0
30
41
31
42
BUILD_ASSERT (CHAN_COUNT <= CHAN_COUNT_MAX , "Not enough compare channels" );
32
43
/* Ensure that counter driver for RTC1 is not enabled. */
33
44
BUILD_ASSERT (DT_NODE_HAS_STATUS (DT_NODELABEL (RTC_LABEL ), disabled ),
34
45
"Counter for RTC1 must be disabled" );
35
46
36
- #define COUNTER_BIT_WIDTH 24U
47
+ #define COUNTER_BIT_WIDTH CONFIG_NRF_RTC_COUNTER_BIT_WIDTH
37
48
#define COUNTER_SPAN BIT(COUNTER_BIT_WIDTH)
38
49
#define COUNTER_MAX (COUNTER_SPAN - 1U)
39
50
#define COUNTER_HALF_SPAN (COUNTER_SPAN / 2U)
@@ -139,7 +150,7 @@ uint32_t z_nrf_rtc_timer_capture_task_address_get(int32_t chan)
139
150
{
140
151
#if defined(RTC_TASKS_CAPTURE_TASKS_CAPTURE_Msk )
141
152
__ASSERT_NO_MSG (chan >= 0 && chan < CHAN_COUNT );
142
- if (chan == 0 ) {
153
+ if (chan == SYS_CLOCK_CH ) {
143
154
return 0 ;
144
155
}
145
156
@@ -264,6 +275,15 @@ static int set_alarm(int32_t chan, uint32_t req_cc, bool exact)
264
275
*/
265
276
enum { MIN_CYCLES_FROM_NOW = 3 };
266
277
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
267
287
uint32_t cc_inc = MIN_CYCLES_FROM_NOW ;
268
288
269
289
/* Disable event routing for the channel to avoid getting a COMPARE
@@ -427,6 +447,17 @@ uint64_t z_nrf_rtc_timer_read(void)
427
447
428
448
uint32_t cntr = counter ();
429
449
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
+
430
461
val += cntr ;
431
462
432
463
if (cntr < OVERFLOW_RISK_RANGE_END ) {
@@ -565,8 +596,13 @@ void rtc_nrf_isr(const void *arg)
565
596
rtc_pretick_rtc1_isr_hook ();
566
597
}
567
598
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
568
603
if (nrfy_rtc_int_enable_check (RTC , NRF_RTC_INT_OVERFLOW_MASK ) &&
569
604
nrfy_rtc_events_process (RTC , NRF_RTC_INT_OVERFLOW_MASK )) {
605
+ #endif
570
606
overflow_cnt ++ ;
571
607
}
572
608
@@ -625,7 +661,7 @@ int z_nrf_rtc_timer_trigger_overflow(void)
625
661
uint64_t now = z_nrf_rtc_timer_read ();
626
662
627
663
if (err == 0 ) {
628
- sys_clock_timeout_handler (0 , now , NULL );
664
+ sys_clock_timeout_handler (SYS_CLOCK_CH , now , NULL );
629
665
}
630
666
bail :
631
667
full_int_unlock (mcu_critical_state );
@@ -682,7 +718,7 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
682
718
683
719
uint64_t target_time = cyc + last_count ;
684
720
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);
686
722
}
687
723
688
724
uint32_t sys_clock_elapsed (void )
@@ -702,7 +738,9 @@ uint32_t sys_clock_cycle_get_32(void)
702
738
static void int_event_disable_rtc (void )
703
739
{
704
740
uint32_t mask = NRF_RTC_INT_TICK_MASK |
741
+ #if !CUSTOM_COUNTER_BIT_WIDTH
705
742
NRF_RTC_INT_OVERFLOW_MASK |
743
+ #endif
706
744
NRF_RTC_INT_COMPARE0_MASK |
707
745
NRF_RTC_INT_COMPARE1_MASK |
708
746
NRF_RTC_INT_COMPARE2_MASK |
@@ -734,7 +772,9 @@ static int sys_clock_driver_init(void)
734
772
nrfy_rtc_int_enable (RTC , NRF_RTC_CHANNEL_INT_MASK (chan ));
735
773
}
736
774
775
+ #if !CUSTOM_COUNTER_BIT_WIDTH
737
776
nrfy_rtc_int_enable (RTC , NRF_RTC_INT_OVERFLOW_MASK );
777
+ #endif
738
778
739
779
NVIC_ClearPendingIRQ (RTC_IRQn );
740
780
@@ -747,13 +787,13 @@ static int sys_clock_driver_init(void)
747
787
748
788
int_mask = BIT_MASK (CHAN_COUNT );
749
789
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 ) ;
751
791
}
752
792
753
793
uint32_t initial_timeout = IS_ENABLED (CONFIG_TICKLESS_KERNEL ) ?
754
794
MAX_CYCLES : CYC_PER_TICK ;
755
795
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);
757
797
758
798
#if defined(CONFIG_CLOCK_CONTROL_NRF )
759
799
static const enum nrf_lfclk_start_mode mode =
@@ -766,6 +806,29 @@ static int sys_clock_driver_init(void)
766
806
z_nrf_clock_control_lf_on (mode );
767
807
#endif
768
808
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
769
832
return 0 ;
770
833
}
771
834
0 commit comments