-
Notifications
You must be signed in to change notification settings - Fork 27
Description
I had some code that resembled this:
for smnum in 0..STRAND_COUNT {
// irrelevant stuff omitted
p.DMA.ch[smnum].ch_al1_ctrl.write(|w| unsafe {
w.read_error().set_bit() // to clear
.write_error().set_bit() // to clear
.bswap().set_bit()
.treq_sel().bits(0 + smnum as u8) // DREQ_PIO0_TX0..3 are contiguous
.incr_write().clear_bit()
.incr_read().set_bit()
.data_size().size_word()
.high_priority().set_bit()
.en().set_bit()
});
}It causes rather elaborate misbehavior on DMA channel 0.
Can you see why?
Unfortunately, you can't see why, as the critical piece of information does not actually appear in the code. svd2rust defaults any register bitfields that are not explicitly set to its idea of the reset value (a design flaw, imo, but hey). The rp2040 SVD from the RaspPi folx have all the DMA channel registers modeled separately, which is good, because they have different reset values.
Why? Because for the CHAIN_TO field to be a no-op, it has to be set to the ID of the channel being configured. So for channel 0 it's 0, for channel 1, it's 1, etc.
The PAC loses this information from the SVD by throwing away the types of channels 1-7 and using the channel 0 type for everything. Of course, you have to do that to make an array. (svd2rust also makes types distinct just so they can have different reset values, preventing them from being in an array, which, well, you can guess my opinion on that.)
The net effect of this is that every channel other than 0 implicitly triggers channel 0 when it completes. Every time.
I'm not actually sure how to fix this. Moving away from the array would be terribly unfortunate and cause me to basically hack an array back in so that I can loop over channels (god forbid you wanted to allocate channels dynamically, with them all becoming different types!). However, the current situation is a rather elaborate footgun for DMA. I don't believe svd2rust has any notion of a field that must be set explicitly when writing a register, which otherwise would be a reasonable thing to reach for here.