Skip to content

Commit dd8d3a0

Browse files
authored
Merge branch 'master' into split-iram
2 parents 2ff0fa5 + 77451d6 commit dd8d3a0

File tree

26 files changed

+389
-94
lines changed

26 files changed

+389
-94
lines changed

cores/esp8266/Esp.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,15 +200,20 @@ class EspClass {
200200

201201
bool eraseConfig();
202202

203-
inline uint32_t getCycleCount();
203+
#ifndef CORE_MOCK
204+
inline
205+
#endif
206+
uint32_t getCycleCount();
204207
};
205208

209+
#ifndef CORE_MOCK
206210
uint32_t EspClass::getCycleCount()
207211
{
208212
uint32_t ccount;
209213
__asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
210214
return ccount;
211215
}
216+
#endif
212217

213218
extern EspClass ESP;
214219

cores/esp8266/HardwareSerial.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ size_t HardwareSerial::readBytes(char* buffer, size_t size)
139139

140140
while (got < size)
141141
{
142-
esp8266::polledTimeout::oneShot timeOut(_timeout);
142+
esp8266::polledTimeout::oneShotFastMs timeOut(_timeout);
143143
size_t avail;
144144
while ((avail = available()) == 0 && !timeOut);
145145
if (avail == 0)

cores/esp8266/PolledTimeout.h

Lines changed: 173 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2424
*/
2525

26+
#include <limits>
27+
2628
#include <Arduino.h>
2729

2830
namespace esp8266
@@ -45,19 +47,112 @@ struct YieldOrSkip
4547
static void execute() {delay(0);}
4648
};
4749

50+
template <unsigned long delayMs>
51+
struct YieldAndDelayMs
52+
{
53+
static void execute() {delay(delayMs);}
54+
};
55+
4856
} //YieldPolicy
4957

58+
namespace TimePolicy
59+
{
60+
61+
struct TimeSourceMillis
62+
{
63+
// time policy in milli-seconds based on millis()
64+
65+
using timeType = decltype(millis());
66+
static timeType time() {return millis();}
67+
static constexpr timeType ticksPerSecond = 1000;
68+
static constexpr timeType ticksPerSecondMax = 1000;
69+
};
70+
71+
struct TimeSourceCycles
72+
{
73+
// time policy based on ESP.getCycleCount()
74+
// this particular time measurement is intended to be called very often
75+
// (every loop, every yield)
76+
77+
using timeType = decltype(ESP.getCycleCount());
78+
static timeType time() {return ESP.getCycleCount();}
79+
static constexpr timeType ticksPerSecond = F_CPU; // 80'000'000 or 160'000'000 Hz
80+
static constexpr timeType ticksPerSecondMax = 160000000; // 160MHz
81+
};
82+
83+
template <typename TimeSourceType, unsigned long long second_th>
84+
// "second_th" units of timeType for one second
85+
struct TimeUnit
86+
{
87+
using timeType = typename TimeSourceType::timeType;
88+
89+
#if __GNUC__ < 5
90+
// gcc-4.8 cannot compile the constexpr-only version of this function
91+
// using #defines instead luckily works
92+
static constexpr timeType computeRangeCompensation ()
93+
{
94+
#define number_of_secondTh_in_one_tick ((1.0 * second_th) / ticksPerSecond)
95+
#define fractional (number_of_secondTh_in_one_tick - (long)number_of_secondTh_in_one_tick)
96+
97+
return ({
98+
fractional == 0?
99+
1: // no need for compensation
100+
(number_of_secondTh_in_one_tick / fractional) + 0.5; // scalar multiplier allowing exact division
101+
});
50102

51-
template <bool PeriodicT, typename YieldPolicyT = YieldPolicy::DoNothing>
103+
#undef number_of_secondTh_in_one_tick
104+
#undef fractional
105+
}
106+
#else
107+
static constexpr timeType computeRangeCompensation ()
108+
{
109+
return ({
110+
constexpr double number_of_secondTh_in_one_tick = (1.0 * second_th) / ticksPerSecond;
111+
constexpr double fractional = number_of_secondTh_in_one_tick - (long)number_of_secondTh_in_one_tick;
112+
fractional == 0?
113+
1: // no need for compensation
114+
(number_of_secondTh_in_one_tick / fractional) + 0.5; // scalar multiplier allowing exact division
115+
});
116+
}
117+
#endif
118+
119+
static constexpr timeType ticksPerSecond = TimeSourceType::ticksPerSecond;
120+
static constexpr timeType ticksPerSecondMax = TimeSourceType::ticksPerSecondMax;
121+
static constexpr timeType rangeCompensate = computeRangeCompensation();
122+
static constexpr timeType user2UnitMultiplierMax = (ticksPerSecondMax * rangeCompensate) / second_th;
123+
static constexpr timeType user2UnitMultiplier = (ticksPerSecond * rangeCompensate) / second_th;
124+
static constexpr timeType user2UnitDivider = rangeCompensate;
125+
// std::numeric_limits<timeType>::max() is reserved
126+
static constexpr timeType timeMax = (std::numeric_limits<timeType>::max() - 1) / user2UnitMultiplierMax;
127+
128+
static timeType toTimeTypeUnit (const timeType userUnit) {return (userUnit * user2UnitMultiplier) / user2UnitDivider;}
129+
static timeType toUserUnit (const timeType internalUnit) {return (internalUnit * user2UnitDivider) / user2UnitMultiplier;}
130+
static timeType time () {return TimeSourceType::time();}
131+
};
132+
133+
using TimeMillis = TimeUnit< TimeSourceMillis, 1000 >;
134+
using TimeFastMillis = TimeUnit< TimeSourceCycles, 1000 >;
135+
using TimeFastMicros = TimeUnit< TimeSourceCycles, 1000000 >;
136+
using TimeFastNanos = TimeUnit< TimeSourceCycles, 1000000000 >;
137+
138+
} //TimePolicy
139+
140+
template <bool PeriodicT, typename YieldPolicyT = YieldPolicy::DoNothing, typename TimePolicyT = TimePolicy::TimeMillis>
52141
class timeoutTemplate
53142
{
54143
public:
55-
using timeType = decltype(millis());
56-
57-
timeoutTemplate(timeType timeout)
58-
: _timeout(timeout), _start(millis())
59-
{}
144+
using timeType = typename TimePolicyT::timeType;
145+
146+
static constexpr timeType alwaysExpired = 0;
147+
static constexpr timeType neverExpires = std::numeric_limits<timeType>::max();
148+
static constexpr timeType rangeCompensate = TimePolicyT::rangeCompensate; //debug
149+
150+
timeoutTemplate(const timeType userTimeout)
151+
{
152+
reset(userTimeout);
153+
}
60154

155+
ICACHE_RAM_ATTR
61156
bool expired()
62157
{
63158
YieldPolicyT::execute(); //in case of DoNothing: gets optimized away
@@ -66,37 +161,69 @@ class timeoutTemplate
66161
return expiredOneShot();
67162
}
68163

164+
ICACHE_RAM_ATTR
69165
operator bool()
70166
{
71167
return expired();
72168
}
73169

74-
void reset(const timeType newTimeout)
170+
bool canExpire () const
171+
{
172+
return !_neverExpires;
173+
}
174+
175+
bool canWait () const
176+
{
177+
return _timeout != alwaysExpired;
178+
}
179+
180+
void reset(const timeType newUserTimeout)
75181
{
76-
_timeout = newTimeout;
77182
reset();
183+
_timeout = TimePolicyT::toTimeTypeUnit(newUserTimeout);
184+
_neverExpires = (newUserTimeout < 0) || (newUserTimeout > timeMax());
78185
}
79186

80187
void reset()
81188
{
82-
_start = millis();
189+
_start = TimePolicyT::time();
190+
}
191+
192+
void resetToNeverExpires ()
193+
{
194+
_timeout = alwaysExpired + 1; // because canWait() has precedence
195+
_neverExpires = true;
83196
}
84197

85198
timeType getTimeout() const
86199
{
87-
return _timeout;
200+
return TimePolicyT::toUserUnit(_timeout);
88201
}
89202

90-
bool checkExpired(const timeType t) const
203+
static constexpr timeType timeMax()
91204
{
92-
return (t - _start) >= _timeout;
205+
return TimePolicyT::timeMax;
93206
}
94-
207+
208+
private:
209+
210+
ICACHE_RAM_ATTR
211+
bool checkExpired(const timeType internalUnit) const
212+
{
213+
// canWait() is not checked here
214+
// returns "can expire" and "time expired"
215+
return (!_neverExpires) && ((internalUnit - _start) >= _timeout);
216+
}
217+
95218
protected:
96-
219+
220+
ICACHE_RAM_ATTR
97221
bool expiredRetrigger()
98222
{
99-
timeType current = millis();
223+
if (!canWait())
224+
return true;
225+
226+
timeType current = TimePolicyT::time();
100227
if(checkExpired(current))
101228
{
102229
unsigned long n = (current - _start) / _timeout; //how many _timeouts periods have elapsed, will usually be 1 (current - _start >= _timeout)
@@ -106,23 +233,50 @@ class timeoutTemplate
106233
return false;
107234
}
108235

236+
ICACHE_RAM_ATTR
109237
bool expiredOneShot() const
110238
{
111-
return checkExpired(millis());
239+
// returns "always expired" or "has expired"
240+
return !canWait() || checkExpired(TimePolicyT::time());
112241
}
113242

114243
timeType _timeout;
115244
timeType _start;
245+
bool _neverExpires;
116246
};
117247

118-
using oneShot = polledTimeout::timeoutTemplate<false>;
119-
using periodic = polledTimeout::timeoutTemplate<true>;
248+
// legacy type names, deprecated (unit is milliseconds)
249+
250+
using oneShot = polledTimeout::timeoutTemplate<false> /*__attribute__((deprecated("use oneShotMs")))*/;
251+
using periodic = polledTimeout::timeoutTemplate<true> /*__attribute__((deprecated("use periodicMs")))*/;
252+
253+
// standard versions (based on millis())
254+
// timeMax() is 49.7 days ((2^32)-2 ms)
255+
256+
using oneShotMs = polledTimeout::timeoutTemplate<false>;
257+
using periodicMs = polledTimeout::timeoutTemplate<true>;
258+
259+
// Time policy based on ESP.getCycleCount(), and intended to be called very often:
260+
// "Fast" versions sacrifices time range for improved precision and reduced execution time (by 86%)
261+
// (cpu cycles for ::expired(): 372 (millis()) vs 52 (ESP.getCycleCount()))
262+
// timeMax() values:
263+
// Ms: max is 26843 ms (26.8 s)
264+
// Us: max is 26843545 us (26.8 s)
265+
// Ns: max is 1073741823 ns ( 1.07 s)
266+
// (time policy based on ESP.getCycleCount() is intended to be called very often)
267+
268+
using oneShotFastMs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastMillis>;
269+
using periodicFastMs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastMillis>;
270+
using oneShotFastUs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastMicros>;
271+
using periodicFastUs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastMicros>;
272+
using oneShotFastNs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastNanos>;
273+
using periodicFastNs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastNanos>;
120274

121275
} //polledTimeout
122276

123277

124278
/* A 1-shot timeout that auto-yields when in CONT can be built as follows:
125-
* using oneShotYield = esp8266::polledTimeout::timeoutTemplate<false, esp8266::polledTimeout::YieldPolicy::YieldOrSkip>;
279+
* using oneShotYieldMs = esp8266::polledTimeout::timeoutTemplate<false, esp8266::polledTimeout::YieldPolicy::YieldOrSkip>;
126280
*
127281
* Other policies can be implemented by the user, e.g.: simple yield that panics in SYS, and the polledTimeout types built as needed as shown above, without modifying this file.
128282
*/

libraries/ESP8266WiFi/examples/IPv6/IPv6.ino

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
WiFiServer statusServer(TCP_PORT);
3737
WiFiUDP udp;
38-
esp8266::polledTimeout::periodic statusPeriod(STATUSDELAY_MS);
38+
esp8266::polledTimeout::periodicMs showStatusOnSerialNow(STATUSDELAY_MS);
3939

4040
void fqdn(Print& out, const String& fqdn) {
4141
out.print(F("resolving "));
@@ -149,7 +149,7 @@ void setup() {
149149
Serial.print(F(" - UDP server on port "));
150150
Serial.println(UDP_PORT);
151151

152-
statusPeriod.reset();
152+
showStatusOnSerialNow.reset();
153153
}
154154

155155
unsigned long statusTimeMs = 0;
@@ -182,7 +182,7 @@ void loop() {
182182
}
183183

184184

185-
if (statusPeriod) {
185+
if (showStatusOnSerialNow) {
186186
status(Serial);
187187
}
188188

libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ static bool sta_config_equal(const station_config& lhs, const station_config& rh
6363
* @return equal
6464
*/
6565
static bool sta_config_equal(const station_config& lhs, const station_config& rhs) {
66+
67+
#ifdef NONOSDK3V0
68+
static_assert(sizeof(station_config) == 116, "struct station_config has changed, please update comparison function");
69+
#else
70+
static_assert(sizeof(station_config) == 112, "struct station_config has changed, please update comparison function");
71+
#endif
72+
6673
if(strncmp(reinterpret_cast<const char*>(lhs.ssid), reinterpret_cast<const char*>(rhs.ssid), sizeof(lhs.ssid)) != 0) {
6774
return false;
6875
}
@@ -81,6 +88,20 @@ static bool sta_config_equal(const station_config& lhs, const station_config& rh
8188
return false;
8289
}
8390
}
91+
92+
if(lhs.threshold.rssi != rhs.threshold.rssi) {
93+
return false;
94+
}
95+
96+
if(lhs.threshold.authmode != rhs.threshold.authmode) {
97+
return false;
98+
}
99+
100+
#ifdef NONOSDK3V0
101+
if (lhs.open_and_wep_mode_disable != rhs.open_and_wep_mode_disable) {
102+
return false;
103+
}
104+
#endif
84105

85106
return true;
86107
}

libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ void loop(void) {
268268
// Allow MDNS processing
269269
MDNS.update();
270270

271-
static esp8266::polledTimeout::periodic timeout(UPDATE_CYCLE);
271+
static esp8266::polledTimeout::periodicMs timeout(UPDATE_CYCLE);
272272
if (timeout.expired()) {
273273

274274
if (hMDNSService) {

0 commit comments

Comments
 (0)