summaryrefslogtreecommitdiff
path: root/bsp
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2017-01-03 17:45:07 -0800
committerAndrew Waterman <andrew@sifive.com>2017-01-03 18:02:42 -0800
commit2398dfda399f445cf114e29b61d9331fddb09b4e (patch)
tree407c63990049b4fa853aedebb4a20bd5ef5cc333 /bsp
parentb1f048f991e7d743e46be9c48c73d00a843f400c (diff)
Improve HiFive1 CPU frequency measurement routine
- Warm up I$ first. - Correct for integer division truncation error. - Wait for an RTC clock edge before starting the timing loop, which removes an error proportional to the number of loop iterations, allowing us to run for far less time.
Diffstat (limited to 'bsp')
-rw-r--r--bsp/env/freedom-e300-hifive1/init.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/bsp/env/freedom-e300-hifive1/init.c b/bsp/env/freedom-e300-hifive1/init.c
index 167d652..61a1ae3 100644
--- a/bsp/env/freedom-e300-hifive1/init.c
+++ b/bsp/env/freedom-e300-hifive1/init.c
@@ -5,8 +5,6 @@
#include "platform.h"
#include "encoding.h"
-uint32_t cpu_freq = 0;
-
extern int main(int argc, char** argv);
extern void trap_entry();
@@ -116,21 +114,40 @@ static void use_default_clocks()
use_hfrosc(4, 16);
}
-void measure_cpu_freq(size_t n, size_t mtime_freq)
+static unsigned long __attribute__((noinline)) measure_cpu_freq(size_t n)
{
- uint32_t start_mtime = mtime_lo();
- uint32_t start_mcycle = mcycle_lo();
+ unsigned long start_mtime, delta_mtime;
+ unsigned long mtime_freq = get_timer_freq();
+
+ // Don't start measuruing until we see an mtime tick
+ unsigned long tmp = mtime_lo();
+ do {
+ start_mtime = mtime_lo();
+ } while (start_mtime == tmp);
+
+ unsigned long start_mcycle = read_csr(mcycle);
- while (mtime_lo() - start_mtime < n) ;
+ do {
+ delta_mtime = mtime_lo() - start_mtime;
+ } while (delta_mtime < n);
- uint32_t end_mtime = mtime_lo();
- uint32_t end_mcycle = mcycle_lo();
+ unsigned long delta_mcycle = read_csr(mcycle) - start_mcycle;
- cpu_freq = (end_mcycle-start_mcycle)/n*mtime_freq;
+ return (delta_mcycle / delta_mtime) * mtime_freq
+ + ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime;
}
-uint32_t get_cpu_freq()
+unsigned long get_cpu_freq()
{
+ static uint32_t cpu_freq;
+
+ if (!cpu_freq) {
+ // warm up I$
+ measure_cpu_freq(1);
+ // measure for real
+ cpu_freq = measure_cpu_freq(10);
+ }
+
return cpu_freq;
}
@@ -178,7 +195,6 @@ void _init()
{
use_default_clocks();
use_pll(0, 0, 1, 31, 1);
- measure_cpu_freq(1000, 32768);
uart_init(115200);
printf("core freq at %d Hz\n", get_cpu_freq());