khoih-prog / MBED_RPI_PICO_TimerInterrupt

This library enables you to use Interrupt from Hardware Timers on RP2040-based boards such as Nano_RP2040_Connect, RASPBERRY_PI_PICO. These MBED_RPI_PICO_TimerInterrupt 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.
MIT License
11 stars 1 forks source link

Interrupts stop after 94 minutes #7

Closed Garrabrant closed 2 years ago

Garrabrant commented 2 years ago

Describe the bug

I setup an interrupt based on the sample code, running at 8kHz on a Raspberry Pi Pico, developing on PlatformIO, VS Code on a Mac version 11.6. The interrupt runs fine for about 94 minutes, then stops. It then starts up 3.5 hours later, but only runs for another 4 minutes before stopping again.

Expected behavior

Interrupt should continue to run

Actual behavior

Interrupt routine stops after about 94 minutes

Code to Reproduce

// These define's must be placed at the beginning before #include "TimerInterrupt_Generic.h"
// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4
#define _TIMERINTERRUPT_LOGLEVEL_ 4

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "MBED_RPi_Pico_TimerInterrupt.h"

#ifndef LED_BUILTIN
#define LED_BUILTIN 25  // Pin LED_BUILTIN mapped to pin GPIO25 of RPI_PICO, control on-board LED
#endif

#define PIN_D1 1  // Pin D1 mapped to pin GPIO1 of RPI_PICO

volatile uint32_t counter = 0;

// Never use Serial.print inside this mbed ISR. Will hang the system
void TimerHandler1(uint alarm_num) {
    static bool toggle1 = false;

    ///////////////////////////////////////////////////////////
    // Always call this for MBED RP2040 before processing ISR
    TIMER_ISR_START(alarm_num);
    ///////////////////////////////////////////////////////////

    // timer interrupt toggles outputPin
    digitalWrite(PIN_D1, toggle1);
    toggle1 = !toggle1;
    counter++;

    ////////////////////////////////////////////////////////////
    // Always call this for MBED RP2040 after processing ISR
    TIMER_ISR_END(alarm_num);
    ////////////////////////////////////////////////////////////
}

#define TIMER1_INTERVAL_US 125

// Init RPI_PICO_Timer
MBED_RPI_PICO_Timer ITimer1(1);

void setup() {
    pinMode(LED_BUILTIN, OUTPUT);
    pinMode(PIN_D1, OUTPUT);

    Serial.begin(115200);
    while (!Serial)
        ;

    delay(100);

    Serial.print(F("\nStarting Argument_None on "));
    Serial.println(BOARD_NAME);
    Serial.println(MBED_RPI_PICO_TIMER_INTERRUPT_VERSION);

    // Interval in microsecs
    if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_US, TimerHandler1)) {
        Serial.print(F("Starting ITimer1 OK, millis() = "));
        Serial.println(millis());
    } else
        Serial.println(F("Can't set ITimer1. Select another Timer, freq. or timer"));
}

void loop() {
  static uint32_t last_counter = 0;
  static uint32_t last_running = 0;
  uint32_t running = ( counter != last_counter );
  last_counter = counter;
  if ( last_running != running ) {
    last_running = running;
    Serial.print(millis());
    Serial.print(' ');
    Serial.println(running ? " Running ":" Not Running ");
  }
  delay(1);
}

Above code output

Starting Argument_None on RaspberryPi Pico
MBED_RPi_Pico_TimerInterrupt v1.2.0
[TISR] _timerNo = 1, Clock (Hz) = 1000000.00, _fre (Hz) = 8000.00
[TISR] _count = 0-125
[TISR] hardware_alarm_set_target, uS = 125
Starting ITimer1 OK, millis() = 1201
1201  Running 
5637146  Not Running 
18522047  Running 
18790483  Not Running 

Scope output

I also had a scope probe on D1. It output a 4kHz square wave for the first 94 minutes, then stopped.

Information

  • Platform.io version Core 6.1.5·Home 3.4.3
  • khoih-prog/MBED_RPI_PICO_TimerInterrupt@^1.2.0
  • Arduino mbed_rp2040 Core Version (e.g. Arduino mbed_rp2040 core v3.3.0)
  • RP2040 Board type: RASPBERRY_PI_PICO & Seeed XAIO RP2040

Disclaimer

My first time submitting a report. Be gentle if I didn't do it right. :)

khoih-prog commented 2 years ago

HI @Garrabrant

You're doing fine with the report.

However, your loop() code is possibly causing problem. I'll let you figure out yourself what's wrong and learn from that

Try this

#if ( defined(ARDUINO_NANO_RP2040_CONNECT) || defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || \
      defined(ARDUINO_GENERIC_RP2040) ) && defined(ARDUINO_ARCH_MBED)
#define USING_MBED_RPI_PICO_TIMER_INTERRUPT        true
#else
#error This code is intended to run on the MBED RASPBERRY_PI_PICO platform! Please check your Tools->Board setting.
#endif

// These define's must be placed at the beginning before #include "MBED_RPI_PICO_TimerInterrupt.h"
// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4
#define _TIMERINTERRUPT_LOGLEVEL_     4

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "MBED_RPi_Pico_TimerInterrupt.h"

#ifndef LED_BUILTIN
    #define LED_BUILTIN       25        // Pin LED_BUILTIN mapped to pin GPIO25 of RPI_PICO, control on-board LED
#endif

#define PIN_D1              1         // Pin D1 mapped to pin GPIO1 of RPI_PICO

volatile uint32_t counter = 0;

// Never use Serial.print inside this mbed ISR. Will hang the system
void TimerHandler0(uint alarm_num)
{
    static bool toggle0 = false;

    ///////////////////////////////////////////////////////////
    // Always call this for MBED RP2040 before processing ISR
    TIMER_ISR_START(alarm_num);
    ///////////////////////////////////////////////////////////

    //timer interrupt toggles pin LED_BUILTIN
    digitalWrite(LED_BUILTIN, toggle0);
    toggle0 = !toggle0;

    ////////////////////////////////////////////////////////////
    // Always call this for MBED RP2040 after processing ISR
    TIMER_ISR_END(alarm_num);
    ////////////////////////////////////////////////////////////
}

// Never use Serial.print inside this mbed ISR. Will hang the system
void TimerHandler1(uint alarm_num)
{
    static bool toggle1 = false;

    ///////////////////////////////////////////////////////////
    // Always call this for MBED RP2040 before processing ISR
    TIMER_ISR_START(alarm_num);
    ///////////////////////////////////////////////////////////

    //timer interrupt toggles outputPin
    digitalWrite(PIN_D1, toggle1);
    toggle1 = !toggle1;

  counter++;

    ////////////////////////////////////////////////////////////
    // Always call this for MBED RP2040 after processing ISR
    TIMER_ISR_END(alarm_num);
    ////////////////////////////////////////////////////////////
}

#define TIMER0_INTERVAL_MS        2000

#define TIMER1_INTERVAL_MS        5000

#define TIMER1_INTERVAL_US        125

// Init RPI_PICO_Timer
MBED_RPI_PICO_Timer ITimer0(0);
MBED_RPI_PICO_Timer ITimer1(1);

void setup()
{
    pinMode(LED_BUILTIN, OUTPUT);
    pinMode(PIN_D1,      OUTPUT);

    Serial.begin(115200);

    while (!Serial);

    delay(100);

    Serial.print(F("\nStarting Argument_None on "));
    Serial.println(BOARD_NAME);
    Serial.println(MBED_RPI_PICO_TIMER_INTERRUPT_VERSION);

    // Interval in microsecs
    if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0))
    {
        Serial.print(F("Starting ITimer0 OK, millis() = "));
        Serial.println(millis());
    }
    else
        Serial.println(F("Can't set ITimer0. Select another Timer, freq. or timer"));

    // Interval in microsecs
    //if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1))
  if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_US, TimerHandler1))
    {
        Serial.print(F("Starting ITimer1 OK, millis() = "));
        Serial.println(millis());
    }
    else
        Serial.println(F("Can't set ITimer1. Select another Timer, freq. or timer"));
}

void printResult(uint32_t currTime)
{
  Serial.print(F("Time = "));
  Serial.print(currTime);
  Serial.print(F(", Timer1Count = "));
  Serial.println(counter);
}

#define CHECK_INTERVAL_MS     60000L

void loop()
{
  static uint32_t lastTime = 0;
  static uint32_t currTime;

  currTime = millis();

  if (currTime - lastTime > CHECK_INTERVAL_MS)
  {
    printResult(currTime);

    lastTime = currTime;
  }
}

and it's still running, LED blinking and outputting to O-Scope after several hours

Debug Terminal

09:49:23.278 -> Starting Argument_None on RaspberryPi Pico
09:49:23.278 -> MBED_RPi_Pico_TimerInterrupt v1.2.0
09:49:23.278 -> [TISR] _timerNo = 0, Clock (Hz) = 1000000.00, _fre (Hz) = 0.50
09:49:23.278 -> [TISR] _count = 0-2000000
09:49:23.311 -> [TISR] hardware_alarm_set_target, uS = 2000000
09:49:23.311 -> Starting ITimer0 OK, millis() = 1298
09:49:23.311 -> [TISR] _timerNo = 1, Clock (Hz) = 1000000.00, _fre (Hz) = 8000.00
09:49:23.311 -> [TISR] _count = 0-125
09:49:23.311 -> [TISR] hardware_alarm_set_target, uS = 125
09:49:23.311 -> Starting ITimer1 OK, millis() = 1300
09:50:22.001 -> Time = 60001, Timer1Count = 466842
09:51:22.005 -> Time = 120002, Timer1Count = 944632
09:52:22.011 -> Time = 180003, Timer1Count = 1422532
09:53:22.012 -> Time = 240004, Timer1Count = 1900636
09:54:21.992 -> Time = 300005, Timer1Count = 2379229
09:55:22.016 -> Time = 360006, Timer1Count = 2858090
09:56:22.019 -> Time = 420007, Timer1Count = 3336876
09:57:22.000 -> Time = 480008, Timer1Count = 3815681
09:58:22.004 -> Time = 540009, Timer1Count = 4293971
09:59:22.001 -> Time = 600010, Timer1Count = 4771606
10:00:22.001 -> Time = 660011, Timer1Count = 5248629
10:01:22.022 -> Time = 720012, Timer1Count = 5725648
10:02:22.016 -> Time = 780013, Timer1Count = 6202246
10:03:22.016 -> Time = 840014, Timer1Count = 6679381
10:04:21.997 -> Time = 900015, Timer1Count = 7155996
10:05:22.012 -> Time = 960016, Timer1Count = 7632561
10:06:22.023 -> Time = 1020017, Timer1Count = 8108772
10:07:22.023 -> Time = 1080018, Timer1Count = 8584548
10:08:22.031 -> Time = 1140019, Timer1Count = 9060282
10:09:22.011 -> Time = 1200020, Timer1Count = 9536010
10:10:22.024 -> Time = 1260021, Timer1Count = 10011698
10:11:22.009 -> Time = 1320022, Timer1Count = 10487567
10:12:22.019 -> Time = 1380023, Timer1Count = 10963264
10:13:22.036 -> Time = 1440024, Timer1Count = 11439041
10:14:22.018 -> Time = 1500025, Timer1Count = 11914815
10:15:22.025 -> Time = 1560026, Timer1Count = 12390822
10:16:22.130 -> Time = 1620027, Timer1Count = 12866753
10:17:22.158 -> Time = 1680028, Timer1Count = 13342472
10:18:22.132 -> Time = 1740029, Timer1Count = 13818301
10:19:22.148 -> Time = 1800030, Timer1Count = 14294182
10:20:22.168 -> Time = 1860031, Timer1Count = 14770252
10:21:22.152 -> Time = 1920032, Timer1Count = 15246098
10:22:22.179 -> Time = 1980033, Timer1Count = 15722238
10:23:22.198 -> Time = 2040034, Timer1Count = 16198413
10:24:22.176 -> Time = 2100035, Timer1Count = 16675075
10:25:22.155 -> Time = 2160036, Timer1Count = 17151966
10:26:22.145 -> Time = 2220037, Timer1Count = 17628610
10:27:22.155 -> Time = 2280038, Timer1Count = 18105280
10:28:22.167 -> Time = 2340039, Timer1Count = 18582465
10:29:22.153 -> Time = 2400040, Timer1Count = 19059354
10:30:22.160 -> Time = 2460041, Timer1Count = 19536458
10:31:22.138 -> Time = 2520042, Timer1Count = 20013796
10:32:22.149 -> Time = 2580043, Timer1Count = 20491371
10:33:22.159 -> Time = 2640044, Timer1Count = 20968838
10:34:22.170 -> Time = 2700045, Timer1Count = 21445718
10:35:22.164 -> Time = 2760046, Timer1Count = 21923090
10:36:22.180 -> Time = 2820047, Timer1Count = 22400525
10:37:22.161 -> Time = 2880048, Timer1Count = 22878386
10:38:22.165 -> Time = 2940049, Timer1Count = 23355660
10:39:22.164 -> Time = 3000050, Timer1Count = 23833439
10:40:22.159 -> Time = 3060051, Timer1Count = 24311263
10:41:22.177 -> Time = 3120052, Timer1Count = 24789391
10:42:22.187 -> Time = 3180053, Timer1Count = 25266615
10:43:22.177 -> Time = 3240054, Timer1Count = 25743625
10:44:22.179 -> Time = 3300055, Timer1Count = 26220937
10:45:22.189 -> Time = 3360056, Timer1Count = 26698477
10:46:22.178 -> Time = 3420057, Timer1Count = 27176209
10:47:22.208 -> Time = 3480058, Timer1Count = 27653666
10:48:22.189 -> Time = 3540059, Timer1Count = 28131590
10:49:22.217 -> Time = 3600060, Timer1Count = 28609436
10:50:22.213 -> Time = 3660061, Timer1Count = 29087610
10:51:22.202 -> Time = 3720062, Timer1Count = 29564949
10:52:22.201 -> Time = 3780063, Timer1Count = 30042697
10:53:22.214 -> Time = 3840064, Timer1Count = 30520525
10:54:22.226 -> Time = 3900065, Timer1Count = 30998646
10:55:22.207 -> Time = 3960066, Timer1Count = 31476583
10:56:22.186 -> Time = 4020067, Timer1Count = 31954615
10:57:22.190 -> Time = 4080068, Timer1Count = 32432800
10:58:22.196 -> Time = 4140069, Timer1Count = 32911057
10:59:22.202 -> Time = 4200070, Timer1Count = 33389349
11:00:22.179 -> Time = 4260071, Timer1Count = 33867657
11:01:22.169 -> Time = 4320072, Timer1Count = 34345067
11:02:22.182 -> Time = 4380073, Timer1Count = 34821031
11:03:22.199 -> Time = 4440074, Timer1Count = 35297498
11:04:22.193 -> Time = 4500075, Timer1Count = 35773652
11:05:22.184 -> Time = 4560076, Timer1Count = 36249992
11:06:22.174 -> Time = 4620077, Timer1Count = 36726620
11:07:22.200 -> Time = 4680078, Timer1Count = 37203424
11:08:22.193 -> Time = 4740079, Timer1Count = 37680255
11:09:22.210 -> Time = 4800080, Timer1Count = 38156418
11:10:22.184 -> Time = 4860081, Timer1Count = 38633015
11:11:22.191 -> Time = 4920082, Timer1Count = 39109689
11:12:22.211 -> Time = 4980083, Timer1Count = 39586944
11:13:22.204 -> Time = 5040084, Timer1Count = 40063451
11:14:22.189 -> Time = 5100085, Timer1Count = 40540538
11:15:22.214 -> Time = 5160086, Timer1Count = 41017703
11:16:22.206 -> Time = 5220087, Timer1Count = 41495248
11:17:22.197 -> Time = 5280088, Timer1Count = 41971955
11:18:22.201 -> Time = 5340089, Timer1Count = 42448248
11:19:22.210 -> Time = 5400090, Timer1Count = 42924798
11:20:22.195 -> Time = 5460091, Timer1Count = 43401595
11:21:22.221 -> Time = 5520092, Timer1Count = 43878655
11:22:22.218 -> Time = 5580093, Timer1Count = 44355353
11:23:22.204 -> Time = 5640094, Timer1Count = 44832599
11:24:22.204 -> Time = 5700095, Timer1Count = 45309824
11:25:22.210 -> Time = 5760096, Timer1Count = 45787443
11:26:22.214 -> Time = 5820097, Timer1Count = 46264105
11:27:22.211 -> Time = 5880098, Timer1Count = 46741146
11:28:22.231 -> Time = 5940099, Timer1Count = 47218296
11:29:22.216 -> Time = 6000100, Timer1Count = 47695827
11:30:22.225 -> Time = 6060101, Timer1Count = 48173242
11:31:22.212 -> Time = 6120102, Timer1Count = 48650660
11:32:22.224 -> Time = 6180103, Timer1Count = 49128348
11:33:22.233 -> Time = 6240104, Timer1Count = 49606181
11:34:22.227 -> Time = 6300105, Timer1Count = 50083965
11:35:22.231 -> Time = 6360106, Timer1Count = 50560265
11:36:22.247 -> Time = 6420107, Timer1Count = 51036842
11:37:22.226 -> Time = 6480108, Timer1Count = 51513343
11:38:22.247 -> Time = 6540109, Timer1Count = 51990403
11:39:22.235 -> Time = 6600110, Timer1Count = 52467075
11:40:22.260 -> Time = 6660111, Timer1Count = 52944070
11:41:22.247 -> Time = 6720112, Timer1Count = 53421249
11:42:22.254 -> Time = 6780113, Timer1Count = 53898727
11:43:22.250 -> Time = 6840114, Timer1Count = 54375949
11:44:22.258 -> Time = 6900115, Timer1Count = 54852723
11:45:22.266 -> Time = 6960116, Timer1Count = 55329926
11:46:22.249 -> Time = 7020117, Timer1Count = 55807227
11:47:22.255 -> Time = 7080118, Timer1Count = 56284937
11:48:22.240 -> Time = 7140119, Timer1Count = 56762133
11:49:22.229 -> Time = 7200120, Timer1Count = 57239760
11:50:22.241 -> Time = 7260121, Timer1Count = 57717423
11:51:22.224 -> Time = 7320122, Timer1Count = 58195411
11:52:22.242 -> Time = 7380123, Timer1Count = 58672494
11:53:22.239 -> Time = 7440124, Timer1Count = 59149439
11:54:22.241 -> Time = 7500125, Timer1Count = 59626602
11:55:22.222 -> Time = 7560126, Timer1Count = 60104004
11:56:22.233 -> Time = 7620127, Timer1Count = 60581532
11:57:22.243 -> Time = 7680128, Timer1Count = 61058858
11:58:22.229 -> Time = 7740129, Timer1Count = 61536576
11:59:22.224 -> Time = 7800130, Timer1Count = 62014348
12:00:22.236 -> Time = 7860131, Timer1Count = 62492386
12:01:22.221 -> Time = 7920132, Timer1Count = 62969610
12:02:22.242 -> Time = 7980133, Timer1Count = 63447220
12:03:22.229 -> Time = 8040134, Timer1Count = 63924886
12:04:22.244 -> Time = 8100135, Timer1Count = 64402849
12:05:22.225 -> Time = 8160136, Timer1Count = 64880699
12:06:22.243 -> Time = 8220137, Timer1Count = 65358581
12:07:22.259 -> Time = 8280138, Timer1Count = 65836641
12:08:22.245 -> Time = 8340139, Timer1Count = 66314808
12:09:22.245 -> Time = 8400140, Timer1Count = 66793156
12:10:22.260 -> Time = 8460141, Timer1Count = 67271620
12:11:22.246 -> Time = 8520142, Timer1Count = 67750139
12:12:22.248 -> Time = 8580143, Timer1Count = 68228670
12:13:22.266 -> Time = 8640144, Timer1Count = 68706517
12:14:22.237 -> Time = 8700145, Timer1Count = 69184354
12:15:22.247 -> Time = 8760146, Timer1Count = 69661888
12:16:22.258 -> Time = 8820147, Timer1Count = 70139418
12:17:22.242 -> Time = 8880148, Timer1Count = 70616644
12:18:22.243 -> Time = 8940149, Timer1Count = 71094208
12:19:22.264 -> Time = 9000150, Timer1Count = 71571936
12:20:22.243 -> Time = 9060151, Timer1Count = 72049266
12:21:22.246 -> Time = 9120152, Timer1Count = 72526417
12:22:22.261 -> Time = 9180153, Timer1Count = 73003408
12:23:22.271 -> Time = 9240154, Timer1Count = 73480854
12:24:22.250 -> Time = 9300155, Timer1Count = 73957866
12:25:22.261 -> Time = 9360156, Timer1Count = 74435050
12:26:22.257 -> Time = 9420157, Timer1Count = 74912021
12:27:22.259 -> Time = 9480158, Timer1Count = 75389782
12:28:22.248 -> Time = 9540159, Timer1Count = 75867322
12:29:22.259 -> Time = 9600160, Timer1Count = 76344620
12:30:22.263 -> Time = 9660161, Timer1Count = 76821679
12:31:22.248 -> Time = 9720162, Timer1Count = 77298886
khoih-prog commented 2 years ago

FYI, still running OK now after many more hours

...
14:28:22.358 -> Time = 16740279, Timer1Count = 133123594
14:29:22.350 -> Time = 16800280, Timer1Count = 133601388
14:30:22.358 -> Time = 16860281, Timer1Count = 134079057
14:31:22.365 -> Time = 16920282, Timer1Count = 134556297
14:32:22.357 -> Time = 16980283, Timer1Count = 135033374
14:33:22.376 -> Time = 17040284, Timer1Count = 135510251
14:34:22.356 -> Time = 17100285, Timer1Count = 135987430
14:35:22.371 -> Time = 17160286, Timer1Count = 136464312
14:36:22.378 -> Time = 17220287, Timer1Count = 136941951
14:37:22.374 -> Time = 17280288, Timer1Count = 137419491
Garrabrant commented 2 years ago

Thanks, @khoih-prog Your code works fine for me. I'll try to figure out what I did wrong.

Garrabrant commented 2 years ago

@khoih-prog Can you try only running your ITimer1 and not start ITimer0? I found when I did this, your code stopped calling the Timer1 interrupt at 5640 seconds.
Or is it important that both interrupt timers must be run at the same time?

khoih-prog commented 2 years ago

I really don't believe this yet. As I'm travelling now and have no time to test / verify your claim.

If this is true, there must be something very wrong with the mbed_rp2040 core.

Post the issue on mbed_rp2040 core, if you have time and still interested.

I suggest you test and move on to RPI_PICO_TimerInterrupt library and IMHO, better core arduino-pico

Garrabrant commented 2 years ago

@khoih-prog I'd appreciate it if you could, when you have time, confirm you can reproduce my problem when you only use ITimer1 and just delete the ITimer0 code. If you cannot reproduce it, I'll know it is something odd on my end. Thank you!

khoih-prog commented 2 years ago

Hi @Garrabrant

Sorry I'm so busy right now to create many new libraries and have no time to spare. You can try using arduino-pico core

If OK then, raise the issue in ArduinoCore-mbed, certainly with correct MRE

khoih-prog commented 2 years ago

Hi @Garrabrant

I've tested nearly 120 mins without any issue. You really have issue with your code.

Good Luck,


Code

// These define's must be placed at the beginning before #include "TimerInterrupt_Generic.h"
// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4
#define _TIMERINTERRUPT_LOGLEVEL_ 4

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "MBED_RPi_Pico_TimerInterrupt.h"

#ifndef LED_BUILTIN
#define LED_BUILTIN 25  // Pin LED_BUILTIN mapped to pin GPIO25 of RPI_PICO, control on-board LED
#endif

#define PIN_D1      1  // Pin D1 mapped to pin GPIO1 of RPI_PICO

volatile uint32_t counter = 0;

// Never use Serial.print inside this mbed ISR. Will hang the system
void TimerHandler1(uint alarm_num) 
{
  static bool toggle1 = false;

  ///////////////////////////////////////////////////////////
  // Always call this for MBED RP2040 before processing ISR
  TIMER_ISR_START(alarm_num);
  ///////////////////////////////////////////////////////////

  // timer interrupt toggles outputPin
  digitalWrite(PIN_D1, toggle1);
  toggle1 = !toggle1;
  counter++;

  ////////////////////////////////////////////////////////////
  // Always call this for MBED RP2040 after processing ISR
  TIMER_ISR_END(alarm_num);
  ////////////////////////////////////////////////////////////
}

#define TIMER1_INTERVAL_US 125

// Init RPI_PICO_Timer
MBED_RPI_PICO_Timer ITimer1(1);

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(PIN_D1, OUTPUT);

  Serial.begin(115200);
  while (!Serial);

  delay(100);

  Serial.print(F("\nStarting Argument_None on "));
  Serial.println(BOARD_NAME);
  Serial.println(MBED_RPI_PICO_TIMER_INTERRUPT_VERSION);

  // Interval in microsecs
  if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_US, TimerHandler1)) {
    Serial.print(F("Starting ITimer1 OK, millis() = "));
    Serial.println(millis());
  } else
    Serial.println(F("Can't set ITimer1. Select another Timer, freq. or timer"));
}

#if 1
void printResult(uint32_t currTime)
{
  Serial.print(F("Time = "));
  Serial.print(currTime);
  Serial.print(F(", Timer1Count = "));
  Serial.println(counter);
}

#define CHECK_INTERVAL_MS     60000L

void loop()
{
  static uint32_t lastTime = 0;
  static uint32_t currTime;

  currTime = millis();

  if (currTime - lastTime > CHECK_INTERVAL_MS)
  {
    printResult(currTime);

    lastTime = currTime;
  }
}

#else

void loop() {
  static uint32_t last_counter = 0;
  static uint32_t last_running = 0;
  uint32_t running = ( counter != last_counter );
  last_counter = counter;
  if ( last_running != running ) {
    last_running = running;
    Serial.print(millis());
    Serial.print(' ');
    Serial.println(running ? " Running " : " Not Running ");
  }
  delay(1000);
}

#endif

Terminal

Starting Argument_None on RaspberryPi Pico
MBED_RPi_Pico_TimerInterrupt v1.2.0
[TISR] _timerNo = 1, Clock (Hz) = 1000000.00, _fre (Hz) = 8000.00
[TISR] _count = 0-125
[TISR] hardware_alarm_set_target, uS = 125
Starting ITimer1 OK, millis() = 1721
Time = 60001, Timer1Count = 463489
Time = 120002, Timer1Count = 941280
Time = 180003, Timer1Count = 1419173
Time = 240004, Timer1Count = 1897279
Time = 300005, Timer1Count = 2375875
Time = 360006, Timer1Count = 2854735
Time = 420007, Timer1Count = 3333516
Time = 480008, Timer1Count = 3812321
Time = 540009, Timer1Count = 4290610
Time = 600010, Timer1Count = 4768254
Time = 660011, Timer1Count = 5245297
Time = 720012, Timer1Count = 5722315
Time = 780013, Timer1Count = 6198926
Time = 840014, Timer1Count = 6676070
Time = 900015, Timer1Count = 7152699
Time = 960016, Timer1Count = 7629283
Time = 1020017, Timer1Count = 8105491
Time = 1080018, Timer1Count = 8581284
Time = 1140019, Timer1Count = 9057057
Time = 1200020, Timer1Count = 9532821
Time = 1260021, Timer1Count = 10008524
Time = 1320022, Timer1Count = 10484415
Time = 1380023, Timer1Count = 10960130
Time = 1440024, Timer1Count = 11435928
Time = 1500025, Timer1Count = 11911729
Time = 1560026, Timer1Count = 12387769
Time = 1620027, Timer1Count = 12863737
Time = 1680028, Timer1Count = 13339472
Time = 1740029, Timer1Count = 13815318
Time = 1800030, Timer1Count = 14291228
Time = 1860031, Timer1Count = 14767314
Time = 1920032, Timer1Count = 15243188
Time = 1980033, Timer1Count = 15719333
Time = 2040034, Timer1Count = 16195528
Time = 2100035, Timer1Count = 16672198
Time = 2160036, Timer1Count = 17149105
Time = 2220037, Timer1Count = 17625780
Time = 2280038, Timer1Count = 18102464
Time = 2340039, Timer1Count = 18579677
Time = 2400040, Timer1Count = 19056593
22:41:15.300 -> Time = 2460041, Timer1Count = 19533722
22:42:15.294 -> Time = 2520042, Timer1Count = 20011079
22:43:15.284 -> Time = 2580043, Timer1Count = 20488680
22:44:15.303 -> Time = 2640044, Timer1Count = 20966158
22:45:15.292 -> Time = 2700045, Timer1Count = 21443063
22:46:15.305 -> Time = 2760046, Timer1Count = 21920473
22:47:15.282 -> Time = 2820047, Timer1Count = 22397932
22:48:15.301 -> Time = 2880048, Timer1Count = 22875821
22:49:15.283 -> Time = 2940049, Timer1Count = 23353114
22:50:15.289 -> Time = 3000050, Timer1Count = 23830923
22:51:15.284 -> Time = 3060051, Timer1Count = 24308766
22:52:15.294 -> Time = 3120052, Timer1Count = 24786915
22:53:15.311 -> Time = 3180053, Timer1Count = 25264168
22:54:15.294 -> Time = 3240054, Timer1Count = 25741205
22:55:15.311 -> Time = 3300055, Timer1Count = 26218547
22:56:15.299 -> Time = 3360056, Timer1Count = 26696123
22:57:15.303 -> Time = 3420057, Timer1Count = 27173869
22:58:15.294 -> Time = 3480058, Timer1Count = 27651345
22:59:15.320 -> Time = 3540059, Timer1Count = 28129285
23:00:15.313 -> Time = 3600060, Timer1Count = 28607154
23:01:15.299 -> Time = 3660061, Timer1Count = 29085335
23:02:15.297 -> Time = 3720062, Timer1Count = 29562703
23:03:15.297 -> Time = 3780063, Timer1Count = 30040464
23:04:15.316 -> Time = 3840064, Timer1Count = 30518317
23:05:15.300 -> Time = 3900065, Timer1Count = 30996449
23:06:15.325 -> Time = 3960066, Timer1Count = 31474397
23:07:15.317 -> Time = 4020067, Timer1Count = 31952448
23:08:15.325 -> Time = 4080068, Timer1Count = 32430644
23:09:15.312 -> Time = 4140069, Timer1Count = 32908911
23:10:15.303 -> Time = 4200070, Timer1Count = 33387209
23:11:15.305 -> Time = 4260071, Timer1Count = 33865528
23:12:15.312 -> Time = 4320072, Timer1Count = 34342950
23:13:15.314 -> Time = 4380073, Timer1Count = 34818930
23:14:15.319 -> Time = 4440074, Timer1Count = 35295415
23:15:15.306 -> Time = 4500075, Timer1Count = 35771575
23:16:15.317 -> Time = 4560076, Timer1Count = 36247933
23:17:15.330 -> Time = 4620077, Timer1Count = 36724584
23:18:15.326 -> Time = 4680078, Timer1Count = 37201415
23:19:15.341 -> Time = 4740079, Timer1Count = 37678252
23:20:15.331 -> Time = 4800080, Timer1Count = 38154434
23:21:15.332 -> Time = 4860081, Timer1Count = 38631054
23:22:15.343 -> Time = 4920082, Timer1Count = 39107744
23:23:15.316 -> Time = 4980083, Timer1Count = 39585012
23:24:15.339 -> Time = 5040084, Timer1Count = 40061534
23:25:15.333 -> Time = 5100085, Timer1Count = 40538644
23:26:15.346 -> Time = 5160086, Timer1Count = 41015826
23:27:15.323 -> Time = 5220087, Timer1Count = 41493387
23:28:15.329 -> Time = 5280088, Timer1Count = 41970120
23:29:15.344 -> Time = 5340089, Timer1Count = 42446435
23:30:15.351 -> Time = 5400090, Timer1Count = 42922995
23:31:15.352 -> Time = 5460091, Timer1Count = 43399811
23:32:15.354 -> Time = 5520092, Timer1Count = 43876904
23:33:15.339 -> Time = 5580093, Timer1Count = 44353624
23:34:15.347 -> Time = 5640094, Timer1Count = 44807480
23:35:15.334 -> Time = 5700095, Timer1Count = 44807480
23:36:15.341 -> Time = 5760096, Timer1Count = 44807480
23:37:15.344 -> Time = 5820097, Timer1Count = 44807480
23:38:15.343 -> Time = 5880098, Timer1Count = 44807480
23:39:15.347 -> Time = 5940099, Timer1Count = 44807480
23:40:15.352 -> Time = 6000100, Timer1Count = 44807480
23:41:15.333 -> Time = 6060101, Timer1Count = 44807480
23:42:15.344 -> Time = 6120102, Timer1Count = 44807480
23:43:15.334 -> Time = 6180103, Timer1Count = 44807480
23:44:15.355 -> Time = 6240104, Timer1Count = 44807480
23:45:15.351 -> Time = 6300105, Timer1Count = 44807480
23:46:15.337 -> Time = 6360106, Timer1Count = 44807480
23:47:15.353 -> Time = 6420107, Timer1Count = 44807480
23:48:15.344 -> Time = 6480108, Timer1Count = 44807480
23:49:15.362 -> Time = 6540109, Timer1Count = 44807480
23:50:15.370 -> Time = 6600110, Timer1Count = 44807480
23:51:15.354 -> Time = 6660111, Timer1Count = 44807480
23:52:15.354 -> Time = 6720112, Timer1Count = 44807480
23:53:15.348 -> Time = 6780113, Timer1Count = 44807480
23:54:15.353 -> Time = 6840114, Timer1Count = 44807480
23:55:15.350 -> Time = 6900115, Timer1Count = 44807480
Garrabrant commented 1 year ago

Thank you @khoih-prog I really appreciate your taking the time to confirm.

FYI, I learned that if I change MBED_RPI_PICO_Timer ITimer1(1); to MBED_RPI_PICO_Timer ITimer1(0); the problem seems to go away (at least for the first 15 hours).

I'm building with Platform.IO and I don't remember if I was given the option of a non MBED arduino pico core. Is it easy to switch to arduino-pico?

Garrabrant commented 1 year ago

@khoih-prog You reproduced the bug! Notice in your log how after 23:34:15.347 -> Time = 5640094 the counter never goes above 44807480.

BTW, I tested with your non-MBED Timer library RPi_Pico_TimerInterrupt v1.3.1 using

[env:pico]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = pico
framework = arduino
board_build.core = earlephilhower

in platform.ini, and I couldn't reproduce the bug after 18 hours.

But here are my results using the MBED version:

Starting Argument_None on RaspberryPi Pico
MBED_RPi_Pico_TimerInterrupt v1.2.0
[TISR] _timerNo = 1, Clock (Hz) = 1000000.00, _fre (Hz) = 8000.00
[TISR] _count = 0-125
[TISR] hardware_alarm_set_target, uS = 125
Starting ITimer1 OK, millis() = 16263
Time = 60001, Timer1Count = 346283
Time = 120002, Timer1Count = 824227
Time = 180003, Timer1Count = 1301843
Time = 240004, Timer1Count = 1779203

...

Time = 5460091, Timer1Count = 43235149
Time = 5520092, Timer1Count = 43710744
Time = 5580093, Timer1Count = 44186313
Time = 5640094, Timer1Count = 44638525
Time = 5700095, Timer1Count = 44638525
Time = 5760096, Timer1Count = 44638525
Time = 5820097, Timer1Count = 44638525
Time = 5880098, Timer1Count = 44638525

...

Time = 18420307, Timer1Count = 44638525
Time = 18480308, Timer1Count = 44638525
Time = 18540309, Timer1Count = 44784055
Time = 18600310, Timer1Count = 45262106
Time = 18660311, Timer1Count = 45740067
Time = 18720312, Timer1Count = 46218172
Time = 18780313, Timer1Count = 46696180
Time = 18840314, Timer1Count = 46777219
Time = 18900315, Timer1Count = 46777219
Time = 18960316, Timer1Count = 46777219
Time = 19020317, Timer1Count = 46777219

...

Time = 67201120, Timer1Count = 46777219
Time = 67261121, Timer1Count = 46777219
Time = 67321122, Timer1Count = 46777219
Time = 67381123, Timer1Count = 46777219
khoih-prog commented 1 year ago

HI @Garrabrant

It can only be explained that mbed_rp2040 core is using Timer1 for some purpose, periodically, and disrupts your Timer1 operation when it takes over the timer.

You can post the question on Arduino mbed_rp2040 core as I don't have time to investigate further to see where the Timer1 is used.

For your use-case, why not selecting another TImer to use (RP2040 has 4 hardware timers) instead of sticking to Timer1.

As a rule, when select a Timer to use, it must not be used by other purposes, especially the higher-priority core

Garrabrant commented 1 year ago

@khoih-prog Great idea. Thank you for all your help.