Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
New Contributor II
2,119 Views

Using The SPI Port Without the mraa Library Problems

Using the Edison with the mini breakout board. I am trying to get the fastest possible SPI speeds i can.

I have a 7" capacitive touch LCD connected to the board through level shifters and using the mraa lib i have it working.

But its to slow for real use. The cause is that there is a significant delay between CS to CS in writing the data out, and it's not that the SPI clock speed is to slow.

I have this same LCD on the RPI CM, and works just fine there. The CS to CS delays on the RPI are very minimal.

mraa has now been fixed to send 16bit, which helped but now the delays are nagging.

So i though i would skip the mraa lib, and go direct. In doing so i found a very strange issue with multiple writes.

The reason i say this is because i have tried the exact same following code on the Edison, RPI, Arietta G25, & ODROID-U3. The only change between boards was made was

" mcp3008Spi a2d("/dev/spidev5.1", SPI_MODE_0, 100000, 8); " as the location is different for each them.

Using the scope on the RPI, Arietta G25, & ODROID-U3 board i see that 3 bytes are sent out.

When i try the Edison only one gets sent. Moreover the printf reports back that 3 were sent, which were not.

Here is the code used that was used:

# include

# include

# include

# include

# include

# include

# include

# include

# include

# include

# include

# include

# include "mraa.h"

class mcp3008Spi{

public:

mcp3008Spi();

mcp3008Spi(std::string devspi, unsigned char spiMode, unsigned int spiSpeed, unsigned char spibitsPerWord);

~mcp3008Spi();

int spiWriteRead( unsigned char *data, int length);

private:

unsigned char mode;

unsigned char bitsPerWord;

unsigned int speed;

int spifd;

int spiOpen(std::string devspi);

int spiClose();

};

using namespace std;

/**********************************************************

* spiOpen() :function is called by the constructor.

* It is responsible for opening the spidev device

* "devspi" and then setting up the spidev interface.

* private member variables are used to configure spidev.

* They must be set appropriately by constructor before calling

* this function.

* *********************************************************/

int mcp3008Spi::spiOpen(std::string devspi){

int statusVal = -1;

this->spifd = open(devspi.c_str(), O_RDWR);

if(this->spifd < 0){

perror("could not open SPI device");

exit(1);

}

statusVal = ioctl (this->spifd, SPI_IOC_WR_MODE, &(this->mode));

if(statusVal < 0){

perror("Could not set SPIMode (WR)...ioctl fail");

exit(1);

}

statusVal = ioctl (this->spifd, SPI_IOC_RD_MODE, &(this->mode));

if(statusVal < 0) {

perror("Could not set SPIMode (RD)...ioctl fail");

exit(1);

}

statusVal = ioctl (this->spifd, SPI_IOC_WR_BITS_PER_WORD, &(this->bitsPerWord));

if(statusVal < 0) {

perror("Could not set SPI bitsPerWord (WR)...ioctl fail");

exit(1);

}

statusVal = ioctl (this->spifd, SPI_IOC_RD_BITS_PER_WORD, &(this->bitsPerWord));

if(statusVal < 0) {

perror("Could not set SPI bitsPerWord(RD)...ioctl fail");

exit(1);

}

statusVal = ioctl (this->spifd, SPI_IOC_WR_MAX_SPEED_HZ, &(this->speed));

if(statusVal < 0) {

perror("Could not set SPI speed (WR)...ioctl fail");

exit(1);

}

statusVal = ioctl (this->spifd, SPI_IOC_RD_MAX_SPEED_HZ, &(this->speed));

if(statusVal < 0) {

perror("Could not set SPI speed (RD)...ioctl fail");

exit(1);

}

return statusVal;

}

/***********************************************************

* spiClose(): Responsible for closing the spidev interface.

* Called in destructor

* *********************************************************/

int mcp3008Spi::spiClose(){

int statusVal = -1;

statusVal = close(this->spifd);

if(statusVal < 0) {

perror("Could not close SPI device");

exit(1);

}

return statusVal;

}

/********************************************************************

* This function writes data "data" of length "length" to the spidev

* device. Data shifted in from the spidev device is saved back into

* "data".

* ******************************************************************/

int mcp3008Spi::spiWriteRead( unsigned char *data, int length){

struct spi_ioc_transfer spi[length];

int i = 0;

int retVal = -1;

// one spi transfer for each byte

for (i = 0 ; i < length ; i++){

spi[i].tx_buf = (unsigned long)(data + i); // transmit from "data"

spi[i].rx_buf = (unsigned long)(data + i) ; // receive into "data"

spi[i].len = sizeof(*(data + i)) ;

spi[i].delay_usecs = 0 ;

spi[i].speed_hz = this->speed ;

spi[i].bits_per_word = this->bitsPerWord ;

spi[i].cs_change = 0;

}

retVal = ioctl (this->spifd, SPI_IOC_MESSAGE(length), &spi);

if(retVal < 0){

perror("Problem transmitting spi data..ioctl");

exit(1);

}

return retVal;

}

/*************************************************

* Default constructor. Set member variables to

* default values and then call spiOpen()

* ***********************************************/

mcp3008Spi::mcp3008Spi(){

this->mode = SPI_MODE_0 ;

this->bitsPerWord = 8;

this->speed = 1000000;

this->spifd = -1;

this->spiOpen(std::string("/dev/spidev0.0"));

}

/*************************************************

* overloaded constructor. let u...

0 Kudos
16 Replies
Highlighted
Employee
28 Views

Hi mikemoy,

I'd suggest you to take a look at this post /message/253675# 253675 https://communities.intel.com/message/253675# 253675 . Also if you do not want to use mraa library and alternative would to do it on the Linux side instead of a sketch and see if that improves the performance.

Regards

Sergio

Highlighted
New Contributor II
28 Views

Intel_Alvarado wrote:

Hi mikemoy,

I'd suggest you to take a look at this post /message/253675# 253675 https://communities.intel.com/message/253675# 253675 . Also if you do not want to use mraa library and alternative would to do it on the Linux side instead of a sketch and see if that improves the performance.

Regards

Sergio

I am not using a sketch. I am using the IoT with Eclipse.

0 Kudos
Highlighted
28 Views

I gave that code a run and I too see that there is only one byte being chucked out. ( In my pic I have MOSI and MISO in a loop for fun(?))

Whilst on the Raspberry Pi, it does indeed work fine

This highlights an issue with the spi device on the Edison. I will have a deeper investigation to find what is going wrong.

But for something for now, that may or not help you.

The typical behaviour that mraa currently has is to put multiple data into one transfer. I tweaked the function you posted.

struct spi_ioc_transfer spi;

spi.tx_buf = (unsigned long) data;

spi.rx_buf = (unsigned long) data;

spi.len = length;

spi.delay_usecs = 0 ;

spi.speed_hz = this->speed ;

spi.bits_per_word = this->bitsPerWord ;

spi.cs_change = 0;

retVal = ioctl (this->spifd, SPI_IOC_MESSAGE(1), &spi);

Doing so gets all three bytes out on the bus. But it is seen as three transactions, not what is wanted. I currently don't have a solution that works with the current spi dev

Highlighted
New Contributor II
28 Views

Thanks for taking the time to check into it.

0 Kudos
Highlighted
28 Views

Could you let us know what version your Edison has installed.

cat of /etc/version

0 Kudos
Highlighted
New Contributor II
28 Views

edison-weekly_build_68_2014-09-08_13-49-07

0 Kudos
Highlighted
Valued Contributor III
28 Views

FYI - I am also following along here (as I mentioned also on github). I am running:

edison-rel1-maint-weekly_build_16_2014-10-14_14-56-19

0 Kudos
Highlighted
28 Views

Taking a look at the release notes for the latest software release for the Edison, many of the issues seem to have been addressed.

http://downloadmirror.intel.com/24389/eng/edison-image-rel1-maint-rel1-ww42-14.zip http://downloadmirror.intel.com/24389/eng/edison-image-rel1-maint-rel1-ww42-14.zip

Please give this ago.

0 Kudos
Highlighted
Valued Contributor III
28 Views

I have been running with this one. Note: maybe the first while it was not really this one, as when I thought it installed, it did not clear the contents of the drive... So I rebuilt sources and installed, Tried some stuff like try to get the SPI to run at 8mhz, it faulted, then went back and used the OTA, but this time used 7zip to extract files and this time it cleared the contents again... More details of what I am looking at is in the thread:

Right now, I am verifying that I can run an unmodified version of the sources, so I deleted build directory and am building again. Trying a hint from book to speed up the build of setting number of tasks to 2*processor cores, will see how much this speeds things up...

But with my current stuff, running on clean build...

You can see the clock is running at 6.25mhz, that the output of an actual byte is taking something like 1.2us, then there is a gap of about 1.56us...

0 Kudos
Highlighted
New Contributor II
28 Views

KurtE, though i have the same issue, its the gap that is killing me. What kit are you trying this all on? is it the Arduino or the Edison mini ?

0 Kudos
Highlighted
Valued Contributor III
28 Views

It is the Arduino board. Note: I am running this with MRAA stuff compiled locally, not the Arduino version... As I mentioned in other thread, I think I see where the 6.25mhz is coming from, first attempt to make it faster faulted out...

I may go ahead and get another module as well as to do comparisons.

0 Kudos
Highlighted
Employee
28 Views

Hi mikemoy;

Were you able to use the SPI port without problems?

Regards;

CMata

0 Kudos
Highlighted
New Contributor II
28 Views

CMata_Intel wrote:

Hi mikemoy;

Were you able to use the SPI port without problems?

Regards;

CMata

I can use it without problems. I mean it does work, its just that it's far to slow to use it for what i need to. The CS - CS delay is far to great. But i know they are working on it so i am just waiting to see.

Highlighted
New Contributor II
28 Views

Hi Mikemoy,

With the latest libmraa, Version: v0.5.2-37-g148c22f, you should be able to get up to 4 bytes without any CS toggle in between.

When I set 25MHz for SPI, "mraa_spi_frequency(spi,25000000);"

I measure SCLK is only 6.5MHz on my scope. ( As reference the OSC out measures correctly at 19.2 MHz)

The says:

4.4 SPI interface

An SPI interface is available on pins 51, 53, 55, 57, and 59. The interface has two available chip selects.

• In a single-frame transfer, the SoC supports all four possible combinations for the serial clock phase and polarity.

• In multiple frame transfer, the SoC supports SPH=1 and SPO= 0 or 1.

• The SoC may toggle the slave select signal between each data frame for SPH=0.

• 25 MHz Master mode, 16.67 MHz slave mode.

Which clock is 25MHz? The edison internal clock ? or output SCLK ?

Can anyone please confirm if SCLK is supposed to be 25MHz?

0 Kudos
Highlighted
Beginner
28 Views

Hi,

I am facing the same issue here: CS is pulled up after end of each byte and big delays between bytes and transfers.

I am running Edison on mini board with edison-rel1-maint-weekly_build_16_2014-10-14_14-56-19 and MRAA 0.5.4. Pins J17.10-J17.12 respond correctly to mraa_spi_write_buf(context, data, count)

function, but data is not being send as single transfer, but after end of each byte CS is pulled up. This is my first obstacle as the slave expects 2-4 bytes in the single CS frame.

Another issue: I am using 4MHz clock, MODE1, one byte takes 2us to send. Between first and second byte CS stays high for ~12us while the gap between the rest of bytes is 0.75us.

And the third and issue: the gab between consecutive mraa_spi_write_buf(context, data, count) calls varies 250-500us.

Thanks,

Taivo.

0 Kudos
Highlighted
Beginner
28 Views

Hello Mikemoy,

I am also facing the same issue. SPI CS line is toggling at 50Hz even with latest libmraa. Did you find any solution to Intel Edison SPI ?

Many other forum are saying, its hardware issue and cannot be fixed.

Your help will be appreciated. Waiting for your response.

Regards,

Pratik B

0 Kudos