8000 Fix translation of peripheral register addresses · pidou46/micropython-esp32-ulp@ed28d27 · GitHub
[go: up one dir, main page]

Skip to content

Commit ed28d27

Browse files
committed
Fix translation of peripheral register addresses
This was already incorrect in the original ESP32 implementation but was discovered while testing the new S2/S3 implementation. This was also wrong within the ESP-IDF, that we based the translation logic on. Espressif fixed the issue in this pull request: espressif/esp-idf#11652 We now also have unit tests and compat (integration) tests, that compare our binary output against that of binutils-gdb/esp32-ulp-as, which already did this translation correctly, but we didnt have a test for the specific cases we handled incorrectly, so we didn't notice this bug. This fix has also been tested on a real device, because S2/S3 devices need the IOMUX clock enabled in order to be able to read GPIO input from the ULP, and enabling that clock required writing to a register in the SENS address range, which didnt work correctly before this fix.
1 parent a157ebe commit ed28d27

File tree

7 files changed

+130
-5
lines changed

7 files changed

+130
-5
lines changed

esp32_ulp/opcodes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ def i_reg_wr(reg, high_bit, low_bit, val):
379379
_wr_reg.addr = reg & 0xff
380380
_wr_reg.periph_sel = (reg & 0x300) >> 8
381381
else:
382-
_wr_reg.addr = (reg & 0xff) >> 2
382+
_wr_reg.addr = (reg >> 2) & 0xff
383383
_wr_reg.periph_sel = _soc_reg_to_ulp_periph_sel(reg)
384384
_wr_reg.data = get_imm(val)
385385
_wr_reg.low = get_imm(low_bit)
@@ -394,7 +394,7 @@ def i_reg_rd(reg, high_bit, low_bit):
394394
_rd_reg.addr = reg & 0xff
395395
_rd_reg.periph_sel = (reg & 0x300) >> 8
396396
else:
397-
_rd_reg.addr = (reg & 0xff) >> 2
397+
_rd_reg.addr = (reg >> 2) & 0xff
398398
_rd_reg.periph_sel = _soc_reg_to_ulp_periph_sel(reg)
399399
_rd_reg.unused = 0
400400
_rd_reg.low = get_imm(low_bit)

esp32_ulp/opcodes_s2.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ def i_reg_wr(reg, high_bit, low_bit, val):
422422
_wr_reg.addr = reg & 0xff
423423
_wr_reg.periph_sel = (reg & 0x300) >> 8
424424
else:
425-
_wr_reg.addr = (reg & 0xff) >> 2
425+
_wr_reg.addr = (reg >> 2) & 0xff
426426
_wr_reg.periph_sel = _soc_reg_to_ulp_periph_sel(reg)
427427
_wr_reg.data = get_imm(val)
428428
_wr_reg.low = get_imm(low_bit)
@@ -437,7 +437,7 @@ def i_reg_rd(reg, high_bit, low_bit):
437437
_rd_reg.addr = reg & 0xff
438438
_rd_reg.periph_sel = (reg & 0x300) >> 8
439439
else:
440-
_rd_reg.addr = (reg & 0xff) >> 2
440+
_rd_reg.addr = (reg >> 2) & 0xff
441441
_rd_reg.periph_sel = _soc_reg_to_ulp_periph_sel(reg)
442442
_rd_reg.unused = 0
443443
_rd_reg.low = get_imm(low_bit)

tests/01_compat_tests.sh

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,19 @@ calc_file_hash() {
1010
shasum < $1 | cut -d' ' -f1
1111
}
1212

13+
make_log_dir() {
14+
mkdir -p log
15+
}
16+
17+
fetch_esp_idf() {
18+
[ -d esp-idf ] && return
19+
20+
echo "Fetching esp-idf"
21+
log_file=log/fetch-esp-idf.log
22+
git clone --depth 1 \
23+
https://github.com/espressif/esp-idf.git 1>$log_file 2>&1
24+
}
25+
1326
run_tests_for_cpu() {
1427
local cpu=$1
1528
echo "Testing for CPU: $cpu"
@@ -33,7 +46,9 @@ run_tests_for_cpu() {
3346
bin_file="${src_name}.bin"
3447

3548
echo -e "\tBuilding using binutils ($cpu)"
36-
gcc -E -o ${pre_file} $src_file
49+
gcc -I esp-idf/components/soc/$cpu/include -I esp-idf/components/esp_common/include \
50+
-x assembler-with-cpp \
51+
-E -o ${pre_file} $src_file
3752
esp32ulp-elf-as --mcpu=$cpu -o $obj_file ${pre_file}
3853
esp32ulp-elf-ld -T esp32.ulp.ld -o $elf_file $obj_file
3954
esp32ulp-elf-objcopy -O binary $elf_file $bin_file
@@ -56,5 +71,7 @@ run_tests_for_cpu() {
5671
echo ""
5772
}
5873

74+
make_log_dir
75+
fetch_esp_idf
5976
run_tests_for_cpu esp32
6077
run_tests_for_cpu esp32s2

tests/compat/reg.esp32.S

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include "soc/rtc_cntl_reg.h"
2+
#include "soc/soc_ulp.h"
3+
4+
reg_rd 0x012, 1, 2
5+
reg_rd 0x234, 3, 4
6+
reg_rd 0x345, 5, 6
7+
8+
reg_wr 0x012, 1, 2, 1
9+
reg_wr 0x234, 3, 4, 1
10+
reg_wr 0x345, 5, 6, 1
11+
12+
WRITE_RTC_REG(0x3ff484a8, 1, 2, 3)
13+
READ_RTC_REG(0x3ff484a8, 1, 2)
14+
WRITE_RTC_REG(0x3ff48904, 1, 2, 3)
15+
READ_RTC_REG(0x3ff48904, 1, 2)

tests/compat/reg.esp32s2.S

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include "soc/rtc_cntl_reg.h"
2+
#include "soc/soc_ulp.h"
3+
4+
reg_rd 0x012, 1, 2
5+
reg_rd 0x234, 3, 4
6+
reg_rd 0x345, 5, 6
7+
8+
reg_wr 0x012, 1, 2, 1
9+
reg_wr 0x234, 3, 4, 1
10+
reg_wr 0x345, 5, 6, 1
11+
12+
WRITE_RTC_REG(0x3f4084a8, 1, 2, 3)
13+
READ_RTC_REG(0x3f4084a8, 1, 2)
14+
WRITE_RTC_REG(0x3f408904, 1, 2, 3)
15+
READ_RTC_REG(0x3f408904, 1, 2)

tests/opcodes.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,31 @@ def test_reg_address_translations():
174174
assert ins.addr == 0x2a # low 8 bits of 0x12a
175175

176176

177+
def test_reg_address_translations_sens():
178+
"""
179+
Test addressing of 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:0x3ff48904 == ulp:(0x3ff48904-DR_REG_RTCCNTL_BASE) / 4
193+
# full:0x3ff48904 == ulp:(0x3ff48904-0x3f408000) / 4
194+
# full:0x3ff48904 == ulp:0x904 / 4
195+
# full:0x3ff48904 == ulp:0x241
196+
# see: https://github.com/espressif/binutils-esp32ulp/blob/249ec34/gas/config/tc-esp32ulp_esp32s2.c#L78
197+
ins.all = opcodes.i_reg_rd("0x3ff48904", "0", "0")
198+
assert ins.periph_sel == 2 # high 2 bits of 0x241
199+
assert ins.addr == 0x41 # low 8 bits of 0x241
200+
201+
177202
test_make_ins_struct_def()
178203
test_make_ins()
179204
test_arg_qualify()
@@ -183,3 +208,4 @@ def test_reg_address_translations():
183208
test_eval_arg()
184209
test_reg_direct_ulp_addressing()
185210
test_reg_address_translations()
211+
test_reg_address_translations_sens()

tests/opcodes_s2.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,31 @@ def test_reg_address_translations_s2():
174174
assert ins.addr == 0x2a # low 8 bits of 0x12a
175175

176176

177+
def test_reg_address_translations_s2_sens():
178+
"""
179+
Test addressing of ESP32-S2 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:0x3f408904 == ulp:(0x3f408904-DR_REG_RTCCNTL_BASE) / 4
193+
# full:0x3f408904 == ulp:(0x3f408904-0x3f408000) / 4
194+
# full:0x3f408904 == ulp:0x904 / 4
195+
# full:0x3f408904 == ulp:0x241
196+
# see: https://github.com/espressif/binutils-esp32ulp/blob/249ec34/gas/config/tc-esp32ulp_esp32s2.c#L78
197+
ins.all = opcodes.i_reg_rd("0x3f408904", "0", "0")
198+
assert ins.periph_sel == 2 # high 2 bits of 0x241
199+
assert ins.addr == 0x41 # low 8 bits of 0x241
200+
201+
177202
def test_reg_address_translations_s3():
178203
"""
179204
Test addressing of ESP32-S3 peripheral registers using full DPORT bus addresses
@@ -199,6 +224,31 @@ def test_reg_address_translations_s3():
199224
assert ins.addr == 0x2a # low 8 bits of 0x12a
200225

201226

227+
def test_reg_address_translations_s3_sens():
228+
"""
229+
Test addressing of ESP32-S3 peripheral registers using full DPORT bus addresses
230+
"""
231+
232+
ins = make_ins("""
233+
addr : 8 # Address within either RTC_CNTL, RTC_IO, or SARADC
234+
periph_sel : 2 # Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2)
235+
unused : 8 # Unused
236+
low : 5 # Low bit
237+
high : 5 # High bit
238+
opcode : 4 # Opcode (OPCODE_RD_REG)
239+
""")
240+
241+
# direct ULP address is derived from full address as follows:
242+
# full:0x60008904 == ulp:(0x60008904-DR_REG_RTCCNTL_BASE) / 4
243+
# full:0x60008904 == ulp:(0x60008904-0x60008000) / 4
244+
# full:0x60008904 == ulp:0x904 / 4
245+
# full:0x60008904 == ulp:0x241
246+
# see: https://github.com/espressif/binutils-esp32ulp/blob/249ec34/gas/config/tc-esp32ulp_esp32s2.c#L78
247+
ins.all = opcodes.i_reg_rd("0x60008904", "0", "0")
248+
assert ins.periph_sel == 2 # high 2 bits of 0x241
249+
assert ins.addr == 0x41 # low 8 bits of 0x241
250+
251+
202252
test_make_ins_struct_def()
203253
test_make_ins()
204254
test_arg_qualify()
@@ -209,3 +259,5 @@ def test_reg_address_translations_s3():
209259
test_reg_direct_ulp_addressing()
210260
test_reg_address_translations_s2()
211261
test_reg_address_translations_s3()
262+
test_reg_address_translations_s2_sens()
263+
test_reg_address_translations_s3_sens()

0 commit comments

Comments
 (0)
0