Skip to content

ESP8266 Design Notes

Thorsten von Eicken edited this page Oct 2, 2015 · 17 revisions

ESP8266 Espruino Design Notes

This page contains a number of random design notes for the esp8266 port of espruino.

Flash map and access

The esp8266 modules come in a number of forms with varying flash chip sizes. The flash layout for each size is slightly different. There are a number of random tidbits to know about flash layout:

  • There are two binary formats in use: the non-OTA and the OTA update format. The non-OTA has no 2nd stage bootloader, starts at 0x0000 in flash, and has two binary blobs: one for data and one for instructions (+ read-only data). The OTA format has a 2nd stage bootloader at 0x0000 and then a single binary blob for the first firmware image at 0x1000. There is a 2nd binary blob up after the first one to provide the two firmware images necessary for a safe OTA update. All this is described in the Espressif IOT SDK User Manual.
  • The hardware can memory-map 1MBytes of flash, but it has to be read on word (4-byte) boundaries, it cannot be written as far as I know
  • Every memory map has a 16KB "user param" area that is reserved for applications to store non-volatile settings and such. This is used as the "save to flash" area in Espruino. Currently the number of variables is set to 1023, which uses 12KB and in addition the saved data is run-length encoded. Therefore at most 12KB of this flash area really need to be reserved. It is not known whether there's a chance to increase the number of variables at this point.
  • Every memory maps also has a 16KB "system param" area in which the SDK stores settings, including RF parameters and wifi settings
  • Finally there is an unused 4KB area just before the 2nd firmware in the larger memory maps, this "mirrors" the bootloader area but is not used.
Flash size FW size FW#1 start FW #2 start Save to flash System param SPIFFs Free
512KB 480KB 0x000000 N/A 0x78000 0x7C000 N/A N/A
1MB 492KB 0x001000 0x81000 0x7C000 0xFC000 N/A 0x80000 (4KB)
2MB 492KB 0x001000 0x81000 0x7C000 0x1FC000 0x100000 (1MB) 0x80000 (4KB)
4MB 492KB 0x001000 0x81000 0x7C000 0x3FC000 0x100000 (3MB) 0x80000 (4KB)

System time

The esp8266 has two notions of system time implemented in the SDK by system_get_time() and system_get_rtc_time(). The former has 1us granularity and comes off the CPU cycle counter, the latter has approx 57us granularity (need to check) and comes off the RTC clock. Both are 32-bit counters and thus need some form of roll-over handling in software to produce a JsSysTime.

It seems pretty clear from the API and the calibration concepts that the RTC runs off an internal RC oscillator or something similar and the SDK provides functions to calibrate it WRT the crystal oscillator.

The RTC timer is preserved when the chip goes into sleep mode, including deep sleep, as well when it is reset (but not if reset using the ch_pd pin).

It seems that the best course of action is to use the system timer for jshGetSystemTime() and related functions and to use the rtc timer only at start-up to initialize the system timer to the best guess available for the current date-time.

Timers

The esp8266 has a number of timers that can be used. The simplest to use is via os_timer_arm() and related functions. This has millisecond granularity and schedules a task, so it does not have very high priority nor resolution. There is a way to change the timer to have microsecond resolution, but it's not well documented what the side-effects are nor whether this does anything to the priority. Alternatively one can attach a callback to a hardware timer via hw_timer_arm() et. al. and that can fire either at NMI level or at FRC1 level (whatever that is). Clearly there will be task scheduling issues that need to be investigated, i.e., the callback will be limited in what it can safely call.

The current plan is to use the hw_timer at NMI level and see whether this can be made to work reliably.

Clone this wiki locally