Created
September 16, 2020 16:31
-
-
Save felipeasimos/4adfcbeed485a99df62a773da104296b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Nodemcu | |
sources: \ | |
https://www.espressif.com/sites/default/files/documentation/2c-esp8266_non_os_sdk_api_reference_en.pdf \ | |
github repos: \ | |
https://github.com/pfalcon/esp-open-sdk | |
The Nodemcu board purpose is mostly to work as a facilitator for the | |
use of the esp8266 chip. | |
## NONOS SDK | |
The Non-OS SDK provides a set of applications programming interfaces (API) | |
for core ESP8266 functions. | |
### Main Components | |
The main file is `user_main.c`, it is where the `void user_init(void)` | |
definition should go. | |
In version 2.0.0 of the SDK, `void user_rf_pre_init(void)` and | |
`uint32 user_rf_cal_sector_set(void)` also need to be added to | |
`user_main.c`. | |
### Code Structure | |
Since its is an SDK without OS, there is no scheduling | |
mechanism, and has 4 types of functions: | |
* __Application Functions__ | |
* Usual C functions, used in embedded C programming. | |
* Must be called by another function. | |
* Apllication functions with `ICACHE_FLASH_ATTR` attribute | |
fetch and execute programs from the flash. `IRAM_ATTR` functions | |
are stored in iRAM prior to execution. | |
* __Callback Functions__ | |
* Functions that are not called by directly from the user program. | |
* Executed by Non-OS SDK core when an event occurs. | |
* Callback functions are set using the `register_cb` API. | |
* Callbacks should not occupy the CPU for more than 15 ms. | |
* Callbacks can't be called more frequently than 5 ms (they | |
just can't, it isn't fast enough). | |
* __Interrupt Service Routines (ISRs)__ | |
* Callback functions of special type. | |
* Called when hardware interrupt occurs. | |
* Must be attributed as `IRAM_ATTR`. | |
* __User Tasks__ | |
* Can be classified according to three priority levels: 0, 1, 2. | |
* Non-OS SDK can support up to 3 tasks at a time, one priority level | |
per task. | |
* Set using the `system_os_task()` API. | |
* Must not take longer than 500 ms. | |
#### Execution time | |
IMPORTANT NOTE FROM THE DOCS: "Non-OS SDK does not preempt tasks or | |
switch context. Users are responsible for the proper execution of | |
code and the user code must not occupy the CPU on a particular | |
function for too long. This can cause a watchdog reset and prompt | |
ESP8266 to reset." | |
If for some reason a task really must take longer than 500 ms | |
(this is not the exact value), `system_soft_wdt_feed()` API | |
must be called to reset the _Watch Dog Timer (WDT)_. Disabling | |
the _WDT_ is not recommended. | |
To avoid blocking the CPU, please use the system timer task | |
instead of using loops. | |
Try not occupying the CPU for more than 15 ms in callbacks. | |
### System Performance | |
* ESP8266 runs at 80 MHz. The CPU can be configured to run | |
at 160 MHz in high performance applications. | |
* Higher Clock frequency and disabled sleep modes consume | |
more energy. | |
* Code attributed with `ICACHE_FLASH_ATTR` is generally | |
executed slower than the code marked with `IRAM_ATTR`. However, | |
like most embedded plataforms, the iRAM is really limited. | |
* The flash mode and frquency directly impact the | |
performance. Setting flash to a higher frequency and QIO mode | |
may perform better, but costs more energy. | |
### System Memory | |
* ESP8266 supports primary external QSPI flash memory | |
of up to 128 Mbits for code and storage. Secondary | |
chips may also be used for user storage. | |
* There is no internal non-volatile storage for | |
code or data. | |
* 160 KBytes of RAM: | |
* 64 Kb iRAM (32 Kb for `IRAM_ATTR`, 32 Kb `ICACHE_FLASH_ATTR`). | |
* 96 Kb dRAM (80Kb for SDK+HEAP, 16 Kb for ROM). | |
* RAM and flash must be 4 word-aligned. | |
* Casting pointers directly is not recommended, use `os_memcpy` or other | |
API instead. | |
## Setup | |
We need three things: | |
* Toolchain, to compile our programs | |
* Flasher | |
* SDK | |
### Toolchain | |
To facilitate the building of the toolchain, let's clone the | |
`esp-open-sdk` and use it. | |
The README.md has all the necessary information for building the | |
toolchain. There are two main options: | |
* `make STANDALONE=y` - SDK and Toolchain are "merged". Only the IoT SDK, | |
that comes with the repository, will be used. | |
* `make STANDALONE=n` - Toolchain and SDK are build separately. | |
We will go with the `make STANDALONE=n` option, so we can use other | |
SDK if we want to. | |
After that is done (it can take like 30 min), we will add the Xtensa | |
toolchain to our PATH, so we can call it from anywhere. You many want to | |
add this to your `.bashrc`: | |
``` | |
PATH=$PATH:$(ESP_OPEN_SDK)/xtensa-lx106-elf/bin | |
``` | |
### Flasher | |
We need a program to flash our code to the ESP8266. We will use `esptool`. | |
It is really simple to install in some linux distros: | |
``` | |
pip install esptool.py | |
``` | |
With it you can erase the chip memory with | |
`esptool.py --port /dev/ttyUSB0 erase_flash`. | |
### SDK | |
Just download the SDK. We will use the SDK files when compiling. | |
## Compiling | |
To compile we will modify the `Makefile` of the `blinky` example | |
in `esp-open-sdk`: | |
``` | |
SDK_BASE = /home/felipe/Coding/nodemcu/ESP8266_NONOS_SDK_FREEWIFI | |
INIT_DATA = $(firstword $(wildcard $(SDK_BASE)/bin/esp_init_*default*.bin)) | |
BLANK = $(SDK_BASE)/bin/blank.bin | |
CC = xtensa-lx106-elf-gcc | |
CFLAGS = -I. -mlongcalls -I$(SDK_BASE)/include | |
LDLIBS = -nostdlib -Wl,--start-group -lmain -lnet80211 -lwpa -llwip -lpp -lphy -lc -lssl -lcrypto -Wl,--end-group -lgcc | |
LDFLAGS = -T$(SDK_BASE)/ld/eagle.app.v6.ld -L$(SDK_BASE)/lib | |
TARGET = main | |
$(TARGET)-0x00000.bin: $(TARGET) | |
esptool.py elf2image $^ | |
$(TARGET): $(TARGET).o | |
$(TARGET).o: $(TARGET).c | |
flash: $(TARGET)-0x00000.bin | |
esptool.py write_flash 0x00000 $(TARGET)-0x00000.bin \ | |
0x10000 $(TARGET)-0x10000.bin \ | |
0x3fb000 $(BLANK) \ | |
0x3fc000 $(INIT_DATA) \ | |
0x3fe000 $(BLANK) \ | |
-fm dio | |
debug: CFLAGS+= -S | |
debug: | |
$(CC) $(CFLAGS) $(TARGET).c -o $(TARGET).S | |
clean: | |
rm -f $(TARGET)*[^c] $(TARGET) | |
erase: | |
esptool.py erase_flash | |
``` | |
You may change `INIT_DATA` and `SDK_BASE` to the proper values: | |
* `INIT_DATA` - Data to be put in the chip for proper initialization of it. You actually don't | |
need to flash it everytime, since it won't change between development-compile-flash cycles (it | |
comes from the SDK, you only need to change it if you change the SDK). | |
* `SDK_BASE` - Path to the sdk, where we can find the linker script and binaries. | |
You may get some errors related to `user_pre_init`, `user_config.h`, `user_rf_cal_sector_set` | |
or `user_rf_pre_init`: | |
* `user_pre_init` - Some SDK versions require this function to exists, just add it with an | |
empty body. | |
* `user_config.h` - The SDK require a `user_config.h` file. It can be empty though, so just | |
do a `touch user_config.h`. | |
* `user_rf_pre_init`/`user_rf_cal_sector_set` - Some SDK versions require these functions also. | |
Check examples from the SDK to get more info. | |
More information, "check Non-OS SDK Introduction" section [here](https://www.espressif.com/sites/default/files/documentation/2c-esp8266_non_os_sdk_api_reference_en.pdf). | |
You may also get `undefined reference` for library functions like `aes_wrap`. Just | |
add the libraries based on [this](https://github.com/AutomationD/esp-alt-sdk/issues/24). | |
You may also get a `Fatal exception(0)` when connecting to the board in the | |
74880 baud rate (try this baud rate if you are seeing garbage being printed | |
rapidly!) or a error from `make` saying a file wasn't found. It probably means | |
that you uploaded one of the generated binaries to the wrong address. This can | |
happen when scwitching SDK versions, as v1.0.0 writes to `0x40000` and v3.3 writes | |
to `0x10000`. Just change everywhere you see `0x10000` to `0x40000` in the `Makefile`; | |
## Flashing | |
First we need to flash the `esp_init_data_default.bin`, which is usually | |
in the `bin/` subdirectory for the SDKs: | |
``` | |
esptool.py --port /dev/ttyUSB0 write_flash 0x3FC000 ESP8266_NONOS_SDK/bin/esp_init_data_default.bin | |
``` | |
The address `0x3FC000` is just the top address of the flash memory | |
subtracted by `0x3FFF`. You can do this subtraction for every flash | |
memory size to get the right address. The idea is just to put this | |
data at the top of the memory. More info [here](https://nodemcu.readthedocs.io/en/dev/flash/). | |
However, the `Makefile` we saw before handles it all with the `flash` rule. | |
Mind that the you **NEED** to flash the binaries to the addresses | |
specified in their names, which may vary from a SDK version to another. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment