Hello,
I'm using the fsl_ecspi HAL from the MCUXpresso SDK to do ECSPI transfers on the M7 on the i.MX8MP. Specifically, the non-blocking interrupt based one: https://github.com/nxp-mcuxpresso/mcux-sdk/blob/c3cb2055dafdd42fdb5e120eae418413c5fccd73/drivers/ecs....
As far as I can tell, the HAL uses the mode where CONREG.SMC = 1 such that transfers starts immediately when data is written to the FIFO. I need to do chip selections manually via a GPIO as I have multiple devices on the bus.
I'm using the callback in the HAL to determine when the transaction is complete, but this has a tendency to fire before the last bits have been transferred on the physical line (often in the middle of the last byte). I'm using a burst length of 8 bits and SCLK of 10 MHz.
I've studied the datasheet to see if I can use the XCH bit, the TC bit or checking that the TX and RX count in the TESTREG registers are at 0. I've tested all of these solutions, but I manage to reproduce the same issue no matter what in some instances. It seems that these flags represent when the FIFO is empty with or without some delay, but not when the last bit has been shifted out. I can't find any errata on this either.
I looked on the forum and found some other people struggling with the same issue with varying success:
* https://community.nxp.com/t5/i-MX-Processors/iMX6-Solo-SPI-XCH-behaviour-in-master-mode/td-p/339662
* https://community.nxp.com/t5/i-MX-Processors/iMX8MM-Cortex-M4-ECSPI-with-GPIO-chipselect-how-to-dete...
Could someone from NXP confirm what is the best solution in these cases and if there is some reliable solution at all?
已解决! 转到解答。
TC gets set after burst of bits is complete! Looks like in your case burst is 8 bits. So if you fill whole FIFO, data for multiple of bursts, TC is set after first byte is transferred and is keps set until you clear it. If you still need to use FIFO, then you should try increasing burst length to match your transfer size. TC will then set after your real transfer is complete.
Hi @aadvark
I have talk about this question with our internal SPI team, Here are the answer about your below two questions:
1. Does that mean that one should have SMC cleared?
>>>Actually, Because we have not test it before on M-core, i think you can keep this bit 1.
2. Does the XCH bit still provide a reliable check when SMC=1? I've not found that to be the case when experimenting with various transfers.
>>>Yes, I think the XCH bit can provide a reliable check when SMC=1, and also you can add a print log, when SMC=1 and the data exchange is going on, you can read the XCH bit to see if it is 1.
B.R
Since XCH has no corresponding interrupt, it is unusable to toggle GPIO CS at the end of transfer. Perhaps driver using DMA could use it somehow at the end of DMA transaction, but topic is about eCSPI on Cortex-M...
TC is OK on Cortex-M, but you are limited to clear TC before transfer and don't FIFO more TX data until current transfer (burst of bits) is complete.
Actually, In our RM file. The TC bit does not provide a reliable indication that the transfer is complete. Under some conditions, the TC interrupt can occur before the transfer is completed. If the TC bit is used as an interrupt source, the XCH bit should be polled after the TC interrupt occurs to accurately confirm that the transfer is complete.
i will also contact this with our internal SPI expert talk about it. @aadvark i think You can try this method to determine whether the SPI transmission is complete
B.R
Hello @pengyong_zhang,
Thank you for looking into this. This is the procedure:
1. After I get the callback from the HAL that the transfer is complete I monitor the TC flag from the STATREG register in a while loop with a volatile timeout counter.
2. When the TC flag goes high I set the chip select GPIO pin high manually. Note that I print an error message here if the timeout counter has timed out, so it is within the timeout.
3. I see with my logic analyzer that the CS line goes up before the last bit has gone out on the line.
I've tried using the ECSPI_GetStatusFlag and grabbing the value from the register directly.
I've detected that sometimes the timeout counter is non-zero, so the TC flag goes from 0 to 1, but this does not happen every time and is not consistent with when the last bit has gone out on the line.
Note that this happens when I transfer more than the FIFO buffer size: I use a burst length of 8 and have a transfer of 512 bytes. However, to get past the limitation of 32-bit data in the HAL, I need to copy to a temporary 32-bit buffer of length 512 where each element is only filled with a byte.
This code is running on the M7 core.
TC gets set after burst of bits is complete! Looks like in your case burst is 8 bits. So if you fill whole FIFO, data for multiple of bursts, TC is set after first byte is transferred and is keps set until you clear it. If you still need to use FIFO, then you should try increasing burst length to match your transfer size. TC will then set after your real transfer is complete.
Right, you set burst length field accordingly and pack you bytes to single word write to FIFO TX. I'm not sure if byte order is the same on all SOC kinds, you may need to byte swap and align bytes accordingly on your IMX8MP.
Not possible, I think. SAMPLE_PERIOD is again about "bursts", not about nibbles/bytes/words within transfer (burst). What about just lowering SPI frequency?
Max burst length is 4096 bits or 512 bytes. FIFO size is 256 bytes (64 double words), provided your burst length is multiple of 32bits. With burst set to 8 bits, FIFO size is only 64 bytes, because every time your write new doble word to FIFO, only 8 bits are actually used. Since FIFO is shorter than max burst length, you just need to monitor FIFO status and write more data to FIFO when FIFO is ready.