关于 ESP8266 端口的一般信息¶
ESP8266 是乐鑫推出的一款流行的支持 WiFi 的片上系统 (SoC)。
多块板子¶
有许多来自不同来源的模块和电路板带有 ESP8266 芯片。MicroPython 试图提供一个可以在尽可能多的板/模块上运行的通用端口,但可能存在限制。以Adafruit Feather HUZZAH板作为端口的参考板(例如对其进行测试)。如果您有另一块电路板,请确保您有一份数据表、原理图和其他参考材料,以便您方便地查找电路板功能的各个方面。
为了制作通用的 ESP8266 端口并支持尽可能多的板卡,做出了以下设计和实现决策:
GPIO 引脚编号基于 ESP8266 芯片编号,而不是特定板的某种“逻辑”编号。请手头有您的电路板的手册/引脚图,以查找您的电路板引脚与实际 ESP8266 引脚之间的对应关系。我们还鼓励各种板的用户通过 MicroPython 论坛共享此映射,最终收集社区维护的参考资料。
MicroPython 支持所有有意义的引脚(例如,用于连接 SPI 闪存的引脚不会暴露,因为它们不太可能对其他任何东西有用,并且对它们进行操作会导致电路板锁定) . 然而,任何特定的电路板可能只暴露引脚的子集。请查阅您的电路板参考手册。
某些开发板可能缺少外部引脚/内部连接以支持 ESP8266 深度睡眠模式。
技术规格和 SoC 数据表¶
ESP8266 芯片的数据表和其他参考资料可从供应商站点获得:http://bbs.espressif.com/viewtopic.php?f=67&t=225 。它们是芯片技术规格、功能、操作模式、内部功能等的主要参考。
为了您的方便,下面提供了一些技术规格:
架构:Xtensa lx106
CPU频率:80MHz可超频至160MHz
可用内存总量:96KB(部分预留给系统)
引导ROM:64KB
内部闪存:无
外部 FlashROM:代码和数据,通过 SPI Flash。正常大小 512KB-4MB。
GPIO:16+1(GPIO与其他功能复用,包括外部FlashROM、UART、深度睡眠唤醒等)
UART:1 个 RX/TX UART(无硬件握手),1 个 TX-only UART。
SPI:2个SPI接口(1个用于FlashROM)。
I2C:没有本地外部 I2C(在任何引脚上都可以使用 bitbang 实现)。
I2S:1。
编程:使用来自 UART 的 BootROM 引导加载程序。由于外部 FlashROM 和始终可用的 BootROM 引导加载程序,ESP8266 不可变砖。
运行时资源稀缺¶
ESP8266 的资源非常有限(首先是 RAM 内存)。因此,请避免分配太大的容器对象(列表、字典)和缓冲区。也没有成熟的操作系统来跟踪资源并自动清理它们,因此这是用户/用户应用程序的任务:请确保在使用后尽快关闭打开的文件、套接字等。
启动过程¶
启动时,MicroPython EPS8266 端口_boot.py
从内部冻结模块执行脚本。它在 FlashROM 中安装文件系统,或者如果它不可用,则执行模块的首次设置并创建文件系统。这部分启动过程被认为是固定的,不能为最终用户定制(即使你从源代码构建,也请不要对其进行更改;早期启动过程的定制仅适用于高级用户和开发人员,他们可以诊断因修改标准流程而产生的任何问题)。
一旦文件系统被挂载,boot.py
就会从它执行。该文件的标准版本是在第一次模块设置期间创建的,并具有启动 WebREPL 守护程序(默认禁用,可使用webrepl_setup
模块配置)等的命令。该文件可由最终用户自定义(例如,您可能想要设置一些参数或添加其他应在模块启动时运行的服务)。但请记住,对 boot.py 的错误修改仍可能导致引导循环或锁定,需要从头开始刷新模块。(特别是,建议您使用
webrepl_setup
模块或手动编辑来配置 WebREPL,但不能同时使用两者)。
作为引导程序的最后一步,main.py
从文件系统执行(如果存在)。这个文件是一个钩子,用于在每次启动时启动用户应用程序(而不是去 REPL)。对于小型测试应用程序,您可以直接将它们命名为main.py
,然后上传到模块,但建议将您的应用程序保存在单独的文件中,并且在 中只包含以下内容 main.py
:
import my_app
my_app.main()
这将允许保持应用程序的结构清晰,并允许在板上安装多个应用程序,并在它们之间切换。
已知的问题¶
实时时钟¶
ESP8266 中的 RTC 精度非常差,漂移可能是每分钟几秒。作为一种解决方法,要测量足够短的间隔,您可以使用
utime.time()
等功能,对于挂钟时间,请使用包含的ntptime.py
模块从网络同步。
由于 ESP8266 芯片的限制,内部实时时钟 (RTC) 将每 7:45h 溢出一次。如果需要长期工作的 RTC 时间,则
time()
或 localtime()
必须在 7 小时内至少调用一次。MicroPython 然后将处理溢出。
STA_IF 和 AP_IF 同时操作¶
支持STA_IF和AP_IF接口同时操作。
但是由于硬件的限制,如果STA_IF没有连接和搜索,AP_IF可能会出现性能问题。应用程序应管理这些接口,例如在仅使用 AP_IF 的环境中停用 STA_IF。
套接字和 WiFi 缓冲区溢出¶
套接字实例保持活动状态,直到它们被显式关闭。这有两个后果。首先,它们占用 RAM,因此打开套接字而不关闭套接字的应用程序最终可能会耗尽内存。其次,未正确关闭套接字会导致供应商 WiFi 堆栈的低级部分发出
Lmac
错误。如果数据进入套接字并且未及时处理,则会发生这种情况。这可能会溢出 WiFi 堆栈输入队列并导致死锁。唯一的恢复是通过硬重置。
在应用程序因任何原因(包括异常)终止并退出 REPL 后,上述情况也可能发生。数据的后续到达会引发失败,并重复发出上述错误消息。因此,在任何情况下都应该关闭套接字,无论应用程序是成功终止还是异常终止,例如使用 try/finally:
sock = socket(...)
try:
# Use sock
finally:
sock.close()
SSL/TLS 限制¶
ESP8266 使用axTLS库,这是最小的具有兼容许可的 TLS 库之一。但是,它也有一些已知问题/限制:
不支持 Diffie-Hellman (DH) 密钥交换和椭圆曲线加密 (ECC)。这意味着它不能与需要使用这些功能的站点一起工作(它可以与使用 RSA 证书的典型站点一起工作)。
半双工通信性质。axTLS 使用单个缓冲区进行发送和接收,这可以节省大量内存,并且可以很好地与 HTTP 等协议配合使用。但是不遵循经典请求-响应模型的协议可能存在问题。
除了 axTLS 自身的限制之外,用于 MicroPython 的配置针对代码大小进行了高度优化,这导致了额外的限制(这些限制可能会在未来解除):
未启用优化的 RSA 算法,这可能会导致 SSL 握手缓慢。
未启用会话重用,这意味着每个连接都必须进行完整的、昂贵的 SSL 握手。
除了上述 axTLS 特定限制之外,在低内存设备上使用 TLS 还存在另一个通用限制:
TLS 标准规定 TLS 记录的最大长度(TLS 通信的单位,整个记录必须经过缓冲才能被处理)为 16KB。这几乎是可用 ESP8266 内存的一半,由于内存碎片问题,在或多或少的高级应用程序中很难分配。作为折衷方案,使用了更小的缓冲区,因为 SSL 最有趣的用法是访问各种 REST API,这通常需要更小的消息。缓冲区大小在5KB左右,不时调整,参考可以访问 https://google.com. 然而,较小的缓冲区意味着无法使用它访问某些站点,并且不可能流式传输大量数据。axTLS 确实支持 TLS 的 Max Fragment Size 扩展,但没有 HTTPS 网站支持,因此使用该扩展实际上只对与其他设备的本地通信有效。
在ussl
基于axTLS 的 MicroPython模块中也有一些未实现的特性 :
证书未经验证(这使得连接容易受到中间人攻击)。
不支持客户端证书(计划在 1.9.4 版本中修复)。