stm32duino / Arduino_Core_STM32

STM32 core support for Arduino
https://github.com/stm32duino/Arduino_Core_STM32/wiki
Other
2.85k stars 979 forks source link

Timer period error #2515

Closed drmcnelson closed 2 months ago

drmcnelson commented 2 months ago

Describe the bug

Using the Timer API, the clock consistently runs about 5% fast, periods of 50usecs, and produces errors above and below the programmed time interval for intervals in the range of 10 usec and below.

To Reproduce Here is the code:

 #if defined(TIM1)
 TIM_TypeDef *timxTimerInstance = TIM1;
 #else
 TIM_TypeDef *timxTimerInstance = TIM2;
 #endif

 //HardwareTimer *timxTimer = NULL;
 HardwareTimer *timxTimer = new HardwareTimer(timxTimerInstance);

 void setupTimer()
 {
        //  HardwareTimer *timxTimer = new HardwareTimer(timxTimerInstance);
  }

 void timerStart( unsigned int usecs, void (*function)(void) )
 {
       timxTimer->setOverflow(usecs, MICROSEC_FORMAT); // 10 Hz
       timxTimer->attachInterrupt(function);
       timxTimer->resume();
 }

 void timerStop( )
{
     timxTimer->pause();
 }

 void timer_test_isr() {

        DIGITALTOGGLE(timertest_outpin);

        if (!cpucycles1) {
             cpucycles1 = elapsed_cycles();
        }
        if (timertest_countdown) {
             timertest_countdown--;
             if (!timertest_countdown) {
                 cpucycles2 = elapsed_cycles();
                 timerStop();
             }
       }
      else {
             Serial.println("Warning: timer_test_isr called after countdown expired");
       }
 }

void timerTestStart(unsigned int usecs, uint8_t outpin, unsigned int cycles)
{
     pinMode(outpin,OUTPUT);

     cpucycles = 0;
     cpucycles1 = 0;
     cpucycles2 = 0;

     Serial.print( "// timerTestStart usecs " );
     Serial.print( usecs );
     Serial.print( " pin " );
     Serial.print( outpin );
     Serial.print( " cycles " );
     Serial.println( cycles );

     timertest_outpin = outpin;
     timertest_countdown = cycles;

     elapsed_cycles_start();
    timerStart(usecs,timer_test_isr);
    cpucycles = elapsed_cycles();
 }

Here are some scope traces.

In this one we set the interval to 10usecs. Notice by the end of 200 usecs, the accumulated error is -10usecs.

TEK0002

And here we set the interval to 5usecs. Notice that the intervals are not constant, the first interval is shorter than the later intervals.

TEK0004

fpistm commented 2 months ago

Hi @drmcnelson Could you be more precise. Which board you used? Is it the default clock config? Timer precision is linked to clock config. At this unit microsecond it is not surprising.