1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

[BREAKING] Disable WiFi at boot by default (#7902)

* Disable WiFi at boot by default

* +define WIFI_IS_OFF_AT_BOOT

* remove now useless example

* mv enableWiFiAtBootTime() to core_esp8266_features.h

* sync with master

* per @earlephilhower review: a file was missing

* doc

* WiFi persistence is now false by default

* fix doc

* ditto

* doc: remove sphinx warnings (fix links and formatting)

* fix link name

* fix doc

* legacy: restore persistence

* undeprecate preinit()

* move force modem up to when mode has changed (per @mcspr review)

* do not wake up from sleep when mode if OFF

* fix doc per review
This commit is contained in:
david gauchard 2021-04-09 23:01:11 +02:00 committed by GitHub
parent da6ec83b5f
commit 1cc6960a55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 107 additions and 142 deletions

View File

@ -31,6 +31,7 @@
#define CORE_HAS_UMM #define CORE_HAS_UMM
#define WIFI_HAS_EVENT_CALLBACK #define WIFI_HAS_EVENT_CALLBACK
#define WIFI_IS_OFF_AT_BOOT
#include <stdlib.h> // malloc() #include <stdlib.h> // malloc()
#include <stddef.h> // size_t #include <stddef.h> // size_t
@ -104,6 +105,8 @@ uint64_t micros64(void);
void delay(unsigned long); void delay(unsigned long);
void delayMicroseconds(unsigned int us); void delayMicroseconds(unsigned int us);
void enableWiFiAtBootTime (void) __attribute__((noinline));
#if defined(F_CPU) || defined(CORE_MOCK) #if defined(F_CPU) || defined(CORE_MOCK)
#ifdef __cplusplus #ifdef __cplusplus
constexpr constexpr

View File

@ -332,7 +332,18 @@ extern "C" void app_entry (void)
extern "C" void preinit (void) __attribute__((weak)); extern "C" void preinit (void) __attribute__((weak));
extern "C" void preinit (void) extern "C" void preinit (void)
{ {
/* do nothing by default */ /* does nothing, kept for backward compatibility */
}
extern "C" void __disableWiFiAtBootTime (void) __attribute__((weak));
extern "C" void __disableWiFiAtBootTime (void)
{
// Starting from arduino core v3: wifi is disabled at boot time
// WiFi.begin() or WiFi.softAP() will wake WiFi up
wifi_set_opmode_current(0/*WIFI_OFF*/);
wifi_fpm_set_sleep_type(MODEM_SLEEP_T);
wifi_fpm_open();
wifi_fpm_do_sleep(0xFFFFFFF);
} }
extern "C" void user_init(void) { extern "C" void user_init(void) {
@ -365,6 +376,7 @@ extern "C" void user_init(void) {
umm_init_iram(); umm_init_iram();
#endif #endif
preinit(); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable. preinit(); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable.
__disableWiFiAtBootTime(); // default weak function disables WiFi
ets_task(loop_task, ets_task(loop_task,
LOOP_TASK_PRIORITY, s_loop_queue, LOOP_TASK_PRIORITY, s_loop_queue,

View File

@ -18,6 +18,7 @@ void esp_schedule();
void tune_timeshift64 (uint64_t now_us); void tune_timeshift64 (uint64_t now_us);
void disable_extra4k_at_link_time (void) __attribute__((noinline)); void disable_extra4k_at_link_time (void) __attribute__((noinline));
bool sntp_set_timezone_in_seconds(int32_t timezone); bool sntp_set_timezone_in_seconds(int32_t timezone);
void __disableWiFiAtBootTime (void) __attribute__((noinline));
void __real_system_restart_local() __attribute__((noreturn)); void __real_system_restart_local() __attribute__((noreturn));
uint32_t sqrt32 (uint32_t n); uint32_t sqrt32 (uint32_t n);
@ -34,6 +35,6 @@ using TrivialCB = std::function<void()>;
void settimeofday_cb (const BoolCB& cb); void settimeofday_cb (const BoolCB& cb);
void settimeofday_cb (const TrivialCB& cb); void settimeofday_cb (const TrivialCB& cb);
#endif #endif // __cplusplus
#endif // __COREDECLS_H #endif // __COREDECLS_H

View File

@ -42,6 +42,33 @@ persistent
WiFi.persistent(persistent) WiFi.persistent(persistent)
Starting from version 3 of this core, **persistence is disabled by default
and WiFi does not start automatically at boot** (see PR `#7902 <https://github.com/esp8266/Arduino/pull/7902>`__).
Previously, SDK was automatically starting WiFi at boot. This was probably
intended for the Espressif AT FW which is interactive and preserves WiFi
state accross reboots. This behavior is generally irrelevant with the
Arduino API because sketches start with ``WiFi.begin()`` or
``WiFi.softAP()``.
This change is harmless with standard sketches: Calls to ``WiFi.mode()`` do
enable radio as usual. It also smooths current spikes at boot and decreases
DHCP stress.
Legacy behavior can be restored by calling ``enableWiFiAtBootTime()`` from
anywhere in the code (it is a weak void function intended to play with the
linker).
.. code:: cpp
void setup () {
#ifdef WIFI_IS_OFF_AT_BOOT
enableWiFiAtBootTime(); // can be called from anywhere with the same effect
#endif
....
}
When legacy behavior is restored thanks to this call,
ESP8266 is able to reconnect to the last used WiFi network or establishes the same Access Point upon power up or reset. ESP8266 is able to reconnect to the last used WiFi network or establishes the same Access Point upon power up or reset.
By default, these settings are written to specific sectors of flash memory every time they are changed in ``WiFi.begin(ssid, passphrase)`` or ``WiFi.softAP(ssid, passphrase, channel)``, and when ``WiFi.disconnect`` or ``WiFi.softAPdisconnect`` is invoked. By default, these settings are written to specific sectors of flash memory every time they are changed in ``WiFi.begin(ssid, passphrase)`` or ``WiFi.softAP(ssid, passphrase, channel)``, and when ``WiFi.disconnect`` or ``WiFi.softAPdisconnect`` is invoked.
Frequently calling these functions could cause wear on the flash memory (see issue `#1054 <https://github.com/esp8266/Arduino/issues/1054>`__). Frequently calling these functions could cause wear on the flash memory (see issue `#1054 <https://github.com/esp8266/Arduino/issues/1054>`__).

View File

@ -164,6 +164,7 @@ WiFi Multi
Example: Example:
.. code:: cpp .. code:: cpp
#include <ESP8266WiFiMulti.h> #include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti wifiMulti; ESP8266WiFiMulti wifiMulti;

View File

@ -41,9 +41,8 @@ following three things right: 1. Module is provided with enough power,
2. GPIO0, GPIO15 and CH\_PD are connected using pull up / pull down 2. GPIO0, GPIO15 and CH\_PD are connected using pull up / pull down
resistors, 3. Module is put into boot loader mode. resistors, 3. Module is put into boot loader mode.
For specific details please refer to section on `Generic ESP8266 For specific details please refer to section on `Generic ESP8266 module <../boards.rst#generic-esp8266-module>`__.
modules <../boards.rst#generic-esp8266-modules>`__. Example modules Example modules without USB to serial converter on board are shown below.
without USB to serial converter on board are shown below.
.. figure:: pictures/a01-example-boards-without-usb.png .. figure:: pictures/a01-example-boards-without-usb.png
:alt: Example ESP8266 modules without USB to serial converter :alt: Example ESP8266 modules without USB to serial converter

View File

@ -48,7 +48,7 @@ follows:
Error compiling for board Generic ESP8266 Module. Error compiling for board Generic ESP8266 Module.
Below is an example messages for Below is an example messages for
`WeMos <../boards.rst#wemos-d1-r2-mini>`__: `WeMos <../boards.rst#lolin-wemos-d1-r2-mini>`__:
:: ::

View File

@ -177,3 +177,12 @@ will need to implement an additional (short) deep sleep using
``WAKE_RF_DEFAULT``. ``WAKE_RF_DEFAULT``.
Ref. `#3072 <https://github.com/esp8266/Arduino/issues/3072>`__ Ref. `#3072 <https://github.com/esp8266/Arduino/issues/3072>`__
My WiFi was previously automatically connected right after booting, but isn't anymore
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This was WiFi persistence. Starting from version 3 of this core, WiFi is
indeed off at boot and is powered on only when starting to be used with the
regular API.
Read more at `former WiFi persistent mode <../esp8266wifi/generic-class.rst#persistent>`__.

View File

@ -474,8 +474,8 @@ Performs the same operation as ``info`` but allows for reporting greater than
4GB for filesystem size/used/etc. Should be used with the SD and SDFS 4GB for filesystem size/used/etc. Should be used with the SD and SDFS
filesystems since most SD cards today are greater than 4GB in size. filesystems since most SD cards today are greater than 4GB in size.
setTimeCallback(time_t (*cb)(void)) setTimeCallback(time_t (\*cb)(void))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: cpp .. code:: cpp
@ -574,8 +574,8 @@ rewind
Resets the internal pointer to the start of the directory. Resets the internal pointer to the start of the directory.
setTimeCallback(time_t (*cb)(void)) setTimeCallback(time_t (\*cb)(void))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets the time callback for any files accessed from this Dir object via openNextFile. Sets the time callback for any files accessed from this Dir object via openNextFile.
Note that the SD and SDFS filesystems only support a filesystem-wide callback and Note that the SD and SDFS filesystems only support a filesystem-wide callback and
@ -693,7 +693,7 @@ Close the file. No other operations should be performed on *File* object
after ``close`` function was called. after ``close`` function was called.
openNextFile (compatibiity method, not recommended for new code) openNextFile (compatibiity method, not recommended for new code)
~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: cpp .. code:: cpp
@ -705,7 +705,7 @@ Opens the next file in the directory pointed to by the File. Only valid
when ``File.isDirectory() == true``. when ``File.isDirectory() == true``.
rewindDirectory (compatibiity method, not recommended for new code) rewindDirectory (compatibiity method, not recommended for new code)
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: cpp .. code:: cpp
@ -718,8 +718,8 @@ rewindDirectory (compatibiity method, not recommended for new code)
Resets the ``openNextFile`` pointer to the top of the directory. Only Resets the ``openNextFile`` pointer to the top of the directory. Only
valid when ``File.isDirectory() == true``. valid when ``File.isDirectory() == true``.
setTimeCallback(time_t (*cb)(void)) setTimeCallback(time_t (\*cb)(void))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets the time callback for this specific file. Note that the SD and Sets the time callback for this specific file. Note that the SD and
SDFS filesystems only support a filesystem-wide callback and calls to SDFS filesystems only support a filesystem-wide callback and calls to

View File

@ -87,7 +87,7 @@ Some ESP-specific APIs related to deep sleep, RTC and flash memories are availab
``ESP.getHeapFragmentation()`` returns the fragmentation metric (0% is clean, more than ~50% is not harmless) ``ESP.getHeapFragmentation()`` returns the fragmentation metric (0% is clean, more than ~50% is not harmless)
``ESP.getMaxFreeBlockSize()`` returns the largest contiguous free RAM block in the heap, useful for checking heap fragmentation. **NOTE:** Maximum ``malloc()``able block will be smaller due to memory manager overheads. ``ESP.getMaxFreeBlockSize()`` returns the largest contiguous free RAM block in the heap, useful for checking heap fragmentation. **NOTE:** Maximum ``malloc()`` -able block will be smaller due to memory manager overheads.
``ESP.getChipId()`` returns the ESP8266 chip ID as a 32-bit integer. ``ESP.getChipId()`` returns the ESP8266 chip ID as a 32-bit integer.

View File

@ -233,5 +233,3 @@ address range of IRAM or DRAM.
uint8_t mmu_set_uint8(void *p8, const uint8_t val); uint8_t mmu_set_uint8(void *p8, const uint8_t val);
uint16_t mmu_set_uint16(uint16_t *p16, const uint16_t val); uint16_t mmu_set_uint16(uint16_t *p16, const uint16_t val);
int16_t mmu_set_int16(int16_t *p16, const int16_t val); int16_t mmu_set_int16(int16_t *p16, const int16_t val);
::

View File

@ -161,7 +161,7 @@ If signing is desired, sign the gzip compressed file *after* compression.
Updating apps in the field to support compression Updating apps in the field to support compression
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you have applications deployed in the field and wish to update them to support compressed OTA uploads, you will need to first recompile the application, then _upload the uncompressed `.bin` file once_. Attempting to upload a `gzip` compressed binary to a legacy app will result in the Updater rejecting the upload as it does not understand the `gzip` format. After this initial upload, which will include the new bootloader and `Updater` class with compression support, compressed updates can then be used. If you have applications deployed in the field and wish to update them to support compressed OTA uploads, you will need to first recompile the application, then _upload the uncompressed `.bin` file once. Attempting to upload a `gzip` compressed binary to a legacy app will result in the Updater rejecting the upload as it does not understand the `gzip` format. After this initial upload, which will include the new bootloader and `Updater` class with compression support, compressed updates can then be used.
Safety Safety

View File

@ -1,59 +0,0 @@
#include <ESP8266WiFi.h>
#include <AddrList.h>
#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK "your-password"
#endif
// preinit() is called before system startup
// from nonos-sdk's user entry point user_init()
void preinit() {
// Global WiFi constructors are not called yet
// (global class instances like WiFi, Serial... are not yet initialized)..
// No global object methods or C++ exceptions can be called in here!
//The below is a static class method, which is similar to a function, so it's ok.
ESP8266WiFiClass::preinitWiFiOff();
}
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println("sleeping 5s");
// during this period, a simple amp meter shows
// an average of 20mA with a Wemos D1 mini
// a DSO is needed to check #2111
delay(5000);
Serial.println("waking WiFi up, sleeping 5s");
WiFi.forceSleepWake();
// amp meter raises to 75mA
delay(5000);
Serial.println("connecting to AP " STASSID);
WiFi.mode(WIFI_STA);
WiFi.begin(STASSID, STAPSK);
for (bool configured = false; !configured;) {
for (auto addr : addrList)
if ((configured = !addr.isLocal() && addr.ifnumber() == STATION_IF)) {
Serial.printf("STA: IF='%s' hostname='%s' addr= %s\n",
addr.ifname().c_str(),
addr.ifhostname(),
addr.toString().c_str());
break;
}
Serial.print('.');
delay(500);
}
// amp meter cycles within 75-80 mA
}
void loop() {
}

View File

@ -24,11 +24,6 @@ WiFiState state;
const char* ssid = STASSID; const char* ssid = STASSID;
const char* password = STAPSK; const char* password = STAPSK;
void preinit(void) {
// Make sure, wifi stays off after boot.
ESP8266WiFiClass::preinitWiFiOff();
}
void setup() { void setup() {
Serial.begin(74880); Serial.begin(74880);
//Serial.setDebugOutput(true); // If you need debug output //Serial.setDebugOutput(true); // If you need debug output

View File

@ -83,7 +83,7 @@ struct WiFiEventHandlerOpaque
static std::list<WiFiEventHandler> sCbEventList; static std::list<WiFiEventHandler> sCbEventList;
bool ESP8266WiFiGenericClass::_persistent = true; bool ESP8266WiFiGenericClass::_persistent = false;
WiFiMode_t ESP8266WiFiGenericClass::_forceSleepLastMode = WIFI_OFF; WiFiMode_t ESP8266WiFiGenericClass::_forceSleepLastMode = WIFI_OFF;
ESP8266WiFiGenericClass::ESP8266WiFiGenericClass() ESP8266WiFiGenericClass::ESP8266WiFiGenericClass()
@ -418,12 +418,6 @@ bool ESP8266WiFiGenericClass::mode(WiFiMode_t m, WiFiState* state) {
DEBUG_WIFI("core: state is useless without SHUTDOWN or RESUME\n"); DEBUG_WIFI("core: state is useless without SHUTDOWN or RESUME\n");
} }
if (wifi_fpm_get_sleep_type() != NONE_SLEEP_T) {
// wifi may have been put asleep by ESP8266WiFiGenericClass::preinitWiFiOff
wifi_fpm_do_wakeup();
wifi_fpm_close();
}
if(_persistent){ if(_persistent){
if(wifi_get_opmode() == (uint8) m && wifi_get_opmode_default() == (uint8) m){ if(wifi_get_opmode() == (uint8) m && wifi_get_opmode_default() == (uint8) m){
return true; return true;
@ -432,6 +426,12 @@ bool ESP8266WiFiGenericClass::mode(WiFiMode_t m, WiFiState* state) {
return true; return true;
} }
if (m != WIFI_OFF && wifi_fpm_get_sleep_type() != NONE_SLEEP_T) {
// wifi starts asleep by default
wifi_fpm_do_wakeup();
wifi_fpm_close();
}
bool ret = false; bool ret = false;
ETS_UART_INTR_DISABLE(); ETS_UART_INTR_DISABLE();
if(_persistent) { if(_persistent) {
@ -855,25 +855,7 @@ bool ESP8266WiFiGenericClass::resumeFromShutdown (WiFiState* state)
return true; return true;
} }
//meant to be called from user-defined ::preinit()
void ESP8266WiFiGenericClass::preinitWiFiOff () { void ESP8266WiFiGenericClass::preinitWiFiOff () {
// https://github.com/esp8266/Arduino/issues/2111#issuecomment-224251391 // It was meant to be called from user-defined ::preinit()
// WiFi.persistent(false); // It is now deprecated by enableWiFiAtBootTime() and __disableWiFiAtBootTime()
// WiFi.mode(WIFI_OFF);
// WiFi.forceSleepBegin();
//WiFi.mode(WIFI_OFF) equivalent:
// datasheet:
// Set Wi-Fi working mode to Station mode, SoftAP
// or Station + SoftAP, and do not update flash
// (not persistent)
wifi_set_opmode_current(WIFI_OFF);
//WiFi.forceSleepBegin(/*default*/0) equivalent:
// sleep forever until wifi_fpm_do_wakeup() is called
wifi_fpm_set_sleep_type(MODEM_SLEEP_T);
wifi_fpm_open();
wifi_fpm_do_sleep(0xFFFFFFF);
// use WiFi.forceSleepWake() to wake WiFi up
} }

View File

@ -120,7 +120,7 @@ class ESP8266WiFiGenericClass {
void setOutputPower(float dBm); void setOutputPower(float dBm);
void persistent(bool persistent); static void persistent(bool persistent);
bool mode(WiFiMode_t, WiFiState* state = nullptr); bool mode(WiFiMode_t, WiFiState* state = nullptr);
WiFiMode_t getMode(); WiFiMode_t getMode();
@ -133,7 +133,7 @@ class ESP8266WiFiGenericClass {
static uint32_t shutdownCRC (const WiFiState* state); static uint32_t shutdownCRC (const WiFiState* state);
static bool shutdownValidCRC (const WiFiState* state); static bool shutdownValidCRC (const WiFiState* state);
static void preinitWiFiOff (); //meant to be called in user-defined preinit() static void preinitWiFiOff () __attribute__((deprecated("WiFi is off by default at boot, use enableWiFiAtBoot() for legacy behavior")));
protected: protected:
static bool _persistent; static bool _persistent;

View File

@ -0,0 +1,28 @@
/*
* empty wrappers to play with linker and reenable wifi at boot time
*/
#include "coredecls.h"
#include <ESP8266WiFi.h>
extern "C" void enableWiFiAtBootTime()
{
/*
* Called by user from anywhere, does nothing and allows overriding
* the core_esp8266_main.cpp's default disableWiFiAtBootTime() by the
* one below, at link time.
*/
}
extern "C" void __disableWiFiAtBootTime()
{
// overrides the default __disableWiFiAtBootTime:
// Does (almost) nothing: WiFi is enabled by default in nonos-sdk
// ... but restores legacy WiFi credentials persistence to true at boot time
// (can be still overriden by user before setting up WiFi, like before)
// (note: c++ ctors not called yet at this point)
ESP8266WiFiClass::persistent(true);
}

View File

@ -57,12 +57,6 @@ void error(const char* what) {
} }
} }
void preinit() {
// (no C++ in function)
// disable wifi
ESP8266WiFiClass::preinitWiFiOff();
}
void setup() { void setup() {
pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT);

View File

@ -98,12 +98,6 @@ void proxyEspSync() {
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void preinit() {
// (no C++ in function)
// disable wifi
ESP8266WiFiClass::preinitWiFiOff();
}
void setup() { void setup() {
// For `proxyEspSync()` to work, the Serial.begin() speed needs to be // For `proxyEspSync()` to work, the Serial.begin() speed needs to be
// 115200bps. This is the data rate used by esptool.py. It expects the Boot // 115200bps. This is the data rate used by esptool.py. It expects the Boot

View File

@ -9,7 +9,6 @@
//or #include <ENC28J60lwIP.h> //or #include <ENC28J60lwIP.h>
#include <WiFiClient.h> // WiFiClient (-> TCPClient) #include <WiFiClient.h> // WiFiClient (-> TCPClient)
#include <ESP8266WiFi.h> // ESP8266WiFiClass::preinitWiFiOff()
const char* host = "djxmmx.net"; const char* host = "djxmmx.net";
const uint16_t port = 17; const uint16_t port = 17;
@ -19,12 +18,6 @@ using TCPClient = WiFiClient;
#define CSPIN 16 // wemos/lolin/nodemcu D0 #define CSPIN 16 // wemos/lolin/nodemcu D0
Wiznet5500lwIP eth(CSPIN); Wiznet5500lwIP eth(CSPIN);
void preinit() {
// (no C++ in function)
// disable wifi
ESP8266WiFiClass::preinitWiFiOff();
}
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);

View File

@ -33,12 +33,6 @@ static uint64_t in_total = 0, in_prev = 0;
static uint64_t start_ms, last_ms; static uint64_t start_ms, last_ms;
static uint64_t timeout; static uint64_t timeout;
void preinit() {
// (no C++ in function)
// disable wifi
ESP8266WiFiClass::preinitWiFiOff();
}
void setup() void setup()
{ {
Serial.begin(SSBAUD); Serial.begin(SSBAUD);

View File

@ -3,12 +3,6 @@
BS_ENV_DECLARE(); BS_ENV_DECLARE();
void preinit() {
// (no C++ in function)
// disable wifi
ESP8266WiFiClass::preinitWiFiOff();
}
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);