@@ -59,9 +59,13 @@ void system_tick_init(void) {
5959 utimer_control_enable (UTIMER , UTIMER_CHANNEL );
6060 utimer_counter_start (UTIMER , UTIMER_CHANNEL );
6161
62- // Set up the UTIMER compare interrupt, to be used later .
62+ // Set up the UTIMER compare A interrupt, to be used by system_tick_wfe_with_timeout_us .
6363 system_tick_nvic_config (2 );
6464 UTIMER -> UTIMER_CHANNEL_CFG [UTIMER_CHANNEL ].UTIMER_COMPARE_CTRL_A |= COMPARE_CTRL_DRV_COMPARE_EN ;
65+
66+ // Set up the UTIMER compare B interrupt, to be used by soft-timer.
67+ system_tick_nvic_config (4 );
68+ UTIMER -> UTIMER_CHANNEL_CFG [UTIMER_CHANNEL ].UTIMER_COMPARE_CTRL_B |= COMPARE_CTRL_DRV_COMPARE_EN ;
6569}
6670
6771// COMPARE_A_BUF1
@@ -73,6 +77,17 @@ void UTIMER_IRQ90Handler(void) {
7377 }
7478}
7579
80+ // COMPARE_B_BUF1
81+ void UTIMER_IRQ92Handler (void ) {
82+ uint32_t chan_interrupt = UTIMER -> UTIMER_CHANNEL_CFG [UTIMER_CHANNEL ].UTIMER_CHAN_INTERRUPT ;
83+ if (chan_interrupt & CHAN_INTERRUPT_COMPARE_B_BUF1_MASK ) {
84+ utimer_clear_interrupt (UTIMER , UTIMER_CHANNEL , CHAN_INTERRUPT_COMPARE_B_BUF1_MASK );
85+ utimer_mask_interrupt (UTIMER , UTIMER_CHANNEL , CHAN_INTERRUPT_COMPARE_B_BUF1_MASK );
86+ system_tick_schedule_callback ();
87+ __SEV ();
88+ }
89+ }
90+
7691// OVER_FLOW
7792void UTIMER_IRQ95Handler (void ) {
7893 uint32_t chan_interrupt = UTIMER -> UTIMER_CHANNEL_CFG [UTIMER_CHANNEL ].UTIMER_CHAN_INTERRUPT ;
@@ -106,7 +121,7 @@ uint64_t system_tick_get_u64(void) {
106121}
107122
108123void system_tick_wfe_with_timeout_us (uint32_t timeout_us ) {
109- // Maximum 10 second timeout, to not overflow signed 32-bit ticks when
124+ // Maximum 10 second timeout, to not overflow 32-bit ticks when
110125 // system_core_clock_mhz==400.
111126 uint32_t timeout_ticks = MIN (timeout_us , 10000000 ) * system_core_clock_mhz ;
112127
@@ -126,3 +141,28 @@ void system_tick_wfe_with_timeout_us(uint32_t timeout_us) {
126141 // Disable the UTIMER compare interrupt.
127142 utimer_mask_interrupt (UTIMER , UTIMER_CHANNEL , CHAN_INTERRUPT_COMPARE_A_BUF1_MASK );
128143}
144+
145+ void system_tick_schedule_after_us (uint32_t ticks_us ) {
146+ // Disable the interrupt in case it's still active.
147+ utimer_mask_interrupt (UTIMER , UTIMER_CHANNEL , CHAN_INTERRUPT_COMPARE_B_BUF1_MASK );
148+
149+ // Maximum 10 second timeout, to not overflow 32-bit ticks when
150+ // system_core_clock_mhz==400.
151+ uint32_t timeout_ticks = MIN (ticks_us , 10000000 ) * system_core_clock_mhz ;
152+
153+ // Set up the UTIMER compare interrupt to fire after the given timeout.
154+ uint32_t cntr = utimer_get_count (UTIMER , UTIMER_CHANNEL , UTIMER_CNTR );
155+ utimer_set_count (UTIMER , UTIMER_CHANNEL , UTIMER_COMPARE_B_BUF1 , cntr + timeout_ticks );
156+ utimer_clear_interrupt (UTIMER , UTIMER_CHANNEL , CHAN_INTERRUPT_COMPARE_B_BUF1_MASK );
157+ utimer_unmask_interrupt (UTIMER , UTIMER_CHANNEL , CHAN_INTERRUPT_COMPARE_B_BUF1_MASK );
158+
159+ // Handle the case of short timeouts.
160+ uint32_t cntr2 = utimer_get_count (UTIMER , UTIMER_CHANNEL , UTIMER_CNTR );
161+ if ((uint32_t )(cntr2 - cntr ) >= timeout_ticks ) {
162+ if (!(UTIMER -> UTIMER_CHANNEL_CFG [UTIMER_CHANNEL ].UTIMER_CHAN_INTERRUPT_MASK & CHAN_INTERRUPT_COMPARE_B_BUF1_MASK )) {
163+ // Interrupt is still enabled, so disable it and manually call the callback.
164+ utimer_mask_interrupt (UTIMER , UTIMER_CHANNEL , CHAN_INTERRUPT_COMPARE_B_BUF1_MASK );
165+ system_tick_schedule_callback ();
166+ }
167+ }
168+ }
0 commit comments