如何计算芯片的ESP mac 地址

文章目录

    • 如何判断芯片是 ESP32 or ESP8266 ?
      • ESP32
      • ESP8266
    • 如何判断芯片是 ESP8285 or ESP8286 ?
    • 如何计算芯片的 mac 地址?
      • ESP32
      • ESP8266
    • write_mem 疑问

如何判断芯片是 ESP32 or ESP8266 ?

ESP32

detect_chip 0x60000078

UART_DATE_REG_ADDR = 0x60000078  # used to differentiate ESP8266 vs ESP32*
UART_DATE_REG2_ADDR = 0x3f400074  # used to differentiate ESP32S2 vs other models

uart_register.h` 中定义如下所示:(这里为何读取0x60000078, REG_UART_BASE( i )的确定在哪里)

#define DR_REG_UART_BASE                        0x3ff40000
#define REG_UART_BASE( i )  (DR_REG_UART_BASE + (i) * 0x10000 + ( (i) > 1 ? 0xe000 : 0 ) )
#define REG_UART_AHB_BASE(i)  (0x60000000 + (i) * 0x10000 + ( (i) > 1 ? 0xe000 : 0 ) )
#define UART_FIFO_AHB_REG(i)  (REG_UART_AHB_BASE(i) + 0x0)
#define UART_FIFO_REG(i)          (REG_UART_BASE(i) + 0x0)

#define UART_DATE_REG(i)          (REG_UART_BASE(i) + 0x78)
/* UART_DATE : R/W ;bitpos:[31:0] ;default: 32'h15122500 ; */

(1) 从esp32 的技术手册未查找到的 0x60000078 的内容

(2) 该寄存器在 esptool.py 的注释

​ “”" Use serial access to detect the chip type.

​ We use the UART’s datecode register for this, it’s mapped at

​ the same address on ESP8266 & ESP32 so we can use one

​ memory read and compare to the datecode register for each chip

​ type.

​ This routine automatically performs ESPLoader.connect() (passing

​ connect_mode parameter) as part of querying the chip.

​ “”"

而在 esp32.peripherals.ld 中,UART 的外设地址如下:

PROVIDE ( UART0 = 0x3ff40000 );
PROVIDE ( UART1 = 0x3ff50000 );
PROVIDE ( UART2 = 0x3ff6E000 );

则,读该寄存器,内容为 0x15122500,那么识别此芯片为 ESP32.

ESP8266

detect_chip 0x60000078

UART_DATE_REG_ADDR = 0x60000078  # used to differentiate ESP8266 vs ESP32*

uart_register.h 中定义如下所示:

#define REG_UART_BASE(i)                (0x60000000 + (i)*0xf00)
//version value:32'h062000
...
#define UART_DATE(i)                    (REG_UART_BASE(i) + 0x78)

esp8266 的技术手册中描述如下:

在这里插入图片描述

则,读该寄存器,内容为 0x60000200,那么识别此芯片为 ESP8266.

如何判断芯片是 ESP8285 or ESP8286 ?

ESP8266 技术手册中只有 GPIO, SPI, UART 寄存器的介绍, 然而并没有将介绍 efuse 寄存器,只能从代码中获取此部分信息。

esp8266/efuse_register.h 的定义如下图所示:

#define DR_REG_EFUSE_BASE   0x3FF00050
#define EFUSE_DATA0_REG     (DR_REG_EFUSE_BASE + 0x000)
#define EFUSE_IS_ESP8285    (1 << 4)

返回的128 bits of ESP8266 efuse

    //esptool.py  code
    ESP_OTP_MAC0    = 0x3ff00050
    ESP_OTP_MAC1    = 0x3ff00054
    ESP_OTP_MAC4    = 0x3ff00058
    ESP_OTP_MAC3    = 0x3ff0005c

则,(efuses & ((1 << 4)) != 0 ,芯片就是ESP8285.

然而 esptool.py 中的判断如下:

is_8285 = (efuses & ((1 << 4) | 1 << 80)) != 0  # One or the other efuse bit is set for ESP8285

难道 第 4 bit 和 第 80 bit 只有 1 bit 是 1, 就可以识别为 8285 了?

如何计算芯片的 mac 地址?

ESP32

MAC 地址的读取也是从 efuse 寄存器读取,如下图,可在技术

esp32/include/soc/efuse_reg.h 的定义如下图所示:

#define DR_REG_EFUSE_BASE                       0x3ff5A000
#define EFUSE_BLK0_RDATA0_REG          (DR_REG_EFUSE_BASE + 0x000)

利用这个信息可在技术手册找到相应内容:

如何计算芯片的ESP mac 地址_第1张图片

如何计算芯片的ESP mac 地址_第2张图片

如何计算芯片的ESP mac 地址_第3张图片

接下来:我们直接将 efuse 区 dump 出来:

$ espefuse.py --port /dev/ttyUSB2 dump
espefuse.py v2.8
Connecting........_
EFUSE block 0:
00000000 c4014d9c 00eb240a 00000000 00000032 00000000 00000004
EFUSE block 1:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
EFUSE block 2:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
EFUSE block 3:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

然后,我们利用 esptool 直接读出 mac 地址:

$ esptool.py read_mac
esptool.py v2.8
...
MAC: 24:0a:c4:01:4d:9c
...
Hard resetting via RTS pin...

可以看出:esp32 的 mac 地址为 EFUSE_BLK0_RDATA2_REG 中 EFUSE_RD_WIFI_MAC_CRC_HIGH 值 与 EFUSE_BLK0_RDATA1_REG 的值拼接之后的后六个字节,其中 EFUSE_RD_WIFI_MAC_CRC_HIGH 值的第一个字节是 mac 地址的校验码

最后进行验证:

$ espefuse.py --port /dev/ttyUSB1 summary
espefuse.py v2.8
Connecting........_
...
Identity fuses:
MAC                    Factory MAC Address                               
  = 24:0a:c4:01:4d:9c (CRC 0xeb OK) R/W 
...

存在的疑问:esptool.py 中 EFUSE_REG_BASE = 0x6001a000 ,而不是 0x3ff5A000

//esptool.py 
EFUSE_REG_BASE = 0x6001a000

ESP8266

针对 esp8266, 貌似不能用 espefuse.py 命令来 dump efuse. 也没有找到公开的文档描述,SDK 中efuse_register.h 的信息也很少。

$ espefuse.py --port /dev/ttyUSB1 dump
espefuse.py v2.8
Connecting....

A fatal error occurred: Timed out waiting for packet header

这里只是从 esptool.py 的源码中来解读 esp8266 的 mac 地址是如何计算出来的。

首先,从如下的 efuse 地址中获取数值,为对应寄存器的值,其中,可以从代码中看出寄存器的位数为32.

ESP_OTP_MAC0    = 0x3ff00050
ESP_OTP_MAC1    = 0x3ff00054
ESP_OTP_MAC3    = 0x3ff0005c

def read_mac(self):
        """ Read MAC from OTP ROM """
        mac0 = self.read_reg(self.ESP_OTP_MAC0)
        mac1 = self.read_reg(self.ESP_OTP_MAC1)
        mac3 = self.read_reg(self.ESP_OTP_MAC3)
        if (mac3 != 0):
            oui = ((mac3 >> 16) & 0xff, (mac3 >> 8) & 0xff, mac3 & 0xff)
        elif ((mac1 >> 16) & 0xff) == 0:
            oui = (0x18, 0xfe, 0x34)
        elif ((mac1 >> 16) & 0xff) == 1:
            oui = (0xac, 0xd0, 0x74)
        else:
            raise FatalError("Unknown OUI")
        return oui + ((mac1 >> 8) & 0xff, mac1 & 0xff, (mac0 >> 24) & 0xff)

这里用表格来表示寄存器:
MAC3

F E D C B A 9 8 7 6 5 4 3 2 1 0H
F E D C B A 9 8 7 6 5 4 3 2 1 0L

MAC1:

F E D C B A 9 8 7 6 5 4 3 2 1 0H
F E D C B A 9 8 7 6 5 4 3 2 1 0L

MAC0:

F E D C B A 9 8 7 6 5 4 3 2 1 0H
F E D C B A 9 8 7 6 5 4 3 2 1 0L

如果 MAC3 的值不为 0 时,芯片 mac 地址的组成为:A:B:C:D:E:F(如下所示)

A: (mac3 >> 16) & 0xff

* * * * * * * * * * * * * * * *H
L

B: (mac3 >> 8) & 0xff

* * * * * * * *H
* * * * * * * * L

C: (mac3 >> 16) & 0xff

H
* * * * * * * * * * * * * * * *L

D: (mac1 >> 8) & 0xff

* * * * * * * *H
* * * * * * * * L

E: mac1 & 0xff

H
* * * * * * * * * * * * * * * *L

F: (mac0 >> 24) & 0xff

* * * * * * * * H
*L

如果 MAC3 的值为 0 时,MAC1 的高 16 位为0, 芯片 mac 地址的组成为:0x18 : 0xfe : 0x34 : D : E : F(DEF 如上所示)

如果 MAC3 的值为 0 时,MAC1 的高 16 位为1, 芯片 mac 地址的组成为:0xac : 0xd0 : 0x74 : D : E : F(DEF 如上所示)

除此以外的情况,芯片 mac 地址都不会识别出来。

关于 芯片mac 地址的一点说明:

esp8266 有 chip_id, esp32 没有 chip_id

其中,chid_ip 长 4 个字节,低三字节为 mac 地址,最高字节为 0.

write_mem 疑问

可能写入又有了别的用途,被覆盖

esp-idf/examples/get-started/hello_world$ esptool.py write_mem 0x3FFAF000 0xAAAAAAAA 0xFFFFFFFF
esptool.py v2.8
Found 2 serial ports
Serial port /dev/ttyUSB1
Connecting....
Detecting chip type... ESP32
Chip is ESP32D0WDQ6 (revision 0)
Features: WiFi, BT, Dual Core, Coding Scheme None
Crystal is 40MHz
MAC: 24:0a:c4:01:4d:9c
Uploading stub...
Running stub...
Stub running...
Wrote aaaaaaaa, mask ffffffff to 3ffaf000
Hard resetting via RTS pin...

esp-idf/examples/get-started/hello_world$ esptool.py read_mem 0x3FFAF000 
esptool.py v2.8
Found 2 serial ports
Serial port /dev/ttyUSB1
Connecting........__
Detecting chip type... ESP32
Chip is ESP32D0WDQ6 (revision 0)
Features: WiFi, BT, Dual Core, Coding Scheme None
Crystal is 40MHz
MAC: 24:0a:c4:01:4d:9c
Uploading stub...
Running stub...
Stub running...
0x3ffaf000 = 0x6129e3c8
Hard resetting via RTS pin...

你可能感兴趣的:(物联网)