Skip to content

Commit 03e740a

Browse files
Add CPU cycle counter accessors (#226)
Use the 24-bit SYSTICK peripheral, wrapped in logic to extend it to a full 32 or 64bits. W/o the wrapper, SYSTICK will wrap around in ~100ms. Adds rp2040.getCycleCount() and rp2040.getCycleCount64() Clean up the libpico build process as crt0.S from the pico-sdk should be directly used. Clean up the keywords file.
1 parent e628c8e commit 03e740a

File tree

7 files changed

+87
-329
lines changed

7 files changed

+87
-329
lines changed

assembly/crt0.S

Lines changed: 0 additions & 315 deletions
This file was deleted.

cores/rp2040/RP2040.h

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include <hardware/clocks.h>
2222
#include <hardware/irq.h>
2323
#include <hardware/pio.h>
24+
#include <hardware/exception.h>
25+
#include <hardware/structs/systick.h>
2426
#include <pico/multicore.h>
2527
#include <pico/util/queue.h>
2628
#include <CoreMutex.h>
@@ -114,8 +116,21 @@ class _MFIFO {
114116
static constexpr int _GOTOSLEEP = 0x66666666;
115117
};
116118

119+
class RP2040;
120+
extern RP2040 rp2040;
117121
class RP2040 {
118122
public:
123+
RP2040() {
124+
_epoch = 0;
125+
// Enable SYSTICK exception
126+
exception_set_exclusive_handler(SYSTICK_EXCEPTION, _SystickHandler);
127+
systick_hw->csr = 0x7;
128+
systick_hw->rvr = 0x00FFFFFF;
129+
}
130+
131+
~RP2040() { /* noop */ }
132+
133+
119134
// Convert from microseconds to PIO clock cycles
120135
static int usToPIOCycles(int us) {
121136
// Parenthesis needed to guarantee order of operations to avoid 32bit overflow
@@ -127,18 +142,44 @@ class RP2040 {
127142
return clock_get_hz(clk_sys);
128143
}
129144

145+
// Get CPU cycle count. Needs to do magic to extens 24b HW to something longer
146+
volatile uint64_t _epoch = 0;
147+
inline uint32_t getCycleCount() {
148+
uint32_t epoch;
149+
uint32_t ctr;
150+
do {
151+
epoch = (uint32_t)_epoch;
152+
ctr = systick_hw->cvr;
153+
} while (epoch != (uint32_t)_epoch);
154+
return epoch + (1 << 24) - ctr; /* CTR counts down from 1<<24-1 */
155+
}
156+
157+
inline uint64_t getCycleCount64() {
158+
uint64_t epoch;
159+
uint64_t ctr;
160+
do {
161+
epoch = _epoch;
162+
ctr = systick_hw->cvr;
163+
} while (epoch != _epoch);
164+
return epoch + (1LL << 24) - ctr;
165+
}
166+
130167
void idleOtherCore() {
131168
fifo.idleOtherCore();
132169
}
170+
133171
void resumeOtherCore() {
134172
fifo.resumeOtherCore();
135173
}
136174

137175
// Multicore comms FIFO
138176
_MFIFO fifo;
139-
};
140177

141-
extern RP2040 rp2040;
178+
private:
179+
static void _SystickHandler() {
180+
rp2040._epoch += 1LL << 24;
181+
}
182+
};
142183

143184
// Wrapper class for PIO programs, abstracting common operations out
144185
// TODO - Add unload/destructor

0 commit comments

Comments
 (0)