Skip to content

Commit 1f77fe5

Browse files
mikee47slaff
authored andcommitted
Introduce Clock framework and Polled Timers (#1821)
* Define Clocks and Polled Timers `NanoTime` provides time calculation support and base template classes for Clocks and Time Sources. `Platform/Clocks.h` parameterises all clock sources `PolledTimer.h` provides template class for implementing polled (elapse and timeout) timers `Platform/Timers.h` defines available timer types Add implementation of `esp_get_count()' to `esp_clk.h`, together with `ets_get_cpu_frequency` declaration. * Update documentation * Simplify samples and framework code using polled timers * Add clocks module to HostTests * Add section on timer range checking to docs. and add PolledTimer::checkTime() method. * Fix NanoTime::Ticks methods * Revise hosttests display of clock limit values
1 parent 82d21e4 commit 1f77fe5

File tree

20 files changed

+1997
-189
lines changed

20 files changed

+1997
-189
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
#include <sming_attr.h>
5+
6+
#ifdef __cplusplus
7+
extern "C" {
8+
#endif
9+
10+
// system_get_cpu_frequency is just a wrapper for this ROM function.
11+
uint8_t ets_get_cpu_frequency(void);
12+
13+
__forceinline static uint32_t esp_get_ccount()
14+
{
15+
uint32_t ccount;
16+
__asm__ __volatile__("rsr %0, ccount\n" : "=a"(ccount) : : "memory");
17+
return ccount;
18+
}
19+
20+
#ifdef __cplusplus
21+
}
22+
#endif

Sming/Arch/Esp8266/Components/gdbstub/gdbuart.cpp

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212

1313
#include "gdbuart.h"
1414
#include "GdbPacket.h"
15-
#include "driver/uart.h"
16-
#include "driver/SerialBuffer.h"
17-
#include "Platform/System.h"
18-
#include "HardwareSerial.h"
19-
#include <driver/hw_timer.h>
15+
#include <driver/uart.h>
16+
#include <driver/SerialBuffer.h>
17+
#include <Platform/System.h>
18+
#include <HardwareSerial.h>
19+
#include <Platform/Timers.h>
2020
#include "gdbsyscall.h"
2121

2222
#define GDB_UART UART0 // Only UART0 supports for debugging as RX/TX required
@@ -109,14 +109,7 @@ static size_t ATTR_GDBEXTERNFN gdb_uart_write_char(char c)
109109

110110
int ATTR_GDBEXTERNFN gdbReceiveChar()
111111
{
112-
#if GDBSTUB_UART_READ_TIMEOUT
113-
constexpr uint32_t timeout = round(double(HW_TIMER2_CLK) * GDBSTUB_UART_READ_TIMEOUT / 1000);
114-
auto startTicks = NOW();
115-
#define checkTimeout() (NOW() - startTicks >= timeout)
116-
#else
117-
#define checkTimeout() (false)
118-
#endif
119-
112+
OneShotElapseTimer<NanoTime::Milliseconds> timer(GDBSTUB_UART_READ_TIMEOUT);
120113
do {
121114
wdt_feed();
122115
system_soft_wdt_feed();
@@ -127,7 +120,7 @@ int ATTR_GDBEXTERNFN gdbReceiveChar()
127120
#endif
128121
return c;
129122
}
130-
} while(!checkTimeout());
123+
} while(GDBSTUB_UART_READ_TIMEOUT == 0 || !timer.expired());
131124

132125
return -1;
133126
}
Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,42 @@
11
#include "include/esp_clk.h"
2+
#include "include/esp_system.h"
23

3-
// The current CPU frequency
4-
static uint8_t __cpu_frequency = 80;
4+
// The current CPU frequency in MHz (ticks per us)
5+
static uint8_t cpu_frequency = SYS_CPU_80MHZ;
56

67
bool system_update_cpu_freq(uint8 freq)
78
{
8-
if(freq == 80 || freq == 160) {
9-
__cpu_frequency = freq;
9+
if(freq == SYS_CPU_80MHZ || freq == SYS_CPU_160MHZ) {
10+
cpu_frequency = freq;
1011
return true;
1112
} else {
1213
return false;
1314
}
1415
}
1516

17+
uint8_t ets_get_cpu_frequency(void)
18+
{
19+
return cpu_frequency;
20+
}
21+
1622
uint8 system_get_cpu_freq(void)
1723
{
18-
return __cpu_frequency;
24+
return ets_get_cpu_frequency();
25+
}
26+
27+
/*
28+
* The 'correct' conversion is actually:
29+
*
30+
* `os_get_nanoseconds() / (1000UL * cpu_frequency)`
31+
*
32+
* However, in use this just ends up returning 0 all the time which is
33+
* not particularly useful.
34+
*
35+
* On my dev. system a straight nanosecond count gives quite useful
36+
* values when evaluating code paths. Try :sample:`Basic_Delegates`.
37+
*
38+
*/
39+
uint32_t esp_get_ccount()
40+
{
41+
return os_get_nanoseconds();
1942
}

Sming/Arch/Host/Components/esp_hal/include/esp_clk.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ extern "C" {
1111
#define SYS_CPU_160MHZ 160
1212

1313
bool system_update_cpu_freq(uint8 freq);
14-
uint8 system_get_cpu_freq(void);
14+
uint8_t ets_get_cpu_frequency(void);
15+
uint8_t system_get_cpu_freq(void);
16+
17+
/* Emulation of CPU cycle count */
18+
uint32_t esp_get_ccount();
1519

1620
#ifdef __cplusplus
1721
}

Sming/Arch/Host/Components/esp_hal/system.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include <hostlib/hostapi.h>
33
#include <hostlib/threads.h>
44
#include <sys/time.h>
5-
#include <Rational.h>
5+
#include <Platform/Timers.h>
66

77
/* System time */
88

@@ -54,8 +54,8 @@ uint32_t system_get_time()
5454

5555
void os_delay_us(uint32_t us)
5656
{
57-
auto start = system_get_time();
58-
while(system_get_time() - start < us) {
57+
ElapseTimer timer(us);
58+
while(!timer.expired()) {
5959
//
6060
}
6161
}

Sming/Arch/Host/Components/hostlib/startup.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@
2626
#include "options.h"
2727
#include <spi_flash/flashmem.h>
2828
#include <driver/uart_server.h>
29-
#include <driver/hw_timer.h>
3029
#include <BitManipulations.h>
3130
#include <esp_timer_legacy.h>
3231
#include <esp_tasks.h>
3332
#include <host_lwip.h>
3433
#include <stdlib.h>
3534

3635
#include <Platform/System.h>
36+
#include <Platform/Timers.h>
3737

3838
static int exitCode = 0;
3939
static bool done = false;
@@ -237,15 +237,13 @@ int main(int argc, char* argv[])
237237

238238
init();
239239

240-
const uint32_t lwipServiceInterval = 50000;
241-
uint32_t lwipNextService = 0;
240+
OneShotElapseTimer<NanoTime::Milliseconds> lwipServiceTimer(50);
242241
while(!done) {
243-
auto now = system_get_time();
244242
host_service_tasks();
245243
host_service_timers();
246-
if(lwip_initialised && (now >= lwipNextService)) {
244+
if(lwip_initialised && lwipServiceTimer.expired()) {
247245
host_lwip_service();
248-
lwipNextService = now + lwipServiceInterval;
246+
lwipServiceTimer.start();
249247
}
250248
system_soft_wdt_feed();
251249
}

Sming/Core/NanoTime.cpp

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/****
2+
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
3+
* Created 2015 by Skurydin Alexey
4+
* http://github.com/SmingHub/Sming
5+
* All files of the Sming Core are provided under the LGPL v3 license.
6+
*
7+
* NanoTime.cpp
8+
*
9+
* @author mikee47 <[email protected]>
10+
*
11+
****/
12+
13+
#include "NanoTime.h"
14+
15+
#include <WString.h>
16+
17+
namespace NanoTime
18+
{
19+
const char* unitToString(Unit unit)
20+
{
21+
switch(unit) {
22+
case Nanoseconds:
23+
return "ns";
24+
case Microseconds:
25+
return "us";
26+
case Milliseconds:
27+
return "ms";
28+
case Seconds:
29+
return "s";
30+
case Minutes:
31+
return "m";
32+
case Hours:
33+
return "h";
34+
case Days:
35+
return "d";
36+
default:
37+
return "?s";
38+
}
39+
}
40+
41+
const char* unitToLongString(Unit unit)
42+
{
43+
switch(unit) {
44+
case Nanoseconds:
45+
return "nanoseconds";
46+
case Microseconds:
47+
return "microseconds";
48+
case Milliseconds:
49+
return "milliseconds";
50+
case Seconds:
51+
return "seconds";
52+
case Minutes:
53+
return "minutes";
54+
case Hours:
55+
return "hours";
56+
case Days:
57+
return "days";
58+
default:
59+
return "?s";
60+
}
61+
}
62+
63+
String Frequency::toString() const
64+
{
65+
auto freq = frequency;
66+
unsigned div = 0;
67+
while(freq % 1000 == 0) {
68+
freq /= 1000;
69+
++div;
70+
}
71+
String s(freq);
72+
if(div == 1) {
73+
s += 'K';
74+
} else if(div == 2) {
75+
s += 'M';
76+
} else if(div == 3) {
77+
s += 'G';
78+
}
79+
s += "Hz";
80+
return s;
81+
}
82+
83+
template <unsigned BufSize> class FormatBuffer
84+
{
85+
public:
86+
FormatBuffer()
87+
{
88+
buffer[0] = '\0';
89+
}
90+
91+
void add(unsigned value, unsigned digits)
92+
{
93+
pos += strlen(ultoa_wp(value, &buffer[pos], 10, digits, '0'));
94+
}
95+
96+
void add(char c)
97+
{
98+
buffer[pos++] = c;
99+
}
100+
101+
operator String() const
102+
{
103+
return String(buffer, pos);
104+
}
105+
106+
private:
107+
char buffer[BufSize];
108+
unsigned pos = 0;
109+
};
110+
111+
String TimeValue::toString() const
112+
{
113+
if(overflow) {
114+
return "(OVF)";
115+
}
116+
117+
FormatBuffer<64> buf;
118+
119+
if(days != 0) {
120+
buf.add(days, 0);
121+
buf.add('d');
122+
buf.add(' ');
123+
}
124+
125+
buf.add(hours, 2);
126+
buf.add(':');
127+
buf.add(minutes, 2);
128+
buf.add(':');
129+
buf.add(seconds, 2);
130+
131+
if(unit < NanoTime::Seconds) {
132+
buf.add('.');
133+
buf.add(milliseconds, 3);
134+
if(microseconds != 0 || nanoseconds != 0) {
135+
buf.add(microseconds, 3);
136+
if(nanoseconds != 0) {
137+
buf.add(nanoseconds, 3);
138+
}
139+
}
140+
}
141+
142+
return buf;
143+
}
144+
145+
} // namespace NanoTime

0 commit comments

Comments
 (0)