Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions cores/esp8266/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,6 @@ void analogWrite(uint8_t pin, int val);
void analogWriteFreq(uint32_t freq);
void analogWriteRange(uint32_t range);

unsigned long millis(void);
unsigned long micros(void);
uint64_t micros64(void);
void delay(unsigned long);
void delayMicroseconds(unsigned int us);
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout);

Expand Down
11 changes: 9 additions & 2 deletions cores/esp8266/Esp.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
#include <Arduino.h>
#include "spi_vendors.h"

// brings PolledTimeout at the same level as `millis()`
#include <PolledTimeout.h>
using namespace esp8266::polledTimeout;

/**
* AVR macros for WDT managment
*/
Expand Down Expand Up @@ -124,10 +128,13 @@ class EspClass {
#if defined(F_CPU) || defined(CORE_MOCK)
constexpr uint8_t getCpuFreqMHz() const
{
return clockCyclesPerMicrosecond();
return esp_get_cpu_freq_mhz();
}
#else
uint8_t getCpuFreqMHz();
uint8_t getCpuFreqMHz() const
{
return esp_get_cpu_freq_mhz();
}
#endif

uint32_t getFlashChipId();
Expand Down
47 changes: 30 additions & 17 deletions cores/esp8266/PolledTimeout.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

/*
PolledTimeout.h - Encapsulation of a polled Timeout

Copyright (c) 2018 Daniel Salazar. All rights reserved.
This file is part of the esp8266 core for Arduino environment.

Expand All @@ -23,9 +23,10 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <limits>

#include <Arduino.h>
#include <c_types.h> // IRAM_ATTR
#include <limits> // std::numeric_limits
#include <type_traits> // std::is_unsigned
#include <core_esp8266_features.h>

namespace esp8266
{
Expand Down Expand Up @@ -70,13 +71,13 @@ struct TimeSourceMillis

struct TimeSourceCycles
{
// time policy based on ESP.getCycleCount()
// time policy based on esp_get_cycle_count()
// this particular time measurement is intended to be called very often
// (every loop, every yield)

using timeType = decltype(ESP.getCycleCount());
static timeType time() {return ESP.getCycleCount();}
static constexpr timeType ticksPerSecond = ESP.getCpuFreqMHz() * 1000000UL; // 80'000'000 or 160'000'000 Hz
using timeType = decltype(esp_get_cycle_count());
static timeType time() {return esp_get_cycle_count();}
static constexpr timeType ticksPerSecond = esp_get_cpu_freq_mhz() * 1000000UL; // 80'000'000 or 160'000'000 Hz
static constexpr timeType ticksPerSecondMax = 160000000; // 160MHz
};

Expand Down Expand Up @@ -161,13 +162,13 @@ class timeoutTemplate
return expiredRetrigger();
return expiredOneShot();
}

IRAM_ATTR // fast
operator bool()
{
return expired();
return expired();
}

bool canExpire () const
{
return !_neverExpires;
Expand All @@ -192,6 +193,18 @@ class timeoutTemplate
_start = TimePolicyT::time();
}

void resetAndSetExpired (const timeType newUserTimeout)
{
reset(newUserTimeout);
_start -= _timeout;
}

void resetAndSetExpired ()
{
reset();
_start -= _timeout;
}

void resetToNeverExpires ()
{
_timeout = alwaysExpired + 1; // because canWait() has precedence
Expand All @@ -202,7 +215,7 @@ class timeoutTemplate
{
return TimePolicyT::toUserUnit(_timeout);
}

static constexpr timeType timeMax()
{
return TimePolicyT::timeMax;
Expand Down Expand Up @@ -235,14 +248,14 @@ class timeoutTemplate
}
return false;
}

IRAM_ATTR // fast
bool expiredOneShot() const
{
// returns "always expired" or "has expired"
return !canWait() || checkExpired(TimePolicyT::time());
}

timeType _timeout;
timeType _start;
bool _neverExpires;
Expand All @@ -259,14 +272,14 @@ using periodic = polledTimeout::timeoutTemplate<true> /*__attribute__((deprecate
using oneShotMs = polledTimeout::timeoutTemplate<false>;
using periodicMs = polledTimeout::timeoutTemplate<true>;

// Time policy based on ESP.getCycleCount(), and intended to be called very often:
// Time policy based on esp_get_cycle_count(), and intended to be called very often:
// "Fast" versions sacrifices time range for improved precision and reduced execution time (by 86%)
// (cpu cycles for ::expired(): 372 (millis()) vs 52 (ESP.getCycleCount()))
// (cpu cycles for ::expired(): 372 (millis()) vs 52 (esp_get_cycle_count()))
// timeMax() values:
// Ms: max is 26843 ms (26.8 s)
// Us: max is 26843545 us (26.8 s)
// Ns: max is 1073741823 ns ( 1.07 s)
// (time policy based on ESP.getCycleCount() is intended to be called very often)
// (time policy based on esp_get_cycle_count() is intended to be called very often)

using oneShotFastMs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastMillis>;
using periodicFastMs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastMillis>;
Expand Down
23 changes: 23 additions & 0 deletions cores/esp8266/core_esp8266_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,29 @@ extern "C" {
#endif

void precache(void *f, uint32_t bytes);
unsigned long millis(void);
unsigned long micros(void);
uint64_t micros64(void);
void delay(unsigned long);
void delayMicroseconds(unsigned int us);

#if defined(F_CPU) || defined(CORE_MOCK)
#ifdef __cplusplus
constexpr
#else
inline
#endif
int esp_get_cpu_freq_mhz()
{
return F_CPU / 1000000L;
}
#else
inline int esp_get_cpu_freq_mhz()
{
return system_get_cpu_freq();
}
#endif


#ifdef __cplusplus
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
*/


#include <PolledTimeout.h>

void ledOn() {
digitalWrite(LED_BUILTIN, LOW); // Turn the LED on (Note that LOW is the voltage level
}
Expand All @@ -38,29 +36,27 @@ void ledToggle() {
}


esp8266::polledTimeout::periodicFastUs halfPeriod(500000); //use fully qualified type and avoid importing all ::esp8266 namespace to the global namespace
periodicFastUs halfPeriod(500000);

// the setup function runs only once at start
void setup() {
Serial.begin(115200);

Serial.println();
Serial.printf("periodic/oneShotMs::timeMax() = %u ms\n", (uint32_t)esp8266::polledTimeout::periodicMs::timeMax());
Serial.printf("periodic/oneShotFastMs::timeMax() = %u ms\n", (uint32_t)esp8266::polledTimeout::periodicFastMs::timeMax());
Serial.printf("periodic/oneShotFastUs::timeMax() = %u us\n", (uint32_t)esp8266::polledTimeout::periodicFastUs::timeMax());
Serial.printf("periodic/oneShotFastNs::timeMax() = %u ns\n", (uint32_t)esp8266::polledTimeout::periodicFastNs::timeMax());
Serial.printf("periodic/oneShotMs::timeMax() = %u ms\n", (uint32_t)periodicMs::timeMax());
Serial.printf("periodic/oneShotFastMs::timeMax() = %u ms\n", (uint32_t)periodicFastMs::timeMax());
Serial.printf("periodic/oneShotFastUs::timeMax() = %u us\n", (uint32_t)periodicFastUs::timeMax());
Serial.printf("periodic/oneShotFastNs::timeMax() = %u ns\n", (uint32_t)periodicFastNs::timeMax());

#if 0 // 1 for debugging polledTimeout
Serial.printf("periodic/oneShotMs::rangeCompensate = %u\n", (uint32_t)esp8266::polledTimeout::periodicMs::rangeCompensate);
Serial.printf("periodic/oneShotFastMs::rangeCompensate = %u\n", (uint32_t)esp8266::polledTimeout::periodicFastMs::rangeCompensate);
Serial.printf("periodic/oneShotFastUs::rangeCompensate = %u\n", (uint32_t)esp8266::polledTimeout::periodicFastUs::rangeCompensate);
Serial.printf("periodic/oneShotFastNs::rangeCompensate = %u\n", (uint32_t)esp8266::polledTimeout::periodicFastNs::rangeCompensate);
Serial.printf("periodic/oneShotMs::rangeCompensate = %u\n", (uint32_t)periodicMs::rangeCompensate);
Serial.printf("periodic/oneShotFastMs::rangeCompensate = %u\n", (uint32_t)periodicFastMs::rangeCompensate);
Serial.printf("periodic/oneShotFastUs::rangeCompensate = %u\n", (uint32_t)periodicFastUs::rangeCompensate);
Serial.printf("periodic/oneShotFastNs::rangeCompensate = %u\n", (uint32_t)periodicFastNs::rangeCompensate);
#endif

pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output

using esp8266::polledTimeout::oneShotMs; //import the type to the local namespace

//STEP1; turn the led ON
ledOn();

Expand Down
7 changes: 6 additions & 1 deletion tests/host/common/MockEsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ uint32_t EspClass::getFlashChipSize(void)

String EspClass::getFullVersion ()
{
return "host-emulation";
return "emulation-on-host";
}

uint32_t EspClass::getFreeContStack()
Expand All @@ -216,6 +216,11 @@ void EspClass::resetFreeContStack()
}

uint32_t EspClass::getCycleCount()
{
return esp_get_cycle_count();
}

uint32_t esp_get_cycle_count()
{
timeval t;
gettimeofday(&t, NULL);
Expand Down
47 changes: 26 additions & 21 deletions tests/host/common/mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,29 @@

#define CORE_MOCK 1

//

#define ARDUINO 267
#define ESP8266 1
#define A0 0
#define LED_BUILTIN 0
#define F_CPU 80000000
#define LWIP_OPEN_SRC
#define TCP_MSS 536
#define LWIP_FEATURES 1

//

#define D0 0
#define D1 1
#define D2 3
#define D3 3
#define D4 4
#define D5 5
#define D6 6
#define D7 7
#define D8 8

// include host's STL before any other include file
// because core definition like max() is in the way

Expand Down Expand Up @@ -61,28 +84,10 @@ typedef uint32_t uint32;

//

#define ARDUINO 267
#define ESP8266 1
#define A0 0
#define LED_BUILTIN 0
#define F_CPU 80000000
#define LWIP_OPEN_SRC
#define TCP_MSS 536
#define LWIP_FEATURES 1

//

#define D0 0
#define D1 1
#define D2 3
#define D3 3
#define D4 4
#define D5 5
#define D6 6
#define D7 7
#define D8 8
#include <c_types.h>
#include <core_esp8266_features.h>

//
uint32_t esp_get_cycle_count();

#include <Arduino.h>

Expand Down