-
Notifications
You must be signed in to change notification settings - Fork 205
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
Refactor spi modules to improve structure #467
Conversation
3558a40
to
81176e2
Compare
81176e2
to
1f9a6cb
Compare
8fc3a97
to
3d9294b
Compare
hal/src/sercom/v2/spi.rs
Outdated
/// Change the transaction [`Length`] | ||
/// | ||
/// Changing the transaction [`Length`] while is enabled is permissible but | ||
/// `unsafe`. If you have sent or received *any* bytes at the current | ||
/// [`Length`], you **must** wait for a TXC flag before changing to a new | ||
/// [`Length`]. | ||
#[inline] | ||
#[cfg(feature = "min-samd51g")] | ||
pub unsafe fn length<L: Length>(self) -> Spi<Config<C::Pads, C::OpMode, L>, A> | ||
where | ||
Config<C::Pads, C::OpMode, L>: ValidConfig, | ||
{ | ||
Spi { | ||
config: self.config.into().length(), | ||
capability: self.capability, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really unsafe
? In a previous discussion we agreed that unsafe
should, as much as possible, be used only for things that may incur memory unsafety/UB. I guess it could be argued that this is "memory unsafe" as the data received is not what was expected. I'm not sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think you're right. It can put you in a sort of dead lock, or it can give you incorrect values, but it can't corrupt memory. Maybe it could in combination with DMA, but I think that's a separate issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also removed unsafe
from set_dyn_length
for the same reason. Now only getting a reference to the underlying Sercom
type and directly reading and writing the DATA
register are unsafe. I think those are closer to memory unsafety.
/// Map an [`OptionalPadNum`] to its corresponding `DIPO` value | ||
pub trait Dipo: OptionalPadNum { | ||
const DIPO: Option<u8>; | ||
} | ||
|
||
impl Dipo for NoneT { | ||
const DIPO: Option<u8> = None; | ||
} | ||
|
||
impl Dipo for Pad0 { | ||
const DIPO: Option<u8> = Some(0); | ||
} | ||
impl Dipo for Pad1 { | ||
const DIPO: Option<u8> = Some(1); | ||
} | ||
impl Dipo for Pad2 { | ||
const DIPO: Option<u8> = Some(2); | ||
} | ||
impl Dipo for Pad3 { | ||
const DIPO: Option<u8> = Some(3); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is new. Is there a downside to just setting DIPO/DOPO
to a nonsensical value instead? (asking for uart-v2
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's been several months, but I think I remember why I did this. I have Dipo
and Dopo
traits, but I also have a DipoDopo
trait. The latter trait is responsible for taking two Option<u8>
values and resolving them to valid pairs of DIPO
and DOPO
. I didn't want to accidentally introduce a loopback scenario, so I needed to make sure the two values never collide, even when one of the pins is NoneT
. For SAMD2x chips, that came in the form of expanding the macro. For SAMD5x chips, I did this.
I think I remember concluding that UART doesn't have to worry about loopback in the same way SPI does.
3d9294b
to
ccbde91
Compare
@jacobrosenthal, I refactored this to get rid of its dependence on the pygamer port. I also fixed DMA in light of the UART merge. I still need to go through your comments. |
ccbde91
to
79d68ef
Compare
@jbeaurivage, see the latest commit to address your comments |
Make several improvements to the `sercom::v2::spi` module: - Introduce a `Registers` type that acts as a task-focused API for the registers, as opposed to the register-focused API of the PAC. This abstraction also serves to remove interior mutability of the PAC struct and lets us implement `Sync` for `Registers` - Add a `Capability` trait and three corresponding types: `Rx`, `Tx` and `Duplex`. Add a `Capability` type parameter to the `Spi` struct and use it to differentiate the various embedded HAL trait implementations. This is a better solution than the previous approach, which was a set of marker traits implemented on `Pads` types. - Combine the `thumbv6m` and `thumbv7em` modules to reuse more code. The major differences between the two chips come in the `Pads` type, and the `Length` and `CharSize` types. Introduce a `Size` trait that essentially acts a trait alias for either `Length` or `CharSize`. Split up the modules and use conditional imports to handle everything correctly for the three different chips. Because the `spi` module is no longer split between the two chip-specific modules, also consolidate the `impl_pad` modules as well. Finally, improve the documentation for the `spi` module itself, as well as for the embedded HAL trait implementations.
79d68ef
to
c7126b1
Compare
I had to make some changes to |
Whoops, I already know this is going to fail. I forgot to update the |
@bradleyharden, if you rebase to |
@jbeaurivage, done |
* Refactor `spi` modules to improve structure Make several improvements to the `sercom::v2::spi` module: - Introduce a `Registers` type that acts as a task-focused API for the registers, as opposed to the register-focused API of the PAC. This abstraction also serves to remove interior mutability of the PAC struct and lets us implement `Sync` for `Registers` - Add a `Capability` trait and three corresponding types: `Rx`, `Tx` and `Duplex`. Add a `Capability` type parameter to the `Spi` struct and use it to differentiate the various embedded HAL trait implementations. This is a better solution than the previous approach, which was a set of marker traits implemented on `Pads` types. - Combine the `thumbv6m` and `thumbv7em` modules to reuse more code. The major differences between the two chips come in the `Pads` type, and the `Length` and `CharSize` types. Introduce a `Size` trait that essentially acts a trait alias for either `Length` or `CharSize`. Split up the modules and use conditional imports to handle everything correctly for the three different chips. Because the `spi` module is no longer split between the two chip-specific modules, also consolidate the `impl_pad` modules as well. Finally, improve the documentation for the `spi` module itself, as well as for the embedded HAL trait implementations.
Make several improvements to the
sercom::v2::spi
module:Registers
type that acts as a task-focused API for theregisters, as opposed to the register-focused API of the PAC. This
abstraction also serves to remove interior mutability of the PAC
struct and lets us implement
Sync
forRegisters
Capability
trait and three corresponding types:Rx
,Tx
andDuplex
. Add aCapability
type parameter to theSpi
struct anduse it to differentiate the various embedded HAL trait
implementations. This is a better solution than the previous approach,
which was a set of marker traits implemented on
Pads
types.thumbv6m
andthumbv7em
modules to reuse more code. Themajor differences between the two chips come in the
Pads
type, andthe
Length
andCharSize
types. Introduce aSize
trait thatessentially acts a trait alias for either
Length
orCharSize
.Split up the modules and use conditional imports to handle everything
correctly for the three different chips.
Because the
spi
module is no longer split between the twochip-specific modules, also consolidate the
impl_pad
modules as well.Finally, improve the documentation for the
spi
module itself, as wellas for the embedded HAL trait implementations.