Arduino方式开发

NonOS开发

FreeRTOS开发

ESP-AT开发

乐鑫已经停止了对8266 AT开发的支持, 后续只维护BUG. 现在乐鑫推荐 ESP32-C3也即是RISC-V平台.
ESP-AT Git项目能找到8266最后版本的技术文档

ESP-IDF开发

官方文档是这个: ESP8266 SDK的开发指南, 目前只有英文

CSDN上半颗心脏同学的8266开发笔记
乐鑫关于8266和32开发用IDF的区别, 8266 SDK从V3.0开始与IDF风格统一, 但由于不是完全兼容, 所以名称没有改为IDF.
ESP8266 SDK的GIT库
ESP-IDF的GIT库

环境搭建

还挺费劲, 下载的东西还挺多

准备工作

  1. 大多数人可能还是用windows 环境吧
  2. 需要下载3个包, 1个是msys2模拟linux环境, 1个是8266 编译器, 1个是8266项目包
  3. 需要用到github,所以准备好梯子

具体步骤

  1. 下载并解压 toolchain: https://dl.espressif.com/dl/esp32_win32_msys2_environment_and_toolchain-20181001.zip, 解压缩后把里面的msys32放到一个简短点儿的目录里比较好, 如D:\msys32
  2. 双击里面的mingw32.exe, 这就是以后的主要工作环境了. 先在home\用户名\也就是~目录下建立一个esp目录, 把开发支持工具(等会儿会有2个), 放在这儿. home目录就在D:\msys32下面.
  3. 下载第一个开发支持工具: esp8266 toolchain, https://dl.espressif.com/dl/xtensa-lx106-elf-gcc8_4_0-esp-2020r3-win32.zip, 解压缩到esp目录里面.
  4. mingw32里面用vim .bashrc增加一句话export PATH="$PATH:$HOME/esp/xtensa-lx106-elf/bin"
  5. esp目录里下载第二个支持工具. 这儿要用gitgithub. 所以你可能要先在.bashrc里面设置个代理export http_proxy="192.168.0.1:8080", 然后重启mingw32, 进入esp目录运行: git clone https://github.com/espressif/ESP8266_RTOS_SDK.git , 也可以下载zip包https://github.com/espressif/ESP8266_RTOS_SDK/releases/download/v3.4/ESP8266_RTOS_SDK-v3.4.zip直接解压, 然后把clone后的路径设置为系统变量IDF_PATH. 可以在.bashrc里面设置, 增加一行: export IDF_PATH="$HOME/esp/ESP8266_RTOS_SDK",也可以再windows系统的环境变量里面设置, 如果在winows环境变量设置, 值要设置为/home/用户名/esp/ESP8266_RTOS_SDK这样的形式. 似乎~符号不认. 重启mingw32使设置生效.
  6. 运行 python -m pip install --user -r $IDF_PATH/requirements.txt
  7. 复制一个hello world出来cp -r $IDF_PATH/examples/get-started/hello_world
  8. 进到hello_world目录运行make menuconfig, 出来个UI界面配置一下串口名称如COM18, 保存退出. 注意这个是ESP8266的烧录串口, 波特率74880
  9. 运行make flash, 会检查环境, 并且从github下载项目, 编译, 挺花时间, 没个十几分钟搞不定. 可以增加一个-j8参数, 使用8核编译,速度会快很多
  10. 运行make monitor可以监控串口输出.

好了, 看起来终于可以开始了.

其他有用的命令

make all 只编译而不烧录, 也会在最后显示烧录命令.
make print_flash_cmd 打印烧录命令, 可以用在其他地方
make partition_table 打印分区表, 一般分为两种: 非OTA的分区表Single factory app, no OTA和OTA分区表Two OTA app, 可以在make menuconfig中选择.

分区表

分区表烧录在0x8000位置, 长度为0xC00
非OTA的分区表:

# Espressif ESP8266 Partition Table
# Name,   Type, SubType, Offset,  Size
nvs,      data, nvs,     0x9000,  0x6000
phy_init, data, phy,     0xf000,  0x1000
factory,  app,  factory, 0x10000, 0xF0000

NVS是非易失存储, PHY似乎是物理什么的
OTA的分区表

# Espressif ESP8266 Partition Table
# Name,   Type, SubType, Offset,   Size
nvs,      data, nvs,     0x9000,   0x4000
otadata,  data, ota,     0xd000,   0x2000
phy_init, data, phy,     0xf000,   0x1000
ota_0,    0,    ota_0,   0x10000,  0xF0000
ota_1,    0,    ota_1,   0x110000, 0xF0000

可以看到OTA分区表是兼容非OTA分区表的, 兼容性明显比以前的8266项目好多了. 网上有很多介绍以前的8266分区表的, OTA分为user0/user1, user0起始于0x1000而不是现在的0x10000, 现在应该已经不适用了.
otadata是指示启动那个app的, 如果为空就启动ota_0
分区表可以自定义, 不过我感觉一般是没必要了

系统任务

大写T在最后面的是IDF的任务, 其他的是FREERTOS的任务.

uiT 用户初始化任务, 初始化完以后调用app_main再销毁自己
IDLE FREERTOS的空闲任务, 在其钩子vApplicationIdleHook中调用sleep和喂狗任务
Tmr FREERTOS的软时钟
ppT 处理WIFI硬件驱动,我猜是process protocol的缩写
ppT 系统电源管理, power managerment.
rtT 高优先级的硬时钟中断任务. 主要处理WIFI实时事件. 基于这个组件的程序不要在应用(application)里面调用,以免影响WIFI收发.
tiT Tcp-Ip协议栈的任务(LwIP), 处理TCP-IP包.
esp_event_loop_task 处理系统事件
优先级从低到高依次是:

0 IDLE 
2 Tmr 
8 tiT 
10 esp_event_loop_task
11 pmT
12 rtT
13 ppT
14 uiT

用户任务的优先级要低于rtT也就是12.
如果要加快 TCP/UDP 吞吐量,可以尝试将发送/接收任务的优先级设置为高于“tiT”任务的优先级(8)

PWM和嗅探器Sniffer共存问题

SmartConfig应该属于一种Sniffer.
8266是没有硬件PWM的, 它是用硬时钟模拟的软件PWM. 硬时钟同时用于WIFI, 所以WIFI sniffer和PWM同时用会出现资源争用的问题.
N个通道的PWM每次翻转GPIO将占用6+8N ns的时长. 例如一个通道PWM就是14ns.
占用期间, 如果收到了必须要实时处理的LPDC或HT40包, 这些包就会被丢弃.
同时使用PWM和smartconfig会使得配网时间更长. 而且调整PWM的频率/duty cycle/phase都会影响smartconfig的速度.
如果要同时使用, 需要:

  • PWM 的频率不能太高,最多 2KHz。
  • 修改PWM的占空比和相位,使每个通道反相之间的时间间隔(Tn)等于0或大于50us(Tn = 0,或Tn > 50)
    这样看起来这个软件PWM似乎不太适合用于LED驱动~~

使用API-Reference文档

非常神奇的, 8266仿照IDF风格的API编程手册, 乐鑫已经放弃治疗了, 8266 RTOS SDK 编程指南最后版本V3.4中, 居然只是把每个函数罗列了一遍, 有个球用. 找了网上各种指南, 发现只能参考ESP32的手册, 在同样的目录结构下, Uart的使用就有非常详细的描述.

使用 make menuconfig工具

感觉有些操蛋~ 很多在程序里面定义的参数还要再menuconfig里面预先定义一下, 否则程序编译后运行得总有些问题. 而且make menuconfig重新定义以后,这个编译速度就慢的惊人了

使用linux服务器或者使用docker中加载linux环境, make的速度可以快好几倍.

menuconfig主要是在根目录下生成sdkconfig文件作为编译依据. 同时会把旧的文件改名为sdkconfig.old. 如果熟练的情况可以直接修改sdkconfig文件.

是否要重新编译, 似乎是根据sdkconfig有没有更新决定的. 所以即使修改了一个和编译完全无关的项目, 如PC烧录串口, 也会导致全部重新编译.

IDF版本兼容性

IDF各个版本兼容性不佳, 如8266 v3.4和v3.1是不兼容的. 发现的就有 uart_driver_install在v3.4比v3.1多一个参数,导致编译不能通过.

8266的串口输出

8266只有1.5个串口, 也就是1个完整串口UART0和1个只有TX的串口. 所谓有时候看到的UART2(IO13/15)是UART0交换(swap)过去的.

基于idf, 函数中直接使用printf函数将直接从uart0口输出, 不需要串口初始化的步骤.

  • 在menuconfig中将Swap UART0 I/O pins选上, 编译烧录后, 刚刚启动打印的boot信息在UART0输出, 后面printf的信息都在UART2上输出. 如果使用了软重启esp_restart();, 软重启后的boot信息也将在UART2上输出.

  • 在menuconfig中将Uart for console output选项改为Custom, 如果UART peripheral to use for console output (0-1)仍然为UART0, 结果和上面的一样不变.

  • 如果将UART peripheral to use for console output (0-1)改为UART1, 那么第一次启动的boot信息在UART0输出, printf的信息在UART1输出, 软重启后的boot信息在UART2输出.

  • 在meunconfig中将Partition Table改为Factory app, two OTA definitions不会对运行结果有什么影响, 但是flash烧录的固件名称会改为partitions_two_ota.bin
    如果是单文件, 烧录命令是(project_template是项目的目录名):

    D:\r\esp\esp-idf\components\esptool_py\esptool\esptool.py --chip esp8266 --port COM18 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 2MB 0x0000 build/bootloader/bootloader.bin 0x10000 build/project_template.bin 0x8000 build/partitions_singleapp.bin

    如果是ota,烧录命令是:

    D:\r\esp\esp-idf\components\esptool_py\esptool\esptool.py --chip esp8266 --port COM18 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 2MB 0x0000 build/bootloader/bootloader.bin 0x10000 build/project_template.bin 0x8000 build/partitions_two_ota.bin
  • menuconfig只能控制所谓console的uart设置, 如果要使用uart,还是要自己通过程序进行uart初始化设置.

  • uart初始化使用uart0的影子uart2, 如果在menuconfig中已经设置了swap, 在初始化中就不需要再次调用swap函数了.

    static void uartInit()
    {
      // Configure parameters of an UART driver,
      // communication pins and install the driver
      uart_config_t uart_config = {
          .baud_rate = 115200,
          .data_bits = UART_DATA_8_BITS,
          .parity    = UART_PARITY_DISABLE,
          .stop_bits = UART_STOP_BITS_1,
          .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
      };
      uart_param_config(UART_NUM_0, &uart_config);
      uart_driver_install(UART_NUM_0, BUF_SIZE * 2, 0, 0, NULL);
    }
  • v3.1printf的问题: 有时候不会及时输出, 尤其是在使用了格式化符号%d%x等等后, 必须要用fflush(stdout)后才能输出.

include顺序

idf头文件#include是有顺序的,否则编译不通过.
感觉顺序似乎应该是标准库文件->freertos头文件->esp系统文件->驱动文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "driver/uart.h"

标签: none 阅读量: 1813

添加新评论