2024-06-18 12:01 AM - edited 2024-06-18 01:57 AM
Hello ST Community,
I have setup a SPI master and a SPI slave, both use DMA in Normal mode. The word size is 8-bits and the data size is 8-bytes. The problem is that the slave transmits messages which contains old data.
When it should send:
MISO: { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }
it sends:
MISO: { 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01 }
When it should send:
MISO: { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }
it sends:
MISO: { 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02 }
OBS: The debug gpio is toggled when the ISR finishes and when theTxBuffer is edited in main.
This pattern continues for every transfer it contains 3 old bytes.
Implementation (slave):
The slave updates the response in the main function.
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_SPI1_Init();
HAL_SPI_TransmitReceive_DMA(&hspi1, TxBuffer, RxBuffer, 8);
while (1)
{
if(msgReceived == 1) {
memset(TxBuffer, SPI_Counter, BUFFERSIZE);
HAL_SPI_TransmitReceive_DMA(&hspi1, TxBuffer, RxBuffer, BUFFERSIZE); // update SPI transfer
msgReceived = 0;
HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_1); // DEBUG
}
}
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
msgReceived = 1;
SPI_Counter++;
HAL_SPI_TransmitReceive_DMA(&hspi1, TxBuffer, RxBuffer, 8); // setup a new transfer
HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_1); // DEBUG
}
Setup:
How can it be that the MISO transfer contains old data?
Solved! Go to Solution.
2024-06-19 11:20 PM - edited 2024-06-19 11:43 PM
Thank you for your replies.
@BarryWhit I do want to understand why the current setup isn't working. I am well aware that if I only call the HAL_SPI_TransmitReceive_DMA in the main loop (or in the ISR) it would work as expected.
I have setup this code example to simplify my problem as much as possible. Really I am working on a motor control project with two chips a dedicated motor controller and a main chip that handles bluetooth and so on. The main chip should always be able to ping the motor controller, even if it has requested it to carry out a command. Secondly the motor controller should respons the main controller when it has executed a command and is ready for a new. If the main chip cannot ping the motor controller it should kill the motor controller (turn off the power).
The diagram depicts the current functionality and the desired functionality.
Currently the transfer is handled using synchronization flags, this introduces a delay. Although the slave has finished its task and has a result ready it transfers 'Busy_State', because a transfer only can be setup in the ISR.
Double Buffering has the same problem it still has a response delay.
2024-06-19 11:29 PM - edited 2024-06-19 11:39 PM
The only purpose of the DEBUG pin is to show that there is plenty of time between the TxBuffer is updated in main until a new transfer starts.
I know that I should monitor whether a SPI transfer is ongoing before I update the TxBuffer. I will handle this after I have resolved my main problem, which is that I cannot update the TxBuffer after I have initiated a SPI transfer.
I see the same behaviour as in the Screenshot if I only update the TxBuffer in the main loop and omits calling HAL_SPI_TransmitReceive_DMA
int main() {
...
if (HAL_SPI_TransmitReceive_DMA(&hspi1, currentTxBuffer, RxBuffer, BUFFERSIZE) != HAL_OK) {
Error_Handler(); // Handle error
}
while (1)
{
if(msgReceived == 1) {
memset(TxBuffer, SPI_Counter, BUFFERSIZE);
msgReceived = 0;
HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_1); // DEBUG
}
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
msgReceived = 1;
SPI_Counter++;
HAL_SPI_TransmitReceive_DMA(&hspi1, TxBuffer, RxBuffer, BUFFERSIZE); // setup a new transfer
HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_1); // DEBUG
}
2024-06-20 02:44 AM - edited 2024-06-20 02:46 AM
> @BarryWhit I do want to understand why the current setup isn't working. I am well aware that if I only call
> the HAL_SPI_TransmitReceive_DMA in the main loop (or in the ISR) it would work as expected.
So, you do understand you can't start a DMA while one is ongoing, but you don't understand why your code, which does just that, is corrupting data? I don't follow.
>> I know that I should monitor whether a SPI transfer is ongoing before I update the TxBuffer. I will
>> handle this after I have resolved my main problem, which is that I cannot update the TxBuffer
>> after I have initiated a SPI transfer.
Your original post asked why you're seeing data corruption, and you got an answer.
You also cannot touch the buffer while a transfer is ongoing (not in code, not by restarting DMA). You're not going to "resolve" that.
> Currently the transfer is handled using synchronization flags, this introduces a delay.
are you trying to say that you need a way to interrupt an ongoing transfer? because that's completely unrelated to the issue we've been trying to help you with. If you've resolved the data corruption issue, I suggest you accept the solution @PPopo.1 provided and start a new thread.
2024-06-20 05:53 AM
Sorry for the unclear communication and the inconvenience it has caused. I tried communicated the desired functionality through the sequence diagrams.
I will accept @PPopo.1 s soultion and start a new thread.
2024-06-20 08:00 AM
So the data corruption issue has been resolved. That's progress!