NRF52_MBED_TimerInterrupt Library for Nano-33-BLE

NRF52_MBED_TimerInterrupt Library

How To Install Using Arduino Library Manager

This library enables you to use Interrupt from Hardware Timers on an an NRF52-based board using mbed-RTOS such as Nano-33-BLE.. It now enables you to use up to 16 different ISR-based timers, while actually consuming only 1 Hardware Timer. Timers' interval is very long (ulong millisecs). The most important feature is they're ISR-based timers. Therefore, their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks.

Why do we need this NRF52_MBED_TimerInterrupt Library

Imagine you have a system with a mission-critical function, measuring water level and control the sump pump or doing something much more important. You normally use asoftware timer to poll, or even place the function in loop(). But what if another function is blocking the loop() or setup().

So your function might not be executed, and the result would be disastrous.

You'd prefer to have your function called, no matter what happening with other functions (busy loop, bug, etc.).

The correct choice is to use a Hardware Timer with Interrupt to call your function.

These hardware timers, using interrupt, still work even if other functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software timers using millis() or micros(). That's necessary if you need to measure some data requiring better accuracy.

Functions using normal software timers, relying on loop() and calling millis(), won't work if the loop() or setup() is blocked by certain operation. For example, certain function is blocking while it's connecting to WiFi or some services.

The catch is your function is now part of an ISR (Interrupt Service Routine), must be lean and mean, and follow certain rules. More to read on:

HOWTO Attach Interrupt

Important Notes:

  1. Inside the ISR function, delay() won’t work and the value returned by millis() will not increment. Serial data received while in the ISR function may be lost. You should declare as volatile any variables that you modify within the attached function.

  2. Typically global variables are used to pass data between an ISR and the main program. To make sure variables shared between an ISR and the main program are updated correctly, declare them as volatile.

Releases v1.0.1

  1. Initial coding for Nano-33-BLE and sync with NRF52_TimerInterrupt Library

Supported Boards

  • Arduino Nano-33-BLE.

Examples:

  1. Argument_None
  2. ISR_16_Timers_Array
  3. SwitchDebounce
  4. TimerInterruptTest
  5. TimerInterruptLEDDemo
1 Like

Debug Termimal Output Samples

  1. The following is the sample terminal output when running example ISR_16_Timers_Array on Nano 33 BLE to demonstrate the accuracy of ISR Hardware Timer, especially when system is very busy. The ISR timer is programmed for 2s, is activated exactly after 2.000s !!!

While software timer, programmed for 2s, is activated after more than 3.000s in loop().

Starting ISR_16_Timers_Array on Nano 33 BLE
Version : 1.0.1
NRF52_MBED_TimerInterrupt: Timer = NRF_TIMER3
NRF52_MBED_TimerInterrupt: _fre = 1000000.00, _count = 10000
Starting  ITimer OK, millis() = 714
simpleTimer2s, ms=3714, Dms=3000
Timer : 0, programmed : 5000, actual : 0
Timer : 1, programmed : 10000, actual : 0
Timer : 2, programmed : 15000, actual : 0
Timer : 3, programmed : 20000, actual : 0
Timer : 4, programmed : 25000, actual : 0
Timer : 5, programmed : 30000, actual : 0
Timer : 6, programmed : 35000, actual : 0
Timer : 7, programmed : 40000, actual : 0
Timer : 8, programmed : 45000, actual : 0
Timer : 9, programmed : 50000, actual : 0
Timer : 10, programmed : 55000, actual : 0
Timer : 11, programmed : 60000, actual : 0
Timer : 12, programmed : 65000, actual : 0
Timer : 13, programmed : 70000, actual : 0
Timer : 14, programmed : 75000, actual : 0
Timer : 15, programmed : 80000, actual : 0
....
simpleTimer2s, ms=76098, Dms=3016
Timer : 0, programmed : 5000, actual : 5003
Timer : 1, programmed : 10000, actual : 9995
Timer : 2, programmed : 15000, actual : 14998
Timer : 3, programmed : 20000, actual : 20008
Timer : 4, programmed : 25000, actual : 25004
Timer : 5, programmed : 30000, actual : 30001
Timer : 6, programmed : 35000, actual : 35004
Timer : 7, programmed : 40000, actual : 40001
Timer : 8, programmed : 45000, actual : 45002
Timer : 9, programmed : 50000, actual : 50003
Timer : 10, programmed : 55000, actual : 55006
Timer : 11, programmed : 60000, actual : 60009
Timer : 12, programmed : 65000, actual : 65001
Timer : 13, programmed : 70000, actual : 70004
Timer : 14, programmed : 75000, actual : 75007
Timer : 15, programmed : 80000, actual : 0
simpleTimer2s, ms=79114, Dms=3016
Timer : 0, programmed : 5000, actual : 5003
Timer : 1, programmed : 10000, actual : 9995
Timer : 2, programmed : 15000, actual : 14998
Timer : 3, programmed : 20000, actual : 20008
Timer : 4, programmed : 25000, actual : 25004
Timer : 5, programmed : 30000, actual : 30001
Timer : 6, programmed : 35000, actual : 35004
Timer : 7, programmed : 40000, actual : 40001
Timer : 8, programmed : 45000, actual : 45002
Timer : 9, programmed : 50000, actual : 50003
Timer : 10, programmed : 55000, actual : 55006
Timer : 11, programmed : 60000, actual : 60009
Timer : 12, programmed : 65000, actual : 65001
Timer : 13, programmed : 70000, actual : 70004
Timer : 14, programmed : 75000, actual : 75007
Timer : 15, programmed : 80000, actual : 0
simpleTimer2s, ms=82130, Dms=3016
Timer : 0, programmed : 5000, actual : 5002
Timer : 1, programmed : 10000, actual : 10005
Timer : 2, programmed : 15000, actual : 14998
Timer : 3, programmed : 20000, actual : 20000
Timer : 4, programmed : 25000, actual : 25004
Timer : 5, programmed : 30000, actual : 30001
Timer : 6, programmed : 35000, actual : 35004
Timer : 7, programmed : 40000, actual : 40008
Timer : 8, programmed : 45000, actual : 45002
Timer : 9, programmed : 50000, actual : 50003
Timer : 10, programmed : 55000, actual : 55006
Timer : 11, programmed : 60000, actual : 60009
Timer : 12, programmed : 65000, actual : 65001
Timer : 13, programmed : 70000, actual : 70004
Timer : 14, programmed : 75000, actual : 75007
Timer : 15, programmed : 80000, actual : 80009
  1. The following is the sample terminal output when running exampleTimerInterruptTest on Arduino Nano-33-BLE to demonstrate the accuracy and how to start/stop Hardware Timers.
Starting TimerInterruptTest on Nano 33 BLE
Version : v1.0.1
NRF52_MBED_TimerInterrupt: Timer = NRF_TIMER3
NRF52_MBED_TimerInterrupt: _fre = 1000000.00, _count = 1000000
Starting  ITimer0 OK, millis() = 5660
NRF52_MBED_TimerInterrupt: Timer = NRF_TIMER4
NRF52_MBED_TimerInterrupt: _fre = 1000000.00, _count = 3000000
Starting  ITimer1 OK, millis() = 5665
Stop ITimer0, millis() = 5669
Start ITimer0, millis() = 10670
Stop ITimer1, millis() = 15001
Stop ITimer0, millis() = 15671
Start ITimer0, millis() = 20672
Stop ITimer0, millis() = 25673
Start ITimer1, millis() = 30002
Start ITimer0, millis() = 30674
Stop ITimer0, millis() = 35675
Start ITimer0, millis() = 40676
Stop ITimer1, millis() = 45003
Stop ITimer0, millis() = 45677
Start ITimer0, millis() = 50678
Stop ITimer0, millis() = 55679
Start ITimer1, millis() = 60004
Start ITimer0, millis() = 60680

Thanks @khoih-prog! It looks very useful and also very well documented.

One thing I am having trouble understanding:

It's not clear to me why these modifications to the Ethernet libraries are needed in relation to use of the NRF52_MBED_TimerInterrupt Library? I took a look at the diff of the patch to the Ethernet library, but it's pretty significant so I wasn't able to interpret it.

Thanks for your encouraging words and your support, most so far behind the scene, to everybody in the Community, @pert.

One thing I am having trouble understanding:
GitHub - khoih-prog/NRF52_MBED_TimerInterrupt: This library enables you to use Interrupt from Hardware Timers on an NRF52-based board using mbed-RTOS such as Nano-33-BLE. These nRF52 Hardware Timers, using Interrupt, still work even if other functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software timers using millis() or micros(). That's mandatory if you need to measure some data requiring better accuracy. It now supports 16 ISR-based Timers, while consuming only 1 Hardware Timer. Timers' interval is very long (ulong millisecs). The most important feature is they're ISR-based Timers. Therefore, their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks.
It's not clear to me why these modifications to the Ethernet libraries are needed in relation to use of the NRF52_MBED_TimerInterrupt Library? I took a look at the diff of the patch to the Ethernet library, but it's pretty significant so I wasn't able to interpret it.

The Ethernet libraries' Patches are put there, for every libraries, just in case somebody has problem in using Ethernet libraries along with the library. At that time, hoping to remind and save them some time to look around.

Normally you can ignore the Patches until issue arises, hopefully never.

Best Regards,

OK, so if I understand your explanation correctly, there is nothing specific to the use of the NRF52_MBED_TimerInterrupt Library that would require applying these patches?

That's totally correct.
You don't need to apply any Patch at all, until you have issue using the certain Ethernet library along with the library, such as compile error, buffer issue, etc.