ESP32 系列芯片勘误表
相关资源与法律声明
影响版本: v0.0 v1.0 v1.1 v3.0 v3.1
RMII 工作模式下的以太网 MAC 和 PHY 需要一个公共的 50 MHz 同步时钟(即 RMII 时钟)。如果同时使用以太网与 Wi-Fi,则 RMII 时钟不能由内部的 ESP32 APLL 产生,因为会导致时钟不稳定。
如果要使用内部 APLL 生成同步时钟,则需要关闭 Wi-Fi。
如果要同时使用以太网和 Wi-Fi,则必须使用外部 PHY 或外部时钟源提供同步时钟。
暂无 修复计划。
由于 [CPU-3.3] CPU 访问外设时,如果连续不间断地写同一个地址,会出现数据丢失的现象、[CPU-3.10] 双核 CPU 在读不同地址空间时可能会发生错误 和 [CPU-3.16] CPU 访问 0x3FF0_0000 ~ 0x3FF1_EFFF 与 0x3FF4_0000 ~ 0x3FF7_FFFF 两段地址空间存在限制 章节描述的原因,在不同芯片版本中,CPU 使用 0x3FF0_0000 ~ 0x3FF1_EFFF、0x3FF4_0000 ~ 0x3FF7_FFFF 和 0x6000_0000 ~ 0x6003_FFFF 地址访问外设寄存器时需注意:
地址空间(总线)
寄存器类型
操作
芯片版本
v0.0
v1.0
v1.1
v3.0
v3.1
0x3FF0_0000 ~ 0x3FF1_EFFF 和 0x3FF4_0000 ~ 0x3FF7_FFFF (DPORT)
Non- FIFO
写
Yes
读
No (详见 [CPU-3.10] 双核 CPU 在读不同地址空间时可能会发生错误)
FIFO
No (详见 [CPU-3.3] CPU 访问外设时,如果连续不间断地写同一个地址,会出现数据丢失的现象)
0x6000_0000 ~ 0x6003_FFFF (AHB)
No (无此功能,无法预知结果)
Note
Yes: 操作正确执行
No: 操作失败
落在这两段地址空间的 CPU 读操作具有推测性,推测性读操作会导致程序描述的行为与硬件的真实行为不一致。
如果两个 CPU 同时连续访问 0x3FF0_0000 ~ 0x3FF1_EFFF 地址空间的内容,其中的一些访问可能丢失。
CPU 通过 0x3FF4_0000 ~ 0x3FF7_0000 地址空间读 FIFO 时,FIFO 的读指针会被延时更新。CPU 频率升高后,CPU 发起的两次连续读 FIFO 时间间隔缩短。当新的读 FIFO 请求到来时,FIFO 读指针还没有更新,这会导致 CPU 读到前一次读 FIFO 的值。
落在这两段地址空间的 CPU 访问均需要在对应的操作前加入 “MEMW” 指令。即在 C/C++ 中,软件访问这两段地址内的寄存器时需要加上 “volatile” 属性。
当 CPU 频率为 160 MHz 时,在两次连续读 FIFO 之间添加 6 个 “nop” 指令。CPU 频率为 240 MHz 时,在两次连续读 FIFO 之间添加 7 个 “nop” 指令。
当某个 CPU 使用 0x3FF40000 (UART0)、0x3FF50000 (UART1)、0x3FF6E000 (UART2)、0x3FF4F004 (I2S0)、0x3FF6D004 (I2S1) 这五个特定地址读取 FIFO 数据时,如果此时 CPU 发生中断,则读请求会被打断。 这会导致总线桥一直处于等待读请求结束的状态。接着任意 CPU 访问 APB 外设寄存器(0x3FF40000 ~ 0x3FF7FFFF 或 0x60000000 ~ 0x6003FFFF)请求就会被拒绝, 导致后续 CPU 访问被拖住。
写入这五个地址不会有问题。
读这五个特定地址之前禁用 CPU 中断,访问完成后开启 CPU 中断。
同时有 GPIO 和 RTC_GPIO 功能的 pad 的上拉下拉电阻只能由 RTC_GPIO 的上拉下拉寄存器控制。
GPIO 和 RTC_GPIO 都使用 RTC_GPIO 寄存器。
ESP-IDF v2.1 及更高版本的 GPIO 驱动自动绕过此问题。
在中断配置寄存器上,GPIO0 ~ GPIO31 共用一组寄存器,GPIO32 ~ GPIO39 共用一组寄存器,RTC GPIO0 ~ RTC GPIO17 共用另一组寄存器。在同一组内,如果某一管脚被配置为边沿中断,那么其他中断(包括边沿中断和电平中断)将不可用。
电平中断没有此限制,即一组内如果没有沿中断,则可以有多组电平中断。
GPIO 的以下三组 STATUS/W1TS/W1TC 寄存器操作的同时,可能造成同一组内边沿中断无法正常触发。具体为:
以下寄存器的操作可能造成 GPIO_STATUS_REG 的边沿中断无法正常触发:
GPIO_STATUS_W1TS_REG GPIO_STATUS_W1TC_REG GPIO_STATUS_REG
GPIO_STATUS_W1TS_REG
GPIO_STATUS_W1TC_REG
GPIO_STATUS_REG
以下寄存器的操作可能造成 GPIO_STATUS1_REG 的边沿中断无法正常触发:
GPIO_STATUS1_W1TS_REG GPIO_STATUS1_W1TC_REG GPIO_STATUS1_REG
GPIO_STATUS1_W1TS_REG
GPIO_STATUS1_W1TC_REG
GPIO_STATUS1_REG
以下寄存器的操作可能造成 RTCIO_RTC_GPIO_STATUS_REG 的边沿中断无法正常触发:
RTCIO_RTC_GPIO_STATUS_W1TS_REG
RTCIO_RTC_GPIO_STATUS_W1TC_REG
RTCIO_RTC_GPIO_STATUS_REG
使用电平中断模拟边沿中断,具体如下:
要实现 GPIO 的上升沿中断,按照下面的步骤进行配置:
配置 GPIO 的中断类型为高;
CPU 的中断服务响应后,把 GPIO 的中断类型改为低。此时会发生第二次中断,需要 CPU 忽略这次中断服务程序。
要实现 GPIO 的下降沿中断,按照下面的步骤进行配置:
配置 GPIO 的中断类型为低;
CPU 的中断服务响应后,把 GPIO 的中断类型改为高。此时会发生第二次中断,需要 CPU 忽略这次中断服务程序。
打开以下 RTC 外设的电源会发生此问题:
SAR ADC1 传感器
SAR ADC2 传感器
AMP 传感器
当用户决定把用于控制以上传感器的电源域打开时,应当忽略来自 GPIO36 和 GPIO39 的输入。
在配置 LEDC 为递减渐变且 LEDC_DUTY_SCALE_HSCHn 为 1 的情况下,当 duty 值为 2LEDC_HSTIMERx_DUTY_RES 时,下一次 duty 变化应该为 2LEDC_HSTIMERx_DUTY_RES – 1,但是实际上 duty 值等于 2LEDC_HSTIMERx_DUTY_RES+1,即出现 duty 值溢出的错误。(HSCHn 代表高速通道,n 为 0-7;HSTIMERx 代表高速定时器,x 为 0-3。)
对于低速通道,存在同样的问题。
使用 LEDC 的过程中,应避免以下三个条件同时成立:
LEDC 启动递减渐变功能;
LEDC 渐变过程中 scale 寄存器设置为 1;
LEDC 递减渐变开始时刻或者过程中的某一时刻,duty 值为 2LEDC_HSTIMERx_DUTY_RES 或 2LEDC_LSTIMERx_DUTY_RES。
此问题在 ESP-IDF commit ID 为 b2e264e 及以后版本的 LEDC 驱动中已自动绕过,并于 ESP-IDF v3.1 中发布。
CAN2.0B 协议规定帧间间隔期间的第 3 bit 上的显性位应当被当做帧起始 (SOF) 信号。因此,TWAI 节点应在下一个 bit 上接收或发送(即参与竞争仲裁)ID 字段。
当 ESP32 TWAI 控制器失去仲裁并且下一个帧间间隔期间检测到第 3 位为显性时,ESP32 TWAI 控制器不会将其视作 SOF 并且不会参与竞争仲裁(即,不会重传数据)。
无
总线关闭恢复完成后,TWAI 控制器下一次发送的数据可能出错(即不符合 TWAI 数据帧格式)。
一旦通过错误报警限制中断检测到总线关闭恢复完成,TWAI 控制器应先进入复位模式来复位控制器的内部信号,随后退出复位模式。
当 TWAI 控制器发送数据并且 TEC 的值为 120 ~ 127 时,发送错误帧会使 TEC 增加 8 并且 TWAI 控制器会进入被动错误状态(CAN 2.0B 协议规定 TEC >= 128 时,TWAI 节点应进入错误被动状态)。但是,如果错误界定符的第 8 bit 为显性时,TEC 仍会增加 8,而 TWAI 控制器不会进入被动错误状态。再次发送错误帧后 TWAI 控制器才会进入被动错误状态。注意,由于错误界定符的第 8 bit 为显性,TWAI 控制器仍会产生协议规定的过载帧。
当 TWAI 控制器处于总线关闭恢复过程中时,必须等待总线上出现 128 次总线空闲信号(连续 11 个隐性位),才能再次进入主动错误状态。剩余的总线空闲信号由发送错误计数器 (TEC) 指示。由于错误状态位在总线恢复期间未冻结,因此当发送错误计数器低于用户设置的错误报警限制数值(默认值为 96)时,错误状态位将发生变化,从而导致在总线关闭恢复完成之前触发错误报警限制中断。
在总线关闭恢复过程中,错误报警限制中断并不一定指示恢复过程已完成。用户需检查 STATUS_NODE_BUS_OFF 位来验证恢复过程是否完成。
当 TWAI 控制器接收数据帧时,如果在数据段或 CRC 字段中发生位错误或填充错误,则下一次接收到的数据可能发生字节移位或丢失。因此,下一次接收的数据帧(包括由验收滤波器滤出的数据帧)应视为无效。
用户可以通过置位 INTERRUPT_BUS_ERR_INT_ENA 并在接收到总线错误中断时,读取 ERROR_CODE_CAPTURE_REG 来检测错误类型及错误位置。如果符合错误产生条件(在数据段或 CRC 字段发生位错误或填充错误),可以采用以下两种解决方法:
TWAI 控制器可以发送 0 字节的空数据帧来复位 TWAI 控制器的内部信号。建议给空数据帧分配一个不会被任何 TWAI 总线上的节点接收的 ID。
硬件复位 TWAI 控制器(需要保存并恢复当前寄存器的数值)。
当 TWAI 控制器遇到具有负相位误差的隐性至显性沿(即较早采样)时,将按照 CAN2.0B 协议要求利用再同步来校正相位误差。但是,如果 TWAI 控制器作为发送器并且遇到 e < 0 及 |e| > SJW 的负相位误差,则在相位误差之后发送的位信息将左移一位,导致后续发送的帧内容(即,DLC,数据字节,CRC 序列)被破坏。
当 TWAI 控制器处于复位模式(即 RESET_MODE 位置 1 或由于总线关闭)或总线关闭恢复状态时,接收错误计数器 (REC) 的数值仍会变化,这会引发以下问题:
错误状态位可能发生改变,进而触发错误报警限制中断。
REC > 0 可能导致 TWAI 控制器无法从总线关闭状态恢复。
进入复位模式时,应将 LISTEN_ONLY_MODE 置位,此时 REC 数值不会变化。退出复位模式前或总线关闭恢复完成时,再恢复正常的操作模式。
如果 RX FIFO 溢出多个报文,且 RX 报文计数器达到 64,RX FIFO 将不可恢复。从 RX FIFO 读取的任何报文均无效,且无法从 RX FIFO 中释放任何报文。
TWAI 控制器必须通过软件复位才能恢复 RX FIFO。
此问题在 ESP-IDF v4.3 及以后版本中已自动绕过。
CAN2.0B 协议规定作为发送器并处于被动错误态的 TWAI 节点应在随后的帧间间隔内等待挂起时间。但是,作为接收器的被动错误态 TWAI 节点是不需要等待挂起时间的。
当 ESP32 TWAI 控制器处于被动错误态并且失去仲裁(转为接收器)时,它仍将在随后的帧间间隔中等待挂起时间。这导致 TWAI 控制器的重传延后,如果在其等待帧间间隔挂起时间期间,另一个节点发送数据,则 TWAI 控制器不会参与竞争仲裁。
CAN2.0B 协议规定,TWAI 控制器发送数据时如果在仲裁字段中检测到填充错误,应发送错误帧,但是 TEC 不应增加(错误计数规则 3 中的特例 2)。TWAI 控制器能够满足这一规定。
但是,若在随后发生的错误帧或过载帧中遇到以下两种情况时,TEC 数值将不能按照 CAN2.0B 协议要求实现增加:
在主动错误标志或过载标志期间发生位错误(规则 4)。
在主动错误标志、被动错误标志或过载标志之后检测到过多的显性位(规则 6)。
CPU 通过读取 INTERRUPT_REG 寄存器来复位 TWAI 控制器的中断信号。如果在同一个 APB 时钟周期内 TWAI 控制器刚好产生发送中断信号,则发送中断信号丢失。
数据等待发送完成期间(即发送请求已发起),每一次读取 INTERRUPT_REG 后,用户都应检查 STATUS_TRANSMIT_BUFFER 位。如果 STATUS_TRANSMIT_BUFFER 置位而 TWAI_TRANSMIT_INT_ST 没有置位,则说明发送中断信号丢失。
当 TWAI 控制器发送数据帧时,如果在数据段或 CRC 字段发生总线错误,下一次接收到的数据可能发生字节移位。该帧的标识符和数据长度仍可能正确,且控制器不会对该接收帧报告错误。因此,下一次接收的数据帧应视为无效。
控制器在发送和接收时共用一个字节计数器来监测总线活动。发送期间如果在数据段发生总线错误,且该帧在 CRC 字段之前结束(计数器通常在 CRC 字段被清零),计数器会停留在错误状态,从而使下一次接收帧的数据字节发生移位。
置位 INTERRUPT_BUS_ERR_INT_ENA。接收到总线错误中断时,读取 ERROR_CODE_CAPTURE_REG,以检测发送期间数据段或 CRC 字段中的总线错误。如果符合该条件,复位 TWAI 控制器(需要保存并恢复当前寄存器的数值)。
使用 DPORT 读 UART FIFO 时,如果软件的读 FIFO 操作被中断打断,那么 fifo_cnt 会被错误地减 1。
使用 DPORT 读取 FIFO 时,需结合读/写 FIFO 偏移地址计算 FIFO 中有效数据长度。例如:
if (wr_addr > rd_addr) { len = wr_addr - rd_addr; } else if (wr_addr < rd_addr){ len = (wr_addr + 128) - rd_addr; } else { len = fifo_cnt > 0 ? 128 : 0; }
其中 wr_addr 表示写 FIFO 偏移地址,rd_addr 表示读 FIFO 偏移地址,fifo_cnt 表示芯片记录的 FIFO 中有效字节数,len 表示重新计算后正确的有效字节数。
wr_addr
rd_addr
fifo_cnt
len
ULP 协处理器和触摸传感器的主要工作时钟是 FAST_CLK。在 Deep-sleep 模式下,如果 RTC_PERIH 电源域 (RTC Peripherals) 保持供电,则 ULP 协处理器和触摸传感器会比时钟管理模块更早接收到启动信号。这导致它们在工作时钟切换到 FAST_CLK 之前,会先在 SLOW_CLK 时钟下运行一段时间,从而造成工作时钟的不准确。因此,在 Deep-sleep 模式下,如果 RTC_PERIH 保持供电,则 ULP 协处理器和触摸传感器无法使用。
如果用户要使用 ULP 协处理器和触摸传感器功能,那么在 Deep-sleep 模式下,RTC_PERIPH 必须保持掉电。请注意,此时 EXT0 唤醒不可用,因为 EXT0 唤醒功能只能在 RTC_PERIPH 上电的情况下工作。
因此,用户需要在使用 EXT0 唤醒功能和 ULP 协处理器/触摸传感器功能之间取舍:
如果要用 EXT0 唤醒功能,则 RTC_PERIPH 电源域必须保持供电,此时 ULP 协处理器和触摸传感器功能不可用。
如果要用 ULP 协处理器和触摸传感器功能,则 RTC_PERIPH 必须保持掉电,此时 EXT0 唤醒功能不可用。
影响版本: v3.0 v3.1
使用芯片版本 v3.0,当程序同时满足下列条件时,会出现 live lock(活锁)现象,导致 CPU 一直处于访存状态,不能继续执行指令。
双核系统;
四条访问外存的指令/数据总线 (IBUS/DBUS) 中,有 3 条总线同时发起对同一个 cache 组的访问请求,并且三个 cache 请求均缺失。
发生 live lock 时,软件主动或被动识别并解锁 cache line 竞争,之后两个核按队列节拍分时完成各自的 cache 操作,解锁 live lock。详细过程如下:
当两个核执行的指令均不在代码临界区中时出现 live lock,系统各类型中断会主动解除 cache line 竞争,解锁 live lock;
当两个核执行的指令位于代码临界区中时出现 live lock,在临界区中,系统会屏蔽 3 级及以下中断。因此软件预先为两个核各设置一个高优先级(4 级或 5 级)中断,将它们绑定到同一个定时器,并选择合适的定时器超时门限。由于 live lock 产生的定时器超时中断会迫使两个核均进入高优先级中断处理程序,从而释放两个核的 IBUS 以达到解锁 live lock 目的。解锁过程通过 3 个阶段完成:
第 1 阶段两个核均进行等待以清空 CPU write buffer; 第 2 阶段一个核 (Core 0) 等待,另一个核 (Core 1) 执行; 第 3 阶段 Core 1 等待,Core 0 执行。
第 1 阶段两个核均进行等待以清空 CPU write buffer;
第 2 阶段一个核 (Core 0) 等待,另一个核 (Core 1) 执行;
第 3 阶段 Core 1 等待,Core 0 执行。
如果在 Light-sleep 模式下关闭 RTC 外设的电源,从 Light-sleep 模式唤醒后,ESP32 的 CPU 读取 RTC 电源域的寄存器时会有一定概率出错。
建议用户避免在 Light-sleep 模式下关闭 RTC 外设的电源,此时不会影响功耗。