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.
Tool/software: Linux
We are working on AM335x processor which is connected to MT25QL256ABA Micron Serial NOR Flash Memory.
We are checking SPI interface between them. Please find Schematic and DTS definitions below.
Note: Our NOR flash is connected to SPI0.
Schematic:
SPI definition in DTS:
spi0_pins: spi0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) //spi0_sclk
AM33XX_IOPAD(0x954, PIN_OUTPUT_PULLUP | MUX_MODE0) //spi0_d0
AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) //spi0_d1
AM33XX_IOPAD(0x95c, PIN_OUTPUT | MUX_MODE0) //spi0_cs0
>;
};
spi1_pins: spi1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x90c, PIN_OUTPUT_PULLUP | MUX_MODE2) /* mii1_crs.spi1_d0 */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxerr.spi1_d1 */
AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_col.spi1_sclk */
AM33XX_IOPAD(0x99c, PIN_OUTPUT | MUX_MODE3) /* mcasp0_ahclkr.spi1_cs0 */
>;
};
&spi0
{
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
ti,pindir-d0-out-d1-in = <1>;
status = "okay";
channel@0
{
#address-cells = <1>;
#size-cells = <0>;
compatible = "spidev";
spi-max-frequency = <48000000>;
reg = <0x0>;
};
};
&spi1
{
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
ti,pindir-d0-out-d1-in = <1>;
status = "okay";
spidev@1
{
compatible = "linux,spidev";
spi-max-frequency = <48000000>;
reg = <0x0>;
status = "okay";
};
};
u-boot-2018.01+gitAUTOINC+131dc82830-g131dc82830/configs/am335x_evm_defconfig:
CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_OMAP3_SPI=y
After booting its is visible under devices.
root@am335x-evm:/boot# ls -lrt /dev/s
shm/ snd/ spidev0.0 spidev1.0 stderr stdin stdout
When we try to run the following test program, it is either reading all 0's or 1's.
#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.1"; static uint8_t mode; static uint8_t bits = 8; static uint32_t speed = 500000; static uint16_t delay; static void transfer(int fd) { int ret; uint8_t tx[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 0xF0, 0x0D, }; 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; }
root@am335x-evm:/boot# ./spi_test.out -D /dev/spidev1.0 -b 16 -H -O 0 -C 0 -s 22000000
spi mode: 7
bits per word: 16
max speed: 22000000 Hz (22000 KHz)
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00
root@am335x-evm:/boot# ./spi_test.out -D /dev/spidev0.0 -b 16 -H -O 0 -C 0 -s 22000000
spi mode: 7
bits per word: 16
max speed: 22000000 Hz (22000 KHz)
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF
root@am335x-evm:/boot#
We tried one other program also.
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <string.h>
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 500000;
static uint16_t delay;
const char *device = "/dev/spidev0.0";
char buf[10];
char buf2[10];
struct spi_ioc_transfer xfer[2];
struct spi_ioc_transfer xfer1[2];
void spi_write(int file,int value)
{
unsigned char buf[32];
int status;
buf[0] = 0x06;
xfer1[0].tx_buf = (unsigned long)buf;
xfer1[0].len = 1; /* Length of command to write.*/
status = ioctl(file, SPI_IOC_MESSAGE(1), xfer1);
if (status < 0)
{
perror("SPI_IOC_MESSAGE");
return;
}
sleep(2);
buf[0] = 0x01;
buf[1] = value;
xfer1[0].tx_buf = (unsigned long)buf;
xfer1[0].len = 2; /* Length of command to write*/
status = ioctl(file, SPI_IOC_MESSAGE(1), xfer1);
if (status < 0)
{
perror("SPI_IOC_MESSAGE");
return;
}
printf("env: %02x %02x\n", buf[0], buf[1]);
}
void spi_read(int file)
{
int status;
//memset(buf, 0, 10*sizeof(buf[0]));
//memset(buf2, 0, 10*sizeof(buf2[0]));
buf[0] = 0x05;//0x9E;
xfer[0].tx_buf = (unsigned long)buf;
xfer[0].len = 1; /* Length of command to write*/
xfer[1].rx_buf = (unsigned long) buf2;
xfer[1].len = 1; /* Length of Data to read */
status = ioctl(file, SPI_IOC_MESSAGE(2), xfer);
if (status < 0)
{
perror("SPI_IOC_MESSAGE");
return;
}
printf("read: %02x\n", buf2[0]);
}
int main(int argc, char *argv[])
{
int file;
memset(buf, 0, 10*sizeof(buf[0]));
memset(buf2, 0, 10*sizeof(buf2[0]));
if ((file = open(device,O_RDWR)) < 0)
{
printf("Failed to open the bus.");
/* ERROR HANDLING; you can check errno to see what went wrong */
exit(1);
}
// printf("success to open the bus.");
if (ioctl(file, SPI_IOC_RD_MODE, &mode) < 0)
{
perror("SPI rd_mode");
return -1;
}
if (ioctl(file, SPI_IOC_WR_BITS_PER_WORD, &bits)<0)
{
perror("can't set bits per word");
return -1;
}
if (ioctl(file, SPI_IOC_RD_BITS_PER_WORD, &bits)<0)
{
perror("SPI bits_per_word");
return -1;
}
if (ioctl(file, SPI_IOC_WR_MAX_SPEED_HZ, &speed)<0)
{
perror("can't set max speed hz");
return -1;
}
if (ioctl(file, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0)
{
perror("SPI max_speed_hz");
return -1;
}
int val;
// printf("Enter value to set status: ");
// scanf("%d",&val);
// spi_write(file,val);
spi_read(file);
return 0;
}
For this also read is coming out to be ff.
Our hardware also, we've verified the voltages and clock. Everything looks fine.
I am unable to proceed further. Kindly someone help me how to solve this.
Regards
Vamsi
Vamsi,
You are using spi1_d0 and spidev1.0 in your test, but I do not see SPI1 attached to your SPI NOR flash. If I am not missing something, you should remove the reference to spi1 and spidev1.0, as I do not see how this are related to NOR flash.
Check also below e2e threads:
e2e.ti.com/.../770985
e2e.ti.com/.../771421
Regards,
Pavel
I changed the device to spidev0.0. This time also output is all 0s.
#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/spidev0.0"; static uint8_t mode; static uint8_t bits = 8; static uint32_t speed = 500000; static uint16_t delay; static void transfer(int fd) { int ret; uint8_t tx[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 0xF0, 0x0D, }; 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; }