Skip to content

Last fixes for v1 #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 9, 2021
Merged

Conversation

wnienhaus
Copy link
Collaborator

@wnienhaus wnienhaus commented Oct 7, 2021

I have now fixed the last issues for passing binutils-esp32ulp tests.

Those fixes relate to handling peripheral register addresses correctly with the reg_rd and reg_wr opcodes. While the machine instruction needs the "direct ULP address", the assembly opcode can take either direct ULP addresses or full DPORT bus addresses. binutils-esp32ulp internally converts full addresses to direct addresses and thus supports both. We attempted to support both, but had a few bugs related direct ULP addresses. These are now fixed. (More details in the commits)

You will notice I added a crude "patching mechanism" in the 02_compat_rtc_tests.sh because I needed to work around the bug related to global/not-global absolute symbols (as discussed in PR #52). The workaround was to make all symbols used in problem cases global, because that case binutils-esp32ulp handles correctly.

When this is merged, I guess we can consider the v1 milestone (#49) reached.

binutils-esp32ulp allows peripheral registers to be specified
either as a full address (e.g. 0x3ff48000) or as a direct ULP
address (e.g. 0x120), i.e. the address as seen from the ULP.
"direct" addresses are anything from 0x0 to 0x3ff (inclusive).
This change ensures that 0x3ff is included in what is treated
as a direct ULP address.

(See https://github.com/espressif/binutils-esp32ulp/blob/249ec34/gas/config/tc-esp32ulp_esp32.c#L145
for reference to how binutils treats anything larger than
DR_REG_MAX_DIRECT (0x3ff) as a full address, so everything
less *AND* equal to DR_REG_MAX_DIRECT is therefore a direct
ULP address.)

This commit contributes to being able to eventually assemble the
esp32ulp_ranges.s test from binutils-esp32ulp. It addresses this line:
https://github.com/espressif/binutils-esp32ulp/blob/249ec34/gas/testsuite/gas/esp32ulp/esp32/esp32ulp_ranges.s#L136
When register addresses less than or equal to 0x3ff are given to the
reg_rd and reg_wr opcodes, these addresses should be used unmodified
as the address in the machine instruction.

In our implementation we split the 10 bit address field of the machine
instruction into two fields, namely "addr" for the lower 8 bits and
"periph_sel" for the upper 2 bits.

We already had a mechanism for determining the periph_sel part for
"full" addresses (e.g. 0x3ff48000), but for direct (ULP) addresses, we
always set periph_sel to 0 instead of using the upper 2 bits from the
given address. This commit fixes that.

Note 1: In binutils-esp32ulp, they don't split the address into these 2
fields but simply put the direct ULP address into a single combined
field of 10 bits, which has the same effect. See: https://github.com/espressif/binutils-esp32ulp/blob/249ec34/gas/config/tc-esp32ulp_esp32.c#L145

Note 2: In the "macro approach" in esp-idf for creating ULP code, they
also use the split field approach (I assume our implementation is
modelled after that) and they also don't handle direct (ULP) addresses
correctly (or seemingly at all). See: https://github.com/espressif/esp-idf/blob/9d34a1c/components/ulp/include/esp32/ulp.h#L349

This commit contributes to being able to eventually assemble the
esp32ulp_ranges.s test from binutils-esp32ulp. It addresses this line:
https://github.com/espressif/binutils-esp32ulp/blob/249ec34/gas/testsuite/gas/esp32ulp/esp32/esp32ulp_ranges.s#L136
There is no need to duplicate the "<= DR_REG_MAG_DIRECT" check
in two functions. Now the _soc_reg_to_ulp_periph_sel() function
is used only for "full addresses" (as it was some commits ago)
and will return a ValueError if used with direct ULP addresses.

This commit also masks values correctly when setting the addr
and periph_sel fields for "direct ULP addresses", so only the
bits we're interested in actually get used (rather than being
implicitly trimmed because there aren't more bits available in
a field).
Everything necessary to pass previously skipped binutils-esp32ulp tests is
now fixed. So we no longer need to skip them. (Tests using unsupported
features, such as assembler macros, are still skipped.)

Note 1: There is one test, esp32ulp_ranges.s, which requires symbols defined
in esp32ulp_globals.s. binutils-esp32ulp joins these during the linking stage
in its test scripts. Since we don't separate stages, we simply concatenate the
two files before assembly.

Note 2: binutils-esp32ulp has a bug related to how absolute symbols defined
with .set are interpreted by the JUMP instruction. If a symbol is marked
global, the value is taken as-is, but if a symbol is not global, it's value
is divided by 4. Since py-esp32-ulp treats the symbol value the same, whether
global or not (the believed correct behaviour), we work around the bug in our
test script and patch the input files to make the relevant symbols global.
Copy link
Collaborator

@ThomasWaldmann ThomasWaldmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for fixing!

@wnienhaus wnienhaus mentioned this pull request Oct 9, 2021
@ThomasWaldmann ThomasWaldmann merged commit 037bc58 into micropython:master Oct 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants