This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

HW timer issue

Hi,

  I'm trying to enable a HW timer (TIMER1) in my BLE application.  I'm using SDK 16, and following the pattern shown in examples/peripherals/timer.  However, when I get to nrf_drv_timer_enable(), I get a system reset before exiting this function.  Here is the relevant parts of my code -

const nrf_drv_timer_t SYSTEM_HW_TIMER = NRF_DRV_TIMER_INSTANCE(1);

static void _system_hw_timer_callback(nrf_timer_event_t event_type, void* p_context)
{
    switch (event_type)
    {
        case NRF_TIMER_EVENT_COMPARE0:
            ...
            
            break;

        default:
            break;
    }
}

static void system_timer_tick_init(void)
{
    ...

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    uint32_t err_code = nrf_drv_timer_init(&SYSTEM_HW_TIMER, 
                                           &timer_cfg, 
                                           _system_hw_timer_callback);
    APP_ERROR_CHECK(err_code);

    uint32_t time_ticks = nrf_drv_timer_ms_to_ticks(&SYSTEM_HW_TIMER, 
                                                    SYSTEM_TIMER_TICK_TIME_MS);

    nrf_drv_timer_extended_compare(&SYSTEM_HW_TIMER, 
                                   NRF_TIMER_CC_CHANNEL0, 
                                   time_ticks, 
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, 
                                   true);

    nrf_drv_timer_enable(&SYSTEM_HW_TIMER);  // This function never completes!!!
}

int main(void)
{
    ...
    // Initialize BLE
    ...
    system_timer_tick_init();
    ...
}
In sdk_config.h, I've enabled the timer, like this -
#ifndef NRFX_TIMER_ENABLED
#define NRFX_TIMER_ENABLED 1
#endif
// <q> NRFX_TIMER0_ENABLED  - Enable TIMER0 instance
 

#ifndef NRFX_TIMER0_ENABLED
#define NRFX_TIMER0_ENABLED 1
#endif

// <q> NRFX_TIMER1_ENABLED  - Enable TIMER1 instance
 

#ifndef NRFX_TIMER1_ENABLED
#define NRFX_TIMER1_ENABLED 1
#endif
  Note that I have removed all of the legacy defines in this file, including TIMER_ENABLED.
  Not sure if it's relevant, but I'm also using FreeRTOS in my project, although the scheduler has not been started when I hit this issue.  
  Any idea why my system crashes when I try to enable the hardware timer?
  Thanks...
Brian
  • Note that I have removed all of the legacy defines in this file, including TIMER_ENABLED.

     When you say that you have removed them, did you comment them out/delete them, or set them to 0? The reason I ask is because of a file called apply_old_config.h. Check it out.

    Did you enable logging in your project? Does your log say anything?

     

    I get a system reset before exiting this function.

     It sounds like the error handler is being called. Is that the case?

  • Hi Edvin,

      Yes - I've seen the legacy vs new peripheral defines.  I've removed the old ones rather than set them to 0.  However, I've also tried to go back and add the old timer configurations just for a test, but no difference in behavior. 

      I do not have the NRF logging enabled, but I have re-directed the logging output from the error handlers to the serial port.  So assert_nrf_callback is defined and should output serial data.  I've set a breakpoint on this function, in addition to app_error_fault_handler, but I never get to either of them.  Are there other error handlers I should be looking at?

      I'm using Timer1 and IRQ priority 6, which I believe should be fine as far as the S140 softdevice is concerned.  Are there other considerations I need to take into account?

      Thanks...

    Brian

  • Hi,

      I've tried some additional things to narrow down the source of this problem.  It appears the source of the issue is in the sdk_config.h file, but I'm just not sure what part of it.

      When I go back to the ble_app_hrs_freertos example code and add the changes above, the HW timer works fine.  My project has changed quite a bit since starting with this as the seed code - we added support for various tasks, sensors, I/O peripherals, etc.  So my code now looks quite a bit different than this example code.  Part of this process has been modifications to sdk_config.h to enable various peripherals.  If I take this modified version of sdk_config.h and use it in the ble_app_hrs_freertos example, I get the exact same behavior - the processor resets when trying to enable the HW timer at the call to nrf_drv_timer_enable().  Using the original sdk_config.h, with only the change to enable TIMER1 works fine.

      I'm attaching my version of sdk_config.h which causes the reset problem.

      Any ideas on what part of this file is causing the issue?

      Thanks...

    Brian3716.sdk_config.h

  • You are not trying to use TIMER0 for your application, right? Remember that TIMER0 and RTC0 are used by the softdevice.

    Have you tried to set a breakpoint in the error handler? I suggest that you define "DEBUG" in your preprocessor definitions, and set a breakpoint on app_error_fault_handler() (line 57 in app_error.c). Try to put an APP_ERROR_CHECK(1) in your main() function to test that this breakpoint works properly. Also, use this to check if you need to disable optimization in order to see where the error handler comes from.

    Either way, what does nrf_drv_timer_enable return? If not NRF_SUCCESS, then what function call inside returns the error?

    BR,

    Edvin

  • Hi Edvin,

      I am using TIMER1, not TIMER0.

      I have set a breakpoint in app_error_fault_handler, but my code never hits the breakpoint.  I added the call to APP_ERROR_CHECK(1) for a test, and I do hit the breakpoint in that case.  I can see that app_error_fault_handler is called by app_error_handler, although this is the top of the stack.  I don't see where app_error_handler is being called from.  I have changed my compile optimization from -Og to -O0, with the same results.

      I have DEBUG already defined in my build.

      nrf_drv_timer_enable() is mapped to nrfx_timer_enable() in nrf_drv_timer.h.  This function is 4 lines long -

    void nrfx_timer_enable(nrfx_timer_t const * const p_instance)
    {
        NRFX_ASSERT(m_cb[p_instance->instance_id].state == NRFX_DRV_STATE_INITIALIZED);
        nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_START);
        m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_POWERED_ON;
        NRFX_LOG_INFO("Enabled instance: %d.", p_instance->instance_id);
    }

        I can single-step into this function.  When I step from the 1st line to the 2nd line (which I believe starts the timer), the CPU resets and I go back to main.  I have set a breakpoint on the 3rd line of this function and I never hit it.  I have tried to set a long timeout for the timer (several seconds), but this has no affect.

      I've tested the code I'm using to setup the timer directly in the ble_app_hrs_freertos example code.  This code works fine.  The only other change I had to make was to enable the timer in sdk_config.h (#define TIMER1_ENABLED 1).  Bringing my version of sdk_config.h into this code causes it to also fail.  Therefore, it appears there is something in my sdk_config (attached several messages earlier) that is causing this problem.  I just have not been able to figure out which setting is causing the problem.

      So to answer your last question, nrf_drv_timer_enable never returns, nor does any function inside this function return an error.  The only thing I can see is the MCU resetting when I hit the 2nd line of this function.

      Any ideas on what to try next?

      Thanks...

    Brian

Related