I'm trying to port code that was written on Arduino.It's the millis() function.
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the // the overflow handler is called every 256 ticks. #define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) // the whole number of milliseconds per timer0 overflow #define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) // the fractional number of milliseconds per timer0 overflow. we shift right // by three to fit these numbers into a byte. (for the clock speeds we care // about - 8 and 16 MHz - this doesn't lose precision.) #define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) #define FRACT_MAX (1000 >> 3) volatile unsigned long timer0_overflow_count = 0; volatile unsigned long timer0_millis = 0; static unsigned char timer0_fract = 0; #if defined(TIM0_OVF_vect) ISR(TIM0_OVF_vect) #else ISR(TIMER0_OVF_vect) #endif { // copy these to local variables so they can be stored in registers // (volatile variables must be read from memory on every access) unsigned long m = timer0_millis; unsigned char f = timer0_fract; m += MILLIS_INC; f += FRACT_INC; if (f >= FRACT_MAX) { f -= FRACT_MAX; m += 1; } timer0_fract = f; timer0_millis = m; timer0_overflow_count++; } unsigned long millis() { unsigned long m; uint8_t oldSREG = SREG; // disable interrupts while we read timer0_millis or we might get an // inconsistent value (e.g. in the middle of a write to timer0_millis) cli(); m = timer0_millis; SREG = oldSREG; return m; }
I did not understand what the speed of the Timer.I tried using 'sysTickCount', but I don't know if it returns the same value as the original Arduino function.The code I'm trying to use from Arduino isn't working properly and I can't find the problem.Analyzing I found this snippet that may be the problem.
The returned value is used like this:
elapsedTime = (uint64_t)millis()
Does anyone have an idea of how to implement this function?
Ugh. Don't look at the AVR millis() code to figure out how to implement it on an ARM. the AVR code is obscured by trying to use the timer for multiple purposes, resulting in a "tick" of 1/1024 seconds instead of 1/1000.
On an ARM you can use the sysTick timer to get a tick of exactly 1/1000 s, and the whole millis() stuff becomes much simpler.Have a look at one of the Arduino ARM platforms, where it's only partly obscured by vendor libraries and chip reset code:
/** Tick Counter united by ms */ static volatile uint32_t _ulTickCount=0 ; unsigned long millis( void ) { // todo: ensure no interrupts return _ulTickCount ; } void SysTick_DefaultHandler(void) { // Increment tick count each ms _ulTickCount++; tickReset(); }
(This is from https://github.com/arduino/ArduinoCore-samd/blob/9f91accecc8298976670234e4d6ac0afef5c7a39/cores/arduino/delay.c#L85 )