I seem to have encountered a bug in the DMA mode SPI where it only transfers the first five bytes of data and still reports a 'success'.
To reproduce the issue I wired the SPI0_out to SPI0_in (connect pins 11 and 16 on the J1 header) and created the following test project:
Create new Kinetis SDK 1.x Project
Select the K22FN512xxx12 processor (eventually I will be using a custom board so I didn't want to start with all the premade board files)
Select Processor Expert and hardware configuration
From the Components Library add fsl_dspi and fsl_debug_console to the project.
Open the fsl_clock_manager in the component inspector:
In properties>clock management>clock settings>clock sources> Select External Oscillator 0 and then external crystal as an additional clock source
In properties>clock management>clock settings>clock configurations>MCG settings select PEE mode and MCG output to be 80 MHz, Reference clock source should be 'External Clock'
In properties>clock management>clock settings>clock configurations>System Clocks set core clock and bus clock to 40 MHz, External bus clock to be 20 MHz and the Flash clock to be 10 MHz
Open fsl_dspi in the component inspector:
In properties select "device: SPI0" and "component mode: DMA"
In properties>configuration list set the clock speed to be 20 MHz
In properties>pins:
input: CMP0_IN1/PTC7/SPI0_SIN/USB_SOF_OUT/I2S0_RX_FS/FBa_AD8
output: CMP0_IN0/PTC6/LLWU_P10/SPI0_SOUT/PDB0_EXTRG/I2S0_RX_BCLK/FBa_AD9/I2S0_MCLK
clock: PTC5/LLWU_P9/SPI0_SCK/LPTMR0_ALT2/I2S0_RXD0/FBa_AD10/CMP0_OUT/FTM0_CH2
chip select: ADC0_SE4b/CMP1_IN0/PTC2/SPI0_PCS2/UART1_CTS_b/FTM0_CH1/FBa_AD12/...
Open fsl_debug_console in the component inspector:
Device: UART1
RxD: ADC1_SE5a/PTE1/LLWU_P0/SPI1_SOUT/UART1_RX/I2C1_SCL/SPI1_SIN
TxD: ADC1_SE4a/PTE0/CLKOUT32K/SPI1_PCS1/UART1_TX/I2C1_SDA/RTC_CLKOUT
Whew! Ok now generate processor expert code and within your generated main.c put the following code where it says "put your code here":
/* Write your code here */ /* For example: for(;;) { } */ uint8_t spiDataOut[128]={0},spiDataIn[128]={0}; //initialize data buffers for(int i = 0; i<128; i++) { //put nonzero values in buffer that will be sent spiDataOut[i] = i; } DSPI_DRV_EdmaMasterTransferBlocking(dspiCom1_IDX, NULL, spiDataOut, spiDataIn, 128, 10000); for(int j = 0; j < 128; j++) { debug_printf("\r\nsent: %d received: %d\r\n", spiDataOut[j], spiDataIn[j]); //print data } debug_printf("\n\n"); /*** Don't write any code pass this line, or it will be deleted during code generation. ***/
The terminal data then looks like this:
sent: 0 received: 0
sent: 1 received: 1
sent: 2 received: 2
sent: 3 received: 3
sent: 4 received: 4
sent: 5 received: 0
sent: 6 received: 0
sent: 7 received: 0
sent: 8 received: 0
sent: 9 received: 0
sent: 10 received: 0
sent: 11 received: 0
...
sent: 127 received: 0
If you do the same thing with interrupt mode SPI:
Open fsl_dspi in the component inspector and then change component mode to Interrupt
Change line 7 in the code above to:
DSPI_DRV_MasterTransferBlocking(dspiCom1_IDX, NULL, spiDataOut, spiDataIn, 128, 10000);
sent: 0 received: 0
sent: 1 received: 1
sent: 2 received: 2
sent: 3 received: 3
sent: 4 received: 4
sent: 5 received: 5
sent: 6 received: 6
sent: 7 received: 7
sent: 8 received: 8
sent: 9 received: 9
sent: 10 received: 10
sent: 11 received: 11
...
sent: 127 received: 127
Additionally I have tried with the default clock settings and SPI running at only 10 MHz -- same issue.
The data transfer call always returns a zero which indicates a successful transfer, for both the successful interrupt based example and the not working dma based example.
I also tried with a non blocking transfer and checking the status until it no longer says 'busy' before moving on to the rest of the program, this would return busy once and say it had sent 5 bytes and then return 'success' and say it had then transferred all 128 yet only five were correct, the rest were zeros as above.
I also tried playing around with the timeout parameter for the transfer method which didn't appear to have any effect on the number of bytes which were transferred.
Original Attachment has been moved to: dma_bug.zip
Alice,
According to the post the problem exists with a spi clock at 10mhz as well, could you post your project for verification?
I have duplicated the problem with all clock frequencies including this one:
core clock at 80mhz and
bus clock at 40mhz
spi clock at 20mhz
From K22P121M120SF7.pdf The SPI clock is well within the capabilities of the part, and this is evident since it functions properly in interrupt mode. The issues seems to be with the DMA mode.
3.8.3 DSPI switching specifications (limited voltage range)
Frequency of operation 30 MHz
DSPI_SCK output cycle time (min) = 2 x tBUS
Hello ,
The clock rate is slow use DMA than interrupt(cpu), the clock rate range in the Reference Manual
is use the CPU not the DMA.
you can test the 4MHZ, it can work well .
Yes, in your project , when use the 10MHZ, it still have two data is wrong , sorry for my mistake.
Hope it helps
Alice
Hey Alice,
Thank you for looking into the issue. Where are the SPI clock ranges specified? All the manual says is:
"The SPI module is clocked by the internal bus clock (the DSPI refers to it as system clock). The module has an internal divider, with a minimum divide is two. So, the SPI can run at a maximum frequency of bus clock/2."
and
"In VLPR and VLPW modes the max SPI_CLK frequency is 2MHz."
As we are not using low power mode it seems we should be able to run DMA SPI at 20 MHz since our our bus clock is 40 MHz.
Hello Rose,
For the main speed limit is the DMA speed.
About the detail information please check the 22.4.4.3 eDMA performance example of Reference Manual .
Then after calculate , we can see the clock rate limited is 6MH .
Hope it helps
Have a great day,
Alice
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Alice, could we please get an update on this?
Hello,
"A 20 mhz 8 bit spi will generate request to the DMA at 20mhz/8bit = 2.5Mreq/sec which is well within the 6Mreq/sec listed here.", yes, you said is right , thank you !
About your project ,i check one time and one time , you siad your core clock is 80Mhz, while
on the project , you configure it to 40MHZ, this is the reason :
I have test i on my side , after change it to 80MHZ, it can work well .
Have a great day,
Alice
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Thanks Alice, I've tried it with 80 and couldn't make it work! Would you mind posting a project that works so we can see what the difference is?
Dear,
I just change the system clock on your project.
On your project you send to me , the system clock is not 80M, it is 40M.
Ok , attach the project i changed , and also the result.
Hope it helps
Have a great day,
Alice
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Thanks Alice_Yang
The data you provided is request per seconds, not bits per second...
A 20 mhz 8 bit spi will generate request to the DMA at 20mhz/8bit = 2.5Mreq/sec which is well within the 6Mreq/sec listed here.
Looking at the transfer on the oscilloscope, the system has no problems keeping up with the outgoing stream at 20 mhz which we can verify. The problem is the incoming data is not getting filled in.
Hello Rose,
I have check and test your project on my side,
the clock of SPI is too high , i change it to 10M,
then it can work well .
Hope it hleps
Alice