mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
doc: Changed Chinese doc to use dynamic chip name
This commit is contained in:
parent
a7bac4721a
commit
cfeb9e68cb
@ -5,7 +5,7 @@
|
||||
概述
|
||||
----
|
||||
|
||||
为了分析应用程序的行为,IDF 提供了一个有用的功能:应用层跟踪。这个功能以库的形式提供,可以通过 menuconfig 开启。此功能使得用户可以在程序运行开销很小的前提下,通过 JTAG 接口在主机和 ESP32 之间传输任意数据。
|
||||
为了分析应用程序的行为,IDF 提供了一个有用的功能:应用层跟踪。这个功能以库的形式提供,可以通过 menuconfig 开启。此功能使得用户可以在程序运行开销很小的前提下,通过 JTAG 接口在主机和 {IDF_TARGET_NAME} 之间传输任意数据。
|
||||
|
||||
开发人员可以使用这个功能库将应用程序的运行状态发送给主机,在运行时接收来自主机的命令或者其他类型的信息。该库的主要使用场景有:
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
**后验模式:** 这是默认的模式,该模式不需要和主机进行交互。在这种模式下,跟踪模块不会检查主机是否已经从 *HW UP BUFFER* 缓冲区读走所有数据,而是直接使用新数据覆盖旧数据。该模式在用户仅对最新的跟踪数据感兴趣时会很有用,例如分析程序在崩溃之前的行为。主机可以稍后根据用户的请求来读取数据,例如通过特殊的 OpenOCD 命令(假如使用了 JTAG 接口)。
|
||||
|
||||
**流模式:** 当主机连接到 ESP32 时,跟踪模块会进入此模式。在这种模式下,跟踪模块在新数据写入 *HW UP BUFFER* 之前会检查其中是否有足够的空间,并在必要的时候等待主机读取数据并释放足够的内存。用户会将最长的等待时间作为超时时间参数传递给相应的 API 函数,如果超时时间是个有限值,那么应用程序有可能会因为超时而将待写的数据丢弃。尤其需要注意,如果在讲究时效的代码中(如中断处理函数,操作系统调度等)指定了无限的超时时间,那么系统会产生故障。为了避免丢失此类关键数据,开发人员可以通过在 menuconfig 中开启 :ref:`CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX` 选项来启用额外的数据缓冲区。此宏还指定了在上述条件下可以缓冲的数据大小,它有助于缓解由于 USB 总线拥塞等原因导致的向主机传输数据间歇性减缓的状况。但是,当跟踪数据流的平均比特率超过硬件接口的能力时,它也无能为力。
|
||||
**流模式:** 当主机连接到 {IDF_TARGET_NAME} 时,跟踪模块会进入此模式。在这种模式下,跟踪模块在新数据写入 *HW UP BUFFER* 之前会检查其中是否有足够的空间,并在必要的时候等待主机读取数据并释放足够的内存。用户会将最长的等待时间作为超时时间参数传递给相应的 API 函数,如果超时时间是个有限值,那么应用程序有可能会因为超时而将待写的数据丢弃。尤其需要注意,如果在讲究时效的代码中(如中断处理函数,操作系统调度等)指定了无限的超时时间,那么系统会产生故障。为了避免丢失此类关键数据,开发人员可以通过在 menuconfig 中开启 :ref:`CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX` 选项来启用额外的数据缓冲区。此宏还指定了在上述条件下可以缓冲的数据大小,它有助于缓解由于 USB 总线拥塞等原因导致的向主机传输数据间歇性减缓的状况。但是,当跟踪数据流的平均比特率超过硬件接口的能力时,它也无能为力。
|
||||
|
||||
|
||||
配置选项与依赖项
|
||||
@ -56,7 +56,7 @@
|
||||
如何使用这个库
|
||||
--------------
|
||||
|
||||
该库提供了用于在主机和 ESP32 之间传输任意数据的 API。当在 menuconfig 中启用时,目标应用程序的跟踪模块会在系统启动时自动初始化,因此用户需要做的就是调用相应的 API 来发送、接收或者刷新数据。
|
||||
该库提供了用于在主机和 {IDF_TARGET_NAME} 之间传输任意数据的 API。当在 menuconfig 中启用时,目标应用程序的跟踪模块会在系统启动时自动初始化,因此用户需要做的就是调用相应的 API 来发送、接收或者刷新数据。
|
||||
|
||||
.. _app_trace-application-specific-tracing:
|
||||
|
||||
@ -327,7 +327,7 @@ IDF 中另一个基于应用层跟踪库的实用功能是系统级跟踪,它
|
||||
|
||||
若需使用这个功能,需要在 menuconfig 中开启 :ref:`CONFIG_SYSVIEW_ENABLE` 选项,具体路径为: *Component config > Application Level Tracing > FreeRTOS SystemView Tracing* 。在同一个菜单栏下还开启了其他几个选项:
|
||||
|
||||
1. *ESP32 timer to use as SystemView timestamp source* (:ref:`CONFIG_SYSVIEW_TS_SOURCE`)选择 SystemView 事件使用的时间戳来源。在单核模式下,使用 ESP32 内部的循环计数器生成时间戳,其最大的工作频率是 240 MHz(时间戳粒度大约为 4 ns)。在双核模式下,使用工作在 40 MHz 的外部定时器,因此时间戳粒度为 25 ns。
|
||||
1. *{IDF_TARGET_NAME} timer to use as SystemView timestamp source* (:ref:`CONFIG_SYSVIEW_TS_SOURCE`)选择 SystemView 事件使用的时间戳来源。在单核模式下,使用 {IDF_TARGET_NAME} 内部的循环计数器生成时间戳,其最大的工作频率是 240 MHz(时间戳粒度大约为 4 ns)。在双核模式下,使用工作在 40 MHz 的外部定时器,因此时间戳粒度为 25 ns。
|
||||
2. 可以单独启用或禁用的 SystemView 事件集合(``CONFIG_SYSVIEW_EVT_XXX``):
|
||||
|
||||
- Trace Buffer Overflow Event
|
||||
@ -341,7 +341,7 @@ IDF 中另一个基于应用层跟踪库的实用功能是系统级跟踪,它
|
||||
- Task Create Event
|
||||
- Task Terminate Event
|
||||
- System Idle Event
|
||||
- Timer Enter Event
|
||||
- Timer Enter Event
|
||||
- Timer Exit Event
|
||||
|
||||
IDF 中已经包含了所有用于生成兼容 SystemView 跟踪信息的代码,用户只需配置必要的项目选项(如上所示),然后构建、烧写映像到目标板,接着参照前面的介绍,使用 OpenOCD 收集数据。
|
||||
@ -406,7 +406,7 @@ Start 子命令语法:
|
||||
数据可视化
|
||||
""""""""""
|
||||
|
||||
收集到跟踪数据后,用户可以使用特殊的工具来可视化结果并分析程序的行为。遗憾的是,SystemView 不支持从多个核心进行跟踪。所以当追踪双核模式下的 ESP32 时会生成两个文件:一个用于 PRO CPU,另一个用于 APP CPU。用户可以将每个文件加载到工具中单独分析。
|
||||
收集到跟踪数据后,用户可以使用特殊的工具来可视化结果并分析程序的行为。遗憾的是,SystemView 不支持从多个核心进行跟踪。所以当追踪双核模式下的 ESP32 时会生成两个文件:一个用于 PRO CPU,另一个用于 APP CPU。用户可以将每个文件加载到工具中单独分析。
|
||||
|
||||
在工具中单独分析每个核的跟踪数据是比较棘手的,幸运的是, Eclipse 中有一款 *Impulse* 的插件可以加载多个跟踪文件,并且可以在同一个视图中检查来自两个内核的事件。此外,与免费版的 SystemView 相比,此插件没有 1,000,000 个事件的限制。
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
一个 ESP-IDF 项目可以看作是多个不同组件的集合,例如一个显示当前湿度的网页服务器会包含以下组件:
|
||||
|
||||
- ESP32 基础库,包括 libc、ROM bindings 等
|
||||
- {IDF_TARGET_NAME} 基础库,包括 libc、ROM bindings 等
|
||||
- Wi-Fi 驱动
|
||||
- TCP/IP 协议栈
|
||||
- FreeRTOS 操作系统
|
||||
@ -30,7 +30,7 @@ ESP-IDF 可以显式地指定和配置每个组件。在构建项目的时候,
|
||||
- ``项目配置`` 保存在项目根目录下名为 ``sdkconfig`` 的文件中,可以通过 ``idf.py menuconfig`` 进行修改,且一个项目只能包含一个项目配置。
|
||||
- ``应用程序`` 是由 ESP-IDF 构建得到的可执行文件。一个项目通常会构建两个应用程序:项目应用程序(可执行的主文件,即用户自定义的固件)和引导程序(启动并初始化项目应用程序)。
|
||||
- ``组件`` 是模块化且独立的代码,会被编译成静态库(.a 文件)并链接到应用程序。部分组件由 ESP-IDF 官方提供,其他组件则来源于其它开源项目。
|
||||
- ``目标`` 特指运行构建后应用程序的硬件设备。ESP-IDF 当前仅支持 ``ESP32`` 这一个硬件目标。
|
||||
- ``目标`` 特指运行构建后应用程序的硬件设备。ESP-IDF 当前仅支持 ``{IDF_TARGET_NAME}`` 这一个硬件目标。
|
||||
|
||||
请注意,以下内容并不属于项目的组成部分:
|
||||
|
||||
@ -49,7 +49,7 @@ idf.py
|
||||
|
||||
- CMake_,配置待构建的系统
|
||||
- 命令行构建工具(Ninja_ 或 `GNU Make`)
|
||||
- `esptool.py`_,烧录 ESP32
|
||||
- `esptool.py`_,烧录 {IDF_TARGET_NAME}
|
||||
|
||||
:ref:`入门指南 <get-started-configure>` 简要介绍了如何设置 ``idf.py`` 用于配置、构建并烧录项目。
|
||||
|
||||
@ -68,10 +68,10 @@ idf.py
|
||||
|
||||
- ``idf.py clean`` 会把构建输出的文件从构建目录中删除,从而清理整个项目。下次构建时会强制“重新完整构建”这个项目。清理时,不会删除 CMake 配置输出及其他文件。
|
||||
- ``idf.py fullclean`` 会将整个 ``build`` 目录下的内容全部删除,包括所有 CMake 的配置输出文件。下次构建项目时,CMake 会从头开始配置项目。请注意,该命令会递归删除构建目录下的 *所有文件*,请谨慎使用。项目配置文件不会被删除。
|
||||
- ``idf.py flash`` 会在必要时自动构建项目,并将生成的二进制程序烧录进 ESP32 设备中。``-p`` 和 ``-b`` 选项可分别设置串口的设备名和烧录时的波特率。
|
||||
- ``idf.py monitor`` 用于显示 ESP32 设备的串口输出。``-p`` 选项可用于设置主机端串口的设备名,按下 ``Ctrl-]`` 可退出监视器。更多有关监视器的详情,请参阅 :doc:`tools/idf-monitor`。
|
||||
- ``idf.py flash`` 会在必要时自动构建项目,并将生成的二进制程序烧录进 {IDF_TARGET_NAME} 设备中。``-p`` 和 ``-b`` 选项可分别设置串口的设备名和烧录时的波特率。
|
||||
- ``idf.py monitor`` 用于显示 {IDF_TARGET_NAME} 设备的串口输出。``-p`` 选项可用于设置主机端串口的设备名,按下 ``Ctrl-]`` 可退出监视器。更多有关监视器的详情,请参阅 :doc:`tools/idf-monitor`。
|
||||
|
||||
多个 ``idf.py`` 命令可合并成一个,例如,``idf.py -p COM4 clean flash monitor`` 会依次清理源码树,构建项目,烧录进 ESP32 设备,最后运行串口监视器。
|
||||
多个 ``idf.py`` 命令可合并成一个,例如,``idf.py -p COM4 clean flash monitor`` 会依次清理源码树,构建项目,烧录进 {IDF_TARGET_NAME} 设备,最后运行串口监视器。
|
||||
|
||||
.. Note:: 环境变量 ``ESPPORT`` 和 ``ESPBAUD`` 可分别用作 ``-p`` 和 ``-b`` 选项的默认值。在命令行中,重新为这两个选项赋值,会覆盖其默认值。
|
||||
|
||||
@ -81,8 +81,8 @@ idf.py
|
||||
^^^^^^^^
|
||||
|
||||
- ``idf.py app``,``idf.py bootloader``,``idf.py partition_table`` 仅可用于从适用的项目中构建应用程序、引导程序或分区表。
|
||||
- ``idf.py app-flash`` 等匹配命令,仅将项目的特定部分烧录至 ESP32。
|
||||
- ``idf.py -p PORT erase_flash`` 会使用 esptool.py 擦除 ESP32 的整个 Flash。
|
||||
- ``idf.py app-flash`` 等匹配命令,仅将项目的特定部分烧录至 {IDF_TARGET_NAME}。
|
||||
- ``idf.py -p PORT erase_flash`` 会使用 esptool.py 擦除 {IDF_TARGET_NAME} 的整个 Flash。
|
||||
- ``idf.py size`` 会打印应用程序相关的大小信息,``idf.py size-components`` 和 ``idf.py size-files`` 这两个命令相似,分别用于打印每个组件或源文件的详细信息。
|
||||
- ``idf.py reconfigure`` 命令会重新运行 CMake_ (即便无需重新运行)。正常使用时,并不需要运行此命令,但当源码树中添加/删除文件后或更改 CMake cache 变量时,此命令会非常有用,例如,``idf.py -DNAME='VALUE' reconfigure`` 会将 CMake cache 中的变量 ``NAME`` 的值设置为 ``VALUE``。
|
||||
|
||||
@ -776,7 +776,7 @@ Flash 参数
|
||||
|
||||
您可以参照如下命令将任意烧录参数文件传递给 ``esptool.py``::
|
||||
|
||||
python esptool.py --chip esp32 write_flash @build/flash_project_args
|
||||
python esptool.py --chip {IDF_TARGET_PATH_NAME} write_flash @build/flash_project_args
|
||||
|
||||
也可以手动复制参数文件中的数据到命令行中执行。
|
||||
|
||||
|
@ -16,7 +16,7 @@ ESP-IDF 提供了 ``console`` 组件,它包含了开发基于串口的交互
|
||||
|
||||
行编辑功能允许用户通过按键输入来编辑命令,使用退格键删除符号,使用左/右键在命令中移动光标,使用上/下键导航到之前输入的命令,使用制表键(“Tab”)来自动补全命令。
|
||||
|
||||
.. note:: 此功能依赖于终端应用程序对 ANSI 转移符的支持,显示原始 UART 数据的串口监视器不能与行编辑库一同使用。如果运行 get_started/console 示例程序的时候观察到的输出结果是 ``[6n`` 或者类似的转义字符而不是命令行提示符 ``[esp32]>`` 时,就表明当前的串口监视器不支持 ANSI 转移字符。已知可用的串口监视程序有 GNU screen,minicom 和 idf_monitor.py(可以通过在项目目录下执行 ``idf.py monitor`` 来调用)。
|
||||
.. note:: 此功能依赖于终端应用程序对 ANSI 转移符的支持,显示原始 UART 数据的串口监视器不能与行编辑库一同使用。如果运行 get_started/console 示例程序的时候观察到的输出结果是 ``[6n`` 或者类似的转义字符而不是命令行提示符 ``[{IDFT_TARGET_PATH_NAME}]>`` 时,就表明当前的串口监视器不支持 ANSI 转移字符。已知可用的串口监视程序有 GNU screen,minicom 和 idf_monitor.py(可以通过在项目目录下执行 ``idf.py monitor`` 来调用)。
|
||||
|
||||
前往这里可以查看 `linenoise <https://github.com/antirez/linenoise>`_ 库提供的所有函数的描述。
|
||||
|
||||
|
@ -47,7 +47,7 @@ ESP-IDF 完全支持将外部存储器集成到您的应用程序中。您可以
|
||||
.. _external_ram_config_memory_map:
|
||||
|
||||
集成片外 RAM 到 {IDF_TARGET_NAME} 内存映射
|
||||
-----------------------------------
|
||||
---------------------------------------
|
||||
|
||||
在 :ref:`CONFIG_SPIRAM_USE` 中选择 "Integrate RAM into {IDF_TARGET_NAME} memory map(集成片外 RAM 到 {IDF_TARGET_NAME} 内存映射)" 选项。
|
||||
|
||||
|
@ -39,39 +39,28 @@
|
||||
|
||||
不管哪种情况,错误原因都会被打印在括号中。请参阅 :ref:`Guru-Meditation-Errors` 以查看所有可能的出错原因。
|
||||
|
||||
.. only:: esp32
|
||||
紧急处理程序接下来的行为将取决于 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_PANIC` 的设置,支持的选项包括:
|
||||
|
||||
紧急处理程序接下来的行为将取决于 :ref:`CONFIG_ESP32_PANIC` 的设置,支持的选项包括:
|
||||
|
||||
.. only:: esp32s2
|
||||
|
||||
紧急处理程序接下来的行为将取决于 :ref:`CONFIG_ESP32S2_PANIC` 的设置,支持的选项包括:
|
||||
|
||||
- 打印 CPU 寄存器,然后重启(``CONFIG_ESP32_PANIC_PRINT_REBOOT``)- 默认选项
|
||||
- 打印 CPU 寄存器,然后重启(``CONFIG_{IDF_TARGET_CFG_PREFIX}_PANIC_PRINT_REBOOT``)- 默认选项
|
||||
|
||||
打印系统发生异常时 CPU 寄存器的值,打印回溯,最后重启芯片。
|
||||
|
||||
- 打印 CPU 寄存器,然后暂停(``CONFIG_ESP32_PANIC_PRINT_HALT``)
|
||||
- 打印 CPU 寄存器,然后暂停(``CONFIG_E{IDF_TARGET_CFG_PREFIX}_PANIC_PRINT_HALT``)
|
||||
|
||||
与上一个选项类似,但不会重启,而是选择暂停程序的运行。重启程序需要外部执行复位操作。
|
||||
|
||||
- 静默重启(``CONFIG_ESP32_PANIC_SILENT_REBOOT``)
|
||||
- 静默重启(``CONFIG_{IDF_TARGET_CFG_PREFIX}_PANIC_SILENT_REBOOT``)
|
||||
|
||||
不打印 CPU 寄存器的值,也不打印回溯,立即重启芯片。
|
||||
|
||||
- 调用 GDB Stub(``CONFIG_ESP32_PANIC_GDBSTUB``)
|
||||
- 调用 GDB Stub(``CONFIG_{IDF_TARGET_CFG_PREFIX}_PANIC_GDBSTUB``)
|
||||
|
||||
启动 GDB 服务器,通过控制台 UART 接口与 GDB 进行通信。详细信息请参阅 :ref:`GDB-Stub`。
|
||||
|
||||
紧急处理程序的行为还受到另外两个配置项的影响:
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
- 如果 :ref:`CONFIG_ESP32_DEBUG_OCDAWARE` 被使能了(默认),紧急处理程序会检测 ESP32 是否已经连接 JTAG 调试器。如果检测成功,程序会暂停运行,并将控制权交给调试器。在这种情况下,寄存器和回溯不会被打印到控制台,并且也不会使用 GDB Stub 和 Core Dump 的功能。
|
||||
|
||||
.. only:: esp32s2
|
||||
|
||||
- 如果 :ref:`CONFIG_ESP32S2_DEBUG_OCDAWARE` 被使能了(默认),紧急处理程序会检测 ESP32-S2 是否已经连接 JTAG 调试器。如果检测成功,程序会暂停运行,并将控制权交给调试器。在这种情况下,寄存器和回溯不会被打印到控制台,并且也不会使用 GDB Stub 和 Core Dump 的功能。
|
||||
- 如果 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_DEBUG_OCDAWARE` 被使能了(默认),紧急处理程序会检测 {IDF_TARGET_NAME} 是否已经连接 JTAG 调试器。如果检测成功,程序会暂停运行,并将控制权交给调试器。在这种情况下,寄存器和回溯不会被打印到控制台,并且也不会使用 GDB Stub 和 Core Dump 的功能。
|
||||
|
||||
- 如果使能了 :doc:`Core Dump <core_dump>` 功能(``CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH`` 或者 ``CONFIG_ESP32_ENABLE_COREDUMP_TO_UART`` 选项),系统状态(任务堆栈和寄存器)会被转储到 Flash 或者 UART 以供后续分析。
|
||||
|
||||
@ -81,7 +70,7 @@
|
||||
:scale: 100%
|
||||
:caption: 紧急处理程序流程图(点击放大)
|
||||
:align: center
|
||||
|
||||
|
||||
blockdiag panic-handler {
|
||||
orientation = portrait;
|
||||
edge_layout = flowchart;
|
||||
@ -123,15 +112,15 @@
|
||||
寄存器转储与回溯
|
||||
----------------
|
||||
|
||||
除非启用了 ``CONFIG_ESP32_PANIC_SILENT_REBOOT`` 否则紧急处理程序会将 CPU 寄存器和回溯打印到控制台::
|
||||
除非启用了 ``CONFIG_{IDF_TARGET_CFG_PREFIX}_PANIC_SILENT_REBOOT`` 否则紧急处理程序会将 CPU 寄存器和回溯打印到控制台::
|
||||
|
||||
Core 0 register dump:
|
||||
PC : 0x400e14ed PS : 0x00060030 A0 : 0x800d0805 A1 : 0x3ffb5030
|
||||
A2 : 0x00000000 A3 : 0x00000001 A4 : 0x00000001 A5 : 0x3ffb50dc
|
||||
A6 : 0x00000000 A7 : 0x00000001 A8 : 0x00000000 A9 : 0x3ffb5000
|
||||
A10 : 0x00000000 A11 : 0x3ffb2bac A12 : 0x40082d1c A13 : 0x06ff1ff8
|
||||
A14 : 0x3ffb7078 A15 : 0x00000000 SAR : 0x00000014 EXCCAUSE: 0x0000001d
|
||||
EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0xffffffff
|
||||
PC : 0x400e14ed PS : 0x00060030 A0 : 0x800d0805 A1 : 0x3ffb5030
|
||||
A2 : 0x00000000 A3 : 0x00000001 A4 : 0x00000001 A5 : 0x3ffb50dc
|
||||
A6 : 0x00000000 A7 : 0x00000001 A8 : 0x00000000 A9 : 0x3ffb5000
|
||||
A10 : 0x00000000 A11 : 0x3ffb2bac A12 : 0x40082d1c A13 : 0x06ff1ff8
|
||||
A14 : 0x3ffb7078 A15 : 0x00000000 SAR : 0x00000014 EXCCAUSE: 0x0000001d
|
||||
EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0xffffffff
|
||||
|
||||
Backtrace: 0x400e14ed:0x3ffb5030 0x400d0802:0x3ffb5050
|
||||
|
||||
@ -146,21 +135,21 @@
|
||||
如果使用了 :doc:`IDF 监视器 <tools/idf-monitor>`,该工具会将程序计数器的值转换为对应的代码位置(函数名,文件名,行号),并加以注释::
|
||||
|
||||
Core 0 register dump:
|
||||
PC : 0x400e14ed PS : 0x00060030 A0 : 0x800d0805 A1 : 0x3ffb5030
|
||||
PC : 0x400e14ed PS : 0x00060030 A0 : 0x800d0805 A1 : 0x3ffb5030
|
||||
0x400e14ed: app_main at /Users/user/esp/example/main/main.cpp:36
|
||||
|
||||
A2 : 0x00000000 A3 : 0x00000001 A4 : 0x00000001 A5 : 0x3ffb50dc
|
||||
A6 : 0x00000000 A7 : 0x00000001 A8 : 0x00000000 A9 : 0x3ffb5000
|
||||
A10 : 0x00000000 A11 : 0x3ffb2bac A12 : 0x40082d1c A13 : 0x06ff1ff8
|
||||
A2 : 0x00000000 A3 : 0x00000001 A4 : 0x00000001 A5 : 0x3ffb50dc
|
||||
A6 : 0x00000000 A7 : 0x00000001 A8 : 0x00000000 A9 : 0x3ffb5000
|
||||
A10 : 0x00000000 A11 : 0x3ffb2bac A12 : 0x40082d1c A13 : 0x06ff1ff8
|
||||
0x40082d1c: _calloc_r at /Users/user/esp/esp-idf/components/newlib/syscalls.c:51
|
||||
|
||||
A14 : 0x3ffb7078 A15 : 0x00000000 SAR : 0x00000014 EXCCAUSE: 0x0000001d
|
||||
EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0xffffffff
|
||||
A14 : 0x3ffb7078 A15 : 0x00000000 SAR : 0x00000014 EXCCAUSE: 0x0000001d
|
||||
EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0xffffffff
|
||||
|
||||
Backtrace: 0x400e14ed:0x3ffb5030 0x400d0802:0x3ffb5050
|
||||
0x400e14ed: app_main at /Users/user/esp/example/main/main.cpp:36
|
||||
|
||||
0x400d0802: main_task at /Users/user/esp/esp-idf/components/esp32/cpu_start.c:470
|
||||
0x400d0802: main_task at /Users/user/esp/esp-idf/components/{IDF_TARGET_PATH_NAME}/cpu_start.c:470
|
||||
|
||||
若要查找发生严重错误的代码位置,请查看 "Backtrace" 的后面几行,发生严重错误的代码显示在顶行,后续几行显示的是调用堆栈。
|
||||
|
||||
@ -169,7 +158,7 @@
|
||||
GDB Stub
|
||||
--------
|
||||
|
||||
如果启用了 ``CONFIG_ESP32_PANIC_GDBSTUB`` 选项,在发生严重错误时,紧急处理程序不会复位芯片,相反,它将启动 GDB 远程协议服务器,通常称为 GDB Stub。发生这种情况时,可以让主机上运行的 GDB 实例通过 UART 端口连接到 ESP32。
|
||||
如果启用了 ``CONFIG_{IDF_TARGET_CFG_PREFIX}_PANIC_GDBSTUB`` 选项,在发生严重错误时,紧急处理程序不会复位芯片,相反,它将启动 GDB 远程协议服务器,通常称为 GDB Stub。发生这种情况时,可以让主机上运行的 GDB 实例通过 UART 端口连接到 {IDF_TARGET_NAME}。
|
||||
|
||||
如果使用了 :doc:`IDF 监视器 <tools/idf-monitor>`,该工具会在 UART 端口检测到 GDB Stub 提示符后自动启动 GDB,输出会类似于::
|
||||
|
||||
@ -180,7 +169,7 @@ GDB Stub
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
|
||||
and "show warranty" for details.
|
||||
This GDB was configured as "--host=x86_64-build_apple-darwin16.3.0 --target=xtensa-esp32-elf".
|
||||
This GDB was configured as "--host=x86_64-build_apple-darwin16.3.0 --target=xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf".
|
||||
Type "show configuration" for configuration details.
|
||||
For bug reporting instructions, please see:
|
||||
<http://www.gnu.org/software/gdb/bugs/>.
|
||||
@ -193,7 +182,7 @@ GDB Stub
|
||||
0x400e1b41 in app_main ()
|
||||
at /Users/user/esp/example/main/main.cpp:36
|
||||
36 *((int*) 0) = 0;
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
在 GDB 会话中,我们可以检查 CPU 寄存器,本地和静态变量以及内存中任意位置的值。但是不支持设置断点,改变 PC 值或者恢复程序的运行。若要复位程序,请退出 GDB 会话,在 IDF 监视器 中连续输入 Ctrl-T Ctrl-R,或者按下开发板上的复位按键也可以重新运行程序。
|
||||
|
||||
@ -219,10 +208,10 @@ IllegalInstruction
|
||||
- FreeRTOS 中的任务函数已返回。在 FreeRTOS 中,如果想终止任务函数,需要调用 :cpp:func:`vTaskDelete` 函数释放当前任务的资源,而不是直接返回。
|
||||
|
||||
- 无法从 SPI Flash 中加载下一条指令,这通常发生在:
|
||||
|
||||
|
||||
- 应用程序将 SPI Flash 的引脚重新配置为其它功能(如 GPIO,UART 等等)。有关 SPI Flash 引脚的详细信息,请参阅硬件设计指南和芯片/模组的数据手册。
|
||||
|
||||
- 某些外部设备意外连接到 SPI Flash 的引脚上,干扰了 ESP32 和 SPI Flash 之间的通信。
|
||||
|
||||
- 某些外部设备意外连接到 SPI Flash 的引脚上,干扰了 {IDF_TARGET_NAME} 和 SPI Flash 之间的通信。
|
||||
|
||||
|
||||
InstrFetchProhibited
|
||||
@ -277,13 +266,7 @@ Cache disabled but cached memory region accessed
|
||||
欠压
|
||||
^^^^
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
ESP32 内部集成掉电检测电路,并且会默认启用。如果电源电压低于安全值,掉电检测器可以触发系统复位。掉电检测器可以使用 :ref:`CONFIG_ESP32_BROWNOUT_DET` 和 :ref:`CONFIG_ESP32_BROWNOUT_DET_LVL_SEL` 这两个选项进行设置。
|
||||
|
||||
.. only:: esp32s2
|
||||
|
||||
ESP32-S2 内部集成掉电检测电路,并且会默认启用。如果电源电压低于安全值,掉电检测器可以触发系统复位。掉电检测器可以使用 :ref:`CONFIG_ESP32S2_BROWNOUT_DET` 和 :ref:`CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL` 这两个选项进行设置。
|
||||
{IDF_TARGET_NAME} 内部集成掉电检测电路,并且会默认启用。如果电源电压低于安全值,掉电检测器可以触发系统复位。掉电检测器可以使用 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_BROWNOUT_DET` 和 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_BROWNOUT_DET_LVL_SEL` 这两个选项进行设置。
|
||||
|
||||
当掉电检测器被触发时,会打印如下信息::
|
||||
|
||||
|
@ -5,12 +5,12 @@ ESP-IDF 编程注意事项
|
||||
应用程序的启动流程
|
||||
------------------
|
||||
|
||||
本文将会介绍 ESP32 从上电到运行 ``app_main``
|
||||
本文将会介绍 {IDF_TARGET_NAME} 从上电到运行 ``app_main``
|
||||
函数中间所经历的步骤(即启动流程)。
|
||||
|
||||
宏观上,该启动流程可以分为如下 3 个步骤:
|
||||
|
||||
1. 一级引导程序被固化在了 ESP32 内部的 ROM 中,它会从 Flash 的
|
||||
1. 一级引导程序被固化在了 {IDF_TARGET_NAME} 内部的 ROM 中,它会从 Flash 的
|
||||
``0x1000`` 偏移地址处加载二级引导程序至 RAM(IRAM & DRAM) 中。
|
||||
|
||||
2. 二级引导程序从 Flash 中加载分区表和主程序镜像至内存中,主程序中包含了
|
||||
@ -26,10 +26,10 @@ ESP-IDF 编程注意事项
|
||||
SoC 复位后,PRO CPU 会立即开始运行,执行复位向量代码,而 APP CPU
|
||||
仍然保持复位状态。在启动过程中,PRO CPU 会执行所有的初始化操作。APP CPU
|
||||
的复位状态会在应用程序启动代码的 ``call_start_cpu0``
|
||||
函数中失效。复位向量代码位于 ESP32 芯片掩膜 ROM 的 ``0x40000400``
|
||||
函数中失效。复位向量代码位于 {IDF_TARGET_NAME} 芯片掩膜 ROM 的 ``0x40000400``
|
||||
地址处,该地址不能被修改。
|
||||
|
||||
复位向量调用的启动代码会根据 ``GPIO_STRAP_REG`` 寄存器的值来确定 ESP32
|
||||
复位向量调用的启动代码会根据 ``GPIO_STRAP_REG`` 寄存器的值来确定 {IDF_TARGET_NAME}
|
||||
的工作模式,该寄存器保存着复位后 bootstrap
|
||||
引脚的电平状态。根据不同的复位原因,程序会执行不同的操作:
|
||||
|
||||
@ -67,7 +67,7 @@ SoC 复位后,PRO CPU 会立即开始运行,执行复位向量代码,而 A
|
||||
|
||||
在 ESP-IDF 中,存放在 Flash 的 ``0x1000``
|
||||
偏移地址处的二进制镜像就是二级引导程序。二级引导程序的源码可以在 ESP-IDF
|
||||
的 components/bootloader 目录下找到。请注意,对于 ESP32
|
||||
的 components/bootloader 目录下找到。请注意,对于 {IDF_TARGET_NAME}
|
||||
芯片来说,这并不是唯一的安排程序镜像的方式。事实上用户完全可以把一个功能齐全的应用程序烧写到
|
||||
Flash 的 ``0x1000`` 偏移地址处运行,但这超出本文档的范围。ESP-IDF
|
||||
使用二级引导程序可以增加 Flash 分区的灵活性(使用分区表),并且方便实现
|
||||
@ -99,7 +99,7 @@ ESP-IDF 中。目前,可以通过将 bootloader
|
||||
应用程序启动阶段
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
ESP-IDF 应用程序的入口是 ``components/esp32/cpu_start.c`` 文件中的
|
||||
ESP-IDF 应用程序的入口是 ``components/{IDF_TARGET_PATH_NAME}/cpu_start.c`` 文件中的
|
||||
``call_start_cpu0``
|
||||
函数,该函数主要完成了两件事,一是启用堆分配器,二是使 APP CPU
|
||||
跳转到其入口点—— ``call_start_cpu1`` 函数。PRO CPU 上的代码会给 APP
|
||||
@ -110,7 +110,7 @@ CPU 跳转到 ``start_cpu0`` 函数,APP CPU 跳转到 ``start_cpu1`` 函数。
|
||||
``start_cpu0`` 和 ``start_cpu1``
|
||||
这两个函数都是弱类型的,这意味着如果某些特定的应用程序需要修改初始化顺序,就可以通过重写这两个函数来实现。 ``start_cpu0``
|
||||
默认的实现方式是初始化用户在 ``menuconfig``
|
||||
中选择的组件,具体实现步骤可以阅读 ``components/esp32/cpu_start.c``
|
||||
中选择的组件,具体实现步骤可以阅读 ``components/{IDF_TARGET_PATH_NAME}/cpu_start.c``
|
||||
文件中的源码。请注意,此阶段会调用应用程序中存在的 C++
|
||||
全局构造函数。一旦所有必要的组件都初始化好,就会创建 *main
|
||||
task* ,并启动 FreeRTOS 的调度器。
|
||||
@ -129,7 +129,7 @@ task* ,并启动 FreeRTOS 的调度器。
|
||||
应用程序的内存布局
|
||||
------------------
|
||||
|
||||
ESP32 芯片具有灵活的内存映射功能,本小节将介绍 ESP-IDF
|
||||
{IDF_TARGET_NAME} 芯片具有灵活的内存映射功能,本小节将介绍 ESP-IDF
|
||||
默认使用这些功能的方式。
|
||||
|
||||
ESP-IDF 应用程序的代码可以放在以下内存区域之一。
|
||||
@ -154,7 +154,7 @@ RAM。除了开始的 64kB 用作 PRO CPU 和 APP CPU
|
||||
|
||||
void IRAM_ATTR gpio_isr_handler(void* arg)
|
||||
{
|
||||
// ...
|
||||
// ...
|
||||
}
|
||||
|
||||
下面列举了应用程序中可能或者应该放入 IRAM 中运行例子。
|
||||
@ -169,7 +169,7 @@ RAM。除了开始的 64kB 用作 PRO CPU 和 APP CPU
|
||||
DRAM 中。
|
||||
|
||||
- 可以将一些时间关键的代码放在 IRAM 中,这样可以缩减从 Flash
|
||||
加载代码所消耗的时间。ESP32 是通过 32kB 的高速缓存来从外部 Flash
|
||||
加载代码所消耗的时间。{IDF_TARGET_NAME} 是通过 32kB 的高速缓存来从外部 Flash
|
||||
中读取代码和数据的,将函数放在 IRAM
|
||||
中运行可以减少由高速缓存未命中引起的时间延迟。
|
||||
|
||||
|
@ -11,7 +11,7 @@ Linux 环境下从源码编译 OpenOCD
|
||||
下载 OpenOCD 源码
|
||||
=================
|
||||
|
||||
支持 ESP32 的 OpenOCD 源代码可以从乐鑫官方的 GitHub 获得,网址为 https://github.com/espressif/openocd-esp32。请使用以下命令来下载源代码::
|
||||
支持 {IDF_TARGET_NAME} 的 OpenOCD 源代码可以从乐鑫官方的 GitHub 获得,网址为 https://github.com/espressif/openocd-esp32。请使用以下命令来下载源代码::
|
||||
|
||||
cd ~/esp
|
||||
git clone --recursive https://github.com/espressif/openocd-esp32.git
|
||||
@ -73,4 +73,4 @@ Linux 环境下从源码编译 OpenOCD
|
||||
下一步
|
||||
======
|
||||
|
||||
想要进一步配置调试环境,请前往 :ref:`jtag-debugging-configuring-esp32-target` 章节。
|
||||
想要进一步配置调试环境,请前往 :ref:`jtag-debugging-configuring-target` 章节。
|
||||
|
@ -10,7 +10,7 @@ MacOS 环境下从源码编译 OpenOCD
|
||||
下载 OpenOCD 源码
|
||||
=================
|
||||
|
||||
支持 ESP32 的 OpenOCD 源代码可以从乐鑫官方的 GitHub 获得,网址为 https://github.com/espressif/openocd-esp32。请使用以下命令来下载源代码::
|
||||
支持 {IDF_TARGET_NAME} 的 OpenOCD 源代码可以从乐鑫官方的 GitHub 获得,网址为 https://github.com/espressif/openocd-esp32。请使用以下命令来下载源代码::
|
||||
|
||||
cd ~/esp
|
||||
git clone --recursive https://github.com/espressif/openocd-esp32.git
|
||||
@ -50,5 +50,4 @@ MacOS 环境下从源码编译 OpenOCD
|
||||
下一步
|
||||
======
|
||||
|
||||
想要进一步配置调试环境,请前往 :ref:`jtag-debugging-configuring-esp32-target` 章节。
|
||||
|
||||
想要进一步配置调试环境,请前往 :ref:`jtag-debugging-configuring-target` 章节。
|
||||
|
@ -11,7 +11,7 @@ Windows 环境下从源码编译 OpenOCD
|
||||
下载 OpenOCD 源码
|
||||
=================
|
||||
|
||||
支持 ESP32 的 OpenOCD 源代码可以从乐鑫官方的 GitHub 获得,网址为 https://github.com/espressif/openocd-esp32。请使用以下命令来下载源代码::
|
||||
支持 {IDF_TARGET_NAME} 的 OpenOCD 源代码可以从乐鑫官方的 GitHub 获得,网址为 https://github.com/espressif/openocd-esp32。请使用以下命令来下载源代码::
|
||||
|
||||
cd ~/esp
|
||||
git clone --recursive https://github.com/espressif/openocd-esp32.git
|
||||
@ -72,4 +72,4 @@ Windows 环境下从源码编译 OpenOCD
|
||||
下一步
|
||||
======
|
||||
|
||||
想要进一步配置调试环境,请前往 :ref:`jtag-debugging-configuring-esp32-target` 章节。
|
||||
想要进一步配置调试环境,请前往 :ref:`jtag-debugging-configuring-target` 章节。
|
||||
|
@ -2,13 +2,15 @@
|
||||
==================
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
关于适配 OpenOCD 和 ESP32 的 JTAG 接口选择问题,请参考 :ref:`jtag-debugging-selecting-jtag-adapter` 章节,确保 JTAG 适配器能够与 OpenOCD 和 ESP32 一同工作。然后按照以下三个步骤进行设置,使其正常工作。
|
||||
关于适配 OpenOCD 和 {IDF_TARGET_NAME} 的 JTAG 接口选择问题,请参考 :ref:`jtag-debugging-selecting-jtag-adapter` 章节,确保 JTAG 适配器能够与 OpenOCD 和 {IDF_TARGET_NAME} 一同工作。然后按照以下三个步骤进行设置,使其正常工作。
|
||||
|
||||
|
||||
配置硬件
|
||||
^^^^^^^^
|
||||
|
||||
1. 找到 JTAG 接口和 ESP32 板上需要相互连接并建立通信的引脚/信号。
|
||||
1. 找到 JTAG 接口和 {IDF_TARGET_NAME} 板上需要相互连接并建立通信的引脚/信号。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
+---+---------------+-----------+
|
||||
| | ESP32 引脚 | JTAG 信号 |
|
||||
@ -26,9 +28,27 @@
|
||||
| 6 | GND | GND |
|
||||
+---+---------------+-----------+
|
||||
|
||||
2. 检查 ESP32 上用于 JTAG 通信的的引脚是否被连接到了其它硬件上,这可能会影响 JTAG 的工作。
|
||||
.. only:: esp32s2
|
||||
|
||||
3. 连接 ESP32 和 JTAG 接口上的引脚/信号。
|
||||
+---+-----------------------+-------------+
|
||||
| | ESP32-S2 Pin | JTAG Signal |
|
||||
+===+=======================+=============+
|
||||
| 1 | CHIP_PU | TRST_N |
|
||||
+---+-----------------------+-------------+
|
||||
| 2 | MTDO / GPIO40 | TDO |
|
||||
+---+-----------------------+-------------+
|
||||
| 3 | MTDI / GPIO41 | TDI |
|
||||
+---+-----------------------+-------------+
|
||||
| 4 | MTCK / GPIO39 | TCK |
|
||||
+---+-----------------------+-------------+
|
||||
| 5 | MTMS / GPIO42 | TMS |
|
||||
+---+-----------------------+-------------+
|
||||
| 6 | GND | GND |
|
||||
+---+-----------------------+-------------+
|
||||
|
||||
2. 检查 {IDF_TARGET_NAME} 上用于 JTAG 通信的的引脚是否被连接到了其它硬件上,这可能会影响 JTAG 的工作。
|
||||
|
||||
3. 连接 {IDF_TARGET_NAME} 和 JTAG 接口上的引脚/信号。
|
||||
|
||||
|
||||
配置驱动
|
||||
@ -39,7 +59,7 @@
|
||||
连接
|
||||
^^^^
|
||||
|
||||
将 JTAG 接口连接到计算机,打开 ESP32 和 JTAG 接口板上的电源,然后检查计算机是否可以识别到 JTAG 接口。
|
||||
将 JTAG 接口连接到计算机,打开 {IDF_TARGET_NAME} 和 JTAG 接口板上的电源,然后检查计算机是否可以识别到 JTAG 接口。
|
||||
|
||||
|
||||
要继续设置调试环境,请前往 :ref:`jtag-debugging-run-openocd` 章节。
|
||||
|
@ -38,7 +38,7 @@
|
||||
浏览代码,查看堆栈和线程
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
当目标暂停时,调试器会在 “Debug” 窗口中显示线程的列表,程序暂停的代码行在下面的另一个窗口中被高亮显示,如下图所示。此时板子上的 LED 停止了闪烁。
|
||||
当目标暂停时,调试器会在 “Debug” 窗口中显示线程的列表,程序暂停的代码行在下面的另一个窗口中被高亮显示,如下图所示。此时板子上的 LED 停止了闪烁。
|
||||
|
||||
.. figure:: ../../../_static/debugging-target-halted.jpg
|
||||
:align: center
|
||||
@ -47,7 +47,7 @@
|
||||
|
||||
调试时目标停止
|
||||
|
||||
暂停的程序所在线程也会被展开,显示函数调用的堆栈,它表示直到目标暂停所在代码行(下图高亮处)为止的相关函数的调用关系。1 号线程下函数调用堆栈的第一行包含了最后一个调用的函数 ``app_main()``,根据下一行显示,它又是在函数 ``main_task()`` 中被调用的。堆栈的每一行还包含调用函数的文件名和行号。通过单击每个堆栈的条目,在下面的窗口中,你将看到此文件的内容。
|
||||
暂停的程序所在线程也会被展开,显示函数调用的堆栈,它表示直到目标暂停所在代码行(下图高亮处)为止的相关函数的调用关系。1 号线程下函数调用堆栈的第一行包含了最后一个调用的函数 ``app_main()``,根据下一行显示,它又是在函数 ``main_task()`` 中被调用的。堆栈的每一行还包含调用函数的文件名和行号。通过单击每个堆栈的条目,在下面的窗口中,你将看到此文件的内容。
|
||||
|
||||
通过展开线程,你可以浏览整个应用程序。展开 5 号线程,它包含了更长的函数调用堆栈,你可以看到函数调用旁边的数字,比如 ``0x4000000c``,它们代表未以源码形式提供的二进制代码所在的内存地址。
|
||||
|
||||
@ -153,7 +153,16 @@
|
||||
|
||||
要显示或者设置内存的内容,请使用“调试”视图中位于底部的 “Memory” 选项卡。
|
||||
|
||||
在 “Memory” 选项卡下,我们将在内存地址 ``0x3FF44004`` 处读取和写入内容。该地址也是 ``GPIO_OUT_REG`` 寄存器的地址,可以用来控制(设置或者清除)某个 GPIO 的电平。关于该寄存器的更多详细信息,请参阅 `ESP32 技术参考手册 <https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_cn.pdf>`_ 中的 IO_MUX 和 GPIO Matrix 章节。
|
||||
在 “Memory” 选项卡下,我们将在内存地址 ``0x3FF44004`` 处读取和写入内容。该地址也是 ``GPIO_OUT_REG`` 寄存器的地址,可以用来控制(设置或者清除)某个 GPIO 的电平。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
关于该寄存器的更多详细信息,请参阅 `ESP32 技术参考手册 <https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_cn.pdf>`_ 中的 IO_MUX 和 GPIO Matrix 章节。
|
||||
|
||||
.. only:: esp32s2beta
|
||||
|
||||
关于该寄存器的更多详细信息,请参阅 `ESP32-S2 技术参考手册 <https://espressif.com/sites/default/files/documentation/esp32s2_technical_reference_manual_cn.pdf>`_ 中的 IO_MUX 和 GPIO Matrix 章节。
|
||||
|
||||
|
||||
同样在 ``blink.c`` 项目文件中,在两个 ``gpio_set_level`` 语句的后面各设置一个断点,单击 “Memory” 选项卡,然后单击 “Add Memory Monitor” 按钮,在弹出的对话框中输入 ``0x3FF44004``。
|
||||
|
||||
@ -184,7 +193,7 @@
|
||||
|
||||
常见的调试任务是在程序运行期间检查程序中某个变量的值,为了演示这个功能,更新 ``blink.c`` 文件,在 ``blink_task`` 函数的上面添加一个全局变量的声明 ``int i``,然后在 ``while(1)`` 里添加 ``i++``,这样每次 LED 改变状态的时候,变量 ``i`` 都会增加 1。
|
||||
|
||||
退出调试器,这样就不会与新代码混淆,然后重新构建并烧写代码到 ESP32 中,接着重启调试器。注意,这里不需要我们重启 OpenOCD。
|
||||
退出调试器,这样就不会与新代码混淆,然后重新构建并烧写代码到 {IDF_TARGET_NAME} 中,接着重启调试器。注意,这里不需要我们重启 OpenOCD。
|
||||
|
||||
一旦程序停止运行,在代码 ``i++`` 处添加一个断点。
|
||||
|
||||
@ -229,7 +238,7 @@
|
||||
|
||||
Temporary breakpoint 1, app_main () at /home/user-name/esp/blink/main/./blink.c:43
|
||||
43 xTaskCreate(&blink_task, "blink_task", configMINIMAL_STACK_SIZE, NULL, 5, NULL);
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
|
||||
|
||||
@ -250,19 +259,19 @@
|
||||
浏览代码,查看堆栈和线程
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
当看到 ``(gdb)`` 提示符的时候,应用程序已停止运行,LED 也停止闪烁。
|
||||
当看到 ``(gdb)`` 提示符的时候,应用程序已停止运行,LED 也停止闪烁。
|
||||
|
||||
要找到代码暂停的位置,输入 ``l`` 或者 ``list`` 命令,调试器会打印出停止点(``blink.c`` 代码文件的第 43 行)附近的几行代码 ::
|
||||
|
||||
(gdb) l
|
||||
38 }
|
||||
39 }
|
||||
40
|
||||
40
|
||||
41 void app_main()
|
||||
42 {
|
||||
43 xTaskCreate(&blink_task, "blink_task", configMINIMAL_STACK_SIZE, NULL, 5, NULL);
|
||||
44 }
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
|
||||
也可以通过输入 ``l 30, 40`` 等命令来查看特定行号范围内的代码。
|
||||
@ -271,15 +280,15 @@
|
||||
|
||||
(gdb) bt
|
||||
#0 app_main () at /home/user-name/esp/blink/main/./blink.c:43
|
||||
#1 0x400d057e in main_task (args=0x0) at /home/user-name/esp/esp-idf/components/esp32/./cpu_start.c:339
|
||||
(gdb)
|
||||
#1 0x400d057e in main_task (args=0x0) at /home/user-name/esp/esp-idf/components/{IDF_TARGET_PATH_NAME}/./cpu_start.c:339
|
||||
(gdb)
|
||||
|
||||
输出的第 0 行表示应用程序暂停之前调用的最后一个函数,即我们之前列出的 ``app_main ()``。``app_main ()`` 又被位于 ``cpu_start.c`` 文件第 339 行的 ``main_task`` 函数调用。
|
||||
输出的第 0 行表示应用程序暂停之前调用的最后一个函数,即我们之前列出的 ``app_main ()``。``app_main ()`` 又被位于 ``cpu_start.c`` 文件第 339 行的 ``main_task`` 函数调用。
|
||||
|
||||
想查看 ``cpu_start.c`` 文件中 ``main_task`` 函数的上下文,需要输入 ``frame N``,其中 N = 1,因为根据前面的输出,``main_task`` 位于 #1 下::
|
||||
|
||||
(gdb) frame 1
|
||||
#1 0x400d057e in main_task (args=0x0) at /home/user-name/esp/esp-idf/components/esp32/./cpu_start.c:339
|
||||
#1 0x400d057e in main_task (args=0x0) at /home/user-name/esp/esp-idf/components/{IDF_TARGET_PATH_NAME}/./cpu_start.c:339
|
||||
339 app_main();
|
||||
(gdb)
|
||||
|
||||
@ -294,8 +303,8 @@
|
||||
339 app_main();
|
||||
340 vTaskDelete(NULL);
|
||||
341 }
|
||||
342
|
||||
(gdb)
|
||||
342
|
||||
(gdb)
|
||||
|
||||
通过打印前面的一些行,你会看到我们一直在寻找的 ``main_task`` 函数::
|
||||
|
||||
@ -316,27 +325,27 @@
|
||||
339 app_main();
|
||||
340 vTaskDelete(NULL);
|
||||
341 }
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
如果要查看其他代码,可以输入 ``i threads`` 命令,则会输出目标板上运行的线程列表::
|
||||
|
||||
(gdb) i threads
|
||||
Id Target Id Frame
|
||||
Id Target Id Frame
|
||||
8 Thread 1073411336 (dport) 0x400d0848 in dport_access_init_core (arg=<optimized out>)
|
||||
at /home/user-name/esp/esp-idf/components/esp32/./dport_access.c:170
|
||||
7 Thread 1073408744 (ipc0) xQueueGenericReceive (xQueue=0x3ffae694, pvBuffer=0x0, xTicksToWait=1644638200,
|
||||
at /home/user-name/esp/esp-idf/components/{IDF_TARGET_PATH_NAME}/./dport_access.c:170
|
||||
7 Thread 1073408744 (ipc0) xQueueGenericReceive (xQueue=0x3ffae694, pvBuffer=0x0, xTicksToWait=1644638200,
|
||||
xJustPeeking=0) at /home/user-name/esp/esp-idf/components/freertos/./queue.c:1452
|
||||
6 Thread 1073431096 (Tmr Svc) prvTimerTask (pvParameters=0x0)
|
||||
at /home/user-name/esp/esp-idf/components/freertos/./timers.c:445
|
||||
5 Thread 1073410208 (ipc1 : Running) 0x4000bfea in ?? ()
|
||||
4 Thread 1073432224 (dport) dport_access_init_core (arg=0x0)
|
||||
at /home/user-name/esp/esp-idf/components/esp32/./dport_access.c:150
|
||||
at /home/user-name/esp/esp-idf/components/{IDF_TARGET_PATH_NAME}/./dport_access.c:150
|
||||
3 Thread 1073413156 (IDLE) prvIdleTask (pvParameters=0x0)
|
||||
at /home/user-name/esp/esp-idf/components/freertos/./tasks.c:3282
|
||||
2 Thread 1073413512 (IDLE) prvIdleTask (pvParameters=0x0)
|
||||
at /home/user-name/esp/esp-idf/components/freertos/./tasks.c:3282
|
||||
* 1 Thread 1073411772 (main : Running) app_main () at /home/user-name/esp/blink/main/./blink.c:43
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
线程列表显示了每个线程最后一个被调用的函数以及所在的 C 源文件名(如果存在的话)。
|
||||
|
||||
@ -359,7 +368,7 @@
|
||||
#6 0x4000000c in ?? ()
|
||||
#7 0x4000000c in ?? ()
|
||||
#8 0x4000000c in ?? ()
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
如上所示,回溯可能会包含多个条目,方便查看直至目标停止运行的函数调用顺序。如果找不到某个函数的源码文件,将会使用问号 ``??`` 替代,这表示该函数是以二进制格式提供的。像 ``0x4000bfea`` 这样的值是被调用函数所在的内存地址。
|
||||
|
||||
@ -384,18 +393,18 @@
|
||||
|
||||
(gdb) c
|
||||
Continuing.
|
||||
Target halted. PRO_CPU: PC=0x400DB6F6 (active) APP_CPU: PC=0x400D10D8
|
||||
Target halted. PRO_CPU: PC=0x400DB6F6 (active) APP_CPU: PC=0x400D10D8
|
||||
|
||||
Breakpoint 2, blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:33
|
||||
33 gpio_set_level(BLINK_GPIO, 0);
|
||||
(gdb) c
|
||||
Continuing.
|
||||
Target halted. PRO_CPU: PC=0x400DB6F8 (active) APP_CPU: PC=0x400D10D8
|
||||
Target halted. PRO_CPU: PC=0x400DB704 (active) APP_CPU: PC=0x400D10D8
|
||||
Target halted. PRO_CPU: PC=0x400DB6F8 (active) APP_CPU: PC=0x400D10D8
|
||||
Target halted. PRO_CPU: PC=0x400DB704 (active) APP_CPU: PC=0x400D10D8
|
||||
|
||||
Breakpoint 3, blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:36
|
||||
36 gpio_set_level(BLINK_GPIO, 1);
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
只有在输入命令 ``c`` 恢复程序运行后才能看到 LED 改变状态。
|
||||
|
||||
@ -407,16 +416,16 @@
|
||||
breakpoint already hit 1 time
|
||||
3 breakpoint keep y 0x400db704 in blink_task at /home/user-name/esp/blink/main/./blink.c:36
|
||||
breakpoint already hit 1 time
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
请注意,断点序号(在 ``Num`` 栏列出)从 2 开始,这是因为在调试器启动时执行 ``thb app_main`` 命令已经在 ``app_main()`` 函数处建立了第一个断点。由于它是一个临时断点,已经被自动删除,所以没有被列出。
|
||||
|
||||
要删除一个断点,请输入 ``delete N`` 命令(或者简写成 ``d N``),其中 ``N`` 代表断点序号::
|
||||
要删除一个断点,请输入 ``delete N`` 命令(或者简写成 ``d N``),其中 ``N`` 代表断点序号::
|
||||
|
||||
(gdb) delete 1
|
||||
No breakpoint number 1.
|
||||
(gdb) delete 2
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
更多关于断点的信息,请参阅 :ref:`jtag-debugging-tip-breakpoints` 和 :ref:`jtag-debugging-tip-where-breakpoints`。
|
||||
|
||||
@ -437,9 +446,9 @@
|
||||
|
||||
Program received signal SIGINT, Interrupt.
|
||||
[Switching to Thread 1073413512]
|
||||
0x400d0c00 in esp_vApplicationIdleHook () at /home/user-name/esp/esp-idf/components/esp32/./freertos_hooks.c:52
|
||||
0x400d0c00 in esp_vApplicationIdleHook () at /home/user-name/esp/esp-idf/components/{IDF_TARGET_PATH_NAME}/./freertos_hooks.c:52
|
||||
52 asm("waiti 0");
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
在上图所示的情况下,应用程序已经在 ``freertos_hooks.c`` 文件的第 52 行暂停运行,现在您可以通过输入 ``c`` 再次将其恢复运行或者进行如下所述的一些调试工作。
|
||||
|
||||
@ -461,44 +470,44 @@
|
||||
Num Type Disp Enb Address What
|
||||
3 breakpoint keep y 0x400db704 in blink_task at /home/user-name/esp/blink/main/./blink.c:36
|
||||
breakpoint already hit 1 time
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
输入 ``c`` 恢复程序运行然后等它在断点处停止运行::
|
||||
|
||||
(gdb) c
|
||||
Continuing.
|
||||
Target halted. PRO_CPU: PC=0x400DB754 (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB754 (active) APP_CPU: PC=0x400D1128
|
||||
|
||||
Breakpoint 3, blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:36
|
||||
36 gpio_set_level(BLINK_GPIO, 1);
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
然后输入 ``n`` 多次,观察调试器是如何单步执行一行代码的::
|
||||
|
||||
(gdb) n
|
||||
Target halted. PRO_CPU: PC=0x400DB756 (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB758 (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DC04C (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB75B (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB756 (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB758 (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DC04C (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB75B (active) APP_CPU: PC=0x400D1128
|
||||
37 vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
(gdb) n
|
||||
Target halted. PRO_CPU: PC=0x400DB75E (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400846FC (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB761 (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB746 (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB75E (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400846FC (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB761 (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB746 (active) APP_CPU: PC=0x400D1128
|
||||
33 gpio_set_level(BLINK_GPIO, 0);
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
如果你输入 ``s``,那么调试器将进入子程序::
|
||||
|
||||
(gdb) s
|
||||
Target halted. PRO_CPU: PC=0x400DB748 (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB74B (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DC04C (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DC04F (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB748 (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB74B (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DC04C (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DC04F (active) APP_CPU: PC=0x400D1128
|
||||
gpio_set_level (gpio_num=GPIO_NUM_4, level=0) at /home/user-name/esp/esp-idf/components/driver/./gpio.c:183
|
||||
183 GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error", ESP_ERR_INVALID_ARG);
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
上述例子中,调试器进入 ``gpio_set_level(BLINK_GPIO, 0)`` 代码内部,同时代码窗口快速切换到 ``gpio.c`` 驱动文件。
|
||||
|
||||
@ -518,8 +527,8 @@
|
||||
|
||||
(gdb) c
|
||||
Continuing.
|
||||
Target halted. PRO_CPU: PC=0x400DB75E (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB74E (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB75E (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB74E (active) APP_CPU: PC=0x400D1128
|
||||
|
||||
Breakpoint 2, blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:34
|
||||
34 vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
@ -527,14 +536,14 @@
|
||||
0x3ff44004: 0x00000000
|
||||
(gdb) c
|
||||
Continuing.
|
||||
Target halted. PRO_CPU: PC=0x400DB751 (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB75B (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB751 (active) APP_CPU: PC=0x400D1128
|
||||
Target halted. PRO_CPU: PC=0x400DB75B (active) APP_CPU: PC=0x400D1128
|
||||
|
||||
Breakpoint 3, blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:37
|
||||
37 vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
(gdb) x /1wx 0x3FF44004
|
||||
0x3ff44004: 0x00000010
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
如果闪烁的 LED 连接到了 GPIO4,那么每次 LED 改变状态时你会看到第 4 比特被翻转::
|
||||
|
||||
@ -558,7 +567,7 @@
|
||||
|
||||
常见的调试任务是在程序运行期间检查程序中某个变量的值,为了能够演示这个功能,更新 ``blink.c`` 文件,在 ``blink_task`` 函数的上面添加一个全局变量的声明 ``int i``,然后在 ``while(1)`` 里添加 ``i++``,这样每次 LED 改变状态的时候,变量 ``i`` 都会增加 1。
|
||||
|
||||
退出调试器,这样就不会与新代码混淆,然后重新构建并烧写代码到 ESP32 中,接着重启调试器。注意,这里不需要我们重启 OpenOCD。
|
||||
退出调试器,这样就不会与新代码混淆,然后重新构建并烧写代码到 {IDF_TARGET_NAME} 中,接着重启调试器。注意,这里不需要我们重启 OpenOCD。
|
||||
|
||||
一旦程序停止运行,输入命令 ``watch i``::
|
||||
|
||||
@ -570,7 +579,7 @@
|
||||
|
||||
(gdb) c
|
||||
Continuing.
|
||||
Target halted. PRO_CPU: PC=0x400DB751 (active) APP_CPU: PC=0x400D0811
|
||||
Target halted. PRO_CPU: PC=0x400DB751 (active) APP_CPU: PC=0x400D0811
|
||||
[New Thread 1073432196]
|
||||
|
||||
Program received signal SIGTRAP, Trace/breakpoint trap.
|
||||
@ -583,14 +592,14 @@
|
||||
|
||||
(gdb) p i
|
||||
$1 = 3
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
要修改 ``i`` 的值,请使用 ``set`` 命令,如下所示(可以将其打印输出来查看是否确已修改)::
|
||||
|
||||
(gdb) set var i = 0
|
||||
(gdb) p i
|
||||
$3 = 0
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
最多可以使用两个观察点,详细信息请参阅 :ref:`jtag-debugging-tip-breakpoints`。
|
||||
|
||||
@ -613,14 +622,14 @@
|
||||
(gdb) set var i = 0
|
||||
(gdb) c
|
||||
Continuing.
|
||||
Target halted. PRO_CPU: PC=0x400DB755 (active) APP_CPU: PC=0x400D112C
|
||||
Target halted. PRO_CPU: PC=0x400DB753 (active) APP_CPU: PC=0x400D112C
|
||||
Target halted. PRO_CPU: PC=0x400DB755 (active) APP_CPU: PC=0x400D112C
|
||||
Target halted. PRO_CPU: PC=0x400DB753 (active) APP_CPU: PC=0x400D112C
|
||||
Target halted. PRO_CPU: PC=0x400DB755 (active) APP_CPU: PC=0x400D112C
|
||||
Target halted. PRO_CPU: PC=0x400DB753 (active) APP_CPU: PC=0x400D112C
|
||||
Target halted. PRO_CPU: PC=0x400DB755 (active) APP_CPU: PC=0x400D112C
|
||||
Target halted. PRO_CPU: PC=0x400DB753 (active) APP_CPU: PC=0x400D112C
|
||||
|
||||
Breakpoint 3, blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:34
|
||||
34 gpio_set_level(BLINK_GPIO, 0);
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
|
||||
获得命令的帮助信息
|
||||
@ -634,7 +643,7 @@
|
||||
Unlike "step", if the current source line calls a subroutine,
|
||||
this command does not enter the subroutine, but instead steps over
|
||||
the call, in effect treating it as a single source line.
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
只需输入 ``help`` 命令,即可获得高级命令列表,帮助你了解更多详细信息。此外,还可以参考一些 GDB 命令速查表,比如 http://darkdust.net/files/GDB%20Cheat%20Sheet.pdf。虽然不是所有命令都适用于嵌入式环境,但还是会有所裨益。
|
||||
|
||||
@ -642,7 +651,7 @@
|
||||
结束调试会话
|
||||
^^^^^^^^^^^^
|
||||
|
||||
输入命令 ``q`` 可以退出调试器::
|
||||
输入命令 ``q`` 可以退出调试器::
|
||||
|
||||
(gdb) q
|
||||
A debugging session is active.
|
||||
@ -652,4 +661,4 @@
|
||||
Quit anyway? (y or n) y
|
||||
Detaching from program: /home/user-name/esp/blink/build/blink.elf, Remote target
|
||||
Ending remote debugging.
|
||||
user-name@computer-name:~/esp/blink$
|
||||
user-name@computer-name:~/esp/blink$
|
||||
|
@ -2,17 +2,17 @@ JTAG 调试
|
||||
=========
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
本文将指导安装 ESP32 的 OpenOCD 调试环境,并介绍如何使用 GDB 来调试 ESP32 的应用程序。本文的组织结构如下:
|
||||
本文将指导安装 {IDF_TARGET_NAME} 的 OpenOCD 调试环境,并介绍如何使用 GDB 来调试 {IDF_TARGET_NAME} 的应用程序。本文的组织结构如下:
|
||||
|
||||
:ref:`jtag-debugging-introduction`
|
||||
介绍本指南主旨。
|
||||
:ref:`jtag-debugging-how-it-works`
|
||||
介绍 ESP32,JTAG(Joint Test Action Group)接口,OpenOCD 和 GDB 是如何相互连接从而实现 ESP32 的调试功能。
|
||||
介绍 {IDF_TARGET_NAME},JTAG(Joint Test Action Group)接口,OpenOCD 和 GDB 是如何相互连接从而实现 {IDF_TARGET_NAME} 的调试功能。
|
||||
:ref:`jtag-debugging-selecting-jtag-adapter`
|
||||
介绍有关 JTAG 硬件适配器的选择及参照标准。
|
||||
:ref:`jtag-debugging-setup-openocd`
|
||||
介绍如何安装官方预编译好的 OpenOCD 软件包并验证是否安装成功。
|
||||
:ref:`jtag-debugging-configuring-esp32-target`
|
||||
:ref:`jtag-debugging-configuring-target`
|
||||
介绍如何设置 OpenOCD 软件并安装 JTAG 硬件适配器,这两者共同组成最终的调试目标。
|
||||
:ref:`jtag-debugging-launching-debugger`
|
||||
介绍如何从 :ref:`Eclipse 集成开发环境 <jtag-debugging-using-debugger-eclipse>` 和 :ref:`命令行终端 <jtag-debugging-using-debugger-command-line>` 启动 GDB 调试会话。
|
||||
@ -21,20 +21,22 @@ JTAG 调试
|
||||
:ref:`jtag-debugging-building-openocd`
|
||||
介绍如何在 :doc:`Windows <building-openocd-windows>`,:doc:`Linux <building-openocd-linux>` 和 :doc:`MacOS <building-openocd-macos>` 操作系统上从源码构建 OpenOCD。
|
||||
:ref:`jtag-debugging-tips-and-quirks`
|
||||
介绍使用 OpenOCD 和 GDB 通过 JTAG 接口调试 ESP32 时的注意事项和补充内容。
|
||||
介绍使用 OpenOCD 和 GDB 通过 JTAG 接口调试 {IDF_TARGET_NAME} 时的注意事项和补充内容。
|
||||
|
||||
.. _jtag-debugging-introduction:
|
||||
|
||||
引言
|
||||
----
|
||||
|
||||
ESP32 具有两个强大的 Xtensa 内核,支持多种程序架构。ESP-IDF 自带的 FreeRTOS 操作系统具有多核抢占式多线程的功能,它允许用户以更加直观的方式编写软件。
|
||||
.. only:: esp32
|
||||
|
||||
与此相对地,简便的编程方式会给程序的调试带来困难(如果没有合适的工具),比如找出由两个线程引起的错误,并且这两个线程在单独的 CPU 核上同时运行,仅凭 ``printf`` 语句会花费很长的时间来定位到该错误。在大多数情况下,调试此类问题更快的方法是使用调试器,连接到处理器的调试端口。
|
||||
ESP32 具有两个强大的 Xtensa 内核,支持多种程序架构。ESP-IDF 自带的 FreeRTOS 操作系统具有多核抢占式多线程的功能,它允许用户以更加直观的方式编写软件。
|
||||
|
||||
乐鑫已经为 ESP32 处理器和多核 FreeRTOS 架构移植好了 OpenOCD,它将成为大多数 ESP32 应用程序的基础。此外,乐鑫还提供了一些 OpenOCD 本身并不支持的工具来进一步丰富调试的功能。
|
||||
与此相对地,简便的编程方式会给程序的调试带来困难(如果没有合适的工具),比如找出由两个线程引起的错误,并且这两个线程在单独的 CPU 核上同时运行,仅凭 ``printf`` 语句会花费很长的时间来定位到该错误。在大多数情况下,调试此类问题更快的方法是使用调试器,连接到处理器的调试端口。
|
||||
|
||||
本文将指导如何在 Linux,Windows 和 MacOS 环境下为 ESP32 安装 OpenOCD,并使用 GDB 进行软件调试。除了个别操作系统的安装过程有所差别以外,软件用户界面和使用流程都是一样的。
|
||||
乐鑫已经为 {IDF_TARGET_NAME} 处理器和多核 FreeRTOS 架构移植好了 OpenOCD,它将成为大多数 {IDF_TARGET_NAME} 应用程序的基础。此外,乐鑫还提供了一些 OpenOCD 本身并不支持的工具来进一步丰富调试的功能。
|
||||
|
||||
本文将指导如何在 Linux,Windows 和 MacOS 环境下为 {IDF_TARGET_NAME} 安装 OpenOCD,并使用 GDB 进行软件调试。除了个别操作系统的安装过程有所差别以外,软件用户界面和使用流程都是一样的。
|
||||
|
||||
.. note::
|
||||
本文使用的图片素材来自于 Ubuntu 16.04 LTE 上 Eclipse Neon 3 软件的截图,不同的操作系统(Windows, MacOS 或者 Linux)和 Eclipse 软件版本在用户界面上可能会有细微的差别。
|
||||
@ -44,21 +46,21 @@ ESP32 具有两个强大的 Xtensa 内核,支持多种程序架构。ESP-IDF
|
||||
工作原理
|
||||
--------
|
||||
|
||||
通过 JTAG(Joint Test Action Group)接口使用 OpenOCD 调试 ESP32 时所需要的一些关键的软件和硬件包括 **xtensa-esp32-elf-gdb
|
||||
调试器**,**OpenOCD 片上调试器** 和连接到 **ESP32** 目标的 **JTAG 适配器**。
|
||||
通过 JTAG(Joint Test Action Group)接口使用 OpenOCD 调试 {IDF_TARGET_NAME} 时所需要的一些关键的软件和硬件包括 **xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf-gdb
|
||||
调试器**,**OpenOCD 片上调试器** 和连接到 **{IDF_TARGET_NAME}** 目标的 **JTAG 适配器**。
|
||||
|
||||
.. figure:: ../../../_static/jtag-debugging-overview_zh.jpg
|
||||
:align: center
|
||||
:alt: JTAG debugging - overview diagram
|
||||
:alt: JTAG debugging - overview diagram
|
||||
:figclass: align-center
|
||||
|
||||
JTAG 调试 - 概述图
|
||||
|
||||
在 “Application Loading and Monitoring” 下还有另外一组软件和硬件,它们用来编译、构建和烧写应用程序到 ESP32 上,以及监视来自 ESP32 的运行诊断信息。
|
||||
在 “Application Loading and Monitoring” 下还有另外一组软件和硬件,它们用来编译、构建和烧写应用程序到 {IDF_TARGET_NAME} 上,以及监视来自 {IDF_TARGET_NAME} 的运行诊断信息。
|
||||
|
||||
`Eclipse <https://www.eclipse.org/>`__ 环境集成了 JTAG 调试和应用程序加载、监视的功能,它使得软件从编写、编译、加载到调试的迭代过程变得更加快速而简单。所有的软件均适用于 Windows,Linux 和 MacOS 平台。
|
||||
|
||||
如果你使用的是 :doc:`ESP-WROVER-KIT 开发板 <../../hw-reference/modules-and-boards>`,得益于板载的 FT232H 芯片,PC 和 ESP32 的连接仅仅需要一根 USB 线即可完成。FT232H 提供了两路 USB 通道,一路连接到 JTAG,另一路连接到 UART。
|
||||
如果你使用的是 :doc:`ESP-WROVER-KIT 开发板 <../../hw-reference/modules-and-boards>`,得益于板载的 FT232H 芯片,PC 和 {IDF_TARGET_NAME} 的连接仅仅需要一根 USB 线即可完成。FT232H 提供了两路 USB 通道,一路连接到 JTAG,另一路连接到 UART。
|
||||
|
||||
根据用户的喜好,除了使用 Eclipse 集成开发环境,还可以直接在命令行终端运行 `debugger` 和 `idf.py build`。
|
||||
|
||||
@ -67,13 +69,13 @@ ESP32 具有两个强大的 Xtensa 内核,支持多种程序架构。ESP-IDF
|
||||
选择 JTAG 适配器
|
||||
----------------
|
||||
|
||||
上手 JTAG 最快速便捷的方式是使用 :doc:`ESP-WROVER-KIT 开发板 <../../hw-reference/modules-and-boards>`,因为它板载了 JTAG 调试接口,无需使用外部的 JTAG 硬件适配器和额外的线缆来连接 JTAG 与 ESP32。ESP-WROVER-KIT 采用 FT2232H 提供的 JTAG 接口,可以稳定运行在 20 MHz 的时钟频率,外接的适配器很难达到这个速度。
|
||||
上手 JTAG 最快速便捷的方式是使用 :doc:`ESP-WROVER-KIT 开发板 <../../hw-reference/modules-and-boards>`,因为它板载了 JTAG 调试接口,无需使用外部的 JTAG 硬件适配器和额外的线缆来连接 JTAG 与 {IDF_TARGET_NAME}。ESP-WROVER-KIT 采用 FT2232H 提供的 JTAG 接口,可以稳定运行在 20 MHz 的时钟频率,外接的适配器很难达到这个速度。
|
||||
|
||||
如果你想使用单独的 JTAG 适配器,请确保其与 ESP32 的电平电压和 OpenOCD 软件都兼容。ESP32 使用的是业界标准的 JTAG 接口,它省略了(实际上也并不需要)TRST 信号脚。JTAG 使用的 IO 引脚由 VDD_3P3_RTC 电源引脚供电(通常连接到外部 3.3 V 的电源轨),因此 JTAG 硬件适配器的引脚需要能够在该电压范围内正常工作。
|
||||
如果你想使用单独的 JTAG 适配器,请确保其与 {IDF_TARGET_NAME} 的电平电压和 OpenOCD 软件都兼容。{IDF_TARGET_NAME} 使用的是业界标准的 JTAG 接口,它省略了(实际上也并不需要)TRST 信号脚。JTAG 使用的 IO 引脚由 VDD_3P3_RTC 电源引脚供电(通常连接到外部 3.3 V 的电源轨),因此 JTAG 硬件适配器的引脚需要能够在该电压范围内正常工作。
|
||||
|
||||
在软件方面,OpenOCD 支持相当多数量的 JTAG 适配器,可以参阅 `OpenOCD 支持的适配器列表 <http://openocd.org/doc/html/Debug-Adapter-Hardware.html>`_ (尽管上面显示的器件不太完整),这个页面还列出了兼容 SWD 接口的适配器,但是请注意,ESP32 目前并不支持 SWD。此外那些被硬编码为只支持特定产品线的 JTAG 适配器也不能在 ESP32 上工作,比如用于 STM32 产品家族的 ST-LINK 适配器。
|
||||
在软件方面,OpenOCD 支持相当多数量的 JTAG 适配器,可以参阅 `OpenOCD 支持的适配器列表 <http://openocd.org/doc/html/Debug-Adapter-Hardware.html>`_ (尽管上面显示的器件不太完整),这个页面还列出了兼容 SWD 接口的适配器,但是请注意,{IDF_TARGET_NAME} 目前并不支持 SWD。此外那些被硬编码为只支持特定产品线的 JTAG 适配器也不能在 {IDF_TARGET_NAME} 上工作,比如用于 STM32 产品家族的 ST-LINK 适配器。
|
||||
|
||||
JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 GND。某些 JTAG 适配器还需要 ESP32 提供一路电源到适配器的某个引脚上(比如 Vtar)用以设置适配器的工作电压。SRST 信号线是可选的,它可以连接到 ESP32 的 CH_PD 引脚上,尽管目前 OpenOCD 对该信号线的支持还非常有限。
|
||||
JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 GND。某些 JTAG 适配器还需要 {IDF_TARGET_NAME} 提供一路电源到适配器的某个引脚上(比如 Vtar)用以设置适配器的工作电压。SRST 信号线是可选的,它可以连接到 {IDF_TARGET_NAME} 的 CH_PD 引脚上,尽管目前 OpenOCD 对该信号线的支持还非常有限。
|
||||
|
||||
|
||||
.. _jtag-debugging-setup-openocd:
|
||||
@ -105,12 +107,12 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G
|
||||
另外,我们还可以从源代码编译 OpenOCD 工具,相关详细信息请参阅 :ref:`jtag-debugging-building-openocd` 章节。
|
||||
|
||||
|
||||
.. _jtag-debugging-configuring-esp32-target:
|
||||
.. _jtag-debugging-configuring-target:
|
||||
|
||||
配置 ESP32 目标板
|
||||
-----------------
|
||||
配置 {IDF_TARGET_NAME} 目标板
|
||||
----------------------------
|
||||
|
||||
安装好 OpenOCD 之后就可以配置 ESP32 目标(即带 JTAG 接口的 ESP32 板),具体可以通过以下三个步骤进行:
|
||||
安装好 OpenOCD 之后就可以配置 {IDF_TARGET_NAME} 目标(即带 JTAG 接口的 {IDF_TARGET_NAME} 板),具体可以通过以下三个步骤进行:
|
||||
|
||||
- 配置并连接 JTAG 接口
|
||||
- 运行 OpenOCD
|
||||
@ -120,7 +122,7 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G
|
||||
配置并连接 JTAG 接口
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
此步骤取决于您使用的 JTAG 和 ESP32 板,请参考以下两种情况。
|
||||
此步骤取决于您使用的 JTAG 和 {IDF_TARGET_NAME} 板,请参考以下两种情况。
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
@ -167,7 +169,7 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G
|
||||
|
||||
- 如果出现指示权限问题的错误,请参阅 ``~/esp/openocd-esp32`` 目录下 OpenOCD README 文件中关于 “Permissions delegation” 的说明。
|
||||
- 如果发现配置文件有错误,例如 ``Can't find board/esp32-wrover-kit-3.3v.cfg``,请检查 ``-s`` 后面的路径,OpenOCD 会根据此路径来查找 ``-f`` 指定的文件。此外,还需要检查配置文件是否确实位于该路径下。
|
||||
- 如果看到 JTAG 错误(输出全是 1 或者全是 0),请检查硬件连接,除了 ESP32 的引脚之外是否还有其他信号连接到了 JTAG,并查看是否所有器件都已经上电。
|
||||
- 如果看到 JTAG 错误(输出全是 1 或者全是 0),请检查硬件连接,除了 {IDF_TARGET_NAME} 的引脚之外是否还有其他信号连接到了 JTAG,并查看是否所有器件都已经上电。
|
||||
|
||||
|
||||
.. _jtag-upload-app-debug:
|
||||
@ -175,7 +177,7 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G
|
||||
上传待调试的应用程序
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
您可以像往常一样构建并上传 ESP32 应用程序,具体请参阅 :ref:`get-started-build` 章节。
|
||||
您可以像往常一样构建并上传 {IDF_TARGET_NAME} 应用程序,具体请参阅 :ref:`get-started-build` 章节。
|
||||
|
||||
除此以外,还支持使用 OpenOCD 通过 JTAG 接口将应用程序镜像烧写到闪存中,命令如下::
|
||||
|
||||
@ -199,7 +201,7 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G
|
||||
启动调试器
|
||||
----------
|
||||
|
||||
ESP32 的工具链中带有 GNU 调试器(简称 GDB) ``xtensa-esp32-elf-gdb``,它和其它工具链软件存放在同一个 bin 目录下。除了直接在命令行终端中调用并操作 GDB 外,还可以在 IDE (例如 Eclipse,Visual Studio Code 等)中调用它,在图形用户界面的帮助下间接操作 GDB,无需在终端中输入任何命令。
|
||||
{IDF_TARGET_NAME} 的工具链中带有 GNU 调试器(简称 GDB) ``xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf-gdb``,它和其它工具链软件存放在同一个 bin 目录下。除了直接在命令行终端中调用并操作 GDB 外,还可以在 IDE (例如 Eclipse,Visual Studio Code 等)中调用它,在图形用户界面的帮助下间接操作 GDB,无需在终端中输入任何命令。
|
||||
|
||||
关于以上两种调试器的使用方法,详见以下链接。
|
||||
|
||||
@ -226,7 +228,7 @@ ESP32 的工具链中带有 GNU 调试器(简称 GDB) ``xtensa-esp32-elf-gdb
|
||||
|
||||
此外还会提供 :ref:`在命令行终端进行调试 <jtag-debugging-examples-command-line>` 的案例。
|
||||
|
||||
在演示之前,请设置好 ESP32 目标板并加载 :example:`get-started/blink` 至 ESP32 中。
|
||||
在演示之前,请设置好 {IDF_TARGET_NAME} 目标板并加载 :example:`get-started/blink` 至 {IDF_TARGET_NAME} 中。
|
||||
|
||||
|
||||
.. _jtag-debugging-building-openocd:
|
||||
|
@ -9,7 +9,7 @@
|
||||
可用的断点和观察点
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
ESP32 调试器支持 2 个硬件断点和 64 个软件断点。硬件断点是由 ESP32 芯片内部的逻辑电路实现的,能够设置在代码的任何位置:闪存或者 IRAM 的代码区域。除此以外,OpenOCD 实现了两种软件断点:闪存断点(最多 32 个)和 IRAM 断点(最多 32 个)。目前 GDB 无法在闪存中设置软件断点,因此除非解决此限制,否则这些断点只能由 OpenOCD 模拟为硬件断点。(详细信息可以参阅 :ref:`下面 <jtag-debugging-tip-where-breakpoints>`)。ESP32 还支持 2 个观察点,所以可以观察两个变量的变化或者通过 GDB 命令 ``watch myVariable`` 来读取变量的值。请注意 menuconfig 中的 :ref:`CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK` 选项会使用第二个观察点,如果你想在 OpenOCD 或者 GDB 中再次尝试使用这个观察点,可能不会得到预期的结果。详情请查看 menuconfig 中的帮助文档。
|
||||
{IDF_TARGET_NAME} 调试器支持 2 个硬件断点和 64 个软件断点。硬件断点是由 {IDF_TARGET_NAME} 芯片内部的逻辑电路实现的,能够设置在代码的任何位置:闪存或者 IRAM 的代码区域。除此以外,OpenOCD 实现了两种软件断点:闪存断点(最多 32 个)和 IRAM 断点(最多 32 个)。目前 GDB 无法在闪存中设置软件断点,因此除非解决此限制,否则这些断点只能由 OpenOCD 模拟为硬件断点。(详细信息可以参阅 :ref:`下面 <jtag-debugging-tip-where-breakpoints>`)。{IDF_TARGET_NAME} 还支持 2 个观察点,所以可以观察两个变量的变化或者通过 GDB 命令 ``watch myVariable`` 来读取变量的值。请注意 menuconfig 中的 :ref:`CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK` 选项会使用第二个观察点,如果你想在 OpenOCD 或者 GDB 中再次尝试使用这个观察点,可能不会得到预期的结果。详情请查看 menuconfig 中的帮助文档。
|
||||
|
||||
|
||||
.. _jtag-debugging-tip-where-breakpoints:
|
||||
@ -25,9 +25,9 @@ ESP32 调试器支持 2 个硬件断点和 64 个软件断点。硬件断点是
|
||||
闪存映射 vs 软件闪存断点
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
为了在闪存中设置或者清除软件断点,OpenOCD 需要知道它们在闪存中的地址。为了完成从 ESP32 的地址空间到闪存地址的转换,OpenOCD 使用闪存中程序代码区域的映射。这些映射被保存在程序映像的头部,位于二进制数据(代码段和数据段)之前,并且特定于写入闪存的每一个应用程序的映像。因此,为了支持软件闪存断点,OpenOCD 需要知道待调试的应用程序映像在闪存中的位置。默认情况下,OpenOCD 会在 0x8000 处读取分区表并使用第一个找到的应用程序映像的映射,但是也可能会存在无法工作的情况,比如分区表不在标准的闪存位置,甚至可能有多个映像:一个出厂映像和两个 OTA 映像,你可能想要调试其中的任意一个。为了涵盖所有可能的调试情况,OpenOCD 支持特殊的命令,用于指定待调试的应用程序映像在闪存中的具体位置。该命令具有以下格式:
|
||||
为了在闪存中设置或者清除软件断点,OpenOCD 需要知道它们在闪存中的地址。为了完成从 {IDF_TARGET_NAME} 的地址空间到闪存地址的转换,OpenOCD 使用闪存中程序代码区域的映射。这些映射被保存在程序映像的头部,位于二进制数据(代码段和数据段)之前,并且特定于写入闪存的每一个应用程序的映像。因此,为了支持软件闪存断点,OpenOCD 需要知道待调试的应用程序映像在闪存中的位置。默认情况下,OpenOCD 会在 0x8000 处读取分区表并使用第一个找到的应用程序映像的映射,但是也可能会存在无法工作的情况,比如分区表不在标准的闪存位置,甚至可能有多个映像:一个出厂映像和两个 OTA 映像,你可能想要调试其中的任意一个。为了涵盖所有可能的调试情况,OpenOCD 支持特殊的命令,用于指定待调试的应用程序映像在闪存中的具体位置。该命令具有以下格式:
|
||||
|
||||
``esp32 appimage_offset <offset>``
|
||||
``esp32 appimage_offset <offset>``
|
||||
|
||||
偏移量应为十六进制格式,如果要恢复默认行为,可以将偏移地址设置为 ``-1`` 。
|
||||
|
||||
@ -54,13 +54,7 @@ OpenOCD 支持的编译时的选项
|
||||
|
||||
ESP-IDF 有一些针对 OpenOCD 调试功能的选项可以在编译时进行设置:
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
* :ref:`CONFIG_ESP32_DEBUG_OCDAWARE` 默认会被使能。如果程序抛出了不可修复或者未处理的异常,并且此时已经连接上了 JTAG 调试器(即 OpenOCD 正在运行),那么 ESP-IDF 将会进入调试器工作模式。
|
||||
|
||||
.. only:: esp32s2
|
||||
|
||||
* :ref:`CONFIG_ESP32S2_DEBUG_OCDAWARE` 默认会被使能。如果程序抛出了不可修复或者未处理的异常,并且此时已经连接上了 JTAG 调试器(即 OpenOCD 正在运行),那么 ESP-IDF 将会进入调试器工作模式。
|
||||
* :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_DEBUG_OCDAWARE` 默认会被使能。如果程序抛出了不可修复或者未处理的异常,并且此时已经连接上了 JTAG 调试器(即 OpenOCD 正在运行),那么 ESP-IDF 将会进入调试器工作模式。
|
||||
|
||||
* :ref:`CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK` 默认没有使能。在所有任务堆栈的末尾设置观察点,从 1 号开始索引。这是调试任务堆栈溢出的最准确的方式。
|
||||
|
||||
@ -76,14 +70,16 @@ OpenOCD 完全支持 ESP-IDF 自带的 FreeRTOS 操作系统,GDB 会将 FreeRT
|
||||
|
||||
.. _jtag-debugging-tip-code-flash-voltage:
|
||||
|
||||
在 OpenOCD 的配置文件中设置 SPI 闪存的工作电压
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
.. only:: esp33
|
||||
|
||||
ESP32 的 MTDI 引脚是用于 JTAG 通信的四个引脚之一,同时也是 ESP32 的 bootstrapping 引脚。上电时,ESP32 会在 MTDI 引脚上采样二进制电平,据此来设置内部的稳压器,用于给外部的 SPI 闪存芯片供电。如果上电时 MTDI 引脚上的二进制电平为低电平,则稳压器会被设置为 3.3 V;如果 MTDI 引脚为高电平,则稳压器会被设置为 1.8 V。MTDI 引脚通常需要一个上拉电阻或者直接使能内部的弱下拉电阻(详见 `ESP32 系列芯片技术规格书 <https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_cn.pdf>`_ ),具体取决于所使用的 SPI 芯片的类型。但是一旦连接上 JTAG 后,原来用于实现 bootstrapping 功能的上拉或者下拉电阻都会被覆盖掉。
|
||||
在 OpenOCD 的配置文件中设置 SPI 闪存的工作电压
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
为了解决这个问题,OpenOCD 的板级配置文件(例如 ESP32-WROOM-32 模组的 ``boards\esp-wroom-32.cfg``)提供了 ``ESP32_FLASH_VOLTAGE`` 参数来设置 ``TDO`` 信号线在空闲状态下的二进制电平,这样就可以减少由于闪存电压不正确而导致的应用程序启动不良的几率。
|
||||
ESP32 的 MTDI 引脚是用于 JTAG 通信的四个引脚之一,同时也是 ESP32 的 bootstrapping 引脚。上电时,ESP32 会在 MTDI 引脚上采样二进制电平,据此来设置内部的稳压器,用于给外部的 SPI 闪存芯片供电。如果上电时 MTDI 引脚上的二进制电平为低电平,则稳压器会被设置为 3.3 V;如果 MTDI 引脚为高电平,则稳压器会被设置为 1.8 V。MTDI 引脚通常需要一个上拉电阻或者直接使能内部的弱下拉电阻(详见 `ESP32 系列芯片技术规格书 <https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_cn.pdf>`_ ),具体取决于所使用的 SPI 芯片的类型。但是一旦连接上 JTAG 后,原来用于实现 bootstrapping 功能的上拉或者下拉电阻都会被覆盖掉。
|
||||
|
||||
查看 JTAG 连接的 ESP32 模组的规格书,检查其 SPI 闪存芯片的供电电压值,然后再相应的设置 ``ESP32_FLASH_VOLTAGE``。大多数的 WROOM 模组使用 3.3 V 的闪存芯片,但是 WROVER 模组使用 1.8 V 的闪存芯片。
|
||||
为了解决这个问题,OpenOCD 的板级配置文件(例如 ESP32-WROOM-32 模组的 ``boards\esp-wroom-32.cfg``)提供了 ``ESP32_FLASH_VOLTAGE`` 参数来设置 ``TDO`` 信号线在空闲状态下的二进制电平,这样就可以减少由于闪存电压不正确而导致的应用程序启动不良的几率。
|
||||
|
||||
查看 JTAG 连接的 ESP32 模组的规格书,检查其 SPI 闪存芯片的供电电压值,然后再相应的设置 ``ESP32_FLASH_VOLTAGE``。大多数的 WROOM 模组使用 3.3 V 的闪存芯片,但是 WROVER 模组使用 1.8 V 的闪存芯片。
|
||||
|
||||
|
||||
.. _jtag-debugging-tip-optimize-jtag-speed:
|
||||
@ -106,7 +102,7 @@ ESP32 的 MTDI 引脚是用于 JTAG 通信的四个引脚之一,同时也是 E
|
||||
|
||||
在启动时,调试器发出一系列命令来复位芯片并使其在特定的代码行停止运行。这个命令序列(如下所示)支持自定义,用户可以选择在最方便合适的代码行开始调试工作。
|
||||
|
||||
* ``set remote hardware-watchpoint-limit 2`` — 限制 GDB 仅使用 ESP32 支持的两个硬件观察点。更多详细信息,请查阅 `GDB 配置远程目标 <https://sourceware.org/gdb/onlinedocs/gdb/Remote-Configuration.html>`_ 。
|
||||
* ``set remote hardware-watchpoint-limit 2`` — 限制 GDB 仅使用 {IDF_TARGET_NAME} 支持的两个硬件观察点。更多详细信息,请查阅 `GDB 配置远程目标 <https://sourceware.org/gdb/onlinedocs/gdb/Remote-Configuration.html>`_ 。
|
||||
* ``mon reset halt`` — 复位芯片并使 CPU 停止运行。
|
||||
* ``flushregs`` — monitor (``mon``) 命令无法通知 GDB 目标状态已经更改,GDB 会假设在 ``mon reset halt`` 之前所有的任务堆栈仍然有效。实际上,复位后目标状态将发生变化。执行 ``flushregs`` 是一种强制 GDB 从目标获取最新状态的方法。
|
||||
* ``thb app_main`` — 在 ``app_main`` 处插入一个临时的硬件断点,如果有需要,可以将其替换为其他函数名。
|
||||
@ -139,14 +135,16 @@ OpenOCD 需要知道当前使用的 JTAG 适配器的类型,以及其连接的
|
||||
请参阅 :ref:`jtag-debugging-tip-optimize-jtag-speed` 以获取有关如何设置此值的指导。
|
||||
|
||||
|
||||
单核调试
|
||||
""""""""
|
||||
.. only:: esp32
|
||||
|
||||
::
|
||||
单核调试
|
||||
""""""""
|
||||
|
||||
set ESP32_ONLYCPU 1
|
||||
::
|
||||
|
||||
如果是双核调试,请注释掉这一行。
|
||||
set ESP32_ONLYCPU 1
|
||||
|
||||
如果是双核调试,请注释掉这一行。
|
||||
|
||||
|
||||
禁用 RTOS 支持
|
||||
@ -169,40 +167,44 @@ ESP32 的 SPI 闪存芯片的电源电压
|
||||
如果 SPI 闪存芯片的电源电压为 3.3 V, 请注释掉这一行,更多信息请参阅: :ref:`jtag-debugging-tip-code-flash-voltage`。
|
||||
|
||||
|
||||
|
||||
|
||||
ESP32 的目标配置文件
|
||||
""""""""""""""""""""
|
||||
|
||||
::
|
||||
.. only:: esp32
|
||||
|
||||
source [find target/esp32.cfg]
|
||||
::
|
||||
|
||||
.. note::
|
||||
source [find target/esp32.cfg]
|
||||
|
||||
除非你熟悉 OpenOCD 内部的工作原理,否则请不要更改 ``source [find target/esp32.cfg]`` 这一行。
|
||||
.. note::
|
||||
|
||||
目前 ``target/esp32.cfg`` 仍然是 ESP32 目标(esp108 和 esp32)的唯一配置文件。支持的配置矩阵如下所示:
|
||||
除非你熟悉 OpenOCD 内部的工作原理,否则请不要更改 ``source [find target/esp32.cfg]`` 这一行。
|
||||
|
||||
+---------------+---------------+---------------+
|
||||
| Dual/single | RTOS | Target used |
|
||||
+===============+===============+===============+
|
||||
| dual | FreeRTOS | esp32 |
|
||||
+---------------+---------------+---------------+
|
||||
| single | FreeRTOS | esp108 (*) |
|
||||
+---------------+---------------+---------------+
|
||||
| dual | none | esp108 |
|
||||
+---------------+---------------+---------------+
|
||||
| single | none | esp108 |
|
||||
+---------------+---------------+---------------+
|
||||
目前 ``target/esp32.cfg`` 仍然是 ESP32 目标(esp108 和 esp32)的唯一配置文件。支持的配置矩阵如下所示:
|
||||
|
||||
(*) — 我们计划修复此问题,并在后续提交中添加对 esp32 目标的单核调试的支持。
|
||||
+---------------+---------------+---------------+
|
||||
| Dual/single | RTOS | Target used |
|
||||
+===============+===============+===============+
|
||||
| dual | FreeRTOS | esp32 |
|
||||
+---------------+---------------+---------------+
|
||||
| single | FreeRTOS | esp108 (*) |
|
||||
+---------------+---------------+---------------+
|
||||
| dual | none | esp108 |
|
||||
+---------------+---------------+---------------+
|
||||
| single | none | esp108 |
|
||||
+---------------+---------------+---------------+
|
||||
|
||||
更多信息,请查看 ``board/esp-wroom-32.cfg`` 配置文件的注释部分。
|
||||
(*) — 我们计划修复此问题,并在后续提交中添加对 esp32 目标的单核调试的支持。
|
||||
|
||||
更多信息,请查看 ``board/esp-wroom-32.cfg`` 配置文件的注释部分。
|
||||
|
||||
|
||||
.. _jtag-debugging-tip-reset-by-debugger:
|
||||
|
||||
复位 ESP32
|
||||
^^^^^^^^^^
|
||||
复位 {IDF_TARGET_NAME}
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
通过在 GDB 中输入 ``mon reset`` 或者 ``mon reset halt`` 来复位板子。
|
||||
|
||||
@ -212,7 +214,9 @@ ESP32 的目标配置文件
|
||||
不要将 JTAG 引脚用于其他功能
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
如果除了 ESP32 模组和 JTAG 适配器之外的其他硬件也连接到了 JTAG 引脚,那么 JTAG 的操作可能会受到干扰。ESP32 JTAG 使用以下引脚:
|
||||
如果除了 {IDF_TARGET_NAME} 模组和 JTAG 适配器之外的其他硬件也连接到了 JTAG 引脚,那么 JTAG 的操作可能会受到干扰。{IDF_TARGET_NAME} JTAG 使用以下引脚:
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
+---+----------------+-------------+
|
||||
| | ESP32 JTAG Pin | JTAG Signal |
|
||||
@ -226,7 +230,21 @@ ESP32 的目标配置文件
|
||||
| 4 | MTMS / GPIO14 | TMS |
|
||||
+---+----------------+-------------+
|
||||
|
||||
如果用户应用程序更改了 JTAG 引脚的配置,JTAG 通信可能会失败。如果 OpenOCD 正确初始化(检测到两个 Tensilica 内核),但在程序运行期间失去了同步并报出大量 DTR/DIR 错误,则应用程序可能将 JTAG 引脚重新配置为其他功能或者用户忘记将 Vtar 连接到 JTAG 适配器。
|
||||
.. only:: esp32s2
|
||||
|
||||
+---+-----------------------+-------------+
|
||||
| | ESP32-S2 Pin | JTAG Signal |
|
||||
+===+=======================+=============+
|
||||
| 1 | MTDO / GPIO40 | TDO |
|
||||
+---+-----------------------+-------------+
|
||||
| 2 | MTDI / GPIO41 | TDI |
|
||||
+---+-----------------------+-------------+
|
||||
| 3 | MTCK / GPIO39 | TCK |
|
||||
+---+-----------------------+-------------+
|
||||
| 4 | MTMS / GPIO42 | TMS |
|
||||
+---+-----------------------+-------------+
|
||||
|
||||
如果用户应用程序更改了 JTAG 引脚的配置,JTAG 通信可能会失败。如果 OpenOCD 正确初始化(检测到两个 Tensilica 内核),但在程序运行期间失去了同步并报出大量 DTR/DIR 错误,则应用程序可能将 JTAG 引脚重新配置为其他功能或者用户忘记将 Vtar 连接到 JTAG 适配器。
|
||||
|
||||
.. highlight:: none
|
||||
|
||||
@ -276,7 +294,7 @@ ESP32 的目标配置文件
|
||||
|
||||
::
|
||||
|
||||
xtensa-esp32-elf-gdb -ex "set remotelogfile gdb_log.txt" <all other options>
|
||||
xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf-gdb -ex "set remotelogfile gdb_log.txt" <all other options>
|
||||
|
||||
也可以将命令 ``remotelogfile gdb_log.txt`` 添加到 ``gdbinit`` 文件中。
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
GDB 硬件调试的配置 - Main 选项卡
|
||||
|
||||
6. 点击 “Debugger” 选项卡,在 “GDB Command” 栏中输入 ``xtensa-esp32-elf-gdb`` 来调用调试器。
|
||||
6. 点击 “Debugger” 选项卡,在 “GDB Command” 栏中输入 ``xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf-gdb`` 来调用调试器。
|
||||
|
||||
7. 更改 “Remote host” 的默认配置,在 “Port number” 下面输入 ``3333``。
|
||||
|
||||
@ -82,9 +82,9 @@
|
||||
|
||||
上面的启动序列看起来有些复杂,如果你对其中的初始化命令不太熟悉,请查阅 :ref:`jtag-debugging-tip-debugger-startup-commands` 章节获取更多说明。
|
||||
|
||||
12. 如果你前面已经完成 :ref:`jtag-debugging-configuring-esp32-target` 中介绍的步骤,那么目标正在运行并准备与调试器进行对话。按下 “Debug” 按钮就可以直接调试。否则请按下 “Apply” 按钮保存配置,返回 :ref:`jtag-debugging-configuring-esp32-target` 章节进行配置,最后再回到这里开始调试。
|
||||
12. 如果你前面已经完成 :ref:`jtag-debugging-configuring-target` 中介绍的步骤,那么目标正在运行并准备与调试器进行对话。按下 “Debug” 按钮就可以直接调试。否则请按下 “Apply” 按钮保存配置,返回 :ref:`jtag-debugging-configuring-target` 章节进行配置,最后再回到这里开始调试。
|
||||
|
||||
一旦所有 1 - 12 的配置步骤都已经完成,Eclipse 就会打开 “Debug” 视图,如下图所示。
|
||||
一旦所有 1 - 12 的配置步骤都已经完成,Eclipse 就会打开 “Debug” 视图,如下图所示。
|
||||
|
||||
.. figure:: ../../../_static/debug-perspective.jpg
|
||||
:align: center
|
||||
@ -101,7 +101,7 @@
|
||||
在命令行中使用 GDB
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
1. 为了能够启动调试会话,需要先启动并运行目标,如果还没有完成,请按照 :ref:`jtag-debugging-configuring-esp32-target` 中的介绍进行操作。
|
||||
1. 为了能够启动调试会话,需要先启动并运行目标,如果还没有完成,请按照 :ref:`jtag-debugging-configuring-target` 中的介绍进行操作。
|
||||
|
||||
.. highlight:: bash
|
||||
|
||||
@ -124,7 +124,7 @@
|
||||
thb app_main
|
||||
c
|
||||
|
||||
将此文件保存在当前目录中。
|
||||
将此文件保存在当前目录中。
|
||||
|
||||
有关 ``gdbinit`` 文件内部的更多详细信息,请参阅 :ref:`jtag-debugging-tip-debugger-startup-commands` 章节。
|
||||
|
||||
@ -134,7 +134,7 @@
|
||||
|
||||
::
|
||||
|
||||
xtensa-esp32-elf-gdb -x gdbinit build/blink.elf
|
||||
xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf-gdb -x gdbinit build/blink.elf
|
||||
|
||||
.. highlight:: none
|
||||
|
||||
@ -142,14 +142,14 @@
|
||||
|
||||
::
|
||||
|
||||
user-name@computer-name:~/esp/blink$ xtensa-esp32-elf-gdb -x gdbinit build/blink.elf
|
||||
user-name@computer-name:~/esp/blink$ xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf-gdb -x gdbinit build/blink.elf
|
||||
GNU gdb (crosstool-NG crosstool-ng-1.22.0-61-gab8375a) 7.10
|
||||
Copyright (C) 2015 Free Software Foundation, Inc.
|
||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
|
||||
and "show warranty" for details.
|
||||
This GDB was configured as "--host=x86_64-build_pc-linux-gnu --target=xtensa-esp32-elf".
|
||||
This GDB was configured as "--host=x86_64-build_pc-linux-gnu --target=xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf".
|
||||
Type "show configuration" for configuration details.
|
||||
For bug reporting instructions, please see:
|
||||
<http://www.gnu.org/software/gdb/bugs/>.
|
||||
@ -158,20 +158,20 @@
|
||||
For help, type "help".
|
||||
Type "apropos word" to search for commands related to "word"...
|
||||
Reading symbols from build/blink.elf...done.
|
||||
0x400d10d8 in esp_vApplicationIdleHook () at /home/user-name/esp/esp-idf/components/esp32/./freertos_hooks.c:52
|
||||
0x400d10d8 in esp_vApplicationIdleHook () at /home/user-name/esp/esp-idf/components/{IDF_TARGET_TOOLCHAIN_NAME}/./freertos_hooks.c:52
|
||||
52 asm("waiti 0");
|
||||
JTAG tap: esp32.cpu0 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
|
||||
JTAG tap: esp32.slave tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
|
||||
esp32: Debug controller was reset (pwrstat=0x5F, after clear 0x0F).
|
||||
esp32: Core was reset (pwrstat=0x5F, after clear 0x0F).
|
||||
Target halted. PRO_CPU: PC=0x5000004B (active) APP_CPU: PC=0x00000000
|
||||
esp32: target state: halted
|
||||
esp32: Core was reset (pwrstat=0x1F, after clear 0x0F).
|
||||
Target halted. PRO_CPU: PC=0x40000400 (active) APP_CPU: PC=0x40000400
|
||||
esp32: target state: halted
|
||||
JTAG tap: {IDF_TARGET_PATH_NAME}.cpu0 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
|
||||
JTAG tap: {IDF_TARGET_PATH_NAME}.slave tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
|
||||
{IDF_TARGET_PATH_NAME}: Debug controller was reset (pwrstat=0x5F, after clear 0x0F).
|
||||
{IDF_TARGET_PATH_NAME}: Core was reset (pwrstat=0x5F, after clear 0x0F).
|
||||
{IDF_TARGET_PATH_NAME} halted. PRO_CPU: PC=0x5000004B (active) APP_CPU: PC=0x00000000
|
||||
{IDF_TARGET_PATH_NAME}: target state: halted
|
||||
{IDF_TARGET_PATH_NAME}: Core was reset (pwrstat=0x1F, after clear 0x0F).
|
||||
Target halted. PRO_CPU: PC=0x40000400 (active) APP_CPU: PC=0x40000400
|
||||
{IDF_TARGET_PATH_NAME}: target state: halted
|
||||
Hardware assisted breakpoint 1 at 0x400db717: file /home/user-name/esp/blink/main/./blink.c, line 43.
|
||||
0x0: 0x00000000
|
||||
Target halted. PRO_CPU: PC=0x400DB717 (active) APP_CPU: PC=0x400D10D8
|
||||
Target halted. PRO_CPU: PC=0x400DB717 (active) APP_CPU: PC=0x400D10D8
|
||||
[New Thread 1073428656]
|
||||
[New Thread 1073413708]
|
||||
[New Thread 1073431316]
|
||||
@ -183,7 +183,7 @@
|
||||
|
||||
Temporary breakpoint 1, app_main () at /home/user-name/esp/blink/main/./blink.c:43
|
||||
43 xTaskCreate(&blink_task, "blink_task", 512, NULL, 5, NULL);
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
注意上面日志的倒数第三行显示了调试器已经在 ``app_main()`` 函数的断点处停止,该断点在 ``gdbinit`` 文件中设定。由于处理器已经暂停运行,LED 也不会闪烁。如果这也是你看到的现象,你可以开始调试了。
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
概述
|
||||
----
|
||||
|
||||
ESP32 的代码和数据可以存放在多个 :ref:`内存区域 <memory-layout>`。通常,代码和只读数据存放在 flash 区域,可写数据存放在内存中。我们经常需要更改代码或者数据的默认映射区域,例如为了提高性能,将关键部分的代码和只读数据放置到内存中,或者将代码、数据和只读数据存放到 RTC 内存中以便在 :doc:`唤醒桩 <deep-sleep-stub>` 和 :doc:`ULP 协处理器 <ulp>` 中使用。
|
||||
{IDF_TARGET_NAME} 的代码和数据可以存放在多个 :ref:`内存区域 <memory-layout>`。通常,代码和只读数据存放在 flash 区域,可写数据存放在内存中。我们经常需要更改代码或者数据的默认映射区域,例如为了提高性能,将关键部分的代码和只读数据放置到内存中,或者将代码、数据和只读数据存放到 RTC 内存中以便在 :doc:`唤醒桩 <deep-sleep-stub>` 和 :doc:`ULP 协处理器 <ulp>` 中使用。
|
||||
|
||||
IDF 的链接脚本生成机制允许用户在组件级别定义代码和数据的存放区域。组件通过 :ref:`链接片段文件 <ldgen-fragment-files>` 描述如何映射目标文件的输入段(甚至可以是某个具体的函数或者数据)。在构建应用程序时,链接片段文件会被收集、解析并处理,然后扩充到 :ref:`链接脚本模板 <ldgen-script-templates>` 中形成最终的链接脚本文件,该链接脚本会被用于链接最终的二进制应用程序。
|
||||
|
||||
@ -99,8 +99,8 @@ CMake
|
||||
[mapping]
|
||||
archive: libcomponent.a
|
||||
entries:
|
||||
object1:function1 (noflash)
|
||||
object2:function2 (rtc)
|
||||
object1:function1 (noflash)
|
||||
object2:function2 (rtc)
|
||||
|
||||
``object1.o`` 和 ``object2.o`` 的剩余函数以及整个 ``object3.o`` 目标文件会被存放到默认区域。指定数据存放区域的方法很类似,仅需将 ``:`` 之后的函数名,替换为变量名即可。
|
||||
|
||||
@ -179,7 +179,7 @@ CMake
|
||||
else if CONFIG_PERFORMANCE_LEVEL == 1
|
||||
only place object1.o in RAM
|
||||
else
|
||||
place entire libcomponent.a in RTC memory
|
||||
place entire libcomponent.a in RTC memory
|
||||
|
||||
条件测试还支持 :ref:`其他操作 <ldgen-condition-entries>`。
|
||||
|
||||
@ -220,7 +220,7 @@ CMake
|
||||
I. sections 片段
|
||||
""""""""""""""""
|
||||
|
||||
sections 片段定义了 GCC 编译器输出的目标文件段的列表,可以是默认的段(比如 ``.text`` 段、``.data`` 段),也可以是用户通过 ``__attribute__`` 关键字自定义的段。
|
||||
sections 片段定义了 GCC 编译器输出的目标文件段的列表,可以是默认的段(比如 ``.text`` 段、``.data`` 段),也可以是用户通过 ``__attribute__`` 关键字自定义的段。
|
||||
|
||||
此外,用户还可以在某类段后增加一个 ``+``,表示囊括列表中的“所有这类段”和“所有以这类段开头的段”。相较于显式地罗列所有的段,我们更推荐使用这种方式。
|
||||
|
||||
@ -257,7 +257,7 @@ sections 片段定义了 GCC 编译器输出的目标文件段的列表,可以
|
||||
II. scheme 片段
|
||||
"""""""""""""""
|
||||
|
||||
scheme 片段定义了为每个 sections 指定的 ``target``。
|
||||
scheme 片段定义了为每个 sections 指定的 ``target``。
|
||||
|
||||
**语法**
|
||||
|
||||
@ -288,11 +288,11 @@ scheme 片段定义了为每个 sections 指定的 ``target``。
|
||||
|
||||
*(.literal .literal.* .text .text.*)
|
||||
|
||||
此后,这些生成的 catch-all 规则将用于未指定映射规则的情况。
|
||||
此后,这些生成的 catch-all 规则将用于未指定映射规则的情况。
|
||||
|
||||
.. note::
|
||||
|
||||
``default`` scheme 是在 :component:`esp32/ld/esp32_fragments.lf` 文件中定义的,此外,快速上手指南中提到的内置 ``noflash`` scheme 片段和 ``rtc`` scheme 片段也是在这个文件中定义的。
|
||||
``default`` scheme 是在 :component:`{IDF_TARGET_PATH_NAME}/ld/{IDF_TARGET_PATH_NAME}_fragments.lf` 文件中定义的,此外,快速上手指南中提到的内置 ``noflash`` scheme 片段和 ``rtc`` scheme 片段也是在这个文件中定义的。
|
||||
|
||||
.. _ldgen-mapping-fragment :
|
||||
|
||||
@ -337,7 +337,7 @@ mapping 片段的映射条目共有三种类型,分别为:
|
||||
``Type III``
|
||||
指定了 ``*``,也就是指定了归档文件中所有目标文件。
|
||||
|
||||
接下来,让我们通过展开一个 ``Type II`` 映射条目,更好地理解映射条目的含义。最初:
|
||||
接下来,让我们通过展开一个 ``Type II`` 映射条目,更好地理解映射条目的含义。最初:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
@ -347,8 +347,8 @@ mapping 片段的映射条目共有三种类型,分别为:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
object (sections -> target,
|
||||
sections -> target,
|
||||
object (sections -> target,
|
||||
sections -> target,
|
||||
...)
|
||||
|
||||
然后再根据条目定义,将这个 sections 片段展开:
|
||||
@ -358,11 +358,11 @@ mapping 片段的映射条目共有三种类型,分别为:
|
||||
object (.section,
|
||||
.section,
|
||||
... -> target, # 根据目标文件将这里所列出的所有段放在该目标位置
|
||||
|
||||
|
||||
.section,
|
||||
.section,
|
||||
... -> target, # 同样的方法指定其他段
|
||||
|
||||
... -> target, # 同样的方法指定其他段
|
||||
|
||||
...) # 直至所有段均已展开
|
||||
|
||||
.. _ldgen-type1-limitations :
|
||||
@ -395,11 +395,11 @@ mapping 片段的映射条目共有三种类型,分别为:
|
||||
[mapping:lwip]
|
||||
archive: liblwip.a
|
||||
entries:
|
||||
: LWIP_IRAM_OPTIMIZATION = y # 如果 CONFIG_LWIP_IRAM_OPTIMIZATION 在 sdkconfig 中被定义为 'y'
|
||||
: LWIP_IRAM_OPTIMIZATION = y # 如果 CONFIG_LWIP_IRAM_OPTIMIZATION 在 sdkconfig 中被定义为 'y'
|
||||
ip4:ip4_route_src_hook (noflash) # 将 ip4.o:ip4_route_src_hook,ip4.o:ip4_route_src 和
|
||||
ip4:ip4_route_src (noflash) # ip4.o:ip4_route 映射到 noflash scheme
|
||||
ip4:ip4_route (noflash) # 该 scheme 会将他们存放到 RAM 中
|
||||
|
||||
|
||||
: default # 否则不使用特殊的映射规则
|
||||
|
||||
.. _ldgen-script-templates :
|
||||
@ -491,7 +491,7 @@ mapping 片段的映射条目共有三种类型,分别为:
|
||||
|
||||
链接脚本模板
|
||||
^^^^^^^^^^^^
|
||||
目前使用的链接脚本模板是 :component:`esp32/ld/esp32.project.ld.in`,仅用于应用程序的构建,生成的链接脚本文件将放在同一组件的构建目录下。值得注意的是,修改此链接描述文件模板会触发应用程序的二进制文件的重新链接。
|
||||
目前使用的链接脚本模板是 :component:`{IDF_TARGET_PATH_NAME}/ld/{IDF_TARGET_PATH_NAME}.project.ld.in`,仅用于应用程序的构建,生成的链接脚本文件将放在同一组件的构建目录下。值得注意的是,修改此链接描述文件模板会触发应用程序的二进制文件的重新链接。
|
||||
|
||||
链接片段文件
|
||||
^^^^^^^^^^^^
|
||||
|
@ -5,9 +5,9 @@
|
||||
概述
|
||||
----
|
||||
|
||||
每片 ESP32 的 flash 可以包含多个应用程序,以及多种不同类型的数据(例如校准数据、文件系统数据、参数存储器数据等)。因此,我们需要引入分区表的概念。
|
||||
每片 {IDF_TARGET_NAME} 的 flash 可以包含多个应用程序,以及多种不同类型的数据(例如校准数据、文件系统数据、参数存储器数据等)。因此,我们需要引入分区表的概念。
|
||||
|
||||
具体来说,ESP32 在 flash 的 :ref:`默认偏移地址 <CONFIG_PARTITION_TABLE_OFFSET>` 0x8000 处烧写一张分区表。该分区表的长度为 0xC00 字节(最多可以保存 95 条分区表条目)。分区表数据后还保存着该表的 MD5 校验和,用于验证分区表的完整性。此外,如果芯片使能了 :doc:`安全启动 </security/secure-boot>` 功能,则该分区表后还会保存签名信息。
|
||||
具体来说,{IDF_TARGET_NAME} 在 flash 的 :ref:`默认偏移地址 <CONFIG_PARTITION_TABLE_OFFSET>` 0x8000 处烧写一张分区表。该分区表的长度为 0xC00 字节(最多可以保存 95 条分区表条目)。分区表数据后还保存着该表的 MD5 校验和,用于验证分区表的完整性。此外,如果芯片使能了 :doc:`安全启动 </security/secure-boot>` 功能,则该分区表后还会保存签名信息。
|
||||
|
||||
分区表中的每个条目都包括以下几个部分:Name(标签)、Type(app、data 等)、SubType 以及在 flash 中的偏移量(分区的加载地址)。
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
以下是 "Single factory app, no OTA" 选项的分区表信息摘要:
|
||||
|
||||
|
||||
# Espressif ESP32 Partition Table
|
||||
# Espressif {IDF_TARGET_NAME} Partition Table
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
@ -35,7 +35,7 @@
|
||||
|
||||
以下是 "Factory app, two OTA definitions" 选项的分区表信息摘要:
|
||||
|
||||
# Espressif ESP32 Partition Table
|
||||
# Espressif {IDF_TARGET_NAME} Partition Table
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x4000,
|
||||
otadata, data, ota, 0xd000, 0x2000,
|
||||
@ -70,7 +70,7 @@ CSV 文件的格式与上面摘要中打印的格式相同,但是在 CSV 文
|
||||
Name 字段
|
||||
~~~~~~~~~
|
||||
|
||||
Name 字段可以是任何有意义的名称,但不能超过 16 个字符(之后的内容将被截断)。该字段对 ESP32 并不是特别重要。
|
||||
Name 字段可以是任何有意义的名称,但不能超过 16 个字符(之后的内容将被截断)。该字段对 {IDF_TARGET_NAME} 并不是特别重要。
|
||||
|
||||
Type 字段
|
||||
~~~~~~~~~
|
||||
@ -86,7 +86,7 @@ SubType 字段
|
||||
~~~~~~~~~~~~
|
||||
|
||||
SubType 字段长度为 8 bit,内容与具体 Type 有关。目前,esp-idf 仅仅规定了 “app” 和 “data” 两种子类型。
|
||||
|
||||
|
||||
* 当 Type 定义为 ``app`` 时,SubType 字段可以指定为 factory (0),ota_0 (0x10) ... ota_15 (0x1F) 或者 test (0x20)。
|
||||
|
||||
- factory (0) 是默认的 app 分区。Bootloader 将默认加在该应用程序。但如果存在类型为 data/ota 分区,则 Bootloader 将加载 data/ota 分区中的数据,进而判断启动哪个 OTA 镜像文件。
|
||||
@ -95,12 +95,12 @@ SubType 字段长度为 8 bit,内容与具体 Type 有关。目前,esp-idf
|
||||
|
||||
- ota_0 (0x10) ... ota_15 (0x1F) 为 OTA 应用程序分区,Bootloader 将根据 OTA 数据分区中的数据来决定加载哪个 OTA 应用程序分区中的程序。在使用 OTA 功能时,应用程序应至少拥有 2 个 OTA 应用程序分区(ota_0 和 ota_1)。更多详细信息,请参考 :doc:`OTA 文档 </api-reference/system/ota>` 。
|
||||
- test (0x2) 为预留 app 子类型,用于工厂测试过程。注意,目前,esp-idf 并不支持这种子类型。
|
||||
|
||||
|
||||
* 当 Type 定义为 ``data`` 时,SubType 字段可以指定为 ota (0),phy (1),nvs (2) 或者 nvs_keys (4)。
|
||||
|
||||
- ota (0) 即 :ref:`OTA 数据分区 <ota_data_partition>` ,用于存储当前所选的 OTA 应用程序的信息。这个分区的大小需要设定为 0x2000。更多详细信息,请参考 :doc:`OTA 文档 <../api-reference/system/ota>` 。
|
||||
- phy (1) 分区用于存放 PHY 初始化数据,从而保证可以为每个设备单独配置 PHY,而非必须采用固件中的统一 PHY 初始化数据。
|
||||
|
||||
|
||||
- 默认配置下,phy 分区并不启用,而是直接将 phy 初始化数据编译至应用程序中,从而节省分区表空间(直接将此分区删掉)。
|
||||
- 如果需要从此分区加载 phy 初始化数据,请打开项目配置菜单(``idf.py menuconfig``),并且使能 :ref:`CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION` 选项。此时,您还需要手动将 phy 初始化数据烧至设备 flash(esp-idf 编译系统并不会自动完成该操作)。
|
||||
- nvs (2) 是专门给 :doc:`非易失性存储 (NVS) API <../api-reference/storage/nvs_flash>` 使用的分区。
|
||||
@ -133,7 +133,7 @@ Flags 字段
|
||||
|
||||
当前仅支持 ``encrypted`` 标记。如果 Flags 字段设置为 ``encrypted``,且已启用 :doc:`Flash Encryption </security/flash-encryption>` 功能,则该分区将会被加密。
|
||||
|
||||
.. note::
|
||||
.. note::
|
||||
|
||||
``app`` 分区始终会被加密,不管 Flags 字段是否设置。
|
||||
|
||||
@ -171,7 +171,7 @@ MD5 校验和
|
||||
|
||||
在执行 ``idf.py partition_table`` 命令时,手动烧写分区表的命令也将打印在终端上。
|
||||
|
||||
.. note::
|
||||
.. note::
|
||||
|
||||
分区表的更新并不会擦除根据之前分区表存储的数据。此时,您可以使用 ``idf.py erase_flash`` 命令或者 ``esptool.py erase_flash`` 命令来擦除 flash 中的所有内容。
|
||||
|
||||
|
@ -78,11 +78,11 @@ IDF 监视器为寄存器转储补充如下信息::
|
||||
0x400dbf56: still_dont_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:47
|
||||
0x400dbf5e: dont_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:42
|
||||
0x400dbf82: app_main at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:33
|
||||
0x400d071d: main_task at /home/gus/esp/32/idf/components/esp32/./cpu_start.c:254
|
||||
0x400d071d: main_task at /home/gus/esp/32/idf/components/{IDF_TARGET_PATH_NAME}/./cpu_start.c:254
|
||||
|
||||
IDF 监视器在后台运行以下命令,解码各地址::
|
||||
|
||||
xtensa-esp32-elf-addr2line -pfiaC -e build/PROJECT.elf ADDRESS
|
||||
xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf-addr2line -pfiaC -e build/PROJECT.elf ADDRESS
|
||||
|
||||
|
||||
配置 GDBStub 以启用 GDB
|
||||
@ -92,19 +92,13 @@ IDF 监视器在后台运行以下命令,解码各地址::
|
||||
|
||||
或者选择配置 panic 处理器以运行 GDBStub,GDBStub 工具可以与 GDB_ 项目调试器进行通信,允许读取内存、检查调用堆栈帧和变量等。GDBStub 虽然没有 JTAG 通用,但不需要使用特殊硬件。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
如需启用 GDBStub,请运行 ``idf.py menuconfig`` (适用于 CMake 编译系统),并将 :ref:`CONFIG_ESP32_PANIC` 选项设置为 ``Invoke GDBStub``。
|
||||
|
||||
.. only:: esp32s2
|
||||
|
||||
如需启用 GDBStub,请运行 ``idf.py menuconfig`` (适用于 CMake 编译系统),并将 :ref:`CONFIG_ESP32S2_PANIC` 选项设置为 ``Invoke GDBStub``。
|
||||
如需启用 GDBStub,请运行 ``idf.py menuconfig`` (适用于 CMake 编译系统),并将 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_PANIC` 选项设置为 ``Invoke GDBStub``。
|
||||
|
||||
在这种情况下,如果 panic 处理器被触发,只要 IDF 监视器监控到 GDBStub 已经加载,panic 处理器就会自动暂停串行监控并使用必要的参数运行 GDB。GDB 退出后,通过 RTS 串口线复位开发板。如果未连接 RTS 串口线,请按复位键,手动复位开发板。
|
||||
|
||||
IDF 监控器在后台运行如下命令::
|
||||
|
||||
xtensa-esp32-elf-gdb -ex "set serial baud BAUD" -ex "target remote PORT" -ex interrupt build/PROJECT.elf
|
||||
xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf-gdb -ex "set serial baud BAUD" -ex "target remote PORT" -ex interrupt build/PROJECT.elf
|
||||
|
||||
|
||||
输出筛选
|
||||
|
@ -6,8 +6,8 @@ ULP 协处理器编程
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
ESP32 指令集参考 <ulp_instruction_set>
|
||||
ESP32-S2 指令集参考 <ulps2_instruction_set>
|
||||
:esp32: 指令集参考 <ulp_instruction_set>
|
||||
:esp32s2: 指令集参考 <ulps2_instruction_set>
|
||||
使用宏进行编程(遗留) <ulp_macros>
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ ULP 协处理器代码是用汇编语言编写的,并使用 `binutils-esp32ulp
|
||||
|
||||
1. 用汇编语言编写的 ULP 代码必须导入到一个或多个 `.S` 扩展文件中,且这些文件必须放在组件目录中一个独立的目录中,例如 `ulp/`。
|
||||
|
||||
.. note: 在注册组件(通过 ``idf_component_register``)时,不应将该目录添加到 ``SRC_DIRS`` 参数中。因为 ESP-IDF 构建系统将基于文件扩展名编译在 ``SRC_DIRS`` 中搜索到的文件。对于 ``.S`` 文件,使用的是 ``xtensa-esp32-elf-as`` 汇编器。但这并不适用于 ULP 程序集文件,因此体现这种区别最简单的方式就是将 ULP 程序集文件放到单独的目录中。同样,ULP 程序集源文件也 **不应该** 添加到 ``SRCS`` 中。请参考如下步骤,查看如何正确添加 ULP 程序集源文件。
|
||||
.. note: 在注册组件(通过 ``idf_component_register``)时,不应将该目录添加到 ``SRC_DIRS`` 参数中。因为 ESP-IDF 构建系统将基于文件扩展名编译在 ``SRC_DIRS`` 中搜索到的文件。对于 ``.S`` 文件,使用的是 ``xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf-as`` 汇编器。但这并不适用于 ULP 程序集文件,因此体现这种区别最简单的方式就是将 ULP 程序集文件放到单独的目录中。同样,ULP 程序集源文件也 **不应该** 添加到 ``SRCS`` 中。请参考如下步骤,查看如何正确添加 ULP 程序集源文件。
|
||||
|
||||
|
||||
2. 注册后从组件 CMakeLists.txt 中调用 ``ulp_embed_binary`` 示例如下::
|
||||
@ -53,9 +53,9 @@ ULP 协处理器代码是用汇编语言编写的,并使用 `binutils-esp32ulp
|
||||
在内部,构建系统将按照以下步骤编译 ULP 程序:
|
||||
|
||||
1. **通过 C 预处理器运行每个程序集文件 (foo.S)。** 此步骤在组件编译目录中生成预处理的程序集文件 (foo.ulp.S),同时生成依赖文件 (foo.ulp.d)。
|
||||
|
||||
|
||||
2. **通过汇编器运行预处理过的汇编源码。** 此步骤会生成目标文件 (foo.ulp.o) 和清单 (foo.ulp.lst)。清单文件仅用于调试,不用于编译进程的后续步骤。
|
||||
|
||||
|
||||
3. **通过 C 预处理器运行链接器脚本模板。** 模板位于 ``components/ulp/ld`` 目录中。
|
||||
|
||||
4. **将目标文件链接到 ELF 输出文件** (``ulp_app_name.elf``)。此步骤生成的.map 文件 (``ulp_app_name.map``) 默认用于调试。
|
||||
|
@ -1,5 +1,5 @@
|
||||
ESP32 中的单元测试
|
||||
==========================
|
||||
{IDF_TARGET_NAME} 中的单元测试
|
||||
============================
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
ESP-IDF
|
||||
@ -32,7 +32,7 @@ C 文件可以包含多个测试用例。测试文件的名字要以 “test”
|
||||
没有必要在每个测试用例中使用 ``UNITY_BEGIN()`` 和 ``UNITY_END()``
|
||||
来声明主函数的区域, ``unity_platform.c`` 会自动调用 ``UNITY_BEGIN()``\ , 然后运行测试用例,最后调用 ``UNITY_END()``。
|
||||
|
||||
``test`` 子目录应包含 :ref:`组件 CMakeLists.txt <component-directories>`,因为他们本身就是一种组件。ESP-IDF 使用了
|
||||
``test`` 子目录应包含 :ref:`组件 CMakeLists.txt <component-directories>`,因为他们本身就是一种组件。ESP-IDF 使用了
|
||||
``unity`` 测试框架,需要将其指定为组件的依赖项。通常,组件
|
||||
:ref:`需要手动指定待编译的源文件 <cmake-file-globbing>`;但是,对于测试组件来说,这个要求被放宽为仅建议将参数 ``SRC_DIRS`` 用于 ``idf_component_register``。
|
||||
|
||||
@ -133,7 +133,7 @@ DUT2(slave)终端:
|
||||
TEST_ASSERT(reason == DEEPSLEEP_RESET);
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("reset reason check for deepsleep", "[esp32]", trigger_deepsleep, check_deepsleep_reset_reason);
|
||||
TEST_CASE_MULTIPLE_STAGES("reset reason check for deepsleep", "[{IDF_TARGET_PATH_NAME}]", trigger_deepsleep, check_deepsleep_reset_reason);
|
||||
|
||||
多阶段测试用例向用户呈现了一组测试函数,它需要用户进行交互(选择用例并选择不同的阶段)来运行。
|
||||
|
||||
@ -171,7 +171,7 @@ DUT2(slave)终端:
|
||||
运行单元测试
|
||||
------------
|
||||
|
||||
烧写完成后重启 ESP32, 它将启动单元测试程序。
|
||||
烧写完成后重启 {IDF_TARGET_NAME}, 它将启动单元测试程序。
|
||||
|
||||
当单元测试应用程序空闲时,输入回车键,它会打印出测试菜单,其中包含所有的测试项目。
|
||||
|
||||
@ -199,7 +199,7 @@ DUT2(slave)终端:
|
||||
(17) "SPI Master no response when switch from host1 (HSPI) to host2 (VSPI)" [spi]
|
||||
(18) "SPI Master DMA test, TX and RX in different regions" [spi]
|
||||
(19) "SPI Master DMA test: length, start, not aligned" [spi]
|
||||
(20) "reset reason check for deepsleep" [esp32][test_env=UT_T2_1][multi_stage]
|
||||
(20) "reset reason check for deepsleep" [{IDF_TARGET_PATH_NAME}][test_env=UT_T2_1][multi_stage]
|
||||
(1) "trigger_deepsleep"
|
||||
(2) "check_deepsleep_reset_reason"
|
||||
|
||||
|
@ -6,13 +6,13 @@ Wi-Fi 库
|
||||
概述
|
||||
-----
|
||||
|
||||
Wi-Fi 库支持配置及监控 ESP32 Wi-Fi 连网功能。
|
||||
Wi-Fi 库支持配置及监控 {IDF_TARGET_NAME} Wi-Fi 连网功能。
|
||||
|
||||
支持配置:
|
||||
|
||||
- 基站模式(即 STA 模式或 Wi-Fi 客户端模式),此时 ESP32 连接到接入点 (AP)。
|
||||
- AP 模式(即 Soft-AP 模式或接入点模式),此时基站连接到 ESP32。
|
||||
- AP-STA 共存模式(ESP32 既是接入点,同时又作为基站连接到另外一个接入点)。
|
||||
- 基站模式(即 STA 模式或 Wi-Fi 客户端模式),此时 {IDF_TARGET_NAME} 连接到接入点 (AP)。
|
||||
- AP 模式(即 Soft-AP 模式或接入点模式),此时基站连接到 {IDF_TARGET_NAME}。
|
||||
- AP-STA 共存模式({IDF_TARGET_NAME} 既是接入点,同时又作为基站连接到另外一个接入点)。
|
||||
|
||||
- 上述模式的各种安全模式(WPA、WPA2 及 WEP 等)。
|
||||
- 扫描接入点(包括主动扫描及被动扫描)。
|
||||
@ -26,7 +26,7 @@ ESP-IDF 示例项目的 :example:`wifi` 目录下包含以下应用程序:
|
||||
|
||||
* Wi-Fi 示例代码;
|
||||
|
||||
* 另外一个简单的应用程序 `esp-idf-template <https://github.com/espressif/esp-idf-template>`_,演示了如何将 ESP32 模组连接到 AP。
|
||||
* 另外一个简单的应用程序 `esp-idf-template <https://github.com/espressif/esp-idf-template>`_,演示了如何将 {IDF_TARGET_NAME} 模组连接到 AP。
|
||||
|
||||
|
||||
API 参考
|
||||
|
@ -12,8 +12,8 @@ mDNS 是一种组播 UDP 服务,用来提供本地网络服务和主机发现
|
||||
mDNS 属性
|
||||
^^^^^^^^^
|
||||
|
||||
* ``hostname``:设备会去响应的主机名,如果没有设置,会根据设备的网络接口名定义 ``hostname`` 。例如,``my-esp32`` 会被解析为 ``my-esp32.local``。
|
||||
* ``default_instance``:默认实例名(即易记的设备名),例如 ``Jhon's ESP32 Thing``。如果没有设置,将会使用 ``hostname``。
|
||||
* ``hostname``:设备会去响应的主机名,如果没有设置,会根据设备的网络接口名定义 ``hostname`` 。例如,``my-{IDF_TARGET_PATH_NAME}`` 会被解析为 ``my-{IDF_TARGET_PATH_NAME}.local``。
|
||||
* ``default_instance``:默认实例名(即易记的设备名),例如 ``Jhon's {IDF_TARGET_NAME} Thing``。如果没有设置,将会使用 ``hostname``。
|
||||
|
||||
以下为 STA 接口启动 mDNS 服务并设置 ``hostname`` 和 ``default_instance`` 的示例方法:
|
||||
|
||||
@ -29,11 +29,11 @@ mDNS 属性
|
||||
printf("MDNS Init failed: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 设置 hostname
|
||||
mdns_hostname_set("my-esp32");
|
||||
mdns_hostname_set("my-{IDF_TARGET_PATH_NAME}");
|
||||
// 设置默认实例
|
||||
mdns_instance_name_set("Jhon's ESP32 Thing");
|
||||
mdns_instance_name_set("Jhon's {IDF_TARGET_NAME} Thing");
|
||||
}
|
||||
|
||||
mDNS 服务
|
||||
@ -41,7 +41,7 @@ mDNS 服务
|
||||
|
||||
mDNS 可以广播设备能够提供的网络服务的相关信息,每个服务会由以下属性构成。
|
||||
|
||||
* ``instance_name``:实例名(即易记的服务名),例如 ``Jhon's ESP32 Web Server``。如果没有定义,会使用 ``default_instance``。
|
||||
* ``instance_name``:实例名(即易记的服务名),例如 ``Jhon's {IDF_TARGET_NAME} Web Server``。如果没有定义,会使用 ``default_instance``。
|
||||
* ``service_type``:(必需)服务类型,以下划线为前缀,`这里 <http://www.dns-sd.org/serviceTypes.html>`_ 列出了常见的类型。
|
||||
* ``proto``:(必需)服务运行所依赖的协议,以下划线为前缀,例如 ``_tcp`` 或者 ``_udp``。
|
||||
* ``port``:(必需)服务运行所用的端口号。
|
||||
@ -55,19 +55,19 @@ mDNS 可以广播设备能够提供的网络服务的相关信息,每个服务
|
||||
mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0);
|
||||
mdns_service_add(NULL, "_arduino", "_tcp", 3232, NULL, 0);
|
||||
mdns_service_add(NULL, "_myservice", "_udp", 1234, NULL, 0);
|
||||
|
||||
|
||||
// 注意:必须先添加服务,然后才能设置其属性
|
||||
// web 服务器使用自定义的实例名
|
||||
mdns_service_instance_name_set("_http", "_tcp", "Jhon's ESP32 Web Server");
|
||||
mdns_service_instance_name_set("_http", "_tcp", "Jhon's {IDF_TARGET_NAME} Web Server");
|
||||
|
||||
mdns_txt_item_t serviceTxtData[3] = {
|
||||
{"board","esp32"},
|
||||
{"board","{IDF_TARGET_PATH_NAME}"},
|
||||
{"u","user"},
|
||||
{"p","password"}
|
||||
};
|
||||
// 设置服务的文本数据(会释放并替换当前数据)
|
||||
mdns_service_txt_set("_http", "_tcp", serviceTxtData, 3);
|
||||
|
||||
|
||||
// 修改服务端口号
|
||||
mdns_service_port_set("_myservice", "_udp", 4321);
|
||||
}
|
||||
@ -161,9 +161,9 @@ mDNS 提供查询服务和解析主机 IP/IPv6 地址的方法。
|
||||
使用上述方法的示例::
|
||||
|
||||
void my_app_some_method(){
|
||||
// 搜索 esp32-mdns.local
|
||||
resolve_mdns_host("esp32-mdns");
|
||||
|
||||
// 搜索 {IDF_TARGET_PATH_NAME}-mdns.local
|
||||
resolve_mdns_host("{IDF_TARGET_PATH_NAME}-mdns");
|
||||
|
||||
// 搜索 HTTP 服务器
|
||||
find_mdns_service("_http", "_tcp");
|
||||
// 或者搜索文件服务器
|
||||
|
@ -35,11 +35,11 @@ spiffsgen.py
|
||||
|
||||
python spiffsgen.py --help
|
||||
|
||||
上述可选参数对应 SPIFFS 构建配置选项。若想顺利生成可用的映像,请确保使用的参数或配置与构建 SPIFFS 时所用的参数或配置相同。运行帮助命令将显示参数所对应的 SPIFFS 构建配置。如未指定参数,将使用帮助信息中的默认值。
|
||||
上述可选参数对应 SPIFFS 构建配置选项。若想顺利生成可用的映像,请确保使用的参数或配置与构建 SPIFFS 时所用的参数或配置相同。运行帮助命令将显示参数所对应的 SPIFFS 构建配置。如未指定参数,将使用帮助信息中的默认值。
|
||||
|
||||
映像生成后,您可以使用 ``esptool.py`` 或 ``parttool.py`` 烧录映像。
|
||||
|
||||
您可以在命令行或脚本中手动单独调用 ``spiffsgen.py``,也可以直接从构建系统调用 ``spiffs_create_partition_image`` 来使用 ``spiffsgen.py``。
|
||||
您可以在命令行或脚本中手动单独调用 ``spiffsgen.py``,也可以直接从构建系统调用 ``spiffs_create_partition_image`` 来使用 ``spiffsgen.py``。
|
||||
|
||||
在 Make 构建系统中运行::
|
||||
|
||||
@ -51,14 +51,14 @@ spiffsgen.py
|
||||
|
||||
spiffs_create_partition_image(<partition> <base_dir> [FLASH_IN_PROJECT] [DEPENDS dep dep dep...])
|
||||
|
||||
在构建系统中使用 ``spiffsgen.py`` 更为方便,构建配置自动传递给 ``spiffsgen.py`` 工具,确保生成的映像可用于构建。比如,单独调用 ``spiffsgen.py`` 时需要用到 *image_size* 参数,但在构建系统中调用 ``spiffs_create_partition_image`` 时,仅需要 *partition* 参数,映像大小将直接从工程分区表中获取。
|
||||
在构建系统中使用 ``spiffsgen.py`` 更为方便,构建配置自动传递给 ``spiffsgen.py`` 工具,确保生成的映像可用于构建。比如,单独调用 ``spiffsgen.py`` 时需要用到 *image_size* 参数,但在构建系统中调用 ``spiffs_create_partition_image`` 时,仅需要 *partition* 参数,映像大小将直接从工程分区表中获取。
|
||||
|
||||
Make 构建系统和 CMake 构建系统结构有所不同,请注意以下几点:
|
||||
|
||||
- 在 Make 构建系统中使用 ``spiffs_create_partition_image``,需从工程 Makefile 中调用;
|
||||
- 在 CMake 构建系统中使用 ``spiffs_create_partition_image``,需从组件 CMakeLists.txt 文件调用。
|
||||
|
||||
您也可以指定 ``FLASH_IN_PROJECT``,然后使用 ``idf.py flash`` 或 ``make flash`` 将映像与应用程序二进制文件、分区表等一起自动烧录至设备,例如:
|
||||
您也可以指定 ``FLASH_IN_PROJECT``,然后使用 ``idf.py flash`` 或 ``make flash`` 将映像与应用程序二进制文件、分区表等一起自动烧录至设备,例如:
|
||||
|
||||
在 Make 构建系统中运行::
|
||||
|
||||
@ -75,7 +75,7 @@ Make 构建系统和 CMake 构建系统结构有所不同,请注意以下几
|
||||
|
||||
在 Make 构建系统中运行::
|
||||
|
||||
dep:
|
||||
dep:
|
||||
...
|
||||
|
||||
SPIFFS_IMAGE_DEPENDS := dep
|
||||
@ -87,7 +87,7 @@ Make 构建系统和 CMake 构建系统结构有所不同,请注意以下几
|
||||
|
||||
spiffs_create_partition_image(my_spiffs_partition my_folder DEPENDS dep)
|
||||
|
||||
请参考 :example:`storage/spiffsgen`,查看示例。
|
||||
请参考 :example:`storage/spiffsgen`,查看示例。
|
||||
|
||||
mkspiffs
|
||||
^^^^^^^^^^^
|
||||
@ -107,7 +107,7 @@ mkspiffs
|
||||
|
||||
运行以下命令,将映像烧录到 ESP32(偏移量:0x110000)::
|
||||
|
||||
python esptool.py --chip esp32 --port [port] --baud [baud] write_flash -z 0x110000 spiffs.bin
|
||||
python esptool.py --chip {IDF_TARGET_PATH_NAME} --port [port] --baud [baud] write_flash -z 0x110000 spiffs.bin
|
||||
|
||||
|
||||
选择合适的 SPIFFS 工具
|
||||
|
@ -16,41 +16,35 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
|
||||
- RTOS 可以要求 CPU 在有任务准备开始运行时以最高配置频率工作。
|
||||
- 一些外设可能需要中断才能启用,因此其驱动也会要求禁用 Light-sleep 模式。
|
||||
|
||||
因为请求较高的 APB 频率或 CPU 频率,以及禁用 Light-sleep 模式会增加功耗,请将组件使用的电源管理锁降到最少。
|
||||
因为请求较高的 APB 频率或 CPU 频率,以及禁用 Light-sleep 模式会增加功耗,请将组件使用的电源管理锁降到最少。
|
||||
|
||||
电源管理配置
|
||||
-------------
|
||||
|
||||
编译时可使用 :ref:`CONFIG_PM_ENABLE` 选项启用电源管理功能。
|
||||
编译时可使用 :ref:`CONFIG_PM_ENABLE` 选项启用电源管理功能。
|
||||
|
||||
启用电源管理功能将会增加中断延迟。额外延迟与多个因素有关,例如:CPU 频率、单/双核模式、是否需要进行频率切换等。CPU 频率为 240 MHz 且未启用频率调节时,最小额外延迟为 0.2 us;如果启用频率调节,且在中断入口将频率由 40 MHz 调节至 80 MHz,则最大额外延迟为 40 us。
|
||||
|
||||
应用程序可以通过调用 :cpp:func:`esp_pm_configure` 函数启用动态调频 (DFS) 功能和自动 Light-sleep 模式。此函数的参数为 :cpp:class:`esp_pm_config_esp32_t`,定义了频率调节的相关设置。在此参数结构中,需要初始化下面三个字段:
|
||||
|
||||
.. only:: esp32
|
||||
- ``max_freq_mhz``:最大 CPU 频率 (MHz),即获取 ``ESP_PM_CPU_FREQ_MAX`` 锁后所使用的频率。该字段通常设置为 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_DEFAULT_CPU_FREQ_MHZ`。
|
||||
|
||||
- ``max_freq_mhz``:最大 CPU 频率 (MHz),即获取 ``ESP_PM_CPU_FREQ_MAX`` 锁后所使用的频率。该字段通常设置为 :ref:`CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ`。
|
||||
- ``min_freq_mhz``:最小 CPU 频率 (MHz),即仅获取 ``ESP_PM_APB_FREQ_MAX`` 锁后所使用的频率。该字段可设置为晶振 (XTAL) 频率值,或者 XTAL 频率值除以整数。注意,10 MHz 是生成 1 MHz 的 REF_TICK 默认时钟所需的最小频率。
|
||||
|
||||
.. only:: esp32s2
|
||||
|
||||
- ``max_freq_mhz``:最大 CPU 频率 (MHz),即获取 ``ESP_PM_CPU_FREQ_MAX`` 锁后所使用的频率。该字段通常设置为 :ref:`CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ`。
|
||||
|
||||
- ``min_freq_mhz``:最小 CPU 频率 (MHz),即仅获取 ``ESP_PM_APB_FREQ_MAX`` 锁后所使用的频率。该字段可设置为晶振 (XTAL) 频率值,或者 XTAL 频率值除以整数。注意,10 MHz 是生成 1 MHz 的 REF_TICK 默认时钟所需的最小频率。
|
||||
|
||||
- ``light_sleep_enable``:没有获取任何管理锁时,决定系统是否需要自动进入 Light-sleep 状态 (``true``/``false``)。
|
||||
- ``light_sleep_enable``:没有获取任何管理锁时,决定系统是否需要自动进入 Light-sleep 状态 (``true``/``false``)。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
或者,如果在 menuconfig 中启用了 :ref:`CONFIG_PM_DFS_INIT_AUTO` 选项,最大 CPU 频率将由 :ref:`CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ` 设置决定,最小 CPU 频率将锁定为 XTAL 频率。
|
||||
或者,如果在 menuconfig 中启用了 :ref:`CONFIG_PM_DFS_INIT_AUTO` 选项,最大 CPU 频率将由 :ref:`CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ` 设置决定,最小 CPU 频率将锁定为 XTAL 频率。
|
||||
|
||||
.. only:: esp32s2
|
||||
|
||||
或者,如果在 menuconfig 中启用了 :ref:`CONFIG_PM_DFS_INIT_AUTO` 选项,最大 CPU 频率将由 :ref:`CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ` 设置决定,最小 CPU 频率将锁定为 XTAL 频率。
|
||||
或者,如果在 menuconfig 中启用了 :ref:`CONFIG_PM_DFS_INIT_AUTO` 选项,最大 CPU 频率将由 :ref:`CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ` 设置决定,最小 CPU 频率将锁定为 XTAL 频率。
|
||||
|
||||
.. note::
|
||||
|
||||
1. 自动 Light-sleep 模式基于 FreeRTOS Tickless Idle 功能,因此如果在 menuconfig 中没有启用 :ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE` 选项,在请求自动 Light-sleep 时,:cpp:func:`esp_pm_configure` 将会返回 `ESP_ERR_NOT_SUPPORTED` 错误。
|
||||
2. 在 Light-sleep 状态下,外设设有时钟门控,不会产生来自 GPIO 和内部外设的中断。:doc:`sleep_modes` 文档中所提到的唤醒源可用于从 Light-sleep 状态触发唤醒。例如,EXT0 和 EXT1 唤醒源就可以通过 GPIO 唤醒芯片。
|
||||
2. 在 Light-sleep 状态下,外设设有时钟门控,不会产生来自 GPIO 和内部外设的中断。:doc:`sleep_modes` 文档中所提到的唤醒源可用于从 Light-sleep 状态触发唤醒。例如,EXT0 和 EXT1 唤醒源就可以通过 GPIO 唤醒芯片。
|
||||
|
||||
电源管理锁
|
||||
----------------------
|
||||
@ -73,7 +67,7 @@ ESP32 支持下表中所述的三种电源管理锁。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
.. include:: inc/power_management_esp32.rst
|
||||
.. include:: ../../en/inc/power_management_esp32.rst
|
||||
|
||||
动态调频和外设驱动
|
||||
------------------------------------------------
|
||||
@ -82,7 +76,7 @@ ESP32 支持下表中所述的三种电源管理锁。
|
||||
|
||||
下面的外设不受 APB 频率变更的影响:
|
||||
|
||||
- **UART**:如果 REF_TICK 用作时钟源,则 UART 不受 APB 频率变更影响。请查看 :cpp:class:`uart_config_t` 中的 `use_ref_tick`。
|
||||
- **UART**:如果 REF_TICK 用作时钟源,则 UART 不受 APB 频率变更影响。请查看 :cpp:class:`uart_config_t` 中的 `use_ref_tick`。
|
||||
- **LEDC**:如果 REF_TICK 用作时钟源,则 LEDC 不受 APB 频率变更影响。请查看 :cpp:func:`ledc_timer_config` 函数。
|
||||
- **RMT**:如果 REF_TICK 用作时钟源,则 RMT 不受 APB 频率变更影响。此驱动程序尚不支持 REF_TICK,但可以清除相应通道的 ``RMT_REF_ALWAYS_ON_CHx`` 位来启用该功能。
|
||||
|
||||
@ -98,7 +92,7 @@ ESP32 支持下表中所述的三种电源管理锁。
|
||||
- **SPI slave**:从调用 :cpp:func:`spi_slave_initialize` 至 :cpp:func:`spi_slave_free` 期间。
|
||||
- **Ethernet**:从调用 :cpp:func:`esp_eth_driver_install` 至 :cpp:func:`esp_eth_driver_uninstall` 期间。
|
||||
- **WiFi**:从调用 :cpp:func:`esp_wifi_start` 至 :cpp:func:`esp_wifi_stop` 期间。如果启用了调制解调器睡眠模式,广播关闭时将释放此管理锁。
|
||||
- **CAN**:从调用 :cpp:func:`can_driver_install` 至 :cpp:func:`can_driver_uninstall` 期间。
|
||||
- **CAN**:从调用 :cpp:func:`can_driver_install` 至 :cpp:func:`can_driver_uninstall` 期间。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
|
@ -1,31 +1,33 @@
|
||||
与 ESP32 创建串口连接
|
||||
与 {IDF_TARGET_NAME} 创建串口连接
|
||||
==============================================
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
本章节主要介绍如何创建 ESP32 和 PC 之间的串口连接。
|
||||
本章节主要介绍如何创建 {IDF_TARGET_NAME} 和 PC 之间的串口连接。
|
||||
|
||||
|
||||
连接 ESP32 和 PC
|
||||
--------------------
|
||||
连接 {IDF_TARGET_NAME} 和 PC
|
||||
---------------------------
|
||||
|
||||
用 USB 线将 ESP32 开发板连接到 PC。如果设备驱动程序没有自动安装,请先确认 ESP32 开发板上的 USB 转串口芯片(或外部转串口适配器)型号,然后在网上搜索驱动程序,并进行手动安装。
|
||||
用 USB 线将 {IDF_TARGET_NAME} 开发板连接到 PC。如果设备驱动程序没有自动安装,请先确认 {IDF_TARGET_NAME} 开发板上的 USB 转串口芯片(或外部转串口适配器)型号,然后在网上搜索驱动程序,并进行手动安装。
|
||||
|
||||
以下是乐鑫 ESP32 开发板驱动程序的链接:
|
||||
以下是乐鑫 {IDF_TARGET_NAME} 开发板驱动程序的链接:
|
||||
|
||||
.. csv-table::
|
||||
:header: 开发板, USB 驱动, 备注
|
||||
:widths: 40, 20, 40
|
||||
.. only:: esp32
|
||||
|
||||
:ref:`ESP32-DevKitC <esp-modules-and-boards-esp32-devkitc>`, `CP210x`_
|
||||
`ESP32-LyraT <https://www.espressif.com/en/products/hardware/esp32-lyrat>`_, `CP210x`_
|
||||
`ESP32-LyraTD-MSC <https://www.espressif.com/en/products/hardware/esp32-lyratd-msc>`_, `CP210x`_
|
||||
:ref:`ESP32-PICO-KIT <esp-modules-and-boards-esp32-pico-kit>`, `CP210x`_
|
||||
:ref:`ESP-WROVER-KIT <esp-modules-and-boards-esp-wrover-kit>`, `FTDI`_
|
||||
:ref:`ESP32 Demo 板 <esp-modules-and-boards-esp32-demo-board>`, `FTDI`_
|
||||
`ESP-Prog`_, `FTDI`_, 编程板 (w/o ESP32)
|
||||
`ESP32-MeshKit-Sense <https://github.com/espressif/esp-iot-solution/blob/master/documents/evaluation_boards/ESP32-MeshKit-Sense_guide_en.md#esp32-meshkit-sense-hardware-design-guidelines>`_, n/a, 搭配 `ESP-Prog`_ 使用
|
||||
`ESP32-Sense Kit <https://github.com/espressif/esp-iot-solution/blob/master/documents/evaluation_boards/esp32_sense_kit_guide_en.md#guide-for-esp32-sense-development-kit>`_, n/a, 搭配 `ESP-Prog`_ 使用
|
||||
.. csv-table::
|
||||
:header: 开发板, USB 驱动, 备注
|
||||
:widths: 40, 20, 40
|
||||
|
||||
:ref:`ESP32-DevKitC <esp-modules-and-boards-esp32-devkitc>`, `CP210x`_
|
||||
`ESP32-LyraT <https://www.espressif.com/en/products/hardware/esp32-lyrat>`_, `CP210x`_
|
||||
`ESP32-LyraTD-MSC <https://www.espressif.com/en/products/hardware/esp32-lyratd-msc>`_, `CP210x`_
|
||||
:ref:`ESP32-PICO-KIT <esp-modules-and-boards-esp32-pico-kit>`, `CP210x`_
|
||||
:ref:`ESP-WROVER-KIT <esp-modules-and-boards-esp-wrover-kit>`, `FTDI`_
|
||||
:ref:`ESP32 Demo 板 <esp-modules-and-boards-esp32-demo-board>`, `FTDI`_
|
||||
`ESP-Prog`_, `FTDI`_, 编程板 (w/o ESP32)
|
||||
`ESP32-MeshKit-Sense <https://github.com/espressif/esp-iot-solution/blob/master/documents/evaluation_boards/ESP32-MeshKit-Sense_guide_en.md#esp32-meshkit-sense-hardware-design-guidelines>`_, n/a, 搭配 `ESP-Prog`_ 使用
|
||||
`ESP32-Sense Kit <https://github.com/espressif/esp-iot-solution/blob/master/documents/evaluation_boards/esp32_sense_kit_guide_en.md#guide-for-esp32-sense-development-kit>`_, n/a, 搭配 `ESP-Prog`_ 使用
|
||||
|
||||
.. _CP210x: https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers
|
||||
.. _FTDI: http://www.ftdichip.com/Drivers/VCP.htm
|
||||
@ -34,12 +36,12 @@
|
||||
* CP210x: `CP210x USB 至 UART 桥 VCP 驱动程序 <https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers>`_
|
||||
* FTDI: `FTDI 虚拟 COM 端口驱动程序 <http://www.ftdichip.com/Drivers/VCP.htm>`_
|
||||
|
||||
以上驱动仅用于参考。一般情况下,当上述任一 ESP32 开发板与 PC 连接时,对应驱动程序应该已经被打包在操作系统中,并已经自动安装。
|
||||
以上驱动仅用于参考。一般情况下,当上述任一 {IDF_TARGET_NAME} 开发板与 PC 连接时,对应驱动程序应该已经被打包在操作系统中,并已经自动安装。
|
||||
|
||||
在 Windows 上查看端口
|
||||
---------------------
|
||||
|
||||
检查 Windows 设备管理器中的 COM 端口列表。断开 ESP32 与 PC 的连接,然后重新连接,查看哪个端口从列表中消失,然后再次出现。
|
||||
检查 Windows 设备管理器中的 COM 端口列表。断开 {IDF_TARGET_NAME} 与 PC 的连接,然后重新连接,查看哪个端口从列表中消失,然后再次出现。
|
||||
|
||||
以下为 ESP32 DevKitC 和 ESP32 WROVER KIT 串口:
|
||||
|
||||
@ -61,7 +63,7 @@
|
||||
在 Linux 和 MacOS 上查看端口
|
||||
-----------------------------
|
||||
|
||||
查看 ESP32 开发板(或外部转串口适配器)的串口设备名称,请运行两次以下命令。首先,断开开发板或适配器,第一次运行命令;然后,连接开发板或适配器,第二次运行命令。其中,第二次运行命令后出现的端口即是 ESP32 对应的串口:
|
||||
查看 {IDF_TARGET_NAME} 开发板(或外部转串口适配器)的串口设备名称,请运行两次以下命令。首先,断开开发板或适配器,第一次运行命令;然后,连接开发板或适配器,第二次运行命令。其中,第二次运行命令后出现的端口即是 {IDF_TARGET_NAME} 对应的串口:
|
||||
|
||||
Linux ::
|
||||
|
||||
@ -113,7 +115,7 @@ MacOS ::
|
||||
在 Linux 操作系统中使用 PuTTY 设置串口通信参数
|
||||
|
||||
|
||||
然后,请检查 ESP32 是否有打印日志。如有,请在终端打开串口进行查看。这里,日志内容取决于加载到 ESP32 的应用程序,下图即为一个示例。
|
||||
然后,请检查 {IDF_TARGET_NAME} 是否有打印日志。如有,请在终端打开串口进行查看。这里,日志内容取决于加载到 {IDF_TARGET_NAME} 的应用程序,下图即为一个示例。
|
||||
|
||||
.. highlight:: none
|
||||
|
||||
@ -138,17 +140,17 @@ MacOS ::
|
||||
|
||||
...
|
||||
|
||||
如果打印出的日志是可读的(而不是乱码),则表示串口连接正常。此时,你可以继续进行安装,并最终将应用程序上载到 ESP32。
|
||||
如果打印出的日志是可读的(而不是乱码),则表示串口连接正常。此时,你可以继续进行安装,并最终将应用程序上载到 {IDF_TARGET_NAME}。
|
||||
|
||||
.. note::
|
||||
|
||||
在某些串口接线方式下,在 ESP32 启动并开始打印串口日志前,需要在终端程序中禁用串口 RTS & DTR 引脚。该问题仅存在于将 RTS & DTR 引脚直接连接到 EN & GPIO0 引脚上的情况,绝大多数开发板(包括乐鑫所有的开发板)都没有这个问题。更多详细信息,参见 `esptool 文档`_。
|
||||
在某些串口接线方式下,在 {IDF_TARGET_NAME} 启动并开始打印串口日志前,需要在终端程序中禁用串口 RTS & DTR 引脚。该问题仅存在于将 RTS & DTR 引脚直接连接到 EN & GPIO0 引脚上的情况,绝大多数开发板(包括乐鑫所有的开发板)都没有这个问题。更多详细信息,参见 `esptool 文档`_。
|
||||
|
||||
.. note::
|
||||
|
||||
请在验证完串口通信正常后,关闭串口终端。下一步,我们将使用另一个应用程序将新的固件上传到 ESP32。此时,如果串口被占用则无法成功。
|
||||
请在验证完串口通信正常后,关闭串口终端。下一步,我们将使用另一个应用程序将新的固件上传到 {IDF_TARGET_NAME}。此时,如果串口被占用则无法成功。
|
||||
|
||||
如你在安装 ESP32 硬件开发的软件环境时,从 :ref:`get-started-connect` 跳转到了这里,请从 :ref:`get-started-configure` 继续阅读。
|
||||
如你在安装 {IDF_TARGET_NAME} 硬件开发的软件环境时,从 :ref:`get-started-connect` 跳转到了这里,请从 :ref:`get-started-configure` 继续阅读。
|
||||
|
||||
|
||||
.. _esptool 文档: https://github.com/espressif/esptool/wiki/ESP32-Boot-Mode-Selection#automatic-bootloader
|
||||
|
@ -4,48 +4,58 @@
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
本文档旨在指导用户搭建 ESP32 硬件开发的软件环境,通过一个简单的示例展示如何使用 ESP-IDF (Espressif IoT Development Framework) 配置菜单,并编译、下载固件至 ESP32 开发板等步骤。
|
||||
本文档旨在指导用户搭建 {IDF_TARGET_NAME} 硬件开发的软件环境,通过一个简单的示例展示如何使用 ESP-IDF (Espressif IoT Development Framework) 配置菜单,并编译、下载固件至 {IDF_TARGET_NAME} 开发板等步骤。
|
||||
|
||||
.. include-build-file:: inc/version-note.inc
|
||||
|
||||
概述
|
||||
============
|
||||
|
||||
ESP32 SoC 芯片支持以下功能:
|
||||
.. only:esp32
|
||||
|
||||
* 2.4 GHz Wi-Fi
|
||||
* 蓝牙 4.2
|
||||
* 高性能双核
|
||||
* 超低功耗协处理器
|
||||
* 多种外设
|
||||
ESP32 SoC 芯片支持以下功能:
|
||||
|
||||
ESP32 采用 40 nm 工艺制成,具有最佳的功耗性能、射频性能、稳定性、通用性和可靠性,适用于各种应用场景和不同功耗需求。
|
||||
* 2.4 GHz Wi-Fi
|
||||
* 蓝牙 4.2
|
||||
* 高性能双核
|
||||
* 超低功耗协处理器
|
||||
* 多种外设
|
||||
|
||||
乐鑫为用户提供完整的软、硬件资源,进行 ESP32 硬件设备的开发。其中,乐鑫的软件开发环境 ESP-IDF 旨在协助用户快速开发物联网 (IoT) 应用,可满足用户对 Wi-Fi、蓝牙、低功耗等方面的要求。
|
||||
.. only:esp32s2
|
||||
|
||||
ESP32-S2 SoC 芯片支持以下功能:
|
||||
|
||||
* 2.4 GHz Wi-Fi
|
||||
* 超低功耗协处理器
|
||||
* 多种外设
|
||||
|
||||
{IDF_TARGET_NAME} 采用 40 nm 工艺制成,具有最佳的功耗性能、射频性能、稳定性、通用性和可靠性,适用于各种应用场景和不同功耗需求。
|
||||
|
||||
乐鑫为用户提供完整的软、硬件资源,进行 {IDF_TARGET_NAME} 硬件设备的开发。其中,乐鑫的软件开发环境 ESP-IDF 旨在协助用户快速开发物联网 (IoT) 应用,可满足用户对 Wi-Fi、蓝牙、低功耗等方面的要求。
|
||||
|
||||
准备工作
|
||||
=============
|
||||
|
||||
硬件:
|
||||
|
||||
* 一款 **ESP32** 开发板
|
||||
* 一款 **{IDF_TARGET_NAME}** 开发板
|
||||
* **USB 数据线** (A 转 Micro-B)
|
||||
* PC(Windows、Linux 或 Mac OS)
|
||||
|
||||
软件:
|
||||
|
||||
* 设置 **工具链**,用于编译 ESP32 代码;
|
||||
* **编译工具** —— CMake 和 Ninja 编译工具,用于编译 ESP32 **应用程序**;
|
||||
* 获取 **ESP-IDF** 软件开发框架。该框架已经基本包含 ESP32 使用的 API(软件库和源代码)和运行 **工具链** 的脚本;
|
||||
* 设置 **工具链**,用于编译 {IDF_TARGET_NAME} 代码;
|
||||
* **编译工具** —— CMake 和 Ninja 编译工具,用于编译 {IDF_TARGET_NAME} **应用程序**;
|
||||
* 获取 **ESP-IDF** 软件开发框架。该框架已经基本包含 {IDF_TARGET_NAME} 使用的 API(软件库和源代码)和运行 **工具链** 的脚本;
|
||||
* 安装 C 语言编程(**工程**)的 **文本编辑器**,例如 `Eclipse <https://www.eclipse.org/>`_。
|
||||
|
||||
|
||||
.. figure:: ../../_static/what-you-need.png
|
||||
:align: center
|
||||
:alt: ESP32 应用程序开发
|
||||
:alt: {IDF_TARGET_NAME} 应用程序开发
|
||||
:figclass: align-center
|
||||
|
||||
ESP32 应用程序开发
|
||||
{IDF_TARGET_NAME} 应用程序开发
|
||||
|
||||
|
||||
开发板简介
|
||||
@ -53,13 +63,15 @@ ESP32 采用 40 nm 工艺制成,具有最佳的功耗性能、射频性能、
|
||||
|
||||
请点击下方连接,了解有关具体开发板的详细信息。
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
.. only:: esp32
|
||||
|
||||
ESP32-DevKitC <../hw-reference/get-started-devkitc>
|
||||
ESP-WROVER-KIT <../hw-reference/get-started-wrover-kit>
|
||||
ESP32-PICO-KIT <../hw-reference/get-started-pico-kit>
|
||||
ESP32-Ethernet-Kit <../hw-reference/get-started-ethernet-kit>
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
ESP32-DevKitC <../hw-reference/get-started-devkitc>
|
||||
ESP-WROVER-KIT <../hw-reference/get-started-wrover-kit>
|
||||
ESP32-PICO-KIT <../hw-reference/get-started-pico-kit>
|
||||
ESP32-Ethernet-Kit <../hw-reference/get-started-ethernet-kit>
|
||||
|
||||
|
||||
.. _get-started-step-by-step:
|
||||
@ -127,7 +139,7 @@ ESP32 采用 40 nm 工艺制成,具有最佳的功耗性能、射频性能、
|
||||
第二步:获取 ESP-IDF
|
||||
=================================
|
||||
|
||||
在围绕 ESP32 构建应用程序之前,请先获取乐鑫提供的软件库文件 `ESP-IDF 仓库 <https://github.com/espressif/esp-idf>`_。
|
||||
在围绕 {IDF_TARGET_NAME} 构建应用程序之前,请先获取乐鑫提供的软件库文件 `ESP-IDF 仓库 <https://github.com/espressif/esp-idf>`_。
|
||||
|
||||
获取 ESP-IDF 的本地副本:打开终端,切换到您要保存 ESP-IDF 的工作目录,使用 ``git clone`` 命令克隆远程仓库。针对不同操作系统的详细步骤,请见下文。
|
||||
|
||||
@ -238,7 +250,7 @@ Linux 和 MacOS 操作系统
|
||||
第五步:开始创建工程
|
||||
========================================
|
||||
|
||||
现在,您可以开始准备开发 ESP32 应用程序了。您可以从 ESP-IDF 中 :idf:`examples` 目录下的 :example:`get-started/hello_world` 工程开始。
|
||||
现在,您可以开始准备开发 {IDF_TARGET_NAME} 应用程序了。您可以从 ESP-IDF 中 :idf:`examples` 目录下的 :example:`get-started/hello_world` 工程开始。
|
||||
|
||||
将 :example:`get-started/hello_world` 复制至您本地的 ``~/esp`` 目录下:
|
||||
|
||||
@ -269,7 +281,7 @@ ESP-IDF 的 :idf:`examples` 目录下有一系列示例工程,都可以按照
|
||||
第六步:连接设备
|
||||
==========================================
|
||||
|
||||
现在,请将您的 ESP32 开发板连接到 PC,并查看开发板使用的串口。
|
||||
现在,请将您的 {IDF_TARGET_NAME} 开发板连接到 PC,并查看开发板使用的串口。
|
||||
|
||||
通常,串口在不同操作系统下显示的名称有所不同:
|
||||
|
||||
@ -328,9 +340,11 @@ Windows 操作系统
|
||||
* ``英文问号`` (查询配置选项):调出有关该选项的帮助菜单
|
||||
* ``/ 键``:寻找配置工程
|
||||
|
||||
.. attention::
|
||||
.. only:: esp32
|
||||
|
||||
如果您使用的是 ESP32-DevKitC(板载 ESP32-SOLO-1 模组),请在烧写示例程序前,前往 ``menuconfig`` 中使能单核模式(:ref:`CONFIG_FREERTOS_UNICORE`)。
|
||||
.. attention::
|
||||
|
||||
如果您使用的是 ESP32-DevKitC(板载 ESP32-SOLO-1 模组),请在烧写示例程序前,前往 ``menuconfig`` 中使能单核模式(:ref:`CONFIG_FREERTOS_UNICORE`)。
|
||||
|
||||
.. _get-started-build:
|
||||
|
||||
@ -371,11 +385,11 @@ Windows 操作系统
|
||||
第九步:烧录到设备
|
||||
=============================
|
||||
|
||||
请使用以下命令,将刚刚生成的二进制文件烧录至您的 ESP32 开发板:
|
||||
请使用以下命令,将刚刚生成的二进制文件烧录至您的 {IDF_TARGET_NAME} 开发板:
|
||||
|
||||
``idf.py -p PORT [-b BAUD] flash``
|
||||
|
||||
请将 PORT 替换为 ESP32 开发板的串口名称,具体可见 :ref:`get-started-connect`。
|
||||
请将 PORT 替换为 {IDF_TARGET_NAME} 开发板的串口名称,具体可见 :ref:`get-started-connect`。
|
||||
|
||||
您还可以将 BAUD 替换为您希望的烧录波特率。默认波特率为 ``460800``。
|
||||
|
||||
@ -392,8 +406,8 @@ Windows 操作系统
|
||||
esptool.py -b 460800 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x1000 bootloader/bootloader.bin 0x8000 partition_table/partition-table.bin 0x10000 hello-world.bin
|
||||
esptool.py v2.3.1
|
||||
Connecting....
|
||||
Detecting chip type... ESP32
|
||||
Chip is ESP32D0WDQ6 (revision 1)
|
||||
Detecting chip type... {IDF_TARGET_NAME}
|
||||
Chip is {IDF_TARGET_NAME}D0WDQ6 (revision 1)
|
||||
Features: WiFi, BT, Dual Core
|
||||
Uploading stub...
|
||||
Running stub...
|
||||
@ -465,9 +479,9 @@ Windows 操作系统
|
||||
:align: center
|
||||
:alt: 乱码输出
|
||||
:figclass: align-center
|
||||
|
||||
|
||||
此时,您可以:
|
||||
|
||||
|
||||
1. 退出监视器。
|
||||
2. 打开 :ref:`menuconfig <get-started-configure>`。
|
||||
3. 进入 ``Component config`` --> ``ESP32-specific`` --> ``Main XTAL frequency`` 进行配置,将 :ref:`CONFIG_ESP32_XTAL_FREQ_SEL` 设置为 26 MHz。
|
||||
@ -484,14 +498,14 @@ Windows 操作系统
|
||||
- 请前往 :doc:`IDF 监视器 <../api-guides/tools/idf-monitor>`,了解更多使用 IDF 监视器的快捷键和其他详情。
|
||||
- 请前往 :ref:`idf.py`,查看更多 ``idf.py`` 命令和选项。
|
||||
|
||||
**恭喜,您已完成 ESP32 的入门学习!**
|
||||
**恭喜,您已完成 {IDF_TARGET_NAME} 的入门学习!**
|
||||
|
||||
现在,您可以尝试一些其他 :idf:`examples`,或者直接开发自己的应用程序。
|
||||
|
||||
更新 ESP-IDF
|
||||
================
|
||||
|
||||
乐鑫会不时推出更新版本的 ESP-IDF,修复 bug 或提出新的特性。因此,您在使用时,也应注意更新您本地的版本。最简单的方法是:直接删除您本地的 ``esp-idf`` 文件夹,然后按照 :ref:`get-started-get-esp-idf` 中的指示,重新完成克隆。
|
||||
乐鑫会不时推出更新版本的 ESP-IDF,修复 bug 或提出新的特性。因此,您在使用时,也应注意更新您本地的版本。最简单的方法是:直接删除您本地的 ``esp-idf`` 文件夹,然后按照 :ref:`get-started-get-esp-idf` 中的指示,重新完成克隆。
|
||||
|
||||
此外,您可以仅更新变更部分。具体方式,请前往 :ref:`更新 <updating>` 章节查看。
|
||||
|
||||
|
@ -62,11 +62,13 @@
|
||||
|
||||
编译工具链::
|
||||
|
||||
./ct-ng xtensa-esp32-elf
|
||||
./ct-ng xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf
|
||||
./ct-ng build
|
||||
chmod -R u+w builds/xtensa-esp32-elf
|
||||
chmod -R u+w builds/xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf
|
||||
|
||||
编译得到的工具链会被保存到 ``~/esp/crosstool-NG/builds/xtensa-esp32-elf``。请按照 :ref:`标准设置指南 <setup-linux-toolchain-add-it-to-path-legacy>` 的介绍,将工具链添加到 ``PATH``。
|
||||
.. only:: esp32
|
||||
|
||||
编译得到的工具链会被保存到 ``~/esp/crosstool-NG/builds/xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf``。请按照 :ref:`标准设置指南 <setup-linux-toolchain-add-it-to-path-legacy>` 的介绍,将工具链添加到 ``PATH``。
|
||||
|
||||
|
||||
后续步骤
|
||||
|
@ -30,7 +30,7 @@ Linux 平台工具链的标准设置
|
||||
权限问题 /dev/ttyUSB0
|
||||
------------------------------------------------------------
|
||||
|
||||
使用某些 Linux 版本向 ESP32 烧写固件时,可能会出现 ``Failed to open port /dev/ttyUSB0`` 错误消息。此时,可以将当前用户增加至 :ref:` Linux Dialout 组 <linux-dialout-group>`。
|
||||
使用某些 Linux 版本向 {IDF_TARGET_NAME} 烧写固件时,可能会出现 ``Failed to open port /dev/ttyUSB0`` 错误消息。此时,可以将当前用户增加至 :ref:` Linux Dialout 组 <linux-dialout-group>`。
|
||||
|
||||
后续步骤
|
||||
==========
|
||||
|
@ -67,17 +67,17 @@ MacPorts 需要完整的 XCode 软件,而 homebrew 只需要安装 XCode 命
|
||||
|
||||
cd ~/esp/ctng-volume
|
||||
|
||||
下载并编译 ``crosstool-NG``
|
||||
下载并编译 ``crosstool-NG``
|
||||
|
||||
.. include-build-file:: inc/scratch-build-code.inc
|
||||
|
||||
编译工具链::
|
||||
|
||||
./ct-ng xtensa-esp32-elf
|
||||
./ct-ng xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf
|
||||
./ct-ng build
|
||||
chmod -R u+w builds/xtensa-esp32-elf
|
||||
chmod -R u+w builds/xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf
|
||||
|
||||
编译得到的工具链会被保存到 ``~/esp/ctng-volume/crosstool-NG/builds/xtensa-esp32-elf``。使用工具链前,请将 ``~/esp/ctng-volume/crosstool-NG/builds/xtensa-esp32-elf/bin`` 添加至 ``PATH`` 环境变量。
|
||||
编译得到的工具链会被保存到 ``~/esp/ctng-volume/crosstool-NG/builds/xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf``。使用工具链前,请将 ``~/esp/ctng-volume/crosstool-NG/builds/xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf/bin`` 添加至 ``PATH`` 环境变量。
|
||||
|
||||
|
||||
后续步骤
|
||||
|
@ -35,7 +35,7 @@ ESP-IDF 将下载至 ``%userprofile%\esp\esp-idf``。
|
||||
.. note::
|
||||
|
||||
在克隆远程仓库时,不要忘记加上 ``--recursive`` 选项。否则,请接着运行以下命令,获取所有子模块 ::
|
||||
|
||||
|
||||
cd esp-idf
|
||||
git submodule update --init
|
||||
|
||||
@ -56,7 +56,7 @@ Ninja 编译工具
|
||||
.. note::
|
||||
目前,Ninja 仅提供支持 64 位 Windows 版本的 bin 文件。您也可以配合其他编译工具在 32 位 Windows 版本中使用 CMake 和 ``idf.py`` ,比如 mingw-make。但是目前暂无关于此工具的说明文档。
|
||||
|
||||
从(`下载页面 <ninja-dl_>`_)下载最新发布的 Windows 平台稳定版 ninja_。
|
||||
从(`下载页面 <ninja-dl_>`_)下载最新发布的 Windows 平台稳定版 ninja_。
|
||||
|
||||
适用于 Windows 平台的 Ninja 下载文件是一个 .zip 文件,包含一个 ``ninja.exe`` 文件。您需要将该文件解压到目录,并 :ref:`添加到您的路径 <add-directory-windows-path>` (或者选择您路径中的已有目录)。
|
||||
|
||||
@ -88,12 +88,12 @@ Python 安装完成后,从 Windows 开始菜单中打开“命令提示符”
|
||||
|
||||
|download_link_win32|
|
||||
|
||||
解压压缩包文件到 ``C:\Program Files`` (或其他位置)。压缩包文件包含一个 ``xtensa-esp32-elf`` 目录。
|
||||
解压压缩包文件到 ``C:\Program Files`` (或其他位置)。压缩包文件包含一个 ``xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf`` 目录。
|
||||
|
||||
然后,请将该目录下的 ``bin`` 子目录 :ref:`添加到您的路径 <add-directory-windows-path>`。例如,``C:\Program Files\xtensa-esp32-elf\bin``。
|
||||
然后,请将该目录下的 ``bin`` 子目录 :ref:`添加到您的路径 <add-directory-windows-path>`。例如,``C:\Program Files\xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf\bin``。
|
||||
|
||||
.. note::
|
||||
如果您已安装 MSYS2 环境(适用 "GNU Make" 编译系统),则可以跳过下载那一步,直接添加目录 ``C:\msys32\opt\xtensa-esp32-elf\bin`` 到路径,因为 MSYS2 环境已包含工具链。
|
||||
如果您已安装 MSYS2 环境(适用 "GNU Make" 编译系统),则可以跳过下载那一步,直接添加目录 ``C:\msys32\opt\xtensa-{IDF_TARGET_TOOLCHAIN_NAME}-elf\bin`` 到路径,因为 MSYS2 环境已包含工具链。
|
||||
|
||||
|
||||
.. _add-directory-windows-path:
|
||||
|
@ -12,7 +12,7 @@ Windows 平台工具链的标准设置
|
||||
概述
|
||||
============
|
||||
|
||||
ESP-IDF 需要安装一些必备工具,才能围绕 ESP32 构建固件,包括 Python、Git、交叉编译器、menuconfig 工具、CMake和 Ninja 编译工具等。
|
||||
ESP-IDF 需要安装一些必备工具,才能围绕 {IDF_TARGET_NAME} 构建固件,包括 Python、Git、交叉编译器、menuconfig 工具、CMake和 Ninja 编译工具等。
|
||||
|
||||
在本入门指南中,我们通过 **命令提示符** 进行有关操作。不过,您在安装 ESP-IDF 后还可以使用 :doc:`Eclipse <eclipse-setup>` 或其他支持 CMake 的图形化工具 IDE。
|
||||
|
||||
|
@ -6,11 +6,13 @@ ESP32 H/W 硬件参考
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
ESP32 技术参考手册 (PDF) <https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_cn.pdf>
|
||||
ESP32 技术规格书 (PDF) <https://espressif.com/sites/default/files/documentation/esp32_datasheet_cn.pdf>
|
||||
ESP32 硬件设计指南 (PDF) <https://espressif.com/sites/default/files/documentation/esp32_hardware_design_guidelines_cn.pdf>
|
||||
ESP32 勘误表及解决方法 (PDF) <https://espressif.com/sites/default/files/documentation/eco_and_workarounds_for_bugs_in_esp32_cn.pdf>
|
||||
:esp32: ESP32 技术参考手册 (PDF) <https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_cn.pdf>
|
||||
:esp32s2beta: ESP32-S2 技术参考手册 (PDF) <https://espressif.com/sites/default/files/documentation/esp32s2_technical_reference_manual_cn.pdf>
|
||||
:esp32: ESP32 技术规格书 (PDF) <https://espressif.com/sites/default/files/documentation/esp32_datasheet_cn.pdf>
|
||||
:esp32s2beta: ESP32-S2 技术规格书 (PDF) <https://espressif.com/sites/default/files/documentation/esp32s2_datasheet_cn.pdf>
|
||||
:esp32: ESP32 硬件设计指南 (PDF) <https://espressif.com/sites/default/files/documentation/esp32_hardware_design_guidelines_cn.pdf>
|
||||
:esp32: ESP32 勘误表及解决方法 (PDF) <https://espressif.com/sites/default/files/documentation/eco_and_workarounds_for_bugs_in_esp32_cn.pdf>
|
||||
模组与开发板 <modules-and-boards>
|
||||
模组与开发板(历史版本)<modules-and-boards-previous>
|
||||
乐鑫产品订购信息 (PDF) <http://www.espressif.com/sites/default/files/documentation/espressif_products_ordering_information_cn.pdf>
|
||||
乐鑫产品证书 <https://www.espressif.com/zh-hans/certificates>
|
||||
乐鑫产品证书 <https://www.espressif.com/zh-hans/certificates>
|
||||
|
@ -80,7 +80,7 @@ ESP32-WROOM-32D/ESP32-WROOM-32U 模组
|
||||
|
||||
两款模组均集成了 ESP32-D0WD 芯片,与 :ref:`esp-modules-and-boards-esp32-wroom-32` 集成的 ESP32-D0WDQ6 相比,ESP32-D0WD 芯片的封装更小,在 PCB 上占用的面积更小。
|
||||
|
||||
有关这两款模组的详细信息,请查看 :ref:`esp-wroom-solo-wrover-modules` 中的表格和 `乐鑫产品订购信息`_。
|
||||
有关这两款模组的详细信息,请查看 :ref:`esp-wroom-solo-wrover-modules` 中的表格和 `乐鑫产品订购信息`_。
|
||||
|
||||
ESP32-WROOM-32U 是整个 WROOM/WROVER 模组系列中最小的模组。
|
||||
|
||||
@ -214,7 +214,7 @@ ESP32-PICO-KIT V4.1 开发板集成了 `ESP32-PICO-D4 模组`_,只需在 PCB (
|
||||
|
||||
|
||||
.. _esp-modules-and-boards-esp32-devkitc:
|
||||
|
||||
|
||||
ESP32 DevKitC V4 开发板
|
||||
------------------------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user