Hello Nordic DevZone,
I am having a persistent problem using hardware timers on the nRF52832 with nRF5 SDK v13.
Summary of Issue:
-
I am using
NRF_DRV_TIMER_INSTANCE(3)to create a TIMER3 instance. -
I set up both COMPARE0 (for 1sec interval) and COMPARE1 (for 100ms interval).
-
Only the COMPARE1 event triggers—COMPARE0 never fires.
-
I made sure to avoid hardcoding
NRF_TIMER0and am usingTIMER_INSTANCE.p_regfor all register accesses as recommended in similar posts. -
Interrupts, SHORTS, and compare setup are all being performed with the SDK driver functions and macros.
Troubleshooting attempts:
-
Replaced all direct register access to use appropriate instance pointer.
-
Verified tick values are correct for both channels.
-
Checked that nrf_drv_timer_enable() is called.
-
Handler pointer is correct and COMPARE1 triggers as expected.
-
No error codes returned from API calls.
What am I missing?
-
Is there any known errata or hidden gotcha with configuring multiple COMPARE events using nrf_drv_timer on a TIMER instance other than TIMER0?
-
Is there any additional configuration or sequence needed for COMPARE0 compared to COMPARE1+?
-
Any sample code or checklist known to work for COMPARE0/COMPARE1 on TIMER3 would be appreciated.
Thank you in advance for reviewing and helping resolve this issue.
#define TIMER_INSTANCE_ID 3
static const nrf_drv_timer_t TIMER_INSTANCE = NRF_DRV_TIMER_INSTANCE(TIMER_INSTANCE_ID);
void timer_handler(nrf_timer_event_t event_type, void *p_context)
{
switch (event_type)
{
case NRF_TIMER_EVENT_COMPARE0:
// never hits
break;
case NRF_TIMER_EVENT_COMPARE1:
// always hits (100ms)
break;
}
}
void timer_channel_control(uint8_t channel, bool enable, uint32_t millis)
{
nrf_timer_cc_channel_t comp_ch;
nrf_timer_short_mask_t short_msk;
nrf_timer_int_mask_t int_mask;
switch (channel) {
case 0:
comp_ch = NRF_TIMER_CC_CHANNEL0;
short_msk = NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK;
int_mask = NRF_TIMER_INT_COMPARE0_MASK;
break;
case 1:
comp_ch = NRF_TIMER_CC_CHANNEL1;
short_msk = NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK;
int_mask = NRF_TIMER_INT_COMPARE1_MASK;
break;
default:
return;
}
uint32_t time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_INSTANCE, millis);
NRF_TIMER_Type *timer_reg = TIMER_INSTANCE.p_reg;
if (enable) {
nrf_drv_timer_extended_compare(&TIMER_INSTANCE, comp_ch, time_ticks, short_msk, true);
} else {
timer_reg->INTENCLR = int_mask;
timer_reg->SHORTS &= ~short_msk;
}
}
void hw_timer_init(void)
{
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
timer_cfg.frequency = NRF_TIMER_FREQ_62500Hz;
timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
timer_cfg.mode = NRF_TIMER_MODE_TIMER;
timer_cfg.interrupt_priority = APP_IRQ_PRIORITY_LOW;
ret_code_t err_code = nrf_drv_timer_init(&TIMER_INSTANCE, &timer_cfg, timer_handler);
APP_ERROR_CHECK(err_code);
timer_channel_control(0, true, 1000); // 1s interval, does NOT trigger
timer_channel_control(1, true, 100); // 100ms interval, works fine
nrf_drv_timer_enable(&TIMER_INSTANCE);
}
