This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/AM3358: Multiple SPI CS

Part Number: AM3358

Tool/software: Linux

Greetings,

I appreciate every attempt made to answer my doubts regarding the follwoing questions in advance. I'm using Beaglebone black rev c having AM3358 processor and have been stuck with this obstacle for a long time now.

1.How to make a functional Chip slect lines for SPI 1 in Beahlebone black ?

2.How to modify the program (one which does data transfer using SPI MISO and MOSI) as per the requirement of the slave select lines?

Thanks for all the help in advance.

 

  • Hi,

    What software are you using? Which version?
  • Hi,
    I'm currently using debian os with kernel 3.8. I'm trying write the code in python but C code is fine as well.

    Note: I know 3.8 kernel is not supported by this community but can you please help me with this I have searched a lot with no proper answer to build this function.
  • to add to the above question my current code is like this:

    #include <stdint.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <getopt.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <linux/types.h>
    #include <linux/spi/spidev.h>
    
    #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
    
    static void pabort(const char *s)
    {
    	perror(s);
    	abort();
    }
    
    static const char *device = "/dev/spidev1.0";
    static uint8_t mode;
    static uint8_t bits = 8;
    static uint32_t speed = 5000;
    static uint16_t delay;
    
    static void transfer(int fd)
    {
    	int ret;
    	uint8_t tx[] = {
    		0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
    	};
    	uint8_t rx[ARRAY_SIZE(tx)] = {0, };
    	struct spi_ioc_transfer tr = {
    		.tx_buf = (unsigned long)tx,
    		.rx_buf = (unsigned long)rx,
    		.len = ARRAY_SIZE(tx),
    		.delay_usecs = delay,
    		.speed_hz = speed,
    		.bits_per_word = bits,
    	};
    
    	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    	if (ret < 1)
    		pabort("can't send spi message");
    
    	for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
    		if (!(ret % 6))
    			puts("");
    		printf("%.2X ", rx[ret]);
    	}
    	puts("");
    }
    
    static void print_usage(const char *prog)
    {
    	printf("Usage: %s [-DsbdlHOLC3]\n", prog);
    	puts("  -D --device   device to use (default /dev/spidev1.1)\n"
    	     "  -s --speed    max speed (Hz)\n"
    	     "  -d --delay    delay (usec)\n"
    	     "  -b --bpw      bits per word \n"
    	     "  -l --loop     loopback\n"
    	     "  -H --cpha     clock phase\n"
    	     "  -O --cpol     clock polarity\n"
    	     "  -L --lsb      least significant bit first\n"
    	     "  -C --cs-high  chip select active high\n"
    	     "  -3 --3wire    SI/SO signals shared\n");
    	exit(1);
    }
    
    static void parse_opts(int argc, char *argv[])
    {
    	while (1) {
    		static const struct option lopts[] = {
    			{ "device",  1, 0, 'D' },
    			{ "speed",   1, 0, 's' },
    			{ "delay",   1, 0, 'd' },
    			{ "bpw",     1, 0, 'b' },
    			{ "loop",    0, 0, 'l' },
    			{ "cpha",    0, 0, 'H' },
    			{ "cpol",    0, 0, 'O' },
    			{ "lsb",     0, 0, 'L' },
    			{ "cs-high", 0, 0, 'C' },
    			{ "3wire",   0, 0, '3' },
    			{ "no-cs",   0, 0, 'N' },
    			{ "ready",   0, 0, 'R' },
    			{ NULL, 0, 0, 0 },
    		};
    		int c;
    
    		c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);
    
    		if (c == -1)
    			break;
    
    		switch (c) {
    		case 'D':
    			device = optarg;
    			break;
    		case 's':
    			speed = atoi(optarg);
    			break;
    		case 'd':
    			delay = atoi(optarg);
    			break;
    		case 'b':
    			bits = atoi(optarg);
    			break;
    		case 'l':
    			mode |= SPI_LOOP;
    			break;
    		case 'H':
    			mode |= SPI_CPHA;
    			break;
    		case 'O':
    			mode |= SPI_CPOL;
    			break;
    		case 'L':
    			mode |= SPI_LSB_FIRST;
    			break;
    		case 'C':
    			mode |= SPI_CS_HIGH;
    			break;
    		case '3':
    			mode |= SPI_3WIRE;
    			break;
    		case 'N':
    			mode |= SPI_NO_CS;
    			break;
    		case 'R':
    			mode |= SPI_READY;
    			break;
    		default:
    			print_usage(argv[0]);
    			break;
    		}
    	}
    }
    
    int main(int argc, char *argv[])
    {
    	int ret = 0;
    	int fd;
    
    	parse_opts(argc, argv);
    
    	fd = open(device, O_RDWR);
    	if (fd < 0)
    		pabort("can't open device");
    
    	/*
    	 * spi mode
    	 */
    	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
    	if (ret == -1)
    		pabort("can't set spi mode");
    
    	ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
    	if (ret == -1)
    		pabort("can't get spi mode");
    
    	/*
    	 * bits per word
    	 */
    	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    	if (ret == -1)
    		pabort("can't set bits per word");
    
    	ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
    	if (ret == -1)
    		pabort("can't get bits per word");
    
    	/*
    	 * max speed hz
    	 */
    	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    	if (ret == -1)
    		pabort("can't set max speed hz");
    
    	ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
    	if (ret == -1)
    		pabort("can't get max speed hz");
    
    	printf("spi mode: %d\n", mode);
    	printf("bits per word: %d\n", bits);
    	printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
    
    	transfer(fd);
    
    	close(fd);
    
    	return ret;
    }
    

    Which works fine for single slave device but I'm stuck here with no further lead to modify this code to use multiple chip selct functions.

    Regards

    Hithesh Karanth 

  • Hithesh,

    Since you are using the Beagle distribution and specifically wanting help with a Beaglebone Black, I recommend you work with the Beaglebone community here:

    groups.google.com/.../

    It is a thriving community and I'm sure you'll get some help.
  • RonB,

    I thank you for the effort you took to answer this querry. The problem being the lack of precission in answering for relatively any query raised in the community you mentioned above has forced my to raise an issue here. In addition the community isnt timely in answring theraised query .
  • Hithesh,

    I'm sorry you didn't get an help.

    I looked around a bit and found:

    dev.iachieved.it/.../

    You may have already found this, but if not it might be helpful.

    There are many features in Debian that are different from what we provide in our Linux Distrubution, the Processor SDK.

    The above example uses GPIOs for CS. You should be able to have the SPI module control this as well. At a high level, you need to declare the number of CS you want to use, pinmux those pins to the appropriate mode and give them to the SPI port. Most of this is done in DT. Take a look at Documentation/devicetree/bindings/spi/omap-spi.txt in your kernle source documentation for more information and examples for SPI.

    I hope this helps and wish you good luck in solving this problem.
  • Thank you for your help in solving my queries.