Code: Select all
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
dmaStreamSetMemory0(spip->dmarx, &dummyrx);
dmaStreamSetTransactionSize(spip->dmarx, n);
dmaStreamSetMode(spip->dmarx, spip->rxdmamode);
dmaStreamSetMemory0(spip->dmatx, txbuf);
dmaStreamSetTransactionSize(spip->dmatx, n);
dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC);
dmaStreamEnable(spip->dmarx);
dmaStreamEnable(spip->dmatx);
}
I understand the first two "paragraphs" of that code to set the DMA engine starting address and increments for each buffer (in the case of receive buffer a single memory location, without incrementing the address).
A very similar code is used for U(S)ART transfers, however it just sets the DMA engine for either TX or RX, not both.
What I don't understand is how RX and TX are synchronized and clocking started. In the oscilloscope trace it's clear that starting a DMA transfer will also enable the clocking:
If I understand the STM32 documentation correctly, in order to get a reliably synchronization between RX and TX of a SPI periphial you first have to disable the SPE bit in CR1, then parametize and enable the DMA engine(s), and finally set the SPE bit in CR1 to initiate the transfer. Or does the STM32 not clock the SPI for just a RX and a dummy TX must be started to provide an RX clock?
And how would I extend the USART driver to allow for Exchange transfers? In my current project there are several independent SPI busses; too much as that the STM32Fx07 periphials would suffice. So repurpose one of the USARTs as a slow master only SPI.