Zephyr nrfx_timer_compare

Hi, I am using Zephyr and want to use the nrfx_timer_compare functions.
It seems that the system is working with Timer4 and channel 0 to 4. However, the compare of channel 5 is never fired.

I used IRQ_DIRECT_CONNECT(TIMER4_IRQn, IRQ_PRIO_LOWEST, bus_timer_event, 0); and in my interrupt handler I test NRF_TIMER4->EVENTS_COMPARE[0] up to NRF_TIMER4->EVENTS_COMPARE[5].
All events (NRF_TIMER4->EVENTS_COMPARE[0] to NRF_TIMER4->EVENTS_COMPARE[4]) are detected and handled, but NRF_TIMER4->EVENTS_COMPARE[5] will never be set.

The initialisation looks like:

nrfx_timer_compare( &bus_timer, NRF_TIMER_CC_CHANNEL0, delay, true ); 
nrfx_timer_compare( &bus_timer, NRF_TIMER_CC_CHANNEL1, delay+417, true );
nrfx_timer_compare( &bus_timer, NRF_TIMER_CC_CHANNEL2, 2400, true ); 
nrfx_timer_compare( &bus_timer, NRF_TIMER_CC_CHANNEL3, 5500, true ); 
nrfx_timer_compare( &bus_timer, NRF_TIMER_CC_CHANNEL4, 13500, true );
nrfx_timer_compare( &bus_timer, NRF_TIMER_CC_CHANNEL5, 16300, true );

Any idea why the 5th channel will never be set?

Parents
  • Hi Bob

    There is no reason why CC5 shouldn't work. 

    One thing I notice in your code is that you refer to your own event handler in the call to IRQ_DIRECT_CONNECT, rather than the interrupt handler of the nrfx_timer library. 

    Could you change this to point to the nrfx handler instead, like shown here, and see if it works better?

    Best regards
    Torbjørn

  • Hi Torbjørn,

    Thanks for the reply.

    I changed it into:

    {
        IRQ_DIRECT_CONNECT(TIMER4_IRQn, IRQ_PRIO_LOWEST, bus_timer_event, 0);
        
        const nrfx_timer_config_t bus_timer_config =
            {
                .frequency          = NRF_TIMER_FREQ_1MHz,
                .mode               = NRF_TIMER_MODE_TIMER,
                .bit_width          = NRF_TIMER_BIT_WIDTH_32,
                .interrupt_priority = 3,
                .p_context          = NULL
            } ;
    
    
        nrfx_timer_init( &bus_timer, &bus_timer_config, bus_timer_event );
        
        nrfx_timer_compare( &bus_timer, NRF_TIMER_CC_CHANNEL0, _measdelay, true );  
        nrfx_timer_compare( &bus_timer, NRF_TIMER_CC_CHANNEL1, _measdelay+417, true );
        nrfx_timer_compare( &bus_timer, NRF_TIMER_CC_CHANNEL2, 2400, true );          
        nrfx_timer_compare( &bus_timer, NRF_TIMER_CC_CHANNEL3, 5500, true );          
        nrfx_timer_compare( &bus_timer, NRF_TIMER_CC_CHANNEL4, 13500, true );         
        nrfx_timer_compare( &bus_timer, NRF_TIMER_CC_CHANNEL5, 16300, true );         
            
        nrfx_ppi_channel_alloc( &ppi_channel );
        nrfx_timer_enable( &bus_timer );
    }
    
    void bus_timer_event(nrf_timer_event_t event_type, void * p_context)
    {
        switch( event_type )
        {
        case NRF_TIMER_EVENT_COMPARE0 : 
            ...
            break;
        case NRF_TIMER_EVENT_COMPARE1 : 
            ...
            break;
        case NRF_TIMER_EVENT_COMPARE2 : 
            ...
            break;
        case NRF_TIMER_EVENT_COMPARE3 : 
            ...
            break; 
        case NRF_TIMER_EVENT_COMPARE4 : 
            ...
            break;    
        case NRF_TIMER_EVENT_COMPARE5 : 
            ...
            break;    
        default:
            LOG_INF("Unknow event type %d",event_type);
        }
    }
    
    
    

    There is a continuous event generated with event_type = 0. It seems that the system is never clearing the interrupt flag?  

    removing the nrfx_timer_init does not change anything. Removing the IRQ_DIRECT_CONNECT will result in kernel errors.

  • Hi Bob

    I still don't think it is correct to refer to the bus_timer_event in the call to IRQ_DIRECT_CONNECT. Did you try to replace this with nrfx_timer_4_irq_handler instead?

    I tried to set up a simple example with all 6 compare events, and it seems to work fine here: 

    I get the following log output, as expected:

    *** Booting Zephyr OS build v2.7.99-ncs1-1  ***
    Timer 1 callback 0. Counter = 0
    Timer 1 callback 1. Counter = 1
    Timer 1 callback 2. Counter = 2
    Timer 1 callback 3. Counter = 3
    Timer 1 callback 4. Counter = 4
    Timer 1 callback 5. Counter = 5

    Please ignore that it says "Timer 1" in the log, I based the code on an existing sample using timer 1 instead of timer 4. 

    Best regards
    Torbjørn

  • Hi Torbjørn,

    I implemented your suggestion and was able to narrow down the problem. In the original code, there is a statement under NRF_TIMER_EVENT_COMPARE4 event, that changed the NRF_TIMER_CC_CHANNEL5: nrfx_timer_extended_compare( &bus_timer, NRF_TIMER_CC_CHANNEL5, 16300 + rand(), 0, true );  

    This will be a source of the problem, but only if the log level is LOG_LEVEL_DBG. When I change the log level to LOG_LEVEL_ERR it seems to work....

  • Hi Bob

    It is good to hear you found the problem. I didn't quite understand what the problem was though...

    Do you mean the problem is in one of the Zephyr drivers, or in your own application code? 

    If you think there is a problem in our code we should follow it up, and see if this is something that can be fixed in a future update. 

    Best regards
    Torbjørn

Reply Children
No Data
Related