<firefrommoonligh>
`read_dma` sets `ADC_CFGR_DMAEN`, sets `CFGR_DMACFG` to oneshot, and configures/enables the DMA channel
<firefrommoonligh>
Did I miss anything?
<firefrommoonligh>
* `read_dma` sets `ADC_CFGR_DMAEN`, sets `CFGR_DMACFG` to oneshot, starts a single-length conversion, then configures/enables the DMA channel
<firefrommoonligh>
* `read_dma` sets `ADC_CFGR_DMAEN`, sets `CFGR_DMACFG` to oneshot, starts a single-length conversion, then configures/enables the DMA channel, pointing to the `sr` register
<dirbaio[m]1>
got full code? For this one, or spi
<firefrommoonligh>
Sure do!
<firefrommoonligh>
Focusing on ADC for now since it's simpler (Although not as explicitly documented)
<firefrommoonligh>
What I posted was the user-side code
<dirbaio[m]1>
and to be safe from compiler optimizations you maybe need `compiler_fence(Ordering::SeqCst)` before and after DMAing
<firefrommoonligh>
Could be that too. I tried waiting for periph and dma transfer complete flags, but those would hang
<firefrommoonligh>
Good catch on buf. I may have done something wrong re the `embedded_dma` traits there
<firefrommoonligh>
I'll try the fencing next, as well as trying to read bits like the ones you proposed, and see what's taking and what's not
<firefrommoonligh>
Goal: Make DMA the default API for comm protocols, ADC, and DACs, on my current and future projects, and public HAL
<firefrommoonligh>
* Goal: Make DMA the default API for comm protocols, ADC, and DACs, on my current and future projects, and public HAL code and examples
<firefrommoonligh>
Relegating non-DMA to EH-compatibility for generic drivers
<dirbaio[m]1>
embedded_dma only gives you safety if you own the `B` btw
<firefrommoonligh>
I have a lot of open questiosn about how embedded_dma etc works, but am hoping to save that for after I get the basics working
<firefrommoonligh>
And figure out what should go in the DMA module vice HAL periph vice user code (and examples)
<firefrommoonligh>
On the plus side, all this RM spellunking's let me clean up the ADC module and add functionality to it
<firefrommoonligh>
Even if I'm striking out on DMA
<henrik_alser[m]>
Yeah your read would take an owned WriteBuffer
<henrik_alser[m]>
(+’static)
<firefrommoonligh>
Oh?
<firefrommoonligh>
`embedded_dma::WriteBuffer` for the ADC read?
<dirbaio[m]1>
no idea whether you can point both channels at the same buffer
<dirbaio[m]1>
seems dangerous
<henrik_alser[m]>
You can in some mcu families at least (like nrf)
<dirbaio[m]1>
and it's useful to be able to use separate buffers anyway
<dirbaio[m]1>
maybe you want to tx some data without trashing it because you need it later for something else
<henrik_alser[m]>
Unless they’re huge:)
<firefrommoonligh>
Thank you for the SPI info
<firefrommoonligh>
That's outstanding
<firefrommoonligh>
In the blocking APIs I've been using, you're doing constant alternating writes and reads, even to just write a buf
<dirbaio[m]1>
yeah these are ultra weird
<firefrommoonligh>
Like, the HAL will impl a EH `send` and `read` from EH, and impl default eh::FUllduplex, which blocks and alternates the two
<firefrommoonligh>
This is why I'm focusing on ADC DMA for now!!
<firefrommoonligh>
I'd been using offboard ADCs in my projects, but STM32 ADC seems full-up
<firefrommoonligh>
Unrelated: Why do the VREF pins only exist on high-pin packages?
<firefrommoonligh>
If you want good ADC accuracy, can you just hook up a voltage ref to the VDDA and VSSA pins?
<firefrommoonligh>
What's the effective difference between that and the big-package VREF?
<firefrommoonligh>
Is the dif that VDDA ha to be close to VDD, but VREF can be diff?
<firefrommoonligh>
And otherwise either is fine?
<henrik_alser[m]>
Vdda is the power supply for the adc, dac, rc oscillator, plls etc, Vref+/- are just the reference voltage for the ADC so can be connected to something higher precision or low voltage for better precision at low voltages for example
<henrik_alser[m]>
On the low count packages it's just internally connected to Vdda
<henrik_alser[m]>
So if you don't need other precision than that you can just connect them to Vdda/Vssa yeah
<henrik_alser[m]>
* Vdda is the power supply for the adc, dac, rc oscillator, plls etc, Vref+/- are just the reference voltage for the ADC/DAC so can be connected to something higher precision or low voltage for better precision at low voltages for example
<henrik_alser[m]>
If Vdda < 2.4V Vref must be equal to Vdda however
<henrik_alser[m]>
And if Vdda >= 2.4V Vref can be in the range from 2.4V to Vdda
<henrik_alser[m]>
And yeah Vdda must be equal to Vdd btw
<henrik_alser[m]>
And Vssa to Vss
<firefrommoonligh>
I appreciate it!
<firefrommoonligh>
It's surprising this feature is package-specific. I'm guessing there's no way to MUX it like they do with peripheral pins
<firefrommoonligh>
Another unrelated Q: It looks like SPI can hardware-manage CS pins. The pin state is set by hardware automatically. It's set up as you do with the other pins, ie as an alt fn. Doesn't this defeat the purpose, eg switching between multiple devices? I could see how they might design this where you have a cfg field to choose one of several pins for a given write/read, but that's not how it's set up
<firefrommoonligh>
So, seems... useless?
<firefrommoonligh>
Maybe it's for when you only have one device? Seems like a good fit there
<henrik_alser[m]>
<firefrommoonligh "It's surprising this feature is "> No i think a gpio frontend would sacrifice too much in terms of precision, noise and temperature stability to be useable for a ref input
<firefrommoonligh>
But for that many devices could just hard set it low. Although some need it to go high between writes
<firefrommoonligh>
That makes sense!
<henrik_alser[m]>
Yes it’s for single device use only, can be handy as you don’t have to be juggling around the cs pin as a separate resource
<firefrommoonligh>
Makes sense!
<firefrommoonligh>
(And for devices where you can't get away with hard-setting CS low)
<firefrommoonligh>
Hmm... DMA en is being set
<firefrommoonligh>
* Hmm... DMA en is being set and cleared. It shows set it I read immediately after commanding the xfer. Then shows clear on subsequent checks. So, this appears to be working. Still no updates to the buf though, after adding the fencing and changing it to a &mut write buf.
<thalesfragoso[m]>
<dirbaio[m]1 "Transfer always requires write a"> Yeah, this was an initial work, I have a PR for not requiring for both
<thalesfragoso[m]>
Which reminds me that I need to fix conflicts
<firefrommoonligh>
Oh shit! dirbaio strikes again. The transfer error flag is set
<thalesfragoso[m]>
firefrommoonlight: ADC should use u16, no ?
<firefrommoonligh>
Yep
<thalesfragoso[m]>
Alignment might also be a problem
<firefrommoonligh>
So, `DMA_CNDTR` is by word, not byte?
<dirbaio[m]1>
which is nice because it prevents from dma-transfering Potato values or whatever which is likely UB :)
<firefrommoonligh>
This note on the field implies word ("data items"): `It is decremented after each single DMA ‘read followed by write’ transfer, indicating
<firefrommoonligh>
the remaining amount of data items to transfer`
<henrik_alser[m]>
(Was thinking if you used the embedded-dma traits later)
<firefrommoonligh>
Also, in a description of DMA in RM: `This register contains the remaining number of data items to transfer (number of AHB
<firefrommoonligh>
‘read followed by write’ transfers).`
<firefrommoonligh>
That's what I used most recently
<henrik_alser[m]>
That's probably right! In nrf it's bytes however
<firefrommoonligh>
*Note that `as_mut_ptr()` fix
<firefrommoonligh>
I think the `total number of bytes` line was UART-specific
<henrik_alser[m]>
So yeah if you're allowing stack buffers only in unsafe it should be alright i guess
<thalesfragoso[m]>
Actually `WriteBuffer` is already ok for non 'static stuff and should work with `&'a mut [T] where T: Word` already
<thalesfragoso[m]>
but `WriteBuffer` by itself isn't usually enough for a safe DMA API
<henrik_alser[m]>
Yes that's what i meant :)
<henrik_alser[m]>
* Ahh true
<firefrommoonligh>
It seems like `StaticWriteBuffer` might be safer, but I don't understand the details
<thalesfragoso[m]>
there are docs :)
<thalesfragoso[m]>
Basically, if the thing isn't `'static` you can `mem::forget` the transfer and cause memory corruption if your repurpose the memory buffer
<thalesfragoso[m]>
* Basically, if the thing isn't `'static` you can `mem::forget` the transfer and cause memory corruption if you repurpose the memory buffer
<henrik_alser[m]>
(That's what i was referring to when i said i thought it was ok in unsafe like you did it above)
<henrik_alser[m]>
But you could provide a safe alternative too with StaticWriteBuffer?
<firefrommoonligh>
Sounds like an edge case, especially if you're not familiar with `mem::forget`!
<firefrommoonligh>
Yeah - no downside in offering both
<firefrommoonligh>
Other than a more complex API, since I guess you'd need to implement separate dma functions for each periph, which means 2 extra fns in comm protocols for read and write
<firefrommoonligh>
unless you know of a better way
<firefrommoonligh>
(I'm going to tackle SPI next using the buf fixes you, thalesfrago, and dirbaio made)