-
Notifications
You must be signed in to change notification settings - Fork 140
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
STM32: SPI with DMA - more reliable detection of transfer completed #1043
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -122,26 +122,24 @@ modm::platform::SpiMaster{{ id }}_Dma<DmaChannelRx, DmaChannelTx>::transfer( | |
if (tx) { | ||
Dma::TxChannel::setMemoryAddress(uint32_t(tx)); | ||
Dma::TxChannel::setMemoryIncrementMode(true); | ||
Dma::TxChannel::setDataLength(length); | ||
dmaTransmitComplete = false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't this introduce a bug? In case an RX only transaction follows a TX only one There is another potential issue here. |
||
Dma::TxChannel::start(); | ||
} else { | ||
Dma::TxChannel::setMemoryAddress(uint32_t(&dmaDummy)); | ||
Dma::TxChannel::setMemoryIncrementMode(false); | ||
} | ||
Comment on lines
128
to
131
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we still need this else-branch when we don't enable the channel at all? No transfer will be started. Thus, there should be no need to configure it. Also in line 119-120 we always enable both TX and RX DMA requests even when the respective channel is not enabled. I am wondering if we should really do this after that change. |
||
if (rx) { | ||
Dma::RxChannel::setMemoryAddress(uint32_t(rx)); | ||
Dma::RxChannel::setMemoryIncrementMode(true); | ||
Dma::RxChannel::setDataLength(length); | ||
dmaReceiveComplete = false; | ||
Dma::RxChannel::start(); | ||
} else { | ||
Dma::RxChannel::setMemoryAddress(uint32_t(&dmaDummy)); | ||
Dma::RxChannel::setMemoryIncrementMode(false); | ||
} | ||
|
||
Dma::RxChannel::setDataLength(length); | ||
dmaReceiveComplete = false; | ||
Dma::RxChannel::start(); | ||
|
||
Dma::TxChannel::setDataLength(length); | ||
dmaTransmitComplete = false; | ||
Dma::TxChannel::start(); | ||
|
||
while (true) | ||
{ | ||
if (dmaError) break; | ||
|
@@ -180,26 +178,24 @@ modm::platform::SpiMaster{{ id }}_Dma<DmaChannelRx, DmaChannelTx>::transfer( | |
if (tx) { | ||
Dma::TxChannel::setMemoryAddress(uint32_t(tx)); | ||
Dma::TxChannel::setMemoryIncrementMode(true); | ||
Dma::TxChannel::setDataLength(length); | ||
dmaTransmitComplete = false; | ||
Dma::TxChannel::start(); | ||
} else { | ||
Dma::TxChannel::setMemoryAddress(uint32_t(&dmaDummy)); | ||
Dma::TxChannel::setMemoryIncrementMode(false); | ||
} | ||
if (rx) { | ||
Dma::RxChannel::setMemoryAddress(uint32_t(rx)); | ||
Dma::RxChannel::setMemoryIncrementMode(true); | ||
Dma::RxChannel::setDataLength(length); | ||
dmaReceiveComplete = false; | ||
Dma::RxChannel::start(); | ||
} else { | ||
Dma::RxChannel::setMemoryAddress(uint32_t(&dmaDummy)); | ||
Dma::RxChannel::setMemoryIncrementMode(false); | ||
} | ||
|
||
Dma::RxChannel::setDataLength(length); | ||
dmaReceiveComplete = false; | ||
Dma::RxChannel::start(); | ||
|
||
Dma::TxChannel::setDataLength(length); | ||
dmaTransmitComplete = false; | ||
Dma::TxChannel::start(); | ||
|
||
[[fallthrough]]; | ||
|
||
default: | ||
|
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.
Why is this required?
If you do a transfer with TX and RX, both
dmaTransmitComplete
anddmaReceiveComplete
are set tofalse
before it is started. If you only transfer in one direction waiting for the interrupt is now bypassed as mentioned above. It seems to me there is another issue somewhere else.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.
So the scenario is to send the SPI data with low frequency. It's not a real high-frequency poll, so in general the previous packet would have been sent before the next is ready, but I'd like to have a guard for this case as well.
Before I send a packet, I check, whether SPI is ready to send:
If nothing has been sent before this function is called, the
transfer
always returnRunning
and the real send never occurs.So there is a way to overcome this by sending some dummy at the initialization stage, but I thought it could be also nice to reorganize the code to handle the general case as well.
Also, for the initialisation values:
dmaTransmitComplete
generally marks, that no transfers are active, so i thefalse
value could be valid here.In general, I don't think this PR is important and can be simply deleted.