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

Half duplex SPI #75

Open
dzarda opened this issue Jan 30, 2020 · 3 comments
Open

Half duplex SPI #75

dzarda opened this issue Jan 30, 2020 · 3 comments

Comments

@dzarda
Copy link

dzarda commented Jan 30, 2020

SPI would benefit from half-duplex comms (SPI control register 1: BIDIMODE).

I realize this trait is missing in embedded-hal. I could potentially try to figure this out and bodge a prototype. But that ain't gonna be easy since I'm rather new to Rust.

Any pointers appreciated.

@dzarda
Copy link
Author

dzarda commented Feb 3, 2020

I'm trying to enable SPI1 in RCC.APB2ENR from the consuming crate. I'm unable to do that since the RCC rb has been moved in freeze() and is hiding in hal::Rcc under pub(crate). Is implementing peripheral drivers outside of -hal packages frowned upon?

@hannobraun
Copy link
Contributor

In general, HALs attempt to provide an API that protects the user from making mistakes (although in practice, all that I know fall short in various ways). One such mistake would be to, for example, to initialize a UART at 115200 baud, then invalidating that configuration by changing the clocks in RCC, which this HAL prevents by freezing the clock configuration.

Is implementing peripheral drivers outside of -hal packages frowned upon?

I don't know if it's frowned upon, but I think HALs generally assume that they are in control. You are free to work around that by accessing the PAC API directly (see RCC::ptr). This requires unsafe, and you'd have to take care not to get in the way of anything the HAL is doing, if you're using both APIs in parallel.

@dzarda
Copy link
Author

dzarda commented Feb 10, 2020

Thanks. I then got stuck on figuring out the receiving part. Let's say we'd have some blocking:: API with roughly:

fn read(&mut self, words: &mut [u8]) -> Result<(), Error>;
fn write(&mut self, words: &[u8]) -> Result<(), Error>;

The write impl is pretty straightforward, but with read one has to actively manage the half duplex: BIDIMODE=1 & BIDIOE=0 causes infinite SCK train to be produced. We don't want that, SCK should be disabled after receiving N words.

  1. First solution would be busy polling and setting the control bits afterwards. This is fine as we're talking blocking API anyway. Unusable otherwise.
  2. Use the interrupt to shut down the SCK train afterwards. Requires dependency on enabled interrupts - probably bad?

Ref rust-embedded/embedded-hal#144

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

2 participants