LinuxQuestions.org
Register a domain and help support LQ
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 01-19-2011, 05:19 AM   #1
Lobinho
Member
 
Registered: May 2010
Distribution: Ubuntu
Posts: 67

Rep: Reputation: 17
SPI program using c++


Hi all,

I'm trying to build a spi program using c++. I'm able to perform half-duplex transfers using the read/write functions, it works perfectly.

Now I need to perform a full-duplex transfer, but I'm facing some problems.
When I try to receive more than one byte, the slave returns to me only one byte.

Ex:

I send: FF FF FF FF FF
The slave must return: 03 02 00 13 04

But what is happening is:

1st Transfer:
tx: FF FF FF FF FF
rx: 03 00 00 00 00

2nd Transfer:
tx: FF FF FF FF FF
rx: 02 00 00 00 00

3rd Transfer:
tx: FF FF FF FF FF
rx: 00 00 00 00 00

...
I need to perform 5 transfers to read my 5 bytes... :/

It's so strange, it's look like the spi driver try to receive only one byte.

I based my code on an example code found on kernel Docs (the complete file is attached).

The transfer routine is here:
Code:
static void transfer(int fd)
{
	int ret;
	uint8_t tx[] = {
		0xFF, 0xFF, 0xFF, 0xFF, 0xFF 
	};
	uint8_t rx[ARRAY_SIZE(tx)] = {0, };
        printf("Criando estrutura de transferência\n");
        printf("TX (%d): \n", ARRAY_SIZE(tx));
        printBuffer(tx, ARRAY_SIZE(tx));
        printf("RX (%d):\n", ARRAY_SIZE(rx));
        printBuffer(rx, ARRAY_SIZE(rx));
	struct spi_ioc_transfer tr = {
                tr.tx_buf = (unsigned long)tx,
		tr.rx_buf = (unsigned long)rx,
		tr.len = ARRAY_SIZE(tx),
		tr.delay_usecs = delay,
		tr.speed_hz = speed,
		tr.bits_per_word = bits,
	};

        printf("Enviando dados \n");
	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
	if (ret == 1)
		pabort("can't send spi message");
	if (ret < 0)
		perror("Error - ");

        printf("Imprimindo resposta\n");
        printf("Buffer de envio: %d\n", ARRAY_SIZE(tx));
        printf("Buffer de resposta: %d\n", ARRAY_SIZE(rx));
	printf("TX (%d): \n", ARRAY_SIZE(tx));
        printBuffer(tx, ARRAY_SIZE(tx));
        printf("RX (%d):\n", ARRAY_SIZE(rx));
        printBuffer(rx, ARRAY_SIZE(rx));

        puts("");
}

Someone knows how to help me?
Thanks in advance
Attached Files
File Type: txt spi.c.txt (4.8 KB, 32 views)
 
Old 01-19-2011, 12:20 PM   #2
Lobinho
Member
 
Registered: May 2010
Distribution: Ubuntu
Posts: 67

Original Poster
Rep: Reputation: 17
I think I have to deassert the CS pin between a transfer, so I tried to use the option:

Code:
tr.cs_change = true,
Taken from spidev.h:

* @cs_change: True to deselect device before starting the next transfer.


My pc is attached to a LPC uC, so with help of an oscilloscope I detected that CS (chip select) is not changing his state during the transfer.

I don't know if this is a kernel bug or I'm missing something.
 
Old 02-08-2011, 11:21 AM   #3
gsinde
LQ Newbie
 
Registered: Jan 2011
Posts: 11

Rep: Reputation: 0
Well, I have been seeing no SPI traffic with your code above so I changed the transfer routine a little. When I set all of the spi_ioc_transfer parameters (speed, delay, etc.), no data comes out my SPI bus. However, when I memset the struct to all zeros and just set the three parameters I care about, it works fine. Not sure why yet.

#define SPI_IOC_TRANSFER ((IOC_WRITE << 30) | ((sizeof(struct spi_ioc_transfer)) << 16) | ('k' << 8) | 0)
#define SPI_IOC_SET_MODE ((IOC_WRITE << 30) | (1 << 16) | ('k' << 8) | 1)
#define SPI_IOC_JUSTIFY ((IOC_WRITE << 30) | (0 << 16) | ('k' << 8) | 2)
#define SPI_IOC_SET_BITS ((IOC_WRITE << 30) | (1 << 16) | ('k' << 8) | 3)
#define SPI_IOC_SET_SPEED ((IOC_WRITE << 30) | (4 << 16) | ('k' << 8) | 4)

void BasicSpidev::Transfer(uint8_t *command, uint8_t *response, uint32_t len)
{
struct spi_ioc_transfer xfer;

if (fspi >= 0)
{
if (len)
{
memset((void *)&xfer, 0, sizeof(struct spi_ioc_transfer));
xfer.tx_buf = (uint64_t) command;
xfer.rx_buf = (uint64_t) response;
xfer.len = len;

ioctl(fspi, SPI_IOC_TRANSFER, &xfer);
}
}
}
 
Old 02-10-2011, 05:18 PM   #4
Lobinho
Member
 
Registered: May 2010
Distribution: Ubuntu
Posts: 67

Original Poster
Rep: Reputation: 17
Hi gsinde,

When you declare the struct, theres no guarantee that the struct is cleaned. I think that theres no relation with set speed or mode.

On linux Docs theres some examples for SPI program:
http://www.mjmwired.net/kernel/Documentation/spi/spidev
http://www.kernel.org/doc/Documentation/spi/

spidev_test.c works fine my pc


My problem was with mode configuration. I was using polarity = 0 phase = 0, and my device was using other mode configuration.

Any other doubt post here.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
SPI delays and overhead amitking4ever Linux - Embedded & Single-board computer 0 05-27-2010 06:07 AM
Communication with SPI driver Mactub Linux - Software 2 03-16-2010 02:17 AM
Not able to make node for SPI makphy Linux - Newbie 5 11-04-2009 04:38 PM
Linux SPI Framework ananth86coolguy Linux - Newbie 2 09-22-2009 03:07 AM
Ipsec error: SPI piggyj Linux - Security 0 11-09-2006 10:34 PM


All times are GMT -5. The time now is 10:33 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration