Hello everyone,
I had been working on running spi using mqx drivers. but i am interested in knowing how does MQX SPI polled/ interrupt drivers really work . I mean does interrupt driver uses dma for transfers,does polled driver allows simultaneous read and write, does these drivers toggle chip select themselves, which one is better in performance etc.
As per my knowledge i believe they work in this manner.
1 : Use fopen to open ( spi/ ispi driver , with desired flags )
2: ( Optional ) Set clock speed, transfer mode , endianess using ioctl .
3: Use fwrite/ fread to read number of characters
4: (Optional ) perform simultaneous read and write using ioctl.
4: Close the device using fclose
I have some confusions :
First of all i am using fwrite / fread to write and read characters but i miss the 1st status character byte that comes from slave.I dont know how to get that byte in order.
Secondly , does SPI_READ_WRITE_STRUCT with ioctl use dma to transfer the bytes simultaneously , and is it available for both polled and interrupt mode?
It is worthwhile to use MQX SPI driver rather then using direct spi registers.
I am working on writing/porting wireless modbus for mqx using cc1101 radio, therefore i need to know these details about spi
I shall be very grateful , if someone guide me a little
Solved! Go to Solution.
Hello Muhammad,
as SPI is physically always full-duplex the half duplex behavior in master mode is:
write sends out data to MOSI, data on MISO is ignored, no data is received during write!
read stores data from MISO, shifting out zeros (or configurable pattern in 4.0 drivers) to MOSI
While full-duplex behavior in master mode:
fread sends out buffer provided to it while overwriting it with data being received, that is, it makes use of buffer content which is just discarded in a typical POSIX read - this is a non-standard extension.
fwrite behaves the same as in half-duplex. It cannot behave the same way as read, because there is no buffer to store the received data to - buffer provided to write operation is const.
For true full-duplex operation please use IO_IOCTL_SPI_READ_WRITE.
Please note that there are no background buffers in polled driver, and expecially the new SPI drivers avoid unnecessary copy overhead by directly using application supplied buffer.
Because of this there is no possibility to perform full duplex transfer by calling write first and then read to get data received during previous write. Such feature would be pretty nice and read/write would behave the standard way, but remember, we are in embedded, so unnecessary memory usage and copying is a bad idea in general.
Concerning performance of driver vs register access: direct register acces would certainly perform better compared to DSPI driver included in 3.8 and earlier However DSPI driver went through optimization in 3.8.1 so for larger blocks of data it should be comparable to direct register access. The driver in upcoming 4.0 is in addition able to use interrupts instead of busy loop waiting.
I suggest you using 3.8.1 DSPI driver (polled) until 4.0 is out. The transition to the DSPI driver included in 4.0 should be pretty smooth.
There is lack of documentation about SPI usage - this is also going to be improved in 4.0.
Pavel
Hi Muhammad,
I`m trying to do a SPI communication with CC1101 using MQX but with no success and I found your question.
I have it working on SH08 quite well but when it comes to MQX I cant read rxfifo from transceiver !
the write byte operation works fine, but I cant read data from it !
have you already accomplished that in MQX?
Hello
I am new to SPI, I am using MQX 4.0.1. I am able to read Device ID and manufacturer ID from the SPI module.
But my further Write and Read from SPI seems to be not working. I use the SPI example from mqx. I am working on
a custom board with MK60DN512VLL10 MCU on board. In init_gpio.c, I changed DSPI2 code as follows,
pctl = (PORT_MemMapPtr)PORTB_BASE_PTR;
pctl->PCR[20] = PORT_PCR_MUX(2); /* DSPI2.PCS0 */
pctl->PCR[21] = PORT_PCR_MUX(2); /* DSPI2.SCK */
pctl->PCR[22] = PORT_PCR_MUX(2); /* DSPI2.SOUT */
pctl->PCR[23] = PORT_PCR_MUX(2); /* DSPI2.SIN */
H/W signals are fine that we have checked them with scope.
and example output is as folows:-
0xbf 0x48 0xbf 0x48
Read memory status ... 0x0c
Enable write latch in memory ... OK
Read memory status ... 0x0e
Write unprotect memory ... OK
Enable write latch in memory ... OK
Read memory status ... 0x0e
Write unprotect memory ... OK
Enable write latch in memory ... OK
Read memory status ... 0x0e
Erase whole memory chip:
Read memory status ... 0x0c
Erase chip ... OK
Enable write latch in memory ... OK
Read memory status ... 0x0e
Write byte 0xba to location 0x000000f0 in memory ... done 0xba
Read memory status ... 0x0c
Read byte from location 0x000000f0 in memory ... 0xff
Byte test ... ERROR
Getting statistics:
Rx packets: 16
Tx packets: 49
This is what I get in the console ser port. "0xbf 0x48 0xbf 0x48" is the device ID i get when read.
NOTE: In our H/W ChipSelect and WriteProtect pins of the slave device are pulled up so It always remain High.
Please help me with this. What does "Callback" and "WP_HOLD" do? and is it need to be programmable to make SPI work?
Hi chandra,
I did the same and it works nicely. :smileyhappy:
Hi CHANDRA,
What kind of chip is that SPI module - memory of some kind by the clues in your message?
I do not know what chip the id 0xbf 0x48 identifies.
If it is SRAM or MVRAM memory, then I have no further help for you. (Other than to mention that the WP_HOLD pin - if on your chip - should be held inactive)
If it happens to be Flash memory of some kind, then you likely cannot just "write" data to memory.
You have to go through the process of "programming" the data into the memory - a process that takes a number of writes (commands) to the chip.
Hello Stephen
My SPI's part number is SST25VF040B, a 512kB spi and it is a Flash memory.
I gone through its data sheet and found "commands" to write, read, read status registers and many more.
I have got it working now, I use Auto Address Increment command to program it.
Limitation I have is, before writing to any location it should be in erased state(0xFF) and to erase it has
only 4kB, 32kB and 64kB sector erase commands. But for my application a word erase would have been more effective.
Anyway now I use 4kB erase sectors and developed my application on that.
Thank you
You are welcome.
And should I say it in Tamil? :smileyhappy:
Dear Muhammad,
please do not use interrupt driver in any case. The behavior of the interrupt SPI driver is very different to the polled one.
The SPI drivers present in MQX 3.8.1 are considered legacy and upcoming MQX 4.0 is going to contain brand new SPI driver framework with API very similar to the current polled driver but includes new features like concurrent access from multiple tasks including automatic CS and transfer parameter switching, configurable dummy patter for half duplex read, etc.
The new driver framework includes support for DSPI module, covering most of the MCUs supported by MQX. (Kinetis, PX series).
Concerning your questions:
- DMA is supported only by legacy interrupt DSPI driver and only for Kinetis family. This driver is not recommended for a new design.
- new DSPI driver in upcoming MQX 4.0 is not divided to interrupt and polled one, there is only a single driver, however, it is capable of using interrupts to reduce CPU load.
- SPI_READ_WRITE_STRUCT performs simultaneous (full-duplex) transfer of data, no matter if using DMA or not
- If you are missing the first status character, please have a look at the data transfer diagrams in the documentation of the slave device. Is is possible that you may need to use duplex read/write for this.
- concerning you question whether to use SPI driver or not: In my opinion it is a good idea to use the new SPI drivers for applications where the driver is able to accomplish the given job. If the application has special requirement and needs to use some specific feature of the SPI module, then go for the register access, otherwise use the driver.
Best regards,
Pavel
I am doing spi interface between Two TOWER Board of K60 of MQX 4.0 ,In that Data is not recieved plz help me
Thank you pavel for giving an insight on mqx spi and for answering my queries . I was using mqx 3.7 spi driver and was experimenting with (full duplex communication mode ) .
Regarding byte miss problem :
I was using fwrite and fread calls to write and read bytes and was unable to comprehend how do they provide full duplex communication until recently i came across a similar kind of post discussing the byte miss issue. Its the fread that does it.
spifd = fopen ("spi0:", (pointer)(SPI_FLAG_FULL_DUPLEX))
buffer[0] = BYTE_TRANSMITTED;
result = fread (buffer, 1, 1, spifd);
// buffer[0] == BYTE_RECEIVED;
If fread has the capability to write and read a buffer at the same time, fwrite should work similarly , but i highly suspect its not the case. I tried using fwrite and fread but results were different. I was not able to find this information in mqx documentation. I am also looking at slave documentation in this regard.
Yes , i believe interrupt driver works very differently and using (polled) driver is alright as long as application has no special requirements. I am also in favor of using driver as compared to using direct register access if it does not require any special spi feature . I would try to work on it too and see how much difference does it make in terms of performance.
Regards
Hello Muhammad,
as SPI is physically always full-duplex the half duplex behavior in master mode is:
write sends out data to MOSI, data on MISO is ignored, no data is received during write!
read stores data from MISO, shifting out zeros (or configurable pattern in 4.0 drivers) to MOSI
While full-duplex behavior in master mode:
fread sends out buffer provided to it while overwriting it with data being received, that is, it makes use of buffer content which is just discarded in a typical POSIX read - this is a non-standard extension.
fwrite behaves the same as in half-duplex. It cannot behave the same way as read, because there is no buffer to store the received data to - buffer provided to write operation is const.
For true full-duplex operation please use IO_IOCTL_SPI_READ_WRITE.
Please note that there are no background buffers in polled driver, and expecially the new SPI drivers avoid unnecessary copy overhead by directly using application supplied buffer.
Because of this there is no possibility to perform full duplex transfer by calling write first and then read to get data received during previous write. Such feature would be pretty nice and read/write would behave the standard way, but remember, we are in embedded, so unnecessary memory usage and copying is a bad idea in general.
Concerning performance of driver vs register access: direct register acces would certainly perform better compared to DSPI driver included in 3.8 and earlier However DSPI driver went through optimization in 3.8.1 so for larger blocks of data it should be comparable to direct register access. The driver in upcoming 4.0 is in addition able to use interrupts instead of busy loop waiting.
I suggest you using 3.8.1 DSPI driver (polled) until 4.0 is out. The transition to the DSPI driver included in 4.0 should be pretty smooth.
There is lack of documentation about SPI usage - this is also going to be improved in 4.0.
Pavel
Pavel,
I have a project using a Kinetis K60N512 using the interrupt SPI driver "ispi2:" with MQX 3.8.0 communicating with a CS5532 A2D. This is working fine for my project. Most of my transfers are using the ioctl IO_IOCTL_SPI_READ_WRITE.
Could you explain more about why you recommend not to use the interrupt driver?
Thanks,
Dear Don,
Interrupt driver may defer the transfer requested by read or write and perform it in the background, however, there is no notification that the requested transfer is finished, which means that application performing read on an ispi device typically has to do polling and repeat the read operation until it gets all desired data. This way the ispi driver design just moves polling from driver to the application which means it is even less efficient.
And by the way IO_IOCTL_SPI_READ_WRITE does not use interrupts at all, it always performs polling.
For the reasons above the SPI drivers are completely revised in upcoming release, single API, no matter if the driver is internally using interrups, DMA or just polling.
Pavel
Pavel and Bryan,
Thank you very much. I will revise this code. I am looking forward to MQX 4.0. Any idea when that will be released?
Regards,
Don
Don, MQX 4.0 is planned to be out in December 2012, it is going into beta phase right now.
Look at the transfer on a scope - at around 5 Mhz there is more dead-time between bytes than the transfer of the byte takes (i.e. severe diminishing returns on baud rate increases).