ESP8266 is a wonderful little piece of hardware I stumbled over some months ago. It has gotten a lot of attention since some time back in 2014. Mainly because it is an incredible cheap WiFi module (less than $2 these days). It’s not until recently I’ve had some time to actually look into it. Personally I like to know how things work from bottom up, so that means digging down into electronics and the firmware/software you can either use out of the box or build/construct yourself for ESP8266.
I early on decided that I wanted to know more about the chip and architecture. So far I’ve been doing most research on the components of the ESP8266EX version. The CPU, memory and how it boots.
ESP8266(EX) is made by Espressif and there are multiple vendors out there selling different kind of modules embedding it. See this list which are somewhat updated. Personally I’ve bought ESP-01 and ESP-12E and will probably mostly use the latter. ESP-12E is from AI-thinker based on ESP8266EX chip. See Espressifs newest datasheet (0A-ESP8266EX__Datasheet__EN_V4.7_20160225.pdf)
Espressif is using Tensilica Xtensa in their architecture.
This is a 32bit RISC architecture.
The specific model is
L106 also known as
As far as I understand the architecture doesn’t have any form for CPU cache.
See Max Filippovs crosstool-ng repo for a C/C++ toolchain. You will also need some carefully written linker scripts. An alternative or better option would be to use the esp-open-sdk which bundles the toolchain, Xtensa HAL, esptool and the Espressif SDK. Very handy!
There is a lot of different conflicting information on the inter tubes. The datasheet doesn’t say a lot about it apart from the fact that it includes SRAM and ROM. Apparently there are separate data and instruction buses, respectively dBus and iBus, + a AHB bus. SRAM nor ROM size is specified explicitly. However, this is said about size in the datasheet:
When ESP8266EX is working under the station mode and is connected to the router, programmable space is accessible to user in heap and data section is 50KB.
Information gathered from the linker scripts and looking at how the stack is setup after boot I’ve concluded:
|0x3FFE8000||0x14000||RAM data - Heap|
|0x3FFEC000||0x4000||RAM data - Stack|
|0x40000000||0x10000||ROM (incl. bootloader)|
So there should atleast be:
- 96kB data RAM
- 32KB instruction RAM
In addition to this, SPI flash can be mapped to memory through a cache of some sorts. This is used to read instructions directly from flash instead of copying it over to instruction RAM first. Flash cache should be slower than RAM, but I haven’t done any testing myself.
By using esptool
./esptool.py --port /dev/ttyUSB0 flash_id
my ESP-12E identifies the flash chip:
Manufacturer: e0 Device: 4016
Which I believe is BergMicro BG25Q32 (32Mbit - 4MB).
I’ve skipped all the electronics that you probably either already know or should read more about elsewhere. Buying a module like the ESP-12E require you to do a bit of soldering. The inter tubes are full of articles/posts of how to connect your ESP8266 using a breadboard, protoboard or whatever. Google it!
One thing I should mention, that made me hurt for a while, is the fact that when you boot the stock (AT) firmware, ESP8266 draws >200mA. This means that powering it from USB through your USB to serial adaptor will probably NOT work. I learned this the hard way; After a day of cursing and knocking my head against the wall. You are better of using a separate power supply which can handle 500mA @ 3.3V. A capacitor or two across VDD/VCC and ground close to the chip is probably also recommended. I’m an electronics rookie, so if you are having problems, talk to an expert.
There are a couple of things you should know about the serial interface.
- The first stage bootloader initializes UART0 with baud rate based on the external crystal oscillator.
- The stock (AT) firmware and probably others use a baud rate of 115200.
- Booting in UART mode (also known as flashing/programming mode) uses auto sensing baud rate AFAIK.
I’ve experimented with a couple of applications on Linux for serial communication to ESP8266.
I used picocom for a while because it’s pretty straight forward and supports CRLF
which is what you need for executing AT commands using the AT firmware.
picocom doesn’t support custom baud rates.
You would need to build picocom yourself where you enable it.
So reading bootloader messages wouldn’t work out of the box.
The same thing goes for minicom and screen.
You could probably make it work initializing the serial terminal using
As I’m no expert on serial terminals, serial communication drivers nor the
kernel infrastructure for this, I’ve just tried to find whats easiest to use.
I highly recommend using
miniterm.py (included in pyserial python package).
miniterm.py /dev/ttyUSB0 74880 for reading the bootloader message and
miniterm.py /dev/ttyUSB0 115200 for anything else unless you want
high speed communication and/or you have firmware that uses something else.
Typical output from the bootloader:
ets Jan 8 2013,rst cause:2, boot mode:(3,7) load 0x40100000, len 1396, room 16 tail 4 chksum 0x89 load 0x3ffe8000, len 776, room 4 tail 4 chksum 0xe8 load 0x3ffe8308, len 540, room 4 tail 8 chksum 0xc0 csum 0xc0 2nd boot version : 1.4(b1) SPI Speed : 40MHz SPI Mode : DIO SPI Flash Size & Map: 8Mbit(512KB+512KB) jump to run user1 @ 1000
boot mode:(x,y) gives
x = 3 and
y = 7 where
x is the boot mode.
rst cause:z gives
z = 2
When you reset the ESP8266 it can boot in a couple of different modes.
|L||L||H||1||UART||Download over UART|
|L||H||H||3||Flash||Boot from SPI Flash|
|H||x||x||4-7||SDIO||Boot from SD|
L = low
H = high
x = floating
GPIO2 (3 bit) forms Code.
I’m going to research a bit more to find out how both Flash and UART boot mode actually works. Both modes are already somewhat reverse engineered and documented elsewhere, but it is fun trying to understand and then explain it in a later post. So be sure to check back later for more! :)