Skip to content

Commit 725a69e

Browse files
committed
[driver] Add cycle counter for AVR and Cortex-M
1 parent d5790bf commit 725a69e

File tree

8 files changed

+307
-94
lines changed

8 files changed

+307
-94
lines changed

README.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -723,86 +723,87 @@ you specific needs.
723723
<td align="center"><a href="https://modm.io/reference/module/modm-driver-bmp085">BMP085</a></td>
724724
<td align="center"><a href="https://modm.io/reference/module/modm-driver-bno055">BNO055</a></td>
725725
<td align="center"><a href="https://modm.io/reference/module/modm-driver-cat24aa">CAT24AA</a></td>
726+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-cycle_counter">CYCLE-COUNTER</a></td>
726727
<td align="center"><a href="https://modm.io/reference/module/modm-driver-drv832x_spi">DRV832X</a></td>
727-
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds1302">DS1302</a></td>
728728
</tr><tr>
729+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds1302">DS1302</a></td>
729730
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds1631">DS1631</a></td>
730731
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds18b20">DS18B20</a></td>
731732
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ea_dog">EA-DOG</a></td>
732733
<td align="center"><a href="https://modm.io/reference/module/modm-driver-encoder_input">Encoder Input</a></td>
733734
<td align="center"><a href="https://modm.io/reference/module/modm-driver-encoder_input-bitbang">Encoder Input BitBang</a></td>
734-
<td align="center"><a href="https://modm.io/reference/module/modm-driver-encoder_output-bitbang">Encoder Output BitBang</a></td>
735735
</tr><tr>
736+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-encoder_output-bitbang">Encoder Output BitBang</a></td>
736737
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ft245">FT245</a></td>
737738
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ft6x06">FT6x06</a></td>
738739
<td align="center"><a href="https://modm.io/reference/module/modm-driver-gpio_sampler">Gpio Sampler</a></td>
739740
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hclax">HCLAx</a></td>
740741
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hd44780">HD44780</a></td>
741-
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hmc58x">HMC58x</a></td>
742742
</tr><tr>
743+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hmc58x">HMC58x</a></td>
743744
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hmc6343">HMC6343</a></td>
744745
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hx711">HX711</a></td>
745746
<td align="center"><a href="https://modm.io/reference/module/modm-driver-i2c-eeprom">I2C-EEPROM</a></td>
746747
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ili9341">ILI9341</a></td>
747748
<td align="center"><a href="https://modm.io/reference/module/modm-driver-is31fl3733">IS31FL3733</a></td>
748-
<td align="center"><a href="https://modm.io/reference/module/modm-driver-itg3200">ITG3200</a></td>
749749
</tr><tr>
750+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-itg3200">ITG3200</a></td>
750751
<td align="center"><a href="https://modm.io/reference/module/modm-driver-l3gd20">L3GD20</a></td>
751752
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lan8720a">LAN8720A</a></td>
752753
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lawicel">LAWICEL</a></td>
753754
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lis302dl">LIS302DL</a></td>
754755
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lis3dsh">LIS3DSH</a></td>
755-
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lis3mdl">LIS3MDL</a></td>
756756
</tr><tr>
757+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lis3mdl">LIS3MDL</a></td>
757758
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lm75">LM75</a></td>
758759
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lp503x">LP503x</a></td>
759760
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lsm303a">LSM303A</a></td>
760761
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lsm6ds33">LSM6DS33</a></td>
761762
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lsm6dso">LSM6DSO</a></td>
762-
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ltc2984">LTC2984</a></td>
763763
</tr><tr>
764+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ltc2984">LTC2984</a></td>
764765
<td align="center"><a href="https://modm.io/reference/module/modm-driver-max31855">MAX31855</a></td>
765766
<td align="center"><a href="https://modm.io/reference/module/modm-driver-max31865">MAX31865</a></td>
766767
<td align="center"><a href="https://modm.io/reference/module/modm-driver-max6966">MAX6966</a></td>
767768
<td align="center"><a href="https://modm.io/reference/module/modm-driver-max7219">MAX7219</a></td>
768769
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp23x17">MCP23x17</a></td>
769-
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp2515">MCP2515</a></td>
770770
</tr><tr>
771+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp2515">MCP2515</a></td>
771772
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp7941x">MCP7941x</a></td>
772773
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp990x">MCP990X</a></td>
773774
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mmc5603">MMC5603</a></td>
774775
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ms5611">MS5611</a></td>
775776
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ms5837">MS5837</a></td>
776-
<td align="center"><a href="https://modm.io/reference/module/modm-driver-nokia5110">NOKIA5110</a></td>
777777
</tr><tr>
778+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-nokia5110">NOKIA5110</a></td>
778779
<td align="center"><a href="https://modm.io/reference/module/modm-driver-nrf24">NRF24</a></td>
779780
<td align="center"><a href="https://modm.io/reference/module/modm-driver-parallel_tft_display">TFT-DISPLAY</a></td>
780781
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pat9125el">PAT9125EL</a></td>
781782
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca8574">PCA8574</a></td>
782783
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9535">PCA9535</a></td>
783-
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9548a">PCA9548A</a></td>
784784
</tr><tr>
785+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9548a">PCA9548A</a></td>
785786
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9685">PCA9685</a></td>
786787
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sh1106">SH1106</a></td>
787788
<td align="center"><a href="https://modm.io/reference/module/modm-driver-siemens_s65">SIEMENS-S65</a></td>
788789
<td align="center"><a href="https://modm.io/reference/module/modm-driver-siemens_s75">SIEMENS-S75</a></td>
789790
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk6812">SK6812</a></td>
790-
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk9822">SK9822</a></td>
791791
</tr><tr>
792+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk9822">SK9822</a></td>
792793
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ssd1306">SSD1306</a></td>
793794
<td align="center"><a href="https://modm.io/reference/module/modm-driver-st7586s">ST7586S</a></td>
794795
<td align="center"><a href="https://modm.io/reference/module/modm-driver-st7789">ST7789</a></td>
795796
<td align="center"><a href="https://modm.io/reference/module/modm-driver-stts22h">STTS22H</a></td>
796797
<td align="center"><a href="https://modm.io/reference/module/modm-driver-stusb4500">STUSB4500</a></td>
797-
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx1276">SX1276</a></td>
798798
</tr><tr>
799+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx1276">SX1276</a></td>
799800
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3414">TCS3414</a></td>
800801
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3472">TCS3472</a></td>
801802
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tlc594x">TLC594x</a></td>
802803
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp102">TMP102</a></td>
803804
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp12x">TMP12x</a></td>
804-
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp175">TMP175</a></td>
805805
</tr><tr>
806+
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp175">TMP175</a></td>
806807
<td align="center"><a href="https://modm.io/reference/module/modm-driver-touch2046">TOUCH2046</a></td>
807808
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl53l0">VL53L0</a></td>
808809
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl6180">VL6180</a></td>

examples/generic/delay/main.cpp

Lines changed: 14 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
// ----------------------------------------------------------------------------
1111

1212
#include <modm/board.hpp>
13+
#include <modm/driver/time/cycle_counter.hpp>
1314

1415
using namespace Board;
1516

@@ -18,6 +19,7 @@ using namespace Board;
1819
modm::IODeviceWrapper<UsbUart0, modm::IOBuffer::DiscardIfFull> usb_io_device;
1920
modm::log::Logger modm::log::info(usb_io_device);
2021
#endif
22+
modm_fastdata modm::CycleCounter counter;
2123
#ifdef TCNT1
2224
constexpr uint32_t SystemCoreClock = F_CPU;
2325
#endif
@@ -27,39 +29,19 @@ run_delay_ns(uint32_t ns)
2729
{
2830
#ifdef CFG_TUSB_MCU
2931
tud_task();
30-
#endif
31-
#ifdef TCNT1
32-
uint16_t start, stop;
33-
#else
34-
uint32_t start, stop;
3532
#endif
3633
{
3734
modm::atomic::Lock _;
38-
#ifdef TCNT1
39-
start = TCNT1;
40-
#elif defined DWT
41-
start = DWT->CYCCNT;
42-
#else
43-
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
44-
SysTick->LOAD = (1ul << 23);
45-
SysTick->VAL = 0;
46-
stop = SysTick->VAL;
47-
#endif
35+
counter.start();
4836
modm::delay_ns(ns);
49-
#ifdef TCNT1
50-
stop = TCNT1;
51-
#elif defined DWT
52-
stop = DWT->CYCCNT;
53-
#else
54-
start = SysTick->VAL;
55-
#endif
37+
counter.stop();
5638
}
5739
#ifdef CFG_TUSB_MCU
5840
tud_task();
5941
#endif
60-
const uint32_t cycles = (stop - start) - 4;
42+
const uint32_t cycles = counter.cycles();
6143
const uint32_t expected = uint64_t(SystemCoreClock) * ns / 1'000'000'000ull;
62-
const uint32_t real = cycles * 1'000'000'000ull / SystemCoreClock;
44+
const uint32_t real = counter.nanoseconds();
6345
MODM_LOG_INFO.printf("%8lu | %7lu | %7lu | %8lu %c\n", ns, expected, cycles, real,
6446
(cycles < expected*1.2f ? (cycles > expected*0.8f ? ' ' : '<') : '>')) << modm::flush;
6547
#ifdef CFG_TUSB_MCU
@@ -72,39 +54,19 @@ run_delay_us(uint32_t us)
7254
{
7355
#ifdef CFG_TUSB_MCU
7456
tud_task();
75-
#endif
76-
#ifdef TCNT1
77-
uint16_t start, stop;
78-
#else
79-
uint32_t start, stop;
8057
#endif
8158
{
8259
modm::atomic::Lock _;
83-
#ifdef TCNT1
84-
start = TCNT1;
85-
#elif defined DWT
86-
start = DWT->CYCCNT;
87-
#else
88-
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
89-
SysTick->LOAD = (1ul << 23);
90-
SysTick->VAL = 0;
91-
stop = SysTick->VAL;
92-
#endif
60+
counter.start();
9361
modm::delay_us(us);
94-
#ifdef TCNT1
95-
stop = TCNT1;
96-
#elif defined DWT
97-
stop = DWT->CYCCNT;
98-
#else
99-
start = SysTick->VAL;
100-
#endif
62+
counter.stop();
10163
}
10264
#ifdef CFG_TUSB_MCU
10365
tud_task();
10466
#endif
105-
const uint32_t cycles = (stop - start) - 4;
67+
const uint32_t cycles = counter.cycles();
10668
const uint32_t expected = uint64_t(SystemCoreClock) * us / 1'000'000ull;
107-
const uint32_t real = cycles * 1'000'000ull / SystemCoreClock;
69+
const uint32_t real = counter.microseconds();
10870
MODM_LOG_INFO.printf("%8lu | %8lu | %8lu | %8lu %c\n", us, expected, cycles, real,
10971
(cycles < expected*1.2f ? (cycles > expected*0.8f ? ' ' : '<') : '>')) << modm::flush;
11072
#ifdef CFG_TUSB_MCU
@@ -174,9 +136,7 @@ run_test_us(bool short_test=false)
174136
int main()
175137
{
176138
Board::initialize();
177-
178-
TCCR1A = 0;
179-
TCCR1B = (1 << CS10);
139+
counter.initialize();
180140

181141
run_test_ns();
182142
run_test_us();
@@ -192,6 +152,7 @@ int main()
192152
{
193153
Board::initialize();
194154
Board::initializeUsbFs();
155+
counter.initialize(true);
195156
tusb_init();
196157

197158
MODM_LOG_INFO << "Hello World\n";
@@ -229,11 +190,13 @@ int main()
229190
{
230191
Board::stlink::Uart::connect<Board::stlink::Tx::Tx>();
231192
Board::stlink::Uart::initialize<BootClock, 115200_Bd, 5_pct>();
193+
counter.initialize(true);
232194

233195
run_test_ns();
234196
run_test_us();
235197

236198
Board::initialize();
199+
counter.initialize(true);
237200

238201
run_test_ns();
239202
run_test_us();

examples/generic/delay/project.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
<modules>
2727
<module>modm:build:scons</module>
2828
<module>modm:debug</module>
29+
<module>modm:driver:cycle_counter</module>
2930
<!-- <module>modm:tinyusb</module> -->
3031
</modules>
3132
</library>
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright (c) 2023, Niklas Hauser
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
// ----------------------------------------------------------------------------
11+
12+
#pragma once
13+
#include <cstdint>
14+
#include <modm/platform.hpp>
15+
16+
namespace modm
17+
{
18+
19+
/// @ingroup modm_driver_cycle_counter
20+
class CycleCounter
21+
{
22+
public:
23+
%% if is_avr
24+
using cycle_t = uint16_t;
25+
%% else
26+
using cycle_t = uint32_t;
27+
%% endif
28+
29+
/// @param force overwrite previous timer configuration
30+
/// @param overhead total number of overhead cycles
31+
void
32+
initialize(bool force [[maybe_unused]] = false, uint8_t overhead = 4)
33+
{
34+
%% if is_avr
35+
if (force or not TCCR1B)
36+
{
37+
TCCR1A = 0;
38+
TCCR1B = (1 << CS10);
39+
}
40+
%% elif is_cm0
41+
// Only configure if modm:platform:systick module hasn't already
42+
if (force or not SysTick->CTRL)
43+
{
44+
// SysTick counts down, so start and stop are swapped!
45+
SysTick->LOAD = -1ul;
46+
SysTick->VAL = 0;
47+
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
48+
}
49+
%% endif
50+
this->overhead = overhead;
51+
}
52+
53+
/// Sample the timer at the start of your measurement
54+
modm_always_inline void
55+
start()
56+
{
57+
%% if is_avr
58+
start_ = TCNT1;
59+
%% elif is_cm0
60+
stop_ = SysTick->VAL;
61+
%% else
62+
start_ = DWT->CYCCNT;
63+
%% endif
64+
}
65+
66+
/// Sample the timer at the end of your measurement
67+
modm_always_inline void
68+
stop()
69+
{
70+
%% if is_avr
71+
stop_ = TCNT1;
72+
%% elif is_cm0
73+
start_ = SysTick->VAL;
74+
%% else
75+
stop_ = DWT->CYCCNT;
76+
%% endif
77+
}
78+
79+
/// @return the difference in cycles between start and stop.
80+
cycle_t
81+
cycles()
82+
{
83+
%% if is_cm0
84+
if (stop_ < start_) {
85+
// The SysTick counter has underflowed
86+
stop_ += SysTick->LOAD;
87+
}
88+
uint32_t diff = stop_ - start_;
89+
// SysTick may be using the implementation defined reference clock
90+
if (not (SysTick->CTRL & SysTick_CTRL_CLKSOURCE_Msk))
91+
diff *= {{reference_div}};
92+
return diff - overhead;
93+
%% else
94+
return (stop_ - start_) - overhead;
95+
%% endif
96+
}
97+
98+
/// @return the difference in milliseconds between start and stop.
99+
uint32_t
100+
milliseconds()
101+
{
102+
return (cycles() * 1'000ull) / SystemCoreClock;
103+
}
104+
105+
/// @return the difference in microseconds between start and stop.
106+
uint32_t
107+
microseconds()
108+
{
109+
return (cycles() * 1'000'000ull) / SystemCoreClock;
110+
}
111+
112+
/// @return the difference in nanoseconds between start and stop.
113+
uint32_t
114+
nanoseconds()
115+
{
116+
return (cycles() * 1'000'000'000ull) / SystemCoreClock;
117+
}
118+
119+
private:
120+
cycle_t start_, stop_;
121+
uint8_t overhead{4};
122+
%% if is_avr
123+
static constexpr uint32_t SystemCoreClock = F_CPU;
124+
%% endif
125+
};
126+
127+
}

0 commit comments

Comments
 (0)