Skip to content
This repository has been archived by the owner on Jan 29, 2023. It is now read-only.

Bug when going from a >20000us period to a <20000us period. The timer period become 4 times greater. #3

Closed
thiagothimotti opened this issue Jun 2, 2021 · 9 comments
Labels
bug Something isn't working

Comments

@thiagothimotti
Copy link

thiagothimotti commented Jun 2, 2021

Describe the bug

If I set a interval greater than 20000us and then set a smaller than 20000us, I'll have my period 4 times bigger than expected.

Steps to Reproduce

SAMDTimer ITimer(TIMER_TC3);

uint32_t myClockTimer=0,lastMicros=0;

void clock(void)
{	
	myClockTimer=micros()-lastMicros;    //2us come from here
	lastMicros=micros();
}

void setup() {

}

void loop(){
		ITimer.attachInterruptInterval(20005, clock);  //myClockTimer=20003 (20005 minus 2us, it's correct) 
		delay(5000);
		ITimer.attachInterruptInterval(19995, clock);  //myClockTimer=79978(4 times bigger than expected, minus 2us) 
		delay(5000);
}

Expected behavior

The expected behavior was a timer period of 19995us.

Actual behavior

The actual behavior was a timer period 4 times bigger.

Information

Arduino Core v1.8.9
Atmel Studio

Some observations

If I start with 19000us, works fine. Then I go to 21000us, works fine. When I go back to 19000us, the bug happen.
Only noticed when going from a bigger(>20000) to smaller(<20000). And since this happen the smaller won't work anymore.
I'm suspecting some bug with the preScaler.

@khoih-prog
Copy link
Owner

Hi @thiagothimotti

I'm amazed that you found out an interesting hard-to-find bug. I'm able to duplicate it and will investigate and fix.

This is the sketch to duplicate

#if !( defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) \
    || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \
    || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \
    || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \
    || defined(__SAMD51G19A__) || defined(__SAMD51P19A__) || defined(__SAMD21G18A__) )
#error This code is designed to run on SAMD21/SAMD51 platform! Please check your Tools->Board setting.
#endif

// These define's must be placed at the beginning before #include "SAMDTimerInterrupt.h"
// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4
// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system.
#define TIMER_INTERRUPT_DEBUG         4
#define _TIMERINTERRUPT_LOGLEVEL_     4

#include "SAMDTimerInterrupt.h"

SAMDTimer ITimer(TIMER_TC3);

uint32_t myClockTimer = 0, lastMicros = 0;

void clock(void)
{
  myClockTimer = micros() - lastMicros; //2us come from here
  lastMicros = micros();
}
void setup()
{
  Serial.begin(115200);
  while (!Serial);

  delay(100);

  Serial.print(F("\nStarting Argument_None_uS on ")); Serial.println(BOARD_NAME);
  Serial.println(SAMD_TIMER_INTERRUPT_VERSION);
  Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz"));
}

void loop()
{
  ITimer.attachInterruptInterval(19995, clock);  //myClockTimer=79978(4 times bigger than expected, minus 2us)
  delay(5000);
  Serial.print(F("myClockTimer (19995) = ")); Serial.println(myClockTimer);
  ITimer.attachInterruptInterval(19995, clock);  //myClockTimer=79978(4 times bigger than expected, minus 2us)
  delay(5000);
  Serial.print(F("myClockTimer (19995) = ")); Serial.println(myClockTimer);
  ITimer.attachInterruptInterval(19995, clock);  //myClockTimer=79978(4 times bigger than expected, minus 2us)
  delay(5000);
  Serial.print(F("myClockTimer (19995) = ")); Serial.println(myClockTimer);
  ITimer.attachInterruptInterval(19000, clock);  //myClockTimer=79978(4 times bigger than expected, minus 2us)
  delay(5000);
  Serial.print(F("myClockTimer (19000) = ")); Serial.println(myClockTimer);
  ITimer.attachInterruptInterval(20005, clock);  //myClockTimer=20003 (20005 minus 2us, it's correct)
  delay(5000);
  Serial.print(F("myClockTimer (20005) = ")); Serial.println(myClockTimer);
  ITimer.attachInterruptInterval(30000, clock);  //myClockTimer=79978(4 times bigger than expected, minus 2us)
  delay(5000);
  Serial.print(F("myClockTimer (30000) = ")); Serial.println(myClockTimer);
  ITimer.attachInterruptInterval(19995, clock);  //myClockTimer=79978(4 times bigger than expected, minus 2us)
  delay(5000);
  Serial.print(F("myClockTimer (19995) = ")); Serial.println(myClockTimer);
  ITimer.attachInterruptInterval(30000, clock);  //myClockTimer=79978(4 times bigger than expected, minus 2us)
  delay(5000);
  Serial.print(F("myClockTimer (30000) = ")); Serial.println(myClockTimer);
  
}

and the Terminal output

Starting Argument_None_uS on SEEED_XIAO_M0
SAMDTimerInterrupt v1.3.1
CPU Frequency = 48 MHz
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (19995) = 19993           <========== OK
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (19995) = 19993           <========== OK
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (19995) = 19993           <========== OK
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (19000) = 18998           <========== OK
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (20005) = 20002           <========== OK
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (30000) = 29997           <========== OK
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (19995) = 79978           <========== ERROR ===========================<======ERROR
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (30000) = 29996           <========== OK
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (19995) = 79978           <========== ERROR ===========================<======ERROR
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (19995) = 79978           <========== ERROR ===========================<======ERROR
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (19995) = 79978           <========== ERROR ===========================<======ERROR
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (19000) = 75998           <========== ERROR ===========================<======ERROR
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (20005) = 20002           <========== OK
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
myClockTimer (30000) = 29997           <========== OK
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00

@khoih-prog
Copy link
Owner

khoih-prog commented Jun 2, 2021

Already found out and fixed the bug. Will publish the new release within today.

Test result for TC3 OK

Starting Argument_None_uS on SEEED_XIAO_M0
SAMDTimerInterrupt v1.4.0
CPU Frequency = 48 MHz
[TISR] _period = 19995 , frequency = 50.01
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 19995 , _prescaler = 16
[TISR] _compareValue = 59984
myClockTimer (19995) = 19993           <========== OK===============================<=======OK
[TISR] _period = 19995 , frequency = 50.01
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 19995 , _prescaler = 16
[TISR] _compareValue = 59984
myClockTimer (19995) = 19993           <========== OK===============================<=======OK
[TISR] _period = 19995 , frequency = 50.01
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 19995 , _prescaler = 16
[TISR] _compareValue = 59984
myClockTimer (19995) = 19993           <========== OK===============================<=======OK
[TISR] _period = 19000 , frequency = 52.63
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 19000 , _prescaler = 16
[TISR] _compareValue = 56999
myClockTimer (19000) = 18998
[TISR] _period = 20005 , frequency = 49.99
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 20005 , _prescaler = 64
[TISR] _compareValue = 15002
myClockTimer (20005) = 20002
[TISR] _period = 30000 , frequency = 33.33
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 30000 , _prescaler = 64
[TISR] _compareValue = 22498
myClockTimer (30000) = 29997
[TISR] _period = 19995 , frequency = 50.01
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 19995 , _prescaler = 16
[TISR] _compareValue = 59984
myClockTimer (19995) = 19993           <========== OK===============================<=======OK
[TISR] _period = 30000 , frequency = 33.33
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 30000 , _prescaler = 64
[TISR] _compareValue = 22498
myClockTimer (30000) = 29997
[TISR] _period = 19995 , frequency = 50.01
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 19995 , _prescaler = 16
[TISR] _compareValue = 59984
myClockTimer (19995) = 19993           <========== OK===============================<=======OK
[TISR] _period = 19995 , frequency = 50.01
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 19995 , _prescaler = 16
[TISR] _compareValue = 59984
myClockTimer (19995) = 19993           <========== OK===============================<=======OK
[TISR] _period = 19995 , frequency = 50.01
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 19995 , _prescaler = 16
[TISR] _compareValue = 59984
myClockTimer (19995) = 19993           <========== OK===============================<=======OK
[TISR] _period = 19000 , frequency = 52.63
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 19000 , _prescaler = 16
[TISR] _compareValue = 56999
myClockTimer (19000) = 18998
[TISR] _period = 20005 , frequency = 49.99
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 20005 , _prescaler = 64
[TISR] _compareValue = 15002
myClockTimer (20005) = 20004
[TISR] _period = 30000 , frequency = 33.33
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TC3_Timer::startTimer _Timer = 0x 42002c00 , TC3 = 0x 42002c00
[TISR] SAMD21 TC3 period = 30000 , _prescaler = 64
[TISR] _compareValue = 22498

@thiagothimotti
Copy link
Author

Amazing ! Incredibly fast ! What was?

@khoih-prog
Copy link
Owner

Test for TCC also OK

Starting Argument_None_uS on SEEED_XIAO_M0
SAMDTimerInterrupt v1.4.0
CPU Frequency = 48 MHz
[TISR] _period = 19995 , frequency = 50.01
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TCC_Timer::startTimer _Timer = 0x 42002000 , TCC0 = 0x 42002000
[TISR] SAMD21 TCC period = 19995 , _prescaler = 16
[TISR] _compareValue = 59984
myClockTimer (19995) = 19993           <========== OK===============================<=======OK
[TISR] _period = 19995 , frequency = 50.01
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TCC_Timer::startTimer _Timer = 0x 42002000 , TCC0 = 0x 42002000
[TISR] SAMD21 TCC period = 19995 , _prescaler = 16
[TISR] _compareValue = 59984
myClockTimer (19995) = 19993           <========== OK===============================<=======OK
[TISR] _period = 19995 , frequency = 50.01
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TCC_Timer::startTimer _Timer = 0x 42002000 , TCC0 = 0x 42002000
[TISR] SAMD21 TCC period = 19995 , _prescaler = 16
[TISR] _compareValue = 59984
myClockTimer (19995) = 19993           <========== OK===============================<=======OK
[TISR] _period = 19000 , frequency = 52.63
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TCC_Timer::startTimer _Timer = 0x 42002000 , TCC0 = 0x 42002000
[TISR] SAMD21 TCC period = 19000 , _prescaler = 16
[TISR] _compareValue = 56999
myClockTimer (19000) = 18998
[TISR] _period = 20005 , frequency = 49.99
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TCC_Timer::startTimer _Timer = 0x 42002000 , TCC0 = 0x 42002000
[TISR] SAMD21 TCC period = 20005 , _prescaler = 64
[TISR] _compareValue = 15002
myClockTimer (20005) = 20002
[TISR] _period = 30000 , frequency = 33.33
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TCC_Timer::startTimer _Timer = 0x 42002000 , TCC0 = 0x 42002000
[TISR] SAMD21 TCC period = 30000 , _prescaler = 64
[TISR] _compareValue = 22498
myClockTimer (30000) = 29996
[TISR] _period = 19995 , frequency = 50.01
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TCC_Timer::startTimer _Timer = 0x 42002000 , TCC0 = 0x 42002000
[TISR] SAMD21 TCC period = 19995 , _prescaler = 16
[TISR] _compareValue = 59984
myClockTimer (19995) = 19993           <========== OK===============================<=======OK
[TISR] _period = 30000 , frequency = 33.33
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TCC_Timer::startTimer _Timer = 0x 42002000 , TCC0 = 0x 42002000
[TISR] SAMD21 TCC period = 30000 , _prescaler = 64
[TISR] _compareValue = 22498
myClockTimer (30000) = 29997
[TISR] _period = 19995 , frequency = 50.01
[TISR] SAMDTimerInterrupt: F_CPU (MHz) = 48 , TIMER_HZ = 48
[TISR] TCC_Timer::startTimer _Timer = 0x 42002000 , TCC0 = 0x 42002000
[TISR] SAMD21 TCC period = 19995 , _prescaler = 16
[TISR] _compareValue = 59984

@khoih-prog
Copy link
Owner

What was?

I didn't expect the attachInterruptInterval() to be called repeatedly, and didn't fully reinit the PreScaler register.
Now, I have to reinit every time we have a change in the Timer.
You'll see in the code

@thiagothimotti
Copy link
Author

Great ! 👍 Thank you.

@khoih-prog
Copy link
Owner

I have to thank you 👍 for finding the interesting bug. Your contribution will be noted in new release.

khoih-prog added a commit that referenced this issue Jun 2, 2021
### Releases v1.4.0

1. Fix SAMD21 rare bug caused by not fully init Prescaler. Check [**Bug when going from a >20000us period to a <20000us period. The timer period become 4 times greater.** #3](#3)
khoih-prog added a commit that referenced this issue Jun 2, 2021
### Releases v1.4.0

1. Fix SAMD21 rare bug caused by not fully init Prescaler. Check [**Bug when going from a >20000us period to a <20000us period. The timer period become 4 times greater.** #3](#3)
@khoih-prog
Copy link
Owner

khoih-prog commented Jun 2, 2021

Hi @thiagothimotti

Already published the new SAMD_TimerInterrupt Releases v1.4.0 with your contribution noted in Contributions and Thanks.

You can also see a new RepeatedAttachInterrupt_uS example, based on yours, has also been added to the new Release.

Please test and see if everything is working OK on your side.

I'm looking forward to receiving your next Contributions.

Regards,


Releases v1.4.0

  1. Fix SAMD21 rare bug caused by not fully init Prescaler. Check Bug when going from a >20000us period to a <20000us period. The timer period become 4 times greater. #3

@khoih-prog khoih-prog added the bug Something isn't working label Jun 2, 2021
@thiagothimotti
Copy link
Author

Hi @khoih-prog,
Tested and stable.
I'm new to gitHub, learning how to contribute here. I'll be following this repository.
Your library really helped my application, thank you 👍

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants