-
Notifications
You must be signed in to change notification settings - Fork 182
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
Support for different SPI configurations #118
Comments
Hey @katyo, thanks for this great suggestion. Indeed the implementation is rather barebones and lacking a lot of functionality. Unidirectional communication should be rather easy to implement by defining dummy pins and allowing their use like it has been done e.g. here: https://github.com/stm32-rs/stm32f4xx-hal/blob/master/src/spi.rs . Maybe you'd like to give it a try? |
Okay, it looks not so difficult. |
This is something I would find useful as well! Let us know if you run into any issues if you decide to implement it! |
Hi! My attempt ultimately fails with The only other way I found is to have eight Do you have a better idea on how to do this? |
Okay, this attempt is a bit ugly, since it enumerates all seven possible combinations of "some pin" vs "NoPin", but it looks like it could work. (untested!) |
Hi, thanks for working on this! It is indeed a tricky problem, as I also discovered when doing a similar thing to PWM in #120 which also ended up with some conflicting pin impls. I think your latest attempt is perfectly fine, it doesn't add a lot of code and does exactly what we want. Additionally, it's not public API and unlikely to change, so even if it's not the neatest solution possible, it does what it should. |
Thanks for your reply! I'd say I'm adding the same for UART and other peripherals and file it as a PR soon :). |
Sounds great, though I do foresee a potential problem if this is implemented. Me and @therealprof discussed this in the matrix channel a while back, and I'm not sure he agrees, but I figure it might be worth pointing out anyway because I don't see why it wouldn't be a problem. First, an assumption:
Look at the following code: // Both SPI1 and 3 can use these pins
let pb3 = gpiob.into_alternate_push_pull();
let pb4 = gpiob.into_alternate_push_pull();
let pb5 = gpiob.into_alternate_push_pull();
// Set up SPI1 to only be an input. Since the configuration doesn't
// change, it will still be trying to output stuff to pb3 and pb5.
// Normally, this wouldn't be an issue, because the pins wouldn't be in alternate mode
let spi1 = Spi::spi1(..., (NoSck, NoMosi, pb4), ...);
// However, if another peripheral also uses the pins, they will
// need to be in AFIO mode, which means that we now have
// two peripherals that both try to control the 3 pins.
let spi3 = Spi::spi3(... (pb3, pb5, NoMiso), ...); I'm not sure if there is a neat way to work around this. An easy option might be to just configure the SPI peripheral in Another option might be to always take all the pins as input, and return new versions of the unused pins which can't be switched into AFIO mode. |
Ugh, I just read the RM0008 about the AFIO operation for the first time; I wasn't aware it's that bad until just now. I guess the only sane approach here is to create special versions of the remappable pins and only allow those for peripheral use. To switch the pins into a certain mapping you have to turn in all generic pins changed by a mapping flag into a to-be-created-function which will consume all pins, activate the remapping and return the special pins which will prevent that a remapped pin can be used by a foreign peripheral. However to use them as GPIO we'd have to add another version of the pin which allows all GPIO functions but no AF functions. |
That's probably a good idea anyway but I don't see how that would prevent conflicts with other peripherals.
I don't think promiscuous clock use is a big issue which needs solving at the moment. |
Yep, this was the idea I had as well. It's ugly, and would take a bit of work to implement. Also, this wouldn't allow the use of multiple peripherals which share a pin, but with that pin disabled by one of them.
Presumably, the peripheral wouldn't try to control the pins it doesn't use. Though it does lead to another issue. Should
|
That's the whole idea, no? STM32F1 (unlike other families) don't have a full multiplexer, they always seem to connect a pin to many AF peripherals or a simplified multiplexer (controlled by the remapping) at once.
I don't see anything in the manual which would suggest your presumption to be true and guaranteed. I would not want to implement something like that unless the manual says, "BTW: you can use a pin with a different peripheral if you turn of some function in this peripheral". I would assume that such a configuration bit only disables some internal logic but electrically it's still connected.
I thought you were talking about peripheral block clocks. But why would you ever want to disable SCK? You can't use use SPI without a clock. |
Good point.
SPI is useful for bit-banging. For example, I control the ws2812s in my keyboard using just the MOSI pin |
Fair enough but how does that relate to the pin mapping? You still can't use that pin for another peripheral, only GPIO. |
I suspect that if you would just let the user keep the pin, they would not only be able to use it as GPIO (fine), but also use it to configure a different, conflicting peripheral (bad); right? edit/PS: Maybe the right solution is to not have a Or... we give up and panic at runtime :/ (which I usually frown upon, but I can't think of any legit use case (apart from "let's see if I can break this HAL") that would lead into such problems) |
Yea, I was still thinking that disabling parts of the functionality would free up the pins, never mind.
Yea, that's true. Allthough you could argue that we should have dedicated types for that to avoid confusion.
Yea, that's a bit ugly, it would be nice to achieve the same thing without too many overloads. Perhaps something like fn spi1<PINS>(...) -> (SPI, PINS::TaintedPins)
One problem with this is that you're not always getting panic messages, for example, Also, I could see some projects configuring pins at runtime (for example, drone firmware tends to configure that stuff via a GUI). |
Yeah, so you need different types to prevent that. |
It seem like a long time since the last time anyone did anything in regards to the SPI configuration. But I just wanted to point out that SPI Clock and MOSI pins should also be possible to configure as Open Drain (not just Push-Pull). All STM32Fxxx I've worked with have 5V tolerant SPI pins. So in order to interface something which runs on 5V, you simply add a pull-up on these pins and configure them as Open Drain. As far as I can tell, this HAL will not let you do this. |
That's true. I think adding that functionality wouldn't be super difficult. If you'd like to give it a try, I could tell you where to start looking :) |
Super difficult use crate::gpio::gpioc::{PC10, PC11, PC12};
-use crate::gpio::{Alternate, Floating, Input, PushPull};
+use crate::gpio::{Alternate, Floating, Input, OpenDrain, PushPull};
use crate::rcc::{Clocks, Enable, GetBusFreq, Reset, APB1, APB2};
use crate::time::Hertz;
@@ -144,8 +144,10 @@ macro_rules! remap {
const REMAP: bool = $state;
}
impl Sck<$name> for $SCK<Alternate<PushPull>> {}
+ impl Sck<$name> for $SCK<Alternate<OpenDrain>> {}
impl Miso<$name> for $MISO<Input<Floating>> {}
impl Mosi<$name> for $MOSI<Alternate<PushPull>> {}
+ impl Mosi<$name> for $MOSI<Alternate<OpenDrain>> {}
};
} |
Thanks for the quick response on this. Yes, I will patch the code and try it out during next week. Once more, thanks a lot :) |
358: Allow pullup inputs and opendrain outputs r=burrbull a=Windfisch This fixes #321, #199 and extends on #118, and also fixes this issue for other peripherals that don't mind which pull-ups are configured for their inputs and whether their outputs are pushpull or open drain. This is a superset of #357 and #359. Prefer this PR. Co-authored-by: Florian Jung <flo@windfis.ch>
This is awesome HAL in terms of usage safety than any other I seen before. But it isn't so yet flexible in several cases.
I would like to configure SPI for display driver, which uses unidirectional setup with only SCLK and MOSI lines.
As I can see, the Pins trait implementation for that case is missing.
Since MISO pin in target device already used as GPIO for other purpose, so I cannot use Pins<(sclk, miso, mosi)>.
Also there are some other SPI setups like a bi-directional half-duplex with single data line.
The text was updated successfully, but these errors were encountered: