8000 Support peripheral register addresses of ESP32-S2/S3 · pidou46/micropython-esp32-ulp@d2cd792 · GitHub
[go: up one dir, main page]

Skip to content

Commit d2cd792

Browse files
committed
Support peripheral register addresses of ESP32-S2/S3
Peripheral registers of the ESP32-S2 and S3 are at a different location than those of the original ESP32. The location within the address space is mostly the same, however we need to use the correct base address when calculating periph_sel (type of register) used in REG_RD and REG_WR instructions. Note 1: To avoid creating an entirely new CPU (esp32s3) just for handling the different peripheral register addresses of the S3, while their binary format (instruction set) is identical, our esp32s2 CPU support will now accept both ESP32-S2 and ESP32-S3 addresses. This should make a binary for the one seamlessly work on the other (without reassembly), given that the offsets of different peripheral registers between the S2 and S3 are mostly (but not entirely) identical. Note 2: Our esp32s2 cpu support will also accept peripheral register addresses of the original ESP32. This was originally done because Espressif's binutils-gdb/esp32-ulp-as incorrectly validates addresses for the esp32s2 cpu, and to make our compat tests pass, this was needed. However this also has a nice side- effect of allowing some assembly written for the original ESP32 to work unmodified when assembled for an S2/S3, because some of the peripheral registers live at the same offset from the base for all three variants.
1 parent 863af1c commit d2cd792

File tree

4 files changed

+197
-15
lines changed

4 files changed

+197
-15
lines changed

esp32_ulp/opcodes_s2.py

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from ucollections import namedtuple
66
from uctypes import struct, addressof, LITTLE_ENDIAN, UINT32, BFUINT32, BF_POS, BF_LEN
77

8-
from .soc import *
98
from .util import split_tokens, validate_expression
109

1110
# XXX dirty hack: use a global for the symbol table
@@ -374,16 +373,43 @@ def get_cond(arg):
374373

375374

376375
def _soc_reg_to_ulp_periph_sel(reg):
376+
# Accept peripheral register addresses of either the S2 or S3
377+
# Since the address in the reg_rd or reg_wr instruction is an
378+
# offset and not the actual address, and since the range of
379+
# peripheral register addresses is the same for both the S2
380+
# and S3, we will accept addresses in either address range.
381+
# This allows us to avoid intruducing an additional cpu type
382+
# for the S3, which is otherwise identical (binary format) to
383+
# the S2.
384+
if 0x3f408000 <= reg <= 0x3f40afff: # ESP32-S2 address range
385+
socmod = 'soc_s2'
386+
elif 0x60008000 <= reg <= 0x6000afff: # ESP32-S3 address range
387+
socmod = 'soc_s3'
388+
# Accept original ESP32 range too
389+
# because binutils-gdb, when using cpu esp32s2 is broken
390+
# and does not accept the address ranges of the esp32s2.
391+
# As a nice side-effect some assembly written for an ESP32
392+
# would work as-is when re-assembled for an ESP32-S2,
393+
# because many (not all!) peripheral registers live at the
394+
# same offset on all 3 ESP32s.
395+
elif 0x3ff48000 <= reg <= 0x3ff4afff: # original ESP32 address range
396+
socmod = 'soc'
397+
else:
398+
raise ValueError("invalid register base")
399+
400+
relative_import = 1 if '/' in __file__ else 0
401+
soc = __import__(socmod, None, None, [], relative_import)
402+
377403
# Map SoC peripheral register to periph_sel field of RD_REG and WR_REG instructions.
378-
if reg < DR_REG_RTCCNTL_BASE:
404+
if reg < soc.DR_REG_RTCCNTL_BASE:
379405
raise ValueError("invalid register base")
380-
elif reg < DR_REG_RTCIO_BASE:
406+
elif reg < soc.DR_REG_RTCIO_BASE:
381407
ret = RD_REG_PERIPH_RTC_CNTL
382-
elif reg < DR_REG_SENS_BASE:
408+
elif reg < soc.DR_REG_SENS_BASE:
383409
ret = RD_REG_PERIPH_RTC_IO
384-
elif reg < DR_REG_RTC_I2C_BASE:
410+
elif reg < soc.DR_REG_RTC_I2C_BASE:
385411
ret = RD_REG_PERIPH_SENS
386-
elif reg < DR_REG_IO_MUX_BASE:
412+
elif reg < soc.DR_REG_IO_MUX_BASE:
387413
ret = RD_REG_PERIPH_RTC_I2C
388414
else:
389415
raise ValueError("invalid register base")

esp32_ulp/soc_s2.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""
2+
Address / Register definitions for the ESP32-S2 SoC
3+
"""
4+
5+
# Reference:
6+
# https://github.com/espressif/esp-idf/blob/v5.0.2/components/soc/esp32s2/include/soc/reg_base.h
7+
8+
DR_REG_SYSTEM_BASE = 0x3f4c0000
9+
DR_REG_SENSITIVE_BASE = 0x3f4c1000
10+
DR_REG_INTERRUPT_BASE = 0x3f4c2000
11+
DR_REG_DMA_COPY_BASE = 0x3f4c3000
12+
DR_REG_EXTMEM_BASE = 0x61800000
13+
DR_REG_MMU_TABLE = 0x61801000
14+
DR_REG_ITAG_TABLE = 0x61802000
15+
DR_REG_DTAG_TABLE = 0x61803000
16+
DR_REG_AES_BASE = 0x6003a000
17+
DR_REG_SHA_BASE = 0x6003b000
18+
DR_REG_RSA_BASE = 0x6003c000
19+
DR_REG_HMAC_BASE = 0x6003e000
20+
DR_REG_DIGITAL_SIGNATURE_BASE = 0x6003d000
21+
DR_REG_CRYPTO_DMA_BASE = 0x6003f000
22+
DR_REG_ASSIST_DEBUG_BASE = 0x3f4ce000
23+
DR_REG_DEDICATED_GPIO_BASE = 0x3f4cf000
24+
DR_REG_INTRUSION_BASE = 0x3f4d0000
25+
DR_REG_UART_BASE = 0x3f400000
26+
DR_REG_SPI1_BASE = 0x3f402000
27+
DR_REG_SPI0_BASE = 0x3f403000
28+
DR_REG_GPIO_BASE = 0x3f404000
29+
DR_REG_GPIO_SD_BASE = 0x3f404f00
30+
DR_REG_FE2_BASE = 0x3f405000
31+
DR_REG_FE_BASE = 0x3f406000
32+
DR_REG_FRC_TIMER_BASE = 0x3f407000
33+
DR_REG_RTCCNTL_BASE = 0x3f408000
34+
DR_REG_RTCIO_BASE = 0x3f408400
35+
DR_REG_SENS_BASE = 0x3f408800
36+
DR_REG_RTC_I2C_BASE = 0x3f408C00
37+
DR_REG_IO_MUX_BASE = 0x3f409000
38+
DR_REG_HINF_BASE = 0x3f40B000
39+
DR_REG_I2S_BASE = 0x3f40F000
40+
DR_REG_UART1_BASE = 0x3f410000
41+
DR_REG_I2C_EXT_BASE = 0x3f413000
42+
DR_REG_UHCI0_BASE = 0x3f414000
43+
DR_REG_SLCHOST_BASE = 0x3f415000
44+
DR_REG_RMT_BASE = 0x3f416000
45+
DR_REG_PCNT_BASE = 0x3f417000
46+
DR_REG_SLC_BASE = 0x3f418000
47+
DR_REG_LEDC_BASE = 0x3f419000
48+
DR_REG_CP_BASE = 0x3f4c3000
49+
DR_REG_EFUSE_BASE = 0x3f41A000
50+
DR_REG_NRX_BASE = 0x3f41CC00
51+
DR_REG_BB_BASE = 0x3f41D000
52+
DR_REG_TIMERGROUP0_BASE = 0x3f41F000
53+
DR_REG_TIMERGROUP1_BASE = 0x3f420000
54+
DR_REG_RTC_SLOWMEM_BASE = 0x3f421000
55+
DR_REG_SYSTIMER_BASE = 0x3f423000
56+
DR_REG_SPI2_BASE = 0x3f424000
57+
DR_REG_SPI3_BASE = 0x3f425000
58+
DR_REG_SYSCON_BASE = 0x3f426000
59+
DR_REG_APB_CTRL_BASE = 0x3f426000 # Old name for SYSCON, to be removed
60+
DR_REG_I2C1_EXT_BASE = 0x3f427000
61+
DR_REG_SPI4_BASE = 0x3f437000
62+
DR_REG_USB_WRAP_BASE = 0x3f439000
63+
DR_REG_APB_SARADC_BASE = 0x3f440000
64+
DR_REG_USB_BASE = 0x60080000

esp32_ulp/soc_s3.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
Address / Register definitions for the ESP32-S3 SoC
3+
"""
4+
5+
# Reference:
6+
# https://github.com/espressif/esp-idf/blob/v5.0.2/components/soc/esp32s3/include/soc/reg_base.h
7+
8+
DR_REG_UART_BASE = 0x60000000
9+
DR_REG_SPI1_BASE = 0x60002000
10+
DR_REG_SPI0_BASE = 0x60003000
11+
DR_REG_GPIO_BASE = 0x60004000
12+
DR_REG_GPIO_SD_BASE = 0x60004f00
13+
DR_REG_FE2_BASE = 0x60005000
14+
DR_REG_FE_BASE = 0x60006000
15+
DR_REG_EFUSE_BASE = 0x60007000
16+
DR_REG_RTCCNTL_BASE = 0x60008000
17+
DR_REG_RTCIO_BASE = 0x60008400
18+
DR_REG_SENS_BASE = 0x60008800
19+
DR_REG_RTC_I2C_BASE = 0x60008C00
20+
DR_REG_IO_MUX_BASE = 0x60009000
21+
DR_REG_HINF_BASE = 0x6000B000
22+
DR_REG_UHCI1_BASE = 0x6000C000
23+
DR_REG_I2S_BASE = 0x6000F000
24+
DR_REG_UART1_BASE = 0x60010000
25+
DR_REG_BT_BASE = 0x60011000
26+
DR_REG_I2C_EXT_BASE = 0x60013000
27+
DR_REG_UHCI0_BASE = 0x60014000
28+
DR_REG_SLCHOST_BASE = 0x60015000
29+
DR_REG_RMT_BASE = 0x60016000
30+
DR_REG_PCNT_BASE = 0x60017000
31+
DR_REG_SLC_BASE = 0x60018000
32+
DR_REG_LEDC_BASE = 0x60019000
33+
DR_REG_NRX_BASE = 0x6001CC00
34+
DR_REG_BB_BASE = 0x6001D000
35+
DR_REG_PWM0_BASE = 0x6001E000
36+
DR_REG_TIMERGROUP0_BASE = 0x6001F000
37+
DR_REG_TIMERGROUP1_BASE = 0x60020000
38+
DR_REG_RTC_SLOWMEM_BASE = 0x60021000
39+
DR_REG_SYSTIMER_BASE = 0x60023000
40+
DR_REG_SPI2_BASE = 0x60024000
41+
DR_REG_SPI3_BASE = 0x60025000
42+
DR_REG_SYSCON_BASE = 0x60026000
43+
DR_REG_APB_CTRL_BASE = 0x60026000 # Old name for SYSCON, to be removed
44+
DR_REG_I2C1_EXT_BASE = 0x60027000
45+
DR_REG_SDMMC_BASE = 0x60028000
46+
DR_REG_PERI_BACKUP_BASE = 0x6002A000
47+
DR_REG_TWAI_BASE = 0x6002B000
48+
DR_REG_PWM1_BASE = 0x6002C000
49+
DR_REG_I2S1_BASE = 0x6002D000
50+
DR_REG_UART2_BASE = 0x6002E000
51+
DR_REG_USB_SERIAL_JTAG_BASE = 0x60038000
52+
DR_REG_USB_WRAP_BASE = 0x60039000
53+
DR_REG_AES_BASE = 0x6003A000
54+
DR_REG_SHA_BASE = 0x6003B000
55+
DR_REG_RSA_BASE = 0x6003C000
56+
DR_REG_HMAC_BASE = 0x6003E000
57+
DR_REG_DIGITAL_SIGNATURE_BASE = 0x6003D000
58+
DR_REG_GDMA_BASE = 0x6003F000
59+
DR_REG_APB_SARADC_BASE = 0x60040000
60+
DR_REG_LCD_CAM_BASE = 0x60041000
61+
DR_REG_SYSTEM_BASE = 0x600C0000
62+
DR_REG_SENSITIVE_BASE = 0x600C1000
63+
DR_REG_INTERRUPT_BASE = 0x600C2000
64+
DR_REG_EXTMEM_BASE = 0x600C4000
65+
DR_REG_ASSIST_DEBUG_BASE = 0x600CE000
66+
DR_REG_WCL_BASE = 0x600D0000

tests/opcodes_s2.py

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,9 @@ def test_reg_direct_ulp_addressing():
149149
assert_raises(ValueError, opcodes.i_reg_rd, "0x400", "0", "0")
150150

151151

152-
def test_reg_address_translations():
152+
def test_reg_address_translations_s2():
153153
"""
154-
Test addressing of peripheral registers using full DPORT bus addresses
154+
Test addressing of ESP32-S2 peripheral registers using full DPORT bus addresses
155155
"""
156156

157157
ins = make_ins("""
@@ -164,12 +164,37 @@ def test_reg_address_translations():
164164
""")
165165

166166
# direct ULP address is derived from full address as follows:
167-
# full:0x3ff484a8 == ulp:(0x3ff484a8-DR_REG_RTCCNTL_BASE) / 4
168-
# full:0x3ff484a8 == ulp:(0x3ff484a8-0x3ff48000) / 4
169-
# full:0x3ff484a8 == ulp:0x4a8 / 4
170-
# full:0x3ff484a8 == ulp:0x12a
171-
# see: https://github.com/espressif/binutils-esp32ulp/blob/249ec34/gas/config/tc-esp32ulp_esp32.c#L149
172-
ins.all = opcodes.i_reg_rd("0x3ff484a8", "0", "0")
167+
# full:0x3f4084a8 == ulp:(0x3f4084a8-DR_REG_RTCCNTL_BASE) / 4
168+
# full:0x3f4084a8 == ulp:(0x3f4084a8-0x3f408000) / 4
169+
# full:0x3f4084a8 == ulp:0x4a8 / 4
170+
# full:0x3f4084a8 == ulp:0x12a
171+
# see: https://github.com/espressif/binutils-esp32ulp/blob/249ec34/gas/config/tc-esp32ulp_esp32s2.c#L78
172+
ins.all = opcodes.i_reg_rd("0x3f4084a8", "0", "0")
173+
assert ins.periph_sel == 1 # high 2 bits of 0x12a
174+
assert ins.addr == 0x2a # low 8 bits of 0x12a
175+
176+
177+
def test_reg_address_translations_s3():
178+
"""
179+
Test addressing of ESP32-S3 peripheral registers using full DPORT bus addresses
180+
"""
181+
182+
ins = make_ins("""
183+
addr : 8 # Address within either RTC_CNTL, RTC_IO, or SARADC
184+
periph_sel : 2 # Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2)
185+
unused : 8 # Unused
186+
low : 5 # Low bit
187+
high : 5 # High bit
188+
opcode : 4 # Opcode (OPCODE_RD_REG)
189+
""")
190+
191+
# direct ULP address is derived from full address as follows:
192+
# full:0x600084a8 == ulp:(0x600084a8-DR_REG_RTCCNTL_BASE) / 4
193+
# full:0x600084a8 == ulp:(0x600084a8-0x60008000) / 4
194+
# full:0x600084a8 == ulp:0x4a8 / 4
195+
# full:0x600084a8 == ulp:0x12a
196+
# see: https://github.com/espressif/binutils-esp32ulp/blob/249ec34/gas/config/tc-esp32ulp_esp32s2.c#L78
197+
ins.all = opcodes.i_reg_rd("0x600084a8", "0", "0")
173198
assert ins.periph_sel == 1 # high 2 bits of 0x12a
174199
assert ins.addr == 0x2a # low 8 bits of 0x12a
175200

@@ -182,4 +207,5 @@ def test_reg_address_translations():
182207
test_get_cond()
183208
test_eval_arg()
184209
test_reg_direct_ulp_addressing()
185-
test_reg_address_translations()
210+
test_reg_address_translations_s2()
211+
test_reg_address_translations_s3()

0 commit comments

Comments
 (0)
0