Fix issue #201: Use NonZeroUsize to specify DMA transfer size#203
Conversation
MabezDev
left a comment
There was a problem hiding this comment.
Looks good to me, but I'll get @zRedShift and @ivmarkov's opinions before changing the public API.
zRedShift
left a comment
There was a problem hiding this comment.
LGTM, but if you want to make panics impossible we could create a newtype wrapping NonZeroU16/NonZeroUsize etc., that would return an Option<Self> when given the transfer size, returning None when zero or non-multiple of 4 and saturating at 4096.
|
@lonesometraveler - as @zRedShift mentions above, this PR is only ensuring at compile time that the DMA size is non-zero, while it is still not ensuring - at compile time - that the DMA size is <= 4096 and divisible by 4. Given that the PR introduces a backwards-incompatible change, I think it would be only worth it if the other two constraints (<= 4096 and divisible by 4) are also ensured compile-time. So if you would like to enhance the PR with the additional two constraints - I'm all for it. But in its current shape, I don't feel that the PR has enough weight to justify the backwards-incompatible change. |
|
@lonesometraveler Alternatively, you could implement a backwards-compatibility-preserving PR - along your original suggestion - which checks for dma size <= 4096 and dma size % 4 == 0 at runtime and panicing with a human-readable failure message. |
|
Thank you all for your reviews! How about something like this? This returns #[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct NonZeroTransferSize(usize);
impl NonZeroTransferSize {
pub fn new(size: usize) -> Option<Self> {
if size == 0 {
None
} else {
// Round up to a nearest multiple of 4. Saturate at 4096.
Some(Self(core::cmp::min((size + 3) / 4 * 4, 4096)))
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Dma {
Disabled,
Channel1(NonZeroTransferSize),
Channel2(NonZeroTransferSize),
Auto(NonZeroTransferSize),
}
impl Dma {
pub const fn max_transfer_size(&self) -> usize {
match self {
Dma::Disabled => TRANS_LEN,
Dma::Channel1(size) | Dma::Channel2(size) | Dma::Auto(size) => size.0,
}
}
}I chose to round up instead of returning |
I think not being able to use the standard |
|
Understood. I just made the change. It panics if size is 0. I am learning a lot from this. Thank you. |
|
Hey sorry one more request: can you also make the code panic if the size is > 4096? I know I introduced the current asymmetric behavior but in retrospective, that was not a good idea! |
|
Ok. It now panic if size > 4096. |
I wanted to submit a pull request to change the usage of
usizetoNonZeroUsizein the DMA channel enum. This fixes #201.This is a breaking change, as
NonZeroUsizeis a wrapper aroundusizethat ensures the value is non-zero. This change is being made to prevent panic when a zero value is used. Let me know if you have any questions or concerns.Thank you for considering this change!