Knowing when last bit has been transferred (ECSPI on i.MX8MP)

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Knowing when last bit has been transferred (ECSPI on i.MX8MP)

Jump to solution
3,520 Views
aadvark
Contributor I

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? 

Labels (1)
0 Kudos
Reply
1 Solution
3,423 Views
kef2
Senior Contributor V

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.

View solution in original post

0 Kudos
Reply
16 Replies
3,322 Views
pengyong_zhang
NXP Employee
NXP Employee

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

0 Kudos
Reply
3,244 Views
aadvark
Contributor I
See the comment below the marked solution. I ended up with SMC = 0, which proved more reliable (and more aligned with what the reference manual outlines in the illustrations).

I'm not completely sure that the ECSPI HAL is timing safe with how it is set up now. It might need to be rewritten to use SMC=0 as well.
0 Kudos
Reply
3,348 Views
pengyong_zhang
NXP Employee
NXP Employee

Hi @aadvark 

I've discussed this with our internal SPI team. XCH is used to trigger a check to see if the data transfer is complete and nothing else.

B.R

0 Kudos
Reply
3,347 Views
aadvark
Contributor I
Hello @pengyong_zhang,

I have two questions then:

1. Does that mean that one should have SMC cleared?
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.

Currently the HAL uses SMC = 1 and does not check the XCH bit.

0 Kudos
Reply
3,341 Views
kef2
Senior Contributor V

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. 

 

0 Kudos
Reply
3,416 Views
pengyong_zhang
NXP Employee
NXP Employee

HI @kef2 @aadvark 

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

0 Kudos
Reply
3,407 Views
aadvark
Contributor I
Hello @pengyong_zhang,

In the ECSPI HAL, the TC interrupt is not used. I've polled XCH as well after the callback from the HAL to see if that fixed my issue but I'm still seeing the same problems.

Having some more internal information would be really beneficial, especially when it comes to the burst length and the interoperability with the transfer complete flag as discussed in this post.

Thank you again.
0 Kudos
Reply
3,430 Views
kef2
Senior Contributor V

STATREG.TC flag can be used to indicate transfer is complete. You need to clear it writing '1' to ir prior to starting transfer

0 Kudos
Reply
3,427 Views
aadvark
Contributor I
Yes, forgot to mention that. We clear it before calling ECSPI_MasterTransferNonBlocking by writing a 1 to that bit.
0 Kudos
Reply
3,449 Views
pengyong_zhang
NXP Employee
NXP Employee

Hi @aadvark 

Can you tell me how you monitor the change of the register value in real time? I'll be working on this request with you on my site.

B.R

0 Kudos
Reply
3,431 Views
aadvark
Contributor I

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.

0 Kudos
Reply
3,424 Views
kef2
Senior Contributor V

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.

0 Kudos
Reply
3,246 Views
aadvark
Contributor I
This is what I ended up doing in the end (which is somewhat more aligned with what is specified in the reference manual):

Pre-step: clear SMC bit

1. Clear CS via GPIO

In loop until all bytes are transferred:
2. Fill TX FIFO up to max of TX FIFO size (if remaining transfer size is bigger than the FIFO size) or the remaining transfer size
3. Clear TC from STATREG
4. Set burst length to amount of bits filled in TX FIFO
5. Enable TC interrupt
6. Set XCH = 1
7. Wait for TC interrupt
8. Poll XCH until XCH = 0
9. Read out RX data from RX FIFO
10. Go to step 2 if there still are remaining bytes in the transfer

11. Set CS via GPIO

This has worked well with transfers which are smaller than the TX FIFO size and transfers that are greater than the TX FIFO size. I have not seen any timing issues so far with this method. This is different from how ECSPI HAL does it (with SMC = 1), but as said, I've found this to be more stable in terms of timinig and knowning when the last bit has gone out on the line.
0 Kudos
Reply
3,236 Views
aadvark
Contributor I
Note that this method largely circumvents the use of the ECSPI HAL.
0 Kudos
Reply
3,417 Views
aadvark
Contributor I
That might be the source of the problem. I see that I've misread what burst length actually is.

Then I have two questions:

1. How would one control the world length in this case? Say I want to transfer 3 bytes. I set the burst length to 0x17 to match 24 bits. The device on the line expects a "pause" between each byte, so I adjust the SAMPLE_PERIOD to add wait states, but how would the hardware know when to put in the wait states?

2. Does this mean, at least for a non-DMA case, that we have a maximum transfer size of 128 words? If one goes over that there is not a reliable way to get a transfer complete flag?

Thank you again, this has cleared up some confusion.
0 Kudos
Reply
3,400 Views
kef2
Senior Contributor V
  • How would one control the world length in this case? Say I want to transfer 3 bytes. I set the burst length to 0x17 to match 24 bits.

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. 

  • The device on the line expects a "pause" between each byte

Not possible, I think. SAMPLE_PERIOD is again about "bursts", not about nibbles/bytes/words within transfer (burst). What about just lowering SPI frequency? 

 

  • Does this mean, at least for a non-DMA case, that we have a maximum transfer size of 128 words? If one goes over that there is not a reliable way to get a transfer complete flag?

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.

0 Kudos
Reply