Skip to content

#7832

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
4 changes: 2 additions & 2 deletions cores/esp8266/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ void setup(void);
void loop(void);

void yield(void);

void optimistic_yield(uint32_t interval_us);
void minimal_yield();
void optimistic_yield(uint32_t interval_us); // parameter ignored, is minimal_yield()

#define _PORT_GPIO16 1
#define digitalPinToPort(pin) (((pin)==16)?(_PORT_GPIO16):(0))
Expand Down
8 changes: 3 additions & 5 deletions cores/esp8266/Esp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,20 +115,18 @@ void EspClass::wdtFeed(void)
system_soft_wdt_feed();
}

extern "C" void esp_yield();

void EspClass::deepSleep(uint64_t time_us, WakeMode mode)
{
system_deep_sleep_set_option(static_cast<int>(mode));
system_deep_sleep(time_us);
esp_yield();
esp_suspend_from_cont();
}

void EspClass::deepSleepInstant(uint64_t time_us, WakeMode mode)
{
system_deep_sleep_set_option(static_cast<int>(mode));
system_deep_sleep_instant(time_us);
esp_yield();
esp_suspend_from_cont();
}

//this calculation was taken verbatim from the SDK api reference for SDK 2.1.0.
Expand Down Expand Up @@ -200,7 +198,7 @@ void EspClass::reset(void)
void EspClass::restart(void)
{
system_restart();
esp_yield();
esp_suspend_from_cont();
}

[[noreturn]] void EspClass::rebootIntoUartDownloadMode()
Expand Down
2 changes: 1 addition & 1 deletion cores/esp8266/HardwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ int HardwareSerial::available(void)
{
int result = static_cast<int>(uart_rx_available(_uart));
if (!result) {
optimistic_yield(10000);
minimal_yield();
}
return result;
}
Expand Down
4 changes: 2 additions & 2 deletions cores/esp8266/Schedule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ void run_scheduled_functions()
{
// because scheduled functions might last too long for watchdog etc,
// this is yield() in cont stack:
esp_schedule();
esp_request_for_cont();
cont_yield(g_pcont);
}
}
Expand Down Expand Up @@ -242,7 +242,7 @@ void run_scheduled_recurrent_functions()
{
// because scheduled functions might last too long for watchdog etc,
// this is yield() in cont stack:
esp_schedule();
esp_request_for_cont();
cont_yield(g_pcont);
}
} while (current && !done);
Expand Down
6 changes: 3 additions & 3 deletions cores/esp8266/StreamSend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ size_t Stream::SendGenericPeekBuffer(Print* to, const ssize_t len, const int rea
break;
}

optimistic_yield(1000);
minimal_yield();
}

if (getLastSendReport() == Report::Success && maxLen > 0)
Expand Down Expand Up @@ -215,7 +215,7 @@ size_t Stream::SendGenericRegularUntil(Print* to, const ssize_t len, const int r
break;
}

optimistic_yield(1000);
minimal_yield();
}

if (getLastSendReport() == Report::Success && maxLen > 0)
Expand Down Expand Up @@ -308,7 +308,7 @@ size_t Stream::SendGenericRegular(Print* to, const ssize_t len, const esp8266::p
break;
}

optimistic_yield(1000);
minimal_yield();
}

if (getLastSendReport() == Report::Success && maxLen > 0)
Expand Down
2 changes: 1 addition & 1 deletion cores/esp8266/cont.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ int cont_get_free_stack(cont_t* cont);

// Check if yield() may be called. Returns true if we are running inside
// continuation stack
bool cont_can_yield(cont_t* cont);
bool __esp_is_in_cont(cont_t* cont);

// Repaint the stack from the current SP to the end, to allow individual
// routines' stack usages to be calculated by re-painting, checking current
Expand Down
2 changes: 1 addition & 1 deletion cores/esp8266/cont_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ int cont_get_free_stack(cont_t* cont) {
return freeWords * 4;
}

bool IRAM_ATTR cont_can_yield(cont_t* cont) {
bool IRAM_ATTR __esp_is_in_cont(cont_t* cont) {
return !ETS_INTR_WITHINISR() &&
cont->pc_ret != 0 && cont->pc_yield == 0;
}
Expand Down
6 changes: 3 additions & 3 deletions cores/esp8266/core_esp8266_i2s.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ static bool _i2s_write_sample(uint32_t sample, bool nb) {
if (tx->slc_queue_len > 0) {
break;
} else {
optimistic_yield(10000);
minimal_yield();
}
}
}
Expand Down Expand Up @@ -362,7 +362,7 @@ static uint16_t _i2s_write_buffer(const int16_t *frames, uint16_t frame_count, b
if (tx->slc_queue_len > 0) {
break;
} else {
optimistic_yield(10000);
minimal_yield();
}
}
}
Expand Down Expand Up @@ -422,7 +422,7 @@ bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking) {
if (rx->slc_queue_len > 0){
break;
} else {
optimistic_yield(10000);
minimal_yield();
}
}
}
Expand Down
57 changes: 38 additions & 19 deletions cores/esp8266/core_esp8266_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ extern "C" {
#include <core_esp8266_non32xfer.h>
#include "core_esp8266_vm.h"

/*
iaμs = 1000000 / (bwMiBitsps / 8 * 1024 * 1024 / packet-size-bytes)
=> 1114 μs, 1460 bytes, 10Mibits/s
*/
constexpr auto DelayBetweenRealYield_usec = 1000;

#define LOOP_TASK_PRIORITY 1
#define LOOP_QUEUE_SIZE 1

Expand Down Expand Up @@ -105,55 +111,64 @@ extern "C" void __preloop_update_frequency() {

extern "C" void preloop_update_frequency() __attribute__((weak, alias("__preloop_update_frequency")));

extern "C" bool can_yield() {
return cont_can_yield(g_pcont);
extern "C" bool esp_is_in_cont() {
return __esp_is_in_cont(g_pcont);
}

static inline void esp_yield_within_cont() __attribute__((always_inline));
static void esp_yield_within_cont() {
static inline void esp_suspend_from_cont_within_cont() __attribute__((always_inline));
static void esp_suspend_from_cont_within_cont() {
cont_yield(g_pcont);
s_cycles_at_yield_start = ESP.getCycleCount();
run_scheduled_recurrent_functions();
}

extern "C" void __esp_yield() {
if (can_yield()) {
esp_yield_within_cont();
extern "C" void esp_suspend_from_cont() {
if (esp_is_in_cont()) {
esp_suspend_from_cont_within_cont();
}
}

extern "C" void esp_yield() __attribute__ ((weak, alias("__esp_yield")));

extern "C" IRAM_ATTR void esp_schedule() {
extern "C" IRAM_ATTR void esp_request_for_cont() {
ets_post(LOOP_TASK_PRIORITY, 0, 0);
}

extern "C" void __yield() {
if (can_yield()) {
esp_schedule();
esp_yield_within_cont();
if (esp_is_in_cont()) {
esp_request_for_cont();
esp_suspend_from_cont_within_cont();
}
#ifdef DEBUG_ESP_PORT
else {
panic();
DEBUGV("yield() should not be called from SYS ctx\n");
}
#endif
}

extern "C" void yield(void) __attribute__ ((weak, alias("__yield")));

extern "C" void optimistic_yield(uint32_t interval_us) {
extern "C" void __optimistic_yield(uint32_t interval_us) {
const uint32_t intvl_cycles = interval_us *
#if defined(F_CPU)
clockCyclesPerMicrosecond();
#else
ESP.getCpuFreqMHz();
#endif
if ((ESP.getCycleCount() - s_cycles_at_yield_start) > intvl_cycles &&
can_yield())
esp_is_in_cont())
{
yield();
__yield();
}
}

extern "C" void minimal_yield() {
__optimistic_yield(DelayBetweenRealYield_usec);
}

extern "C" void optimistic_yield(uint32_t interval_us) {
(void)interval_us;
__optimistic_yield(DelayBetweenRealYield_usec);
}

// Replace ets_intr_(un)lock with nestable versions
extern "C" void IRAM_ATTR ets_intr_lock() {
if (ets_intr_lock_stack_ptr < ETS_INTR_LOCK_NEST_MAX)
Expand All @@ -162,6 +177,10 @@ extern "C" void IRAM_ATTR ets_intr_lock() {
xt_rsil(3);
}

extern "C" void esp_yield() __attribute__ ((alias("esp_suspend_from_cont")));
extern "C" void esp_schedule() __attribute__ ((alias("esp_request_for_cont")));
extern "C" bool can_yield() __attribute__ ((alias("esp_is_in_cont")));

extern "C" void IRAM_ATTR ets_intr_unlock() {
if (ets_intr_lock_stack_ptr > 0)
xt_wsr_ps(ets_intr_lock_stack[--ets_intr_lock_stack_ptr]);
Expand Down Expand Up @@ -202,7 +221,7 @@ static void loop_wrapper() {
if (serialEventRun) {
serialEventRun();
}
esp_schedule();
esp_request_for_cont();
}

static void loop_task(os_event_t *events) {
Expand Down Expand Up @@ -261,7 +280,7 @@ void init_done() {
gdb_init();
std::set_terminate(__unhandled_exception_cpp);
do_global_ctors();
esp_schedule();
esp_request_for_cont();
ESP.setDramHeap();
}

Expand Down
9 changes: 4 additions & 5 deletions cores/esp8266/core_esp8266_wiring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@
#include "osapi.h"
#include "user_interface.h"
#include "cont.h"
#include "coredecls.h"

extern "C" {

extern void ets_delay_us(uint32_t us);
extern void esp_schedule();
extern void esp_yield();

static os_timer_t delay_timer;
static os_timer_t micros_overflow_timer;
Expand All @@ -40,17 +39,17 @@ static uint32_t micros_overflow_count = 0;

void delay_end(void* arg) {
(void) arg;
esp_schedule();
esp_request_for_cont();
}

void __delay(unsigned long ms) {
if(ms) {
os_timer_setfn(&delay_timer, (os_timer_func_t*) &delay_end, 0);
os_timer_arm(&delay_timer, ms, ONCE);
} else {
esp_schedule();
esp_request_for_cont();
}
esp_yield();
esp_suspend_from_cont();
if(ms) {
os_timer_disarm(&delay_timer);
}
Expand Down
2 changes: 1 addition & 1 deletion cores/esp8266/core_esp8266_wiring_pulse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ extern uint32_t xthal_get_ccount();
if (xthal_get_ccount() - start_cycle_count > timeout_cycles) { \
return 0; \
} \
optimistic_yield(5000); \
minimal_yield(); \
}

// max timeout is 27 seconds at 160MHz clock and 54 seconds at 80MHz clock
Expand Down
11 changes: 8 additions & 3 deletions cores/esp8266/coredecls.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ extern "C" {
#include <stdint.h>
#include <cont.h> // g_pcont declaration

bool can_yield();
void esp_yield();
void esp_schedule();
bool esp_is_in_cont();
void esp_suspend_from_cont();
void esp_request_for_cont();

void esp_yield() __attribute__ ((deprecated("use esp_suspend_from_cont()")));
void esp_schedule() __attribute__ ((deprecated("use esp_request_for_cont()")));
bool can_yield() __attribute__ ((deprecated("esp_is_in_cont()")));

void tune_timeshift64 (uint64_t now_us);
void disable_extra4k_at_link_time (void) __attribute__((noinline));
bool sntp_set_timezone_in_seconds(int32_t timezone);
Expand Down
6 changes: 3 additions & 3 deletions cores/esp8266/flash_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ extern "C" {
}

int32_t flash_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) {
optimistic_yield(10000);
minimal_yield();

// We use flashRead overload that handles proper alignment
if (ESP.flashRead(addr, dst, size)) {
Expand All @@ -41,7 +41,7 @@ int32_t flash_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) {
}

int32_t flash_hal_write(uint32_t addr, uint32_t size, const uint8_t *src) {
optimistic_yield(10000);
minimal_yield();

// We use flashWrite overload that handles proper alignment
if (ESP.flashWrite(addr, src, size)) {
Expand All @@ -60,7 +60,7 @@ int32_t flash_hal_erase(uint32_t addr, uint32_t size) {
const uint32_t sector = addr / SPI_FLASH_SEC_SIZE;
const uint32_t sectorCount = size / SPI_FLASH_SEC_SIZE;
for (uint32_t i = 0; i < sectorCount; ++i) {
optimistic_yield(10000);
minimal_yield();
if (!ESP.flashEraseSector(sector + i)) {
DEBUGV("_spif_erase addr=%x size=%d i=%d\r\n", addr, size, i);
return FLASH_HAL_ERASE_ERROR;
Expand Down
2 changes: 1 addition & 1 deletion cores/esp8266/uart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ uart_write(uart_t* uart, const char* buf, size_t size)
const int uart_nr = uart->uart_nr;
while (size--) {
uart_do_write_char(uart_nr, pgm_read_byte(buf++));
optimistic_yield(10000UL);
minimal_yield();
}

return ret;
Expand Down
8 changes: 3 additions & 5 deletions libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ extern "C" {
#include "WiFiUdp.h"
#include "debug.h"
#include "include/WiFiState.h"

extern "C" void esp_schedule();
extern "C" void esp_yield();
#include <coredecls.h>


// -----------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -448,7 +446,7 @@ bool ESP8266WiFiGenericClass::mode(WiFiMode_t m, WiFiState* state) {
//Only wait if in CONT context. If this were called from SYS, it's up to the user to serialize
//tasks to wait correctly.
constexpr unsigned int timeoutValue = 1000; //1 second
if(can_yield()) {
if(esp_is_in_cont()) {
using oneShot = esp8266::polledTimeout::oneShotFastMs;
oneShot timeout(timeoutValue);
while(wifi_get_opmode() != (uint8) m && !timeout)
Expand Down Expand Up @@ -716,7 +714,7 @@ void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *ca
if(ipaddr) {
(*reinterpret_cast<IPAddress*>(callback_arg)) = IPAddress(ipaddr);
}
esp_schedule(); // break delay in hostByName
esp_request_for_cont(); // interrupt delay in hostByName
}

uint32_t ESP8266WiFiGenericClass::shutdownCRC (const WiFiState* state)
Expand Down
Loading