2021-10-12 02:16 AM
Hello
Test Szenario:
Setup:
Variables:
volatile uint32_t spiTransferState = SPI_TRANSFER_IDLE;
DMA Circulare Code:
[somewhere in main while loop]
volatile static uint64_t counter = 0;
if(spiTransferState == SPI_TRANSFER_COMPLETE){
counter++;
spiTxBuffer[0] = 8;
memcpy(&spiTxBuffer[1],(uint8_t*)&counter,8);
spiTransferState = SPI_TRANSFER_WAIT;
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
spiTransferState = SPI_TRANSFER_COMPLETE;
}
DMA Normal Mode
Line 9 differs
[somewhere in main while loop]
volatile static uint64_t counter = 0;
if(spiTransferState == SPI_TRANSFER_COMPLETE){
counter++;
spiTxBuffer[0] = 8;
memcpy(&spiTxBuffer[1],(uint8_t*)&counter,8);
spiTransferState = SPI_TRANSFER_WAIT;
HAL_SPI_TransmitReceive_DMA(&hspi1, (uint8_t*) spiTxBuffer, (uint8_t*) spiRxBuffer, SPI_BUFFER_SIZE);
}
When logging the receiving data in ciruclare mode:
b[0]: 8 b[1]: fe b[2]: ff b[3]: 0 b[4]: 0 b[5]: 0 b[6]: 0 b[7]: 0 b[8]: 0
b[0]: 8 b[1]: ff b[2]: ff b[3]: 1 b[4]: 0 b[5]: 0 b[6]: 0 b[7]: 0 b[8]: 0
alfa counter: 65535
received counter: 131071 //check b[3] flipped to early?
b[0]: 8 b[1]: 0 b[2]: 0 b[3]: 1 b[4]: 0 b[5]: 0 b[6]: 0 b[7]: 0 b[8]: 0
b[0]: 8 b[1]: 1 b[2]: 0 b[3]: 1 b[4]: 0 b[5]: 0 b[6]: 0 b[7]: 0 b[8]: 0
When running it without circular mode. this problem does not occure.
What did I wrong? What could cause this? Or probably what did I not understand when using ciruclar mode?
Best regards
Franco
Solved! Go to Solution.
2021-10-12 04:03 AM
Part of the problem here is that you rely on prechewed Cube/HAL functions instead of writing your own, where you would develop an understanding of what's going on.
HAL_SPI_TxRxCpltCallback() is called when the receiver DMA throws the Transfer Complete interrupt, which is at the moment when the whole packet has been transferred. However, if the Tx DMA is circular, it has already transferred the first 3 bytes into the SPI Tx FIFO, with the *old* values, after that the increment happens, so the 4th byte is transmitted already after the increment.
You want to perform the increment in the Tx DMA Transfer Complete interrupt, if you can guarantee it will be completed before the first byte of it gets transferred into the FIFO. Alternatively, you can try to use the Double-Buffer DMA mode.
JW
2021-10-12 04:03 AM
Part of the problem here is that you rely on prechewed Cube/HAL functions instead of writing your own, where you would develop an understanding of what's going on.
HAL_SPI_TxRxCpltCallback() is called when the receiver DMA throws the Transfer Complete interrupt, which is at the moment when the whole packet has been transferred. However, if the Tx DMA is circular, it has already transferred the first 3 bytes into the SPI Tx FIFO, with the *old* values, after that the increment happens, so the 4th byte is transmitted already after the increment.
You want to perform the increment in the Tx DMA Transfer Complete interrupt, if you can guarantee it will be completed before the first byte of it gets transferred into the FIFO. Alternatively, you can try to use the Double-Buffer DMA mode.
JW
2021-10-12 04:39 AM
Thank you for the quick response!
Your answer helped me solve the problem with my current szenario. It did show me that I have to change some concept in our main project, since we are not fast enaugh to load all the data in the interrupt itself.
Cheers!