Using simple hardware timer with event

Hi,

For my app (using zephyr and nrf52840) I want to use hardware Timer like that, is there any manual or example how to do that?  

Need able to set period of timer from 1 to about 100 ms.

1) Set Capture/Compare  reg.

2) Set CLK div for the timer.

3) Set callback (IRQ) for timer event.

4) Run the timer.

Thank you. Jan.

  • Thank you, 

    I am a novice in the Nordic world. I have gone throught NRF Dev academy, but there is still a lot of unknow. E.G. now I am struggling how to use a peripheral like Timer. I want to call IRQ function every 1 seconds with the hardware timer (in datasheet is written it has 5 Timers). How should I do that? I have found example Alarm, but it can not help me much. 
    I tried to modify the example Alarm to find out how to use counter API.

    1) In the example is Timer defined according to MCU like that: Unfortunatelly my nrf52840 is not in that list - how can I bind it with my mcu?

    #if defined(CONFIG_BOARD_ATSAMD20_XPRO)
    #define TIMER DT_LABEL(DT_NODELABEL(tc4))
    #elif defined(CONFIG_SOC_FAMILY_SAM)
    #define TIMER DT_LABEL(DT_NODELABEL(tc0))
    #elif defined(CONFIG_COUNTER_MICROCHIP_MCP7940N)
    #define TIMER DT_LABEL(DT_NODELABEL(extrtc0))
    #elif defined(CONFIG_COUNTER_RTC0)
    #define TIMER DT_LABEL(DT_NODELABEL(rtc0))
    #elif defined(CONFIG_COUNTER_RTC_STM32)
    #define TIMER DT_LABEL(DT_INST(0, st_stm32_rtc))

    2) In example is called 

    counter_start
     before it has been initialized - why that?

    Finally there is some timer settings  and running the channel: 

    alarm_cfg.flags = 0;
    alarm_cfg.ticks = counter_us_to_ticks(counter_dev, 2000);
    alarm_cfg.callback = timerCallback;
    alarm_cfg.user_data = &alarm_cfg;
    
    err = counter_set_channel_alarm(counter_dev, 0,	&alarm_cfg);

    Thank you fo the clarification. Jan
  • Hello - I am too when it comes to firmware projects. I'm on my first firmware project and about 6 months in... It's been a journey to say the least. DevZone, different samples and unit tests are great to learn from. There is still a lot you have to figure out on your own, which can make it aggravating (especially if you have never done firmware and are not familiar with everything like a seasoned pro would be).

    Anyway, are you using the nRF52840-DK? That's what I started on so I can actually help you. I looked at the alarm example you mentioned and got it working doing the following:

    1) We need to find the node in the device tree to the timer we want to use. The easiest way is to see the compiled output of the device tree. You can do this by clicking the following icon in VS code:

    Then just search (CTRL+F) for "timer" and find the group of timers. In this case we can use the first one "timer0".

    2) We have to reference this so we can use it. So in main.c change the following:

    #define TIMER DT_NODELABEL(timer0) // nRF52840-DK Timer
    
    // #if defined(CONFIG_BOARD_ATSAMD20_XPRO)
    // #define TIMER DT_NODELABEL(tc4)
    // #elif defined(CONFIG_SOC_FAMILY_SAM)
    // #define TIMER DT_NODELABEL(tc0)
    // #elif defined(CONFIG_COUNTER_MICROCHIP_MCP7940N)
    // #define TIMER DT_NODELABEL(extrtc0)
    // #elif defined(CONFIG_COUNTER_RTC0)
    // #define TIMER DT_NODELABEL(rtc0)
    // #elif defined(CONFIG_COUNTER_RTC_STM32)
    // #define TIMER DT_INST(0, st_stm32_rtc)
    // #elif defined(CONFIG_COUNTER_NATIVE_POSIX)
    // #define TIMER DT_NODELABEL(counter0)
    // #elif defined(CONFIG_COUNTER_XLNX_AXI_TIMER)
    // #define TIMER DT_INST(0, xlnx_xps_timer_1_00_a)
    // #elif defined(CONFIG_COUNTER_ESP32)
    // #define TIMER DT_NODELABEL(timer0)
    // #elif defined(CONFIG_COUNTER_MCUX_CTIMER)
    // #define TIMER DT_NODELABEL(ctimer0)
    // #endif

    3) If you try to compile this you will get an error, along the lines of "main.c:109: undefined reference to `__device_dts_ord_109'". These error have always confused me and I didn't know where to look for the answers. One trick I learned is to search the entire project for the dts ord. So hit CTRL+Shift+F and search for "dts_ord_109". If you click on the first result it will take you to the following:

    If we look back at our compiled dts and search for that address (40008000) we can see that's it's not seeing our timer0 that we defined...

    Why is this? Well whenever we see an error like this it always means we have forgot to configure something. The solution is to add the following (line 3) to the proj.conf file:

    Once you make these few changes it will compile and run just fine.

    To answer your other question... The timer is already initialized since it's a hardware timer. Calling the counter_start simply calls

    nrf_timer_task_trigger(config->timer, NRF_TIMER_TASK_START);

    on the backend.

    The original code has it set for 2 seconds so the alarm had plenty of time to be configured before the timer would fire. I see you changed it to 2000 us, which is 2 ms. I would suspect that the callback would never be fired in this case since the alarm wasn't configured in time. The counter_start is also a one shot as well, which means it's only going to happen one time. That's the reason it gets reset in the callback. You can move the alarm configuration before you start the timer or increase the delay.

    So you can change it to this:

    alarm_cfg.flags = 0;
    alarm_cfg.ticks = counter_us_to_ticks(counter_dev, DELAY);
    alarm_cfg.callback = test_counter_interrupt_fn;
    alarm_cfg.user_data = &alarm_cfg;
    
    err = counter_set_channel_alarm(counter_dev, ALARM_CHANNEL_ID,
    				&alarm_cfg);
    
    counter_start(counter_dev); // Move this here to ensure the alarm is setup

  • HI,

    Thank you really much for your work!! I tried to progress like you mentioned. I have little diferent step 3 - the error is this: lude\generated\devicetree_unfixed.h:6162:38: note: each undeclared identifier is reported only once for each function it appears in
    6162 | #define DT_N_NODELABEL_timer0 DT_N_S_soc_S_timer_40008000

    So I tried also to add  CONFIG_COUNTER_TIMER0=y but it could not help me. Then I tried to find line 6162, and this is there - have no idea what is the problem:

    Now I am stucked and have no idea what is wrong, also I found Kconfig and there when I look for timer it shows me something about timer - what is that? Could it help?

    Thank you very much. I am used to for STM32 this is really something new to me.

  • You're more than welcome. Did you do try doing a pristine build (CTRL+Shift+P > nRF Connect: Pristine Build)?

Related