NETCPU timer interrupt issues

Hi,

I have an issue with interrupts on TIMER1 on nrf5340 NETCPU. My setup involves 2 timers that are linked via DPPI, TIMER2 counting microseconds and TIMER1 counting milliseconds. I also have 2 DPPI channels routed via IPC, one each way. The IPC events works, so no issue there. However, I am unable to get an interrupt on capture on TIMER1. A capture is made, and the value in the corresponding CC reg is updated. But nothing happens in the EVENTS_COMPARE register, and no interrupt is generated. On TIMER2 it works just fine. Any idea what is wrong? Just to be super clear: the same event and the same setup fires the interrupt for TIMER2 as expected, but for TIMER1 there is no interrupt.

On a related note: On TIMER2 I found that I had to write the corresponding CC reg to clear the interrupt. I write EVENTS_CAPTURE to 0, and read it back. In addition I also tried to read the CC. Only when I added a write to CC did the interrupt clear. I write 0xffffffff, which is the  only value I have tested. Any idea what this is about?

Device marking is QKAAD0 (I think, small letters...).

A bit of code to describe my setup:

// Set up IPC, DPPI and subscribe to capture
NRF_IPC->PUBLISH_RECEIVE[I2S_FRAME_TICK_IPC_CHANNEL] = I2S_FRAME_TICK_DPPI_CHANNEL | (1 << 31);
NRF_IPC->RECEIVE_CNF[I2S_FRAME_TICK_IPC_CHANNEL] = (1 << I2S_FRAME_TICK_IPC_CHANNEL);
NRF_DPPIC->CHENSET = (1 << I2S_FRAME_TICK_DPPI_CHANNEL);
NRF_TIMER1->SUBSCRIBE_CAPTURE[FRAME_TICK_TS_CC] = I2S_FRAME_TICK_DPPI_CHANNEL | (1 << 31);
NRF_TIMER2->SUBSCRIBE_CAPTURE[FRAME_TICK_HS_CC] = I2S_FRAME_TICK_DPPI_CHANNEL | (1 << 31);
NRF_TIMER2->INTENSET = 1 << (FRAME_TICK_HS_CC + TIMER_INTENSET_COMPARE0_Pos);
NRF_TIMER1->INTENSET = 1 << (FRAME_TICK_TS_CC + TIMER_INTENSET_COMPARE0_Pos);
IRQ_DIRECT_CONNECT(TIMER2_IRQn, 2, frame_tick_handler, 0);
irq_enable(TIMER2_IRQn);
IRQ_DIRECT_CONNECT(TIMER1_IRQn, 0, frame_tick_handler2, 0);
irq_enable(TIMER1_IRQn);

/* Count / timestamp timer */
NRF_TIMER1->TASKS_STOP = 1;
NRF_TIMER1->TASKS_CLEAR = 1;
NRF_TIMER1->PRESCALER = 0;
NRF_TIMER1->MODE = TIMER_MODE_MODE_Counter << TIMER_MODE_MODE_Pos;
NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;
NRF_TIMER1->TASKS_START = 1;    

/* Publish the capture compare match on the count (ms) timer to dppi */
NRF_TIMER1->PUBLISH_COMPARE[0] = TIMESTAMP_TO_IPC_CC_DPPI_CHANNEL | (1 << 31);

/* and subscribe ipc channel 8 to the same channel */
NRF_IPC->SUBSCRIBE_SEND[START_EVENT_IPC_CHANNEL] = TIMESTAMP_TO_IPC_CC_DPPI_CHANNEL | (1 << 31);
NRF_IPC->SEND_CNF[START_EVENT_IPC_CHANNEL] = (1 << START_EVENT_IPC_CHANNEL);

/* Aaand enable dppi channel */
NRF_DPPIC->CHENSET = (1 << TIMESTAMP_TO_IPC_CC_DPPI_CHANNEL);

HS_TIMER->PUBLISH_COMPARE[0] = (HS_TO_TIMESTAMP_COUNT_DPPI_CHANNEL) | (1 << 31);
NRF_TIMER1->SUBSCRIBE_COUNT = (HS_TO_TIMESTAMP_COUNT_DPPI_CHANNEL) | (1 << 31);
NRF_DPPIC->CHENSET = (1 << HS_TO_TIMESTAMP_COUNT_DPPI_CHANNEL);

NRF_TIMER2->TASKS_STOP = 1;
NRF_TIMER2->TASKS_CLEAR = 1;
NRF_TIMER2->PRESCALER = HS_TIMER_PRESCALER;
NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;
NRF_TIMER2->CC[0] = TIME_SYNC_TIMER_MAX_VAL;
NRF_TIMER2->CC[1] = 0xFFFFFFFF;
NRF_TIMER2->CC[2] = 0xFFFFFFFF;
NRF_TIMER2->CC[3] = 0xFFFFFFFF;
NRF_TIMER2->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk | TIMER_SHORTS_COMPARE2_CLEAR_Msk;
NRF_TIMER2->TASKS_START = 1;

Parents Reply Children
  • I will, but I am currently working my way around it. With the DK example I feel I can be pretty sure that it is not my code that is the issue, and that I need nordic to look into the design and tell me why I am seeing this undocumented/errata-ish behaviour. Both regarding the missing IRQ and the need to clear CC reg on CC interrupt.

  • A little update: I have found another timer interrupt issue:

    The screenshot shows two pins toggling. The bottom is toggling via GPIOTE, using the aforementioned APPCPU-IPC-DPPi-channel. This is the same signal that triggers the capture and thus initiaties the CC-interrupt. The top is a pin being toggled inside the interrupt. As you can see there are two events that don't lead to an interrupt. I don't have hard numbers right now, but this happens frequently, so it is a serious issue. I will do a more thorough test on the frequency today.

    Time between edges are approx 21ms.

  • I recorded 900 secs of pin toggling. I got 40283 toggles from the event, and 40240 toggles from the interrupt, meaning I have 43 missing interrupts.

  • Hi,

    Any update on this? Did anyone test my code?

  • I will likely not have time to look into this until I am back from vacation in about 3 weeks time.

    I did quickly glance at the blinky example you provided, I found it a bit strange that you in your isr2 cleared both MS_TIMER and US_TIMER EVENTS_COMPARE event, while in isr1 you cleared MS_TIMER EVENTS_COMPARE two times. 

    There is no check in your isr handlers to check which compare event triggered the interrupt, and you should only need to clear the event for the timer that triggered the interrupt before you exit the interrupt handler.

    I notice you are executing capture tasks in main, if you need those to execute straight after eachother I would recommend that you add a disable/enable interrupts around them. If not you can get some race condition where there is an interrupt between the two. The capture task doesn't trigger the interrupt, it only copy the timer's count value to the corresponding CC register. 

    Best regards,
    Kenneth

Related