Skip to content
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

Fix incorrect QSPI setup #2231

Merged
merged 14 commits into from
Sep 26, 2024
Merged

Fix incorrect QSPI setup #2231

merged 14 commits into from
Sep 26, 2024

Conversation

bugadani
Copy link
Contributor

@bugadani bugadani commented Sep 25, 2024

Thank you for your contribution!

We appreciate the time and effort you've put into this pull request.
To help us review it efficiently, please ensure you've gone through the following checklist:

Submission Checklist 📝

  • I have updated existing examples or added new ones (if applicable).
  • I have used cargo xtask fmt-packages command to ensure that all changed code is formatted correctly.
  • My changes were added to the CHANGELOG.md in the proper section.
  • I have added necessary changes to user code to the Migration Guide.
  • My changes are in accordance to the esp-rs API guidelines

Extra:

Pull Request Details 📖

Description

Two-parter:

This fixes #2229 and adds test code to make sure we don't break QSPI again. This PR also works around an ESP32 limitation.

Testing

Observed behaviour change using a logic analyzer and also the changed test cases fail before the fix.

@bugadani bugadani added the skip-changelog No changelog modification needed label Sep 25, 2024
Copy link
Contributor

@bjoernQ bjoernQ left a comment

Choose a reason for hiding this comment

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

This actually fixes #2229 - weird given the result of the bisect and also manually checking that commit and the one before - Thanks!

@bugadani
Copy link
Contributor Author

Awesome. The problem is, that the RX/TX swap introduced a buffer size issue and maybe your flash chip flashed the last 256 ! characters that it received. So one problem was fixed by restoring the buffer sizes in #2139 but then I managed to break this again, later, which your bisect might have jumped over.

@bugadani
Copy link
Contributor Author

I've been banging my head against ESP32 for a while now, and I think that chip simply can't do a 4-line address phase if it doesn't have data to transmit afterwards. The chip defaults back to 1-line address phase if usr_miso and usr_mosi are clear. I guess we could work around this by sending address as data if there is no data...

@bugadani bugadani removed the skip-changelog No changelog modification needed label Sep 25, 2024
@Dominaezzz
Copy link
Collaborator

Just return an error if it's not supported I think.

@bugadani
Copy link
Contributor Author

Why? It's supported everywhere else, users expect it to work and it's simple to work around.

@Dominaezzz
Copy link
Collaborator

It's not like all the SPI hardware on all chips works the same. Some have more features that others. It just so happens the ESP32 can't support this one case.

If users want it to "just work" everywhere, they should just use the data phase for everything themselves. Doing it secretly is too hacky imo.

@Dominaezzz
Copy link
Collaborator

Also, not all implementations of DmaTxBuffer will support the methods you just added.

@bugadani
Copy link
Contributor Author

It's not like all the SPI hardware on all chips works the same.

One of the jobs of the HAL is to equalize support as much as possible.

Also, not all implementations of DmaTxBuffer will support the methods you just added.

Then they will be free to return an error.

@Dominaezzz
Copy link
Collaborator

Also, not all implementations of DmaTxBuffer will support the methods you just added.

Then they will be free to return an error.

How is that different from just returning an error upfront? User will still end up having to deal with it.

Also users won't be expecting their DmaTxBufs to suddenly contain data they never added. If they put it in a loop, the first iteration would do the right thing, then the second iteration would send the address (in the address phase) + the previous address (in the data phase).

It's not like all the SPI hardware on all chips works the same.

One of the jobs of the HAL is to equalize support as much as possible.

Yeah but there should be a line somewhere I think.

@Dominaezzz
Copy link
Collaborator

There's the option of not using DMA and just using the CPU Buffer for the data phase. (I don't really like this solution either to be honest, but it's better than tampering with the DMA buffer).

@bugadani
Copy link
Contributor Author

Sorry @bjoernQ I managed to completely hijack this PR, do you want me to send in the original fix separately?

@bjoernQ
Copy link
Contributor

bjoernQ commented Sep 26, 2024

Sorry @bjoernQ I managed to completely hijack this PR, do you want me to send in the original fix separately?

No problem - thanks for taking care of this

Copy link
Member

@MabezDev MabezDev 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!

// on a single line, regardless of its data mode.
if bytes_to_write == 0 && address.mode() != SpiDataMode::Single {
let bytes_to_write = address.width().div_ceil(8);
let addr_bytes = address.value().to_le_bytes();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Don't be hasty, I need to verify if I got the endianness right here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

iirc the bit order of the data phase can changed so you'll probably have to read that register bit to decide the endianness here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

SPI_WR_BIT_ORDER affects all (CMD, ADDR and DATA) phases so I think I'm fine here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That being said, I wanted to look at this with a logic analyzer because this workaround exists due to the hardware not doing what it's supposed to.

Copy link
Contributor Author

@bugadani bugadani Sep 26, 2024

Choose a reason for hiding this comment

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

Good thing I checked. The bit works as expected, but the address is encoded as big-endian so that had to be aligned.

Demo that we now generate the same waveform with or without data (data is set to 0 to reduce noise). 2 lines only, because my ESP32 devkit doesn't have enough pins 😅

image

Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice!

I just remembered, will this work as the user expects if they specify a dummy phase?

Copy link
Contributor Author

@bugadani bugadani Sep 26, 2024

Choose a reason for hiding this comment

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

No, the dummy phase gets moved to before the address which is wrong. But that'll need to be addressed later as there are a few different approaches to deal with that (error, ignore, emulate). This current PR is done the way it is.

Opened #2240 so we don't forget about it.

"Places the SPI driver in RAM for better performance",
),
(
"spi-address-workaround",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you reckon libraries may want to set this?

Copy link
Member

Choose a reason for hiding this comment

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

There should be one source of truth for the config, and it should lie in the hands of the user. In this case, we've enabled it by default, which is a sane thing to do, and users can opt-out. One thing libraries can do is detect if the setting is enabled and either warn/panic if it should be - but even this I would discourage unless the library functionality depended on it.

Copy link
Contributor

@JurajSadel JurajSadel left a comment

Choose a reason for hiding this comment

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

Thanks!

@bugadani
Copy link
Contributor Author

Hold on there's still something not quite right here :)

@bugadani bugadani enabled auto-merge September 26, 2024 15:15
@bugadani bugadani added this pull request to the merge queue Sep 26, 2024
Merged via the queue into esp-rs:main with commit c481c49 Sep 26, 2024
28 checks passed
@bugadani bugadani deleted the qspi branch September 26, 2024 15:42
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.

qspi_flash example broken (at least on ESP32-S2 - most probably for all chips) since b5f0246
5 participants