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

Delay implementation from scratch and interrupt handlers

Hello to everyone,

I've just started playing with NRF52 DK (NRF52832 SoC). It is my first time with ARM MCU. I've had prior experience with atmega328p and MSP430. Although I'm not very good at C coding or programming, I'm trying my best.

I've tried reading some of the examples in the SDK, but they are really difficult to understand, and .c files references a lot of other files, so it is a mess for me when reading those codes. Also they are not very well explained. That's why I tend to write my own drivers and codes based on the datasheet or reference manual. This way I learn more, it's a slower process but I go for learning.

Currently I'm interested in implementing a delay function based on timers/counters. I've read that this can be implemented using either timer modules or RTC module, where the former is more accurate and consumes more power compared to the latter.

I know that the basic idea of a delay function using a timer/counter is to count up to some value and then reset the counter. Here is my code (mind I'm using timer mode, 32bit words, 0 prescaler):

//Initialization
NRF_TIMER0->MODE = mode;
NRF_TIMER0->BITMODE = bitmode;
NRF_TIMER0->PRESCALER = prescaler;
NRF_TIMER0->SHORTS = (1 << CC_idx); 
NRF_TIMER0->CC[CC_idx] = timeUnit;

NRF_TIMER0->TASKS_START = 1; //Start

Inside the while in the main.c file, I call a function which does the following:

if(NRF_TIMER0->EVENTS_COMPARE[CC_idx] != 0)
     {
      time_counter++;
      NRF_TIMER0->EVENTS_COMPARE[CC_idx] = 0;// if a match is found, EVENTS_COMPARE stays high, so we need to clear it after a match.
      //NRF_TIMER0->TASKS_CLEAR = 1; //this line is not needed since the SHORTCUT feature for compare and clear is used at the initialization   
     }

I would like to mention that I didn't know that the EVENTS_COMPARE reg maintain its value when a match is found. That is not specified by the product specification manual. So the idea is very simple, the timer starts, and I use the while loop in order to find matches or coincidences with the timeUnit value (call it time interval, frequency, whatever you want. It is the value which the counter is compared to). Once a match is found, the counter is cleared. My code works, since I printed the time_counter variable in the console and it was ok, it was counting.

Well, as you can see, the problem is that I can't make a delay function using a while loop and the time_counter variable at the same time, since I use the main while loop to increase the time_counter variable, so I think that it is not possible to use a while loop inside the main while loop in order to make the delay. My questions are the following:

1) is there any more efficient way to implement this kind of delay function rather than using interrupts?

2) A long time ago, when using atmel and TI MCUs, I used Interrupts Service Routines in order to accomplish what I described. I can't find useful information about interrupts and interrupts handlers in the product specification manual. Can anyone provide me useful documentation about interrupts please? I looked for that in this forum, but just found an example code an library which was very difficult to understand.

3) is using interrupts a good way to implement this considering that I want to implement higher complexity functions later? I want to get done all the ground work for my future projects. What I mean with this question, Are timers that work around interrupts reliable when using other interrupts with higher or lower priority? I'm especially interested in implementing BLE later.

Thanks a lot for your help.

  • Hi 

    1) I can't really think of any way to improve this other than using interrupts, no. In order to allow the peripherals to run in the background, without blocking code execution, the interrupts are necessary to alert the MCU that an event has occurred. 

    The best way to set this up using the standard libraries is to use the app_timer module. Then you can schedule a number of callbacks after a certain delay, or set up callbacks to be run repeatedly.
    app_timer uses the RTC module which means the current consumption will be very low. 

    2) Did you find this case?
    https://devzone.nordicsemi.com/f/nordic-q-a/172/hardware-interrupt-example

    I think the example shared by Håkon is pretty short and concise. 

    3) Ideally I would recommend the app_timer module, as mentioned earlier. This module has been used by countless customers and is tested thoroughly over time, to make sure it works reliably both with and without a SoftDevice running. 

    Most interrupt based implementations are reliable as long as the interrupt processing can complete before the next interrupt is about to occur. Put another way, if you expect interrupts every millisecond, and the interrupt processing is delayed by more than a millisecond, then you will normally get into problems. 

    When using a BLE SoftDevice you should expect interrupts of several hundred microseconds whenever the Bluetooth stack needs to do some critical processing.

    Best regards
    Torbjørn

Related