Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 3552

General • System ticks not lasting the expected time (off by several orders of magnitude)

$
0
0
Hello,

Using resources like this thread and this source code, I tried to build a test program to blink the Pico's onboard LED at arbitrary intervals, down from the big (1 second) to the really small (1 microsecond, maybe less).

Unfortunately, I must report that system ticks seem to be occurring at a different time resolution than any source reports.

I assume that the system clock is 125 MHz, since I have never altered it. Initially I built my program to change the LED state after counting 125 million system ticks, expecting to see one state transition per second (1 blink per 2 seconds). The LED seemed always-on, in reality the program was running a huge number of times faster than I expected.

Then I changed variables to 64-bit integers and told it to wait 125 billion (125 e9) ticks. I can finally see the LED flicker. I suppose nobody has accidentally sold me a Raspberry Pi HyperPico from year 2050, so the confusion must be somewhere in software. :D Can anyone figure out why it seems to tick too fast?

The program:

Code:

#include <stdio.h>#include "pico/stdlib.h"// #include "pico/binary_info.h"// #include "hardware/spi.h"// #include "hardware/dma.h"#include "hardware/structs/systick.h"#define GET_SYSTICK systick_hw->cvr#define GET_SYSTICKMAX systick_hw->rvr// Maximum value of system tick.uint32_t max;// A function borrowed from another coder, specifically from:// https://github.com/WestfW/RPi-Pico-Hacks/blob/main/systick_delay/systick_delay.c//// I use it to check if I'm the only person whose code works wrong.// But this also seems to work wrong (runs too fast).void sysTickDelay (uint32_t count) __attribute__((noinline));void sysTickDelay (uint32_t count) {  int32_t start, end, now;  start = GET_SYSTICK;  end = start - count;  if (end > 0) {    while (1) {      now = GET_SYSTICK;      if ((now <= end) || (now > start))        return;    }  } else {    end += max;  // wrap the end time    while (1) {        now = GET_SYSTICK;        if ((now <= end) && (now > start))        return;    }  }}int main() {      // Enable USB output for logging.   stdio_usb_init();      // Ready the LED.   const uint LED_PIN = PICO_DEFAULT_LED_PIN;   gpio_init(LED_PIN);   gpio_set_dir(LED_PIN, GPIO_OUT);         // Configure to get unaltered system ticks.   systick_hw->csr = 0x5;   systick_hw->rvr = 0x00FFFFFF;      // Current system tick.   // Last time we got a system tick.   int32_t cur_tick = 0;   int32_t last_tick = 0;      // Difference in ticks between current and last.   // Cumulative tick counter (goes beyond 24 bit limit).   volatile int32_t diff = 0;   volatile int64_t cumul = 0;   // Current LED state.   volatile int8_t led_state = 0;      // How many ticks do we count before flipping LED state.      volatile int64_t ticks_to_wait = (int64_t) (125e9);   // volatile int64_t ticks_to_wait = (int64_t) (125e6);         // I try to achieve 1 state transion per second (1 blink per 2 seconds).   // At 125 M ticks per second the waiting period should be 125 M ticks.   // However when I use that, the LED blinks faster than my vision limit, or doesn't blink at all.   // I can see it blinking when I set the waiting period to 125 B ticks.   // That seems to contradict sense and available documentation.   // What's the trick?   // Report maximum permissible value of system tick.   int32_t max = GET_SYSTICKMAX;   printf("Max: %lu.\n",max);      // Show that you're alive and allow the coder to read the console for a second. :)   gpio_put(LED_PIN, 1);   sleep_ms(1000);   gpio_put(LED_PIN, 0);   sleep_ms(1000);   // Initialize, start looping.   last_tick = GET_SYSTICK;         while (true) {      cur_tick = GET_SYSTICK;            // NOTE: SYSTICK COUNTS DOWN!      // Invert it here to keep code more understandable.      cur_tick = max - cur_tick;      // If time seems to have run forward, compute time as usual.      // If time has jumped back, compute time until max + the usual.            if (cur_tick >= last_tick) {         diff = cur_tick - last_tick;      } else {         diff = (max - last_tick) + cur_tick;      }            // Accumulate differences      cumul += diff;            // If enough difference has accumulated      if (cumul > ticks_to_wait) {                  // Alter LED state         if (led_state == 0) {            led_state = 1;         } else {            led_state = 0;         }                  // Drive LED to new state         gpio_put(LED_PIN, led_state);                  // Optionally print report.         // Does not influence visually perceivable behaviour,         // but could influence finely measured stuff.         printf("%d %lld\n", led_state, cumul);         // Restart counting         cumul = 0;      }   }      // Uncomment this and comment the loop above   // to test using another programmer's function.      /*   while (true) {      gpio_put(LED_PIN, 1);      sysTickDelay(125e6);      gpio_put(LED_PIN, 0);      sysTickDelay(125e6);   }   */   }
The log (at 125 billion ticks waiting period) - it honestly seems to think it's counting to 125 billion:

Code:

1 1250021937630 1250023403311 1250011638380 1250072519571 1250000227040 1250036024181 1250045244870 1250021216921 1250002748280 1250155851921 1250110736170 1250134929751 1250130546700 1250023678441 1250108674510 1250042788671 1250073155360 1250065238321 1250083747010 1250000580961 1250086106560 1250086635031 1250088718830 1250061725081 1250109869060 1250068636191 1250027454680 1250088719111 1250083196480 1250064222101 1250081456160 1250009301901 1250012918960 125005608936

Statistics: Posted by diastrikos — Mon Aug 19, 2024 11:38 pm



Viewing all articles
Browse latest Browse all 3552

Trending Articles