Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

SPI and uClinux

Altera_Forum
Honored Contributor II
2,627 Views

Hi all, 

 

I have a design in which I have to use SPI in order to communicate with an external PIC. I find that it is not enough to select SPI driver in uClinux kernel configuration because when I try to open /dev/spi0 I receive the message: "No such device or address". What am I missing? Where am I wrong? 

 

Thanks in advance 

 

Marco
0 Kudos
10 Replies
Altera_Forum
Honored Contributor II
903 Views

 

--- Quote Start ---  

Hi all, 

 

I have a design in which I have to use SPI in order to communicate with an external PIC. I find that it is not enough to select SPI driver in uClinux kernel configuration because when I try to open /dev/spi0 I receive the message: "No such device or address". What am I missing? Where am I wrong? 

 

Thanks in advance 

 

Marco 

--- Quote End ---  

 

Can you post your output about the kernel version, configuration and design info?
0 Kudos
Altera_Forum
Honored Contributor II
903 Views

Hi liunx, thanks for your reply. Attached and below you can find the information you asked for.  

 

 

--- Quote Start ---  

 

 

Linux version 2.6.30 (marco@uClinux) (gcc version 3.4.6)# 404 PREEMPT Tue Oct 11 

17:44:02 CEST 2011 

 

 

uClinux/Nios II 

Built 1 zonelists in Zone order, mobility grouping off. Total pages: 32512 

Kernel command line: 

NR_IRQS:32 

PID hash table entries: 512 (order: 9, 2048 bytes) 

Dentry cache hash table entries: 16384 (order: 4, 65536 bytes) 

Inode-cache hash table entries: 8192 (order: 3, 32768 bytes) 

Memory available: 126552k/3382k RAM, 0k/0k ROM (1879k kernel code, 1502k data) 

Calibrating delay loop... 61.64 BogoMIPS (lpj=308224) 

Mount-cache hash table entries: 512 

net_namespace: 264 bytes 

NET: Registered protocol family 16 

init_BSP(): registering device resources 

bio: create slab <bio-0> at 0 

NET: Registered protocol family 2 

IP route cache hash table entries: 1024 (order: 0, 4096 bytes) 

TCP established hash table entries: 4096 (order: 3, 32768 bytes) 

TCP bind hash table entries: 4096 (order: 2, 16384 bytes) 

TCP: Hash tables configured (established 4096 bind 4096) 

TCP reno registered 

NET: Registered protocol family 1 

JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc. 

JFFS2: default compression mode: priority 

io scheduler noop registered 

io scheduler deadline registered (default) 

ienable reg:100 

ienable reg:108 

pio_fpga_in - s 

ttyJ0 at MMIO 0x8004d50 (irq = 1) is a Altera JTAG UART 

console [ttyJ0] enabled 

ttyS0 at MMIO 0x8004c80 (irq = 7) is a Altera UART 

ttyS1 at MMIO 0x8000000 (irq = 6) is a Altera UART 

SLIP: version 0.8.4-NET3.019-NEWTTY (dynamic channels, max=256). 

0 : New Bus ID 

BUG: No TSE MDIO Reset 

Altera TSE MII Bus: probed 

Found phy with ID=0x1410cc2 at address=0x12 

Altera TSE MII Bus: MDIO Bus Registered 

eth0 (): not using net_device_ops yet 

eth0:Successed to register TSE net device 

Altera Triple Speed MAC IP Driver(v8.0) developed by SLS,August-2008,--Linux 2.6 

.27-rc3 

physmap platform flash device: 04000000 at 0c000000 

physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank 

Amd/Fujitsu Extended Query Table at 0x0040 

physmap-flash.0: CFI does not contain boot bank location. Assuming top. 

number of CFI chips: 1 

cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness. 

cmdlinepart partition parsing not available 

RedBoot partition parsing not available 

Using physmap partition information 

Creating 9 MTD partitions on "physmap-flash.0": 

0x000000000000-0x000002800000 : "userspace" 

0x000002800000-0x000002900000 : "U-Boot" 

0x000002900000-0x000002d00000 : "uImage1" 

0x000002d00000-0x000003100000 : "uImage2" 

0x000003100000-0x000003500000 : "uImage3" 

0x000003500000-0x000003880000 : "DEFAULT_MMU" 

0x000003880000-0x000003c00000 : "MAXIMUM_MMU" 

0x000003c00000-0x000003f80000 : "USER_IMAGE" 

0x000003f80000-0x000003fa0000 : "options-bits" 

TCP cubic registered 

NET: Registered protocol family 17 

RPC: Registered udp transport module. 

RPC: Registered tcp transport module. 

Freeing unused kernel memory: 772k freed (0x1028c000 - 0x1034c000) 

Shell invoked to run file: /etc/rc 

Command: hostname uClinux 

Command: mount -t proc proc /proc -o noexec,nosuid,nodev 

Command: mount -t sysfs sysfs /sys -o noexec,nosuid,nodev 

Command: mount -t devpts devpts /dev/pts -o noexec,nosuid 

Command: mkdir /var/tmp 

Command: mkdir /var/log 

Command: mkdir /var/run 

Command: mkdir /var/lock 

Command: mkdir /var/empty 

Command: ifconfig lo 127.0.0.1 

Command: route add -net 127.0.0.0 netmask 255.0.0.0 lo 

Command: ifconfig eth0 hw ether 00:07:ED:11:80:c9 

Command: ifconfig eth0 192.168.100.229 

Command: route add default gw 192.168.100.1 

Command: mount -t jffs2 /dev/mtdblock0 /mnt 

 

Command: inetd& 

[28] 

Command: cat /etc/motd 

Welcome to 

____ _ _ 

/ __| ||_| 

_ _| | | | _ ____ _ _ _ _ 

| | | | | | || | _ \| | | |\ \/ / 

| |_| | |__| || | | | | |_| |/  

| ___\____|_||_|_| |_|\____|\_/\_/ 

| | 

|_| 

 

For further information check: 

http://www.uclinux.org/ 

 

 

Sash command shell (version 1.1.1) 

/> 

--- Quote End ---  

0 Kudos
Altera_Forum
Honored Contributor II
903 Views

Ok, reading documentation in Linux kernel I find that if I want to use open() and write() function within my software I need to write a protocol driver or simply use spidev driver. I added in config.c the following code 

 

static struct spi_board_info nios2_spi_devices = { .modalias = "spidev", .max_speed_hz = 173.3 * 1000, .bus_num = 1, .chip_select = 0, .irq = na_spi_irq, .mode = SPI_MODE_0, };  

 

and I did what is described in spidev documentation, but I am still not able to have spidev1.0 in /dev directory. Can anyone help me?
0 Kudos
Altera_Forum
Honored Contributor II
903 Views

 

--- Quote Start ---  

Ok, reading documentation in Linux kernel I find that if I want to use open() and write() function within my software I need to write a protocol driver or simply use spidev driver. I added in config.c the following code 

 

static struct spi_board_info nios2_spi_devices = { .modalias = "spidev", .max_speed_hz = 173.3 * 1000, .bus_num = 1, .chip_select = 0, .irq = na_spi_irq, .mode = SPI_MODE_0, }; and I did what is described in spidev documentation, but I am still not able to have spidev1.0 in /dev directory. Can anyone help me? 

--- Quote End ---  

 

 

You need to do three things 

1. you need to add your spi device driver like altera_spi in config.c 

2. you need to add spi_board_info, bus_num should match with step1 

3. Make sure your spi device (altera_spi) probe did not returned error with unsupported mode 

 

Point to note is spidev is not spi hardware driver, it is spi user level driver and need to be linked to actual driver with bus_num 

 

I will post snippet of my code asap
0 Kudos
Altera_Forum
Honored Contributor II
903 Views

1. Add a SPI device (Actual SPI device driver), in my case it is altera spi 

static struct resource spi_master_resource = { = { .start = SPI_MASTER_BASE, .end = SPI_MASTER_END, .flags = IORESOURCE_MEM, }, = { .start = SPI_MASTER_IRQ, .end = SPI_MASTER_IRQ, .flags = IORESOURCE_IRQ, }, }; static struct platform_device spi_master_device = { .name = "spi_altera", .id = 0, /* Bus number */ .num_resources = ARRAY_SIZE(spi_master_resource), .resource = spi_master_resource, }; 2. Add spi board info. The id in SPI device and bus_num in spi board info shall match. you can add multiple entries if you have many. 

 

static struct spi_board_info nios2_spi_devices = { /* the modalias must be the same as spi device driver name */ .modalias = "spidev", /* Name of spi_driver for this device */ .max_speed_hz = 4000000, /* max spi clock (SCK) speed in HZ */ .bus_num = 0, /* bus number */ .chip_select = 4, .mode = SPI_CPOL | SPI_CPHA, }, 3. Add a device in device table 

/dev/spimas c 640 0 0 153 0 0 0 - 4. If all these things are done, still spi does show up, debug your spi device probe (not spidev), it may be returning due to not supported mode bits
0 Kudos
Altera_Forum
Honored Contributor II
903 Views

Hi neolux, thanks for your answer :-) 

 

I followed these steps, but it didn't work. After platform_driver_probe in altera_spi_init it returns -19, so there's an error. How can i fix it?Where can I find the error code list?
0 Kudos
Altera_Forum
Honored Contributor II
903 Views

-19 will be a negative errno value, probably -ENODEV.

0 Kudos
Altera_Forum
Honored Contributor II
903 Views

 

--- Quote Start ---  

Hi neolux, thanks for your answer :-) 

 

I followed these steps, but it didn't work. After platform_driver_probe in altera_spi_init it returns -19, so there's an error. How can i fix it?Where can I find the error code list? 

--- Quote End ---  

 

 

 

knowing error code doesn't help much. go to spi_altera.c put printk before all returns and verify why and where it is returning. You can go further if required.
0 Kudos
Altera_Forum
Honored Contributor II
903 Views

I will update you about this. I'm using 20090730 release, so I have no spi_altera.c but altspi.c, but it should be the same.

0 Kudos
Altera_Forum
Honored Contributor II
903 Views

Hi again, 

 

I found that there is an error in drivers/base/platform.c. Error code is ENODEV (dsl you were right). 

 

int __init_or_module platform_driver_probe(struct platform_driver *drv, int (*probe)(struct platform_device *)) { int retval, code; /* temporary section violation during probe() */ drv->probe = probe; retval = code = platform_driver_register(drv); /* Fixup that section violation, being paranoid about code scanning * the list of drivers in order to probe new devices. Check to see * if the probe was successful, and make sure any forced probes of * new devices fail. */ spin_lock(&platform_bus_type.p->klist_drivers.k_lock); //drv->probe = NULL; Commented by me if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list)) retval = -ENODEV; drv->driver.probe = platform_drv_probe_fail; spin_unlock(&platform_bus_type.p->klist_drivers.k_lock); if (code != retval) platform_driver_unregister(drv); return retval; }  

 

I think the error is due to "list_empty" that should returns 0 but returns 1. Am I right? Am i right when I comment drv->probe = NULL? What else should I do?
0 Kudos
Reply