Page 3 of 4
Re: SPI driver for KINETIS K20.
Posted: Tue Sep 02, 2014 10:25 pm
by utzig
Applied.
Re: SPI driver for KINETIS K20.
Posted: Wed Sep 03, 2014 1:12 am
by SpaceCoaster
Thanks Fabio
Re: SPI driver for KINETIS K20.
Posted: Sun Sep 21, 2014 5:12 pm
by SpaceCoaster
I have reimplemented the K20x SPI driver using DMA using the following advice as a guide, thanks to fpga_comp for the pointer.
fpga_comp wrote:There is a DMA SPI library for the Teensy 3.X (K20) ...
The upper control words are defaulted to all 0's. None of the fancy hardware SPI chip select stuff can be used. Those are handled in software for asserting/deasserting GPIO pins. You wouldn't care too much about that if you are doing big block of SPI transfer to a single device. You only need to toggle the chip select before and after the DMA.
The implementation uses software to toggle the chip select in the spiSelect() and spiUnselect() functions. 16 bit transfers are supported.
I achieved 2.1 Mbytes/s (13.5 fps) when clearing a 240x320 TFT display using 8 bit transfers and large blocks. Small transfers are probably a bit faster as we now have just one interrupt (DMA RX complete) instead of 3 (TX,RX and EOQ). 16 bit transfers ran at 2.3 Mbytes/s and looked fine on the scope.
I don't think we have lost much (perhaps some fine tuning of slave select timing in hardware) and we have gained a much simpler and faster driver.
Re: SPI driver for KINETIS K20.
Posted: Sun Sep 21, 2014 10:04 pm
by fpga_comp
I got most of my own code (based on STM32F4 SPI and dmaspi) working today, but having issues with _spi_wait_s(spip) in spiSend() not suspend.
I guess you have beaten me to it. Good job! I'll go download your working code and save myself the headaches.

I have attached my dma.c & dma.h which manages DMA channel allocations and their IRQ stubs. It is quick & dirty and could use some formatting/clean up etc. Do whatever you want with the code.
Here is how I use them in my spi_lld_init() inside spi_lld.c instead of hard coding DMA channels and interrupt.
Code: Select all
SPID1.DMA_Rx = DMA_Alloc(FALSE,SPI_DMA_PRIORITY,
(void (*)(void *))spi_lld_serve_rx_interrupt,&SPID1);
SPID1.DMA_Tx = DMA_Alloc(FALSE,SPI_DMA_PRIORITY,
(void (*)(void *))spi_lld_serve_tx_interrupt,&SPID1);
// can't allocate DMA channels!?
if((SPID1.DMA_Rx==DMA_NONE_AVAIL)||(SPID1.DMA_Tx==DMA_NONE_AVAIL))
{
spi_lld_stop(&SPID1);
return;
}
Re: SPI driver for KINETIS K20.
Posted: Sun Sep 21, 2014 10:34 pm
by SpaceCoaster
fpga_comp,
Well I won't make any claims about this being well tested so don't burn your code just yet!
The DMA channel allocator is a good idea, feel free to integrate it into spi_lld.c. It is still a work in progress.
I was planning on tweaking SPI to work well with uGFX. It would be nice to have a way of transferring from one word repeatedly to do color fills (spi_lld_fill(), spi_lld_repeat(), spi_lld_spray() ???). Tectu said it was supported by uGFX, just need to make the SPI do it and integrate it well.
What hardware are you testing with?
Cheers,
Derek
Re: SPI driver for KINETIS K20.
Posted: Sun Sep 21, 2014 10:54 pm
by fpga_comp
One thing I notice is that your DMA SPI code would always turn on Rx DMA. I use the Tx DMA for interrupt as it is always active driving the transfer. I only enable the Rx DMA when it is expecting to receive data to save memory bandwidth.
Good job for the 16-bit transfer!
I am using on a K22 on my own FPGA Computer/Eval board design here:
https://hackaday.io/project/1347The SPI is going to be used for my data path between my ARM and FPGA and for MicroSD, SPI FLASH. At some point, the SPI may have to carry USB packets from the FPGA to the USB port on the ARM, so DMA would help a lot.
I might also look into the SPI and uGFX too.

FPGA computer cores i am interested in have On Screen Display (overlays) for GUI which is a small frame buffer with SPI.
K. C.
Re: SPI driver for KINETIS K20.
Posted: Mon Sep 22, 2014 12:26 am
by SpaceCoaster
I hadn't thought about the memory bandwidth issue. I was more interested in the simplicity of always waiting for the data to cycle through the RX path. Also the I/O hasn't finished until the RX has happened. Is there a danger of starting a new TX before the RX is finished? I see this as more of an issue at low baud rates.
Currently, if I make it any faster then it overruns the TFT display chip! The polled I/O was about 8%% faster and that needed to be slowed down before it would work.
Nice FPGA board, I might get around to playing with FPGAs soon but my primary OS is OSX and the FPGA guys don't play nice with Macs. I like linux but not with a UI.
I have some K22s, I now have an excuse to add them to my testing.
Derek
Re: SPI driver for KINETIS K20.
Posted: Mon Sep 22, 2014 12:56 am
by utzig
Nice FPGA board, I might get around to playing with FPGAs soon but my primary OS is OSX and the FPGA guys don't play nice with Macs. I like linux but not with a UI.
Derek,
Here's how I run Xilinx's ISE on my Mac inside Linux on Parallels:
http://fabioutzig.com/2013/04/07/runnin ... llels.htmlAlso, I do almost all Verilog/VHDL synth in the command line. Check the Makefile on this project:
https://github.com/utzig/pong-nexys2Fabio Utzig
Re: SPI driver for KINETIS K20.
Posted: Mon Sep 22, 2014 12:58 am
by fpga_comp
Oops. Using the Tx DMA is why my code was acting up! So much for that idea. I am going to try something else and if that fails, I'll use Rx DMA.
Basically because there is Tx FIFO in the SPI. Once it is filled, Tx DMA thinks it is done when the SPI is still sending data. That messed up the timing of the spiUnselect().
-- Edit --
I tried some of the SPI0 interrupts and couldn't find a working solution. Rx DMA interrupt is the right solution.
This is captured on my K22 setup.

K. C.
Re: SPI driver for KINETIS K20.
Posted: Mon Sep 22, 2014 1:23 am
by SpaceCoaster
Fabio,
Thanks, configured Linux and downloading ISE...