17
17
#include <haly/nrfy_rtc.h>
18
18
#include <zephyr/irq.h>
19
19
20
+ /* Ensure that selected counter bit width is within its maximum hardware width. */
21
+ BUILD_ASSERT (CONFIG_NRF_RTC_COUNTER_BIT_WIDTH <= 24 , "Counter bit width exceeds maximum width." );
22
+
23
+ #if (CONFIG_NRF_RTC_COUNTER_BIT_WIDTH < 24 )
24
+ #define CUSTOM_COUNTER_BIT_WIDTH 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)
@@ -33,7 +43,7 @@ BUILD_ASSERT(CHAN_COUNT <= CHAN_COUNT_MAX, "Not enough compare channels");
33
43
BUILD_ASSERT (DT_NODE_HAS_STATUS (DT_NODELABEL (RTC_LABEL ), disabled ),
34
44
"Counter for RTC1 must be disabled" );
35
45
36
- #define COUNTER_BIT_WIDTH 24U
46
+ #define COUNTER_BIT_WIDTH CONFIG_NRF_RTC_COUNTER_BIT_WIDTH
37
47
#define COUNTER_SPAN BIT(COUNTER_BIT_WIDTH)
38
48
#define COUNTER_MAX (COUNTER_SPAN - 1U)
39
49
#define COUNTER_HALF_SPAN (COUNTER_SPAN / 2U)
@@ -259,6 +269,15 @@ static int set_alarm(int32_t chan, uint32_t req_cc, bool exact)
259
269
*/
260
270
enum { MIN_CYCLES_FROM_NOW = 3 };
261
271
uint32_t cc_val = req_cc ;
272
+
273
+ #if CUSTOM_COUNTER_BIT_WIDTH
274
+ /* If a CC value is 0 when a CLEAR task is set, this will not
275
+ * trigger a COMAPRE event. Need to use 1 instead.
276
+ */
277
+ if (cc_val % COUNTER_MAX == 0 ) {
278
+ cc_val = 1 ;
279
+ }
280
+ #endif
262
281
uint32_t cc_inc = MIN_CYCLES_FROM_NOW ;
263
282
264
283
/* Disable event routing for the channel to avoid getting a COMPARE
@@ -422,6 +441,17 @@ uint64_t z_nrf_rtc_timer_read(void)
422
441
423
442
uint32_t cntr = counter ();
424
443
444
+ #if CUSTOM_COUNTER_BIT_WIDTH
445
+ /* If counter is equal to it maximum value while val is greater
446
+ * than anchor, then we can assume that overflow has been recorded
447
+ * in the overflow_cnt, but clear task has not been triggered yet.
448
+ * Treat counter as if it has been cleared.
449
+ */
450
+ if ((cntr == COUNTER_MAX ) && (val > anchor )) {
451
+ cntr = 0 ;
452
+ }
453
+ #endif
454
+
425
455
val += cntr ;
426
456
427
457
if (cntr < OVERFLOW_RISK_RANGE_END ) {
@@ -560,8 +590,13 @@ void rtc_nrf_isr(const void *arg)
560
590
rtc_pretick_rtc1_isr_hook ();
561
591
}
562
592
563
- if (nrfy_rtc_int_enable_check (RTC , NRF_RTC_INT_OVERFLOW_MASK ) &&
564
- nrfy_rtc_events_process (RTC , NRF_RTC_INT_OVERFLOW_MASK )) {
593
+ if ((nrfy_rtc_int_enable_check (RTC , NRF_RTC_INT_OVERFLOW_MASK ) &&
594
+ nrfy_rtc_events_process (RTC , NRF_RTC_INT_OVERFLOW_MASK )) ||
595
+ #if CUSTOM_COUNTER_BIT_WIDTH
596
+ (nrfy_rtc_int_enable_check (RTC , NRF_RTC_INT_COMPARE1_MASK ) &&
597
+ nrfy_rtc_events_process (RTC , NRF_RTC_INT_COMPARE1_MASK )) ||
598
+ #endif
599
+ 0 ) {
565
600
overflow_cnt ++ ;
566
601
}
567
602
@@ -697,7 +732,9 @@ uint32_t sys_clock_cycle_get_32(void)
697
732
static void int_event_disable_rtc (void )
698
733
{
699
734
uint32_t mask = NRF_RTC_INT_TICK_MASK |
735
+ #if !CUSTOM_COUNTER_BIT_WIDTH
700
736
NRF_RTC_INT_OVERFLOW_MASK |
737
+ #endif
701
738
NRF_RTC_INT_COMPARE0_MASK |
702
739
NRF_RTC_INT_COMPARE1_MASK |
703
740
NRF_RTC_INT_COMPARE2_MASK |
@@ -729,7 +766,9 @@ static int sys_clock_driver_init(void)
729
766
nrfy_rtc_int_enable (RTC , NRF_RTC_CHANNEL_INT_MASK (chan ));
730
767
}
731
768
769
+ #if !CUSTOM_COUNTER_BIT_WIDTH
732
770
nrfy_rtc_int_enable (RTC , NRF_RTC_INT_OVERFLOW_MASK );
771
+ #endif
733
772
734
773
NVIC_ClearPendingIRQ (RTC_IRQn );
735
774
@@ -742,7 +781,7 @@ static int sys_clock_driver_init(void)
742
781
743
782
int_mask = BIT_MASK (CHAN_COUNT );
744
783
if (CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT ) {
745
- alloc_mask = BIT_MASK (EXT_CHAN_COUNT ) << 1 ;
784
+ alloc_mask = BIT_MASK (EXT_CHAN_COUNT ) << ( 1 + CUSTOM_COUNTER_BIT_WIDTH ) ;
746
785
}
747
786
748
787
uint32_t initial_timeout = IS_ENABLED (CONFIG_TICKLESS_KERNEL ) ?
@@ -761,6 +800,28 @@ static int sys_clock_driver_init(void)
761
800
z_nrf_clock_control_lf_on (mode );
762
801
#endif
763
802
803
+ #if CUSTOM_COUNTER_BIT_WIDTH
804
+ /* Use channel 1 for wrapping. */
805
+ uint8_t chan = 1 ;
806
+ nrf_rtc_event_t evt = NRF_RTC_CHANNEL_EVENT_ADDR (chan );
807
+ nrfx_err_t result ;
808
+ nrf_ppi_channel_t ch ;
809
+
810
+ nrfy_rtc_event_enable (RTC , NRF_RTC_CHANNEL_INT_MASK (chan ));
811
+ nrfy_rtc_cc_set (RTC , chan , COUNTER_MAX );
812
+ uint32_t evt_addr ;
813
+ uint32_t task_addr ;
814
+
815
+ evt_addr = nrfy_rtc_event_address_get (RTC , evt );
816
+ task_addr = nrfy_rtc_task_address_get (RTC , NRF_RTC_TASK_CLEAR );
817
+
818
+ result = nrfx_ppi_channel_alloc (& ch );
819
+ if (result != NRFX_SUCCESS ) {
820
+ return - ENODEV ;
821
+ }
822
+ (void )nrfx_ppi_channel_assign (ch , evt_addr , task_addr );
823
+ (void )nrfx_ppi_channel_enable (ch );
824
+ #endif
764
825
return 0 ;
765
826
}
766
827
0 commit comments