Anyone have experience using the LPSPIx_CFGR0 CIRFIFO bit?

Status
Not open for further replies.

JimKazmer

Well-known member
This sounds awesome... Loading the SPI transmit buffer with a pre-defined message that you want to repeat, setting one bit (CIRFIFO - Circular FIFO Enable) in a configuration register, and then initiate your transfer... The message is repeatedly sent without having to tie-up any interrupts, DMA, polling, or checking status registers. Well, it sounds great to me, but I haven't gotten it to work. It seems like certain error flags are raised that stop the SPI from doing the circular loop. Seems like there are some details missing from Chapter 47 of the "i.MX RT1060 Processor Reference Manual, Rev. 1, 12/2018" (see pages 2933, 2946, 2497).

I'll try to clean up my code and post it... its a bit of a hack of the existing core SPI libraries. I was hoping to reduce it to a sequence of register writes.

Any insights or other information would be appreciated.
 
I am definitely new to this... I got the SPIs CIRFIFO (circular FIFO) working... It is very awesome! My program can setup the SPI, load up to 16x32-bits of data, and automatically keep the remote device(s) up-to-date with a recurring message, which I can change at any time. All that without a single interrupt or DMA transfer. (very nice).

The thing that hung me up, is that I needed to slow down my data writes to the Transmit Data Regisiter (TDR) and the Transmit Command register (TCR). When the manual says "It requires at least three LPSPI functional clock cycles for the transmit command register to update after it is written", it really means it. That requirement must not be uncommon and would explain (many? most?) of the "asm volatile("nop");" statements I see in the core code.
 
Very cool! Can the transmit message be changed on the fly - or at least the bytes 'padded' after the message?
 
Yes, but there are some constraints. The RT1060RM says you should wait for the end of frame (which can be caught with an interrupt). Yet, I think if you can add a new TCR command followed by the new data, and it will start sending that with the circular FIFO. I haven't tried these things yet, I've been playing with the scope getting my message timings where I need them to be. The device I am communicating with needs some idle time between messages, so I am padding my message with 32-zero-bits for this idle period. My entire messages is only 128 bits long, plus the 32-idle-bits, that amounts to 5 32-bit words. On the teensy, the SPI (combined) command&data FIFO is 16 32-bit words, so I have room to add two "buffered" messages.

I will update this post once I learn if I can just queue a new message (asynchronously), or if must add the ISRs to insert a message synchronously.
 
There must be better ways to connect two Teensy's... But this is just too perfect of a technique for updating an Electronic Speed Controller (ESC) using dShot 600/1200/2400 every 28/14/7 microseconds without any interrupts, DMA activity, or polling software in the main loop.

This is what I have learned... If you interrupt an ongoing message (one this is automatically repeating due to CIRFIFO=1) with a new TCR command (which includes the length of the new message) followed by writes to the TDR for the data for the new message (without stopping/disabling the SPI via the LPSPIx_CR), it works most of the time but occasionally will not work due to an error flag being thrown. I had hoped to be able to use the CONT (in CFGR0) and CONTC (in CFGR1) to have the SPI finish the current message (frame) and automatically move to the next queued command/data; however, I haven't been able to get that to work 100% of the time... seems I can get the failure rate down to 10% which is unacceptable for my application.

What I have found that works consistently is to (asynchronously at anytime) disable the SPI via the LPSPIx_CR, reset both the send and receive FIFOs, blindly reset all error flags, then set the TCR, followed by the data (multiple writes to the TDR), and then enable the SPI via the LPSPIx_CR. This requires 9 SPI register writes for my application. This works for me... the asynchronous disabling of the SPI will interrupt existing messages in progress (not a good thing for many applications). However, my data message has a fixed length of 12 bits plus a 4-bit CRC, so an invalid message will be detected and ignored in my situation.
 
Last edited:
Status
Not open for further replies.
Back
Top