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

Timing issue in configuration. #9

Open
nraynaud opened this issue Mar 3, 2019 · 10 comments
Open

Timing issue in configuration. #9

nraynaud opened this issue Mar 3, 2019 · 10 comments

Comments

@nraynaud
Copy link

nraynaud commented Mar 3, 2019

When using a DMA SPI peripheral, there is no delay between the write and the reads, this leads to some configuration error. The MPU basically never goes into running mode and never sends the interrupt.

I could not pinpoint the exact problem, so I resorted to adding a delay before every write:

    fn write(&mut self, reg: Register, val: u8, spi: &mut SPI) -> Result<(), E> {
        self.ncs.set_low();
        asm::delay(72_000_000 / 100 * 1);
        spi.write(&[reg.write_address(), val])?;
        self.ncs.set_high();
        Ok(())
    }

This happens wether the SPI clock is a 200kHz or at 500kHz.

I am struggling to find which exact timing condition is violated in the datasheet.

@little-arhat
Copy link
Member

We've noticed similar issue as well, but only when compiling with opt-level=3. All other options worked fine for us. We've "solved" that by using "z" level and by adding #[inline(never)] (3c26f9b). Adding memory barrier after transfer also worked, but I'm not sure whether it's reordering or timing issue.

Does compiling with "z" or 2 work for you, btw?

@nraynaud
Copy link
Author

nraynaud commented Mar 3, 2019

I just checked, it happens to me with this:

[profile.release]
opt-level = 2
codegen-units = 1 # better optimizations
debug = true # symbols are nice and they don't increase the size on Flash
lto = true # better optimizations

I will test the Z and 3.

I will check the linked bug, it might see something interesting with the logic analyser.

@nraynaud
Copy link
Author

https://github.com/nraynaud/pill-rust-test/blob/master/src/main.rs#L322
I had to resort to that to get the last version of the plugin working on my MCU.

@little-arhat
Copy link
Member

@nraynaud Yep, I tried something along these lines as well (but only for opt-level3, as I haven't seen any issues with lower levels). I'm still not sure whether it's an issue with non volatile write somewhere, that gets reordered or timing issue (i.e. NSS pin changes state while data transfer in progress).

Perhaps in mpu driver we should poll for transfer status and only toggle NSS pin when it's done, but that seems sub-optimal. I also think that this low level details should be handled by HAL implementation crate, as on some boards you can delegate nss control to hardware, afaik.

@nraynaud
Copy link
Author

for me it's also a problem with O2, and I need optimization because I really don't have a lot of slack in the timing.

I don't have an oscilloscope to check the SPI protocol against a reference.

@jamwaffles
Copy link

I've been having a similar problem in --release mode. I was getting panicked at 'Failed to init MPU: InvalidDevice(0)' in the debug console which seems like a symptom of the same problem.

Adding the following to my Cargo.toml got the device working again:

[profile.release]
opt-level = 'z'

@romixlab
Copy link

Seems like there is similar issue in _calibrate_at_rest function, see the picture.
Screen Shot 2019-04-30 at 09 48 58

Maybe PLL could lock that fast, or some other process inside mpu rejects transaction. With 1ms delay everything works just fine.

@little-arhat
Copy link
Member

little-arhat commented Apr 30, 2019

@romixlab what version do you use? I've added noinline attribute to write, but it seems we should just use compiler or memory barrier around ncs manipulations :-(

Btw, I think calibrate_at_rest should be deprecated, or reimplemented, as it re-initializes device and changes setting. I think we can do it better %)

@romixlab
Copy link

romixlab commented May 1, 2019

I'm using 0.11.0

@justacec
Copy link

I ran into this issue recently when trying to use SPI with an RPi Pico W board. I was running into the issue when trying to use the calibrate_at_rest method. I fixed it by inserting a noop loop right after the SPI CS de-assertions.

As an aside, I do not see anything wrong with the current calibrate_at_rest method. Yes, it does change a bunch of settings, but it does try to bring them back to previous settings at the end.

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

No branches or pull requests

5 participants