Dear all,
The lpspi_dma_s32k144 example for S32K144EVB-Q100 board poses some strange behavior (using S32K14x RTM SDK v2.0.0).
The example is slightly simplified to transfer just 5 bytes from between master and slave on the same board like this:
LPSPI_DRV_SlaveTransfer(RECEIVE, slave_buffer.tx, slave_buffer.rx, 5);
LPSPI_DRV_MasterTransferBlocking(SEND, master_buffer.tx,master_buffer.rx, 5, TIMEOUT);
which works. The problem occurs when the above first line is replaced with:
LPSPI_DRV_SlaveTransfer(RECEIVE, slave_buffer.tx, NULL, 5);
where one would expect for the slave to send just 5 bytes upon master request. However, the slave sends only two bytes.
When trying, instead, to receive only 5 bytes it works without problem. I.e. the following line works:
LPSPI_DRV_SlaveTransfer(RECEIVE, NULL, slave_buffer.rx, 5);
In the following figure one can see that the slave indeed sends only two bytes (yellow signal is the Serial Data Input pin for the master) upon master request (green signal is SCK).
Can someone from NXP comment on this?
Thanks a lot in advance.
Hello Davit,
This problem was investigated and a bug was found. Until the bug is fixed, please use both Tx and Rx buffers for the LPSPI_DRV_SlaveTransfer() function while using DMA.
Thank you,
Dragos
Hi Dragos,
Thanks a lot for the clarification. Do you know in which version will the fix be available?
When using LPSPI_DRV_SlaveTransfer with both TX and RX buffers non-NULL, in the Interrupt mode (i.e. the .transferType variable is set to LPSPI_USING_INTERRUPTS in Send.c and Receive.c files) the following lines:
LPSPI_DRV_SlaveTransfer(RECEIVE, slave_buffer.tx, slave_buffer.rx, 4);
LPSPI_DRV_MasterTransferBlocking(SEND, NULL, master_buffer.rx, 5, TIMEOUT);
end up in LPSPI_DRV_SlaveIRQHandler with LPSPI_TRANSMIT_ERROR set. In the DMA mode no error occurs, and the master node receives its 4 bytes from the slave.
In the interrupt mode despite the LPSPI_TRANSMIT_ERROR the master still receives the 4 bytes from the slave.
Is this another bug or an expected behavior?
Another problematic case
If one instead of the above two lines uses the following (in the interrupt mode):
LPSPI_DRV_SlaveTransfer(RECEIVE, slave_buffer.tx, slave_buffer.rx, 5);
LPSPI_DRV_MasterTransferBlocking(SEND, master_buffer.tx, NULL, 4, TIMEOUT);LPSPI_DRV_SlaveTransfer(RECEIVE, slave_buffer.tx, slave_buffer.rx, 5);
LPSPI_DRV_MasterTransferBlocking(SEND, NULL, master_buffer.rx, 4, TIMEOUT);
__asm("BKPT #0\n\t");
Then BKPT line is never reached.
Thanks.
Hi,
The root cause for your first problem is the interrupt priorities.
Your application runs in the same time slave and master and probably the interrupt for master fill up have a higher priority than slave fill up. In this case when master sends data the slave FIFOs are empty and tx transfer error is detected on slave side.
For the second issue I will investigate more and I will come back with some updates.
Razvan
Thanks you for the clarification. I'll look more closely to the interrupt priorities.
Would be great if you could comment also on the second issue.
Thanks a lot in advance.
Hi Daniel,
Thanks a lot.
Your example works, but it uses interrupts rather than DMA.
Does the DMA variant works in your case?
Hi Davit,
I have tried with the lpspi_dma_s32k144 SDK example.
The only modification:
Yet it works.
Can you try this example?
Can you share a test project?
Please check the return status of the function.
Thanks,
Daniel
Hi Daniel,
Thanks again for your feedback and efforts.
Please find attached the project. It is just newly created from the example as you showed in the picture.
The problem with the original example with setting NULL in place of slave_buffer.rx still can be seen. Once a breakpoint is hit after the line:
LPSPI_DRV_MasterTransferBlocking(SEND, master_buffer.tx,master_buffer.rx, NUMBER_OF_FRAMES, TIMEOUT);
the muster_buffer.rx is mostly field correctly, except the last 4 records. The last 6 bytes of master_buffer.rx looks like the following:
Name : master_buffer.rx[94]
Decimal:6
Hex:0x6
Name : master_buffer.rx[95]
Decimal:5
Hex:0x5
Name : master_buffer.rx[96]
Decimal:100
Hex:0x64
Name : master_buffer.rx[97]
Decimal:99
Hex:0x63
Name : master_buffer.rx[98]
Decimal:98
Hex:0x62
Name : master_buffer.rx[99]
Decimal:97
Hex:0x61
So the buffer starting from address 96 seems to be wrong.
In addition if one sets the NUMBER_OF_FRAMES constant to 5 the same situation is observed which I described in the first post (i.e. only 2 bytes from the slave are sent). It seems that the DMA does something wrong with the last addresses.
Davit,
Indeed, I get the same result when NUMBER_OF_FRAMES = 5U.
The functions do not return any errors.
Interestingly, it works when
Let me check with SDK design team,
Thanks,
Daniel
Daniel thanks a lot for your information.
I hope it will not put a noise to the problem, but one may notice another strange behavior with SPI.
In the same example if one tries to replace the former lines:
LPSPI_DRV_SlaveTransfer(RECEIVE, slave_buffer.tx,NULL/*slave_buffer.rx*/, NUMBER_OF_FRAMES);
LPSPI_DRV_MasterTransferBlocking(SEND, master_buffer.tx,master_buffer.rx, NUMBER_OF_FRAMES, TIMEOUT);
with the following lines:
LPSPI_DRV_SlaveTransfer(RECEIVE, NULL, slave_buffer.rx, 4);
LPSPI_DRV_MasterTransferBlocking(SEND, master_buffer.tx, NULL, 3, TIMEOUT);
__asm("BKPT #0\n\t");
i.e. making the slave to wait for 4 bytes while the master sends 3 bytes (omitting the merit of such a fancy coding), then the modified example (at -O0 optimization) does not reach the BKPT (using Segger J-Link debugger). The program does not seem to stay in some infinite loop or in a continuous interrupt since it is enough to press just the pause button and then the continue button again to make the program to reach the BKPT line. The slave_buffer.rx is then currectly filled with 3 bytes sent from master. This behavior seems to be present in both SPI DMA and non-DMA modes. There is a feeling that somehow this is related to LPSPI_DRV_SlaveIRQHandler interrupt and LPSPI_RECEIVE_ERROR but it is difficult to draw a defined logic.
I understand that this description may be too unspecific but still such behavior of S32K is rather confusing.
Could you please comment whether it is reproduced at your side?
Thanks a lot for your help.