• «
  • 1
  • 2
  • »
  • Pages: 1/2     Go
主题 : mini2440 spi 驱动 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 9064
精华: 0
发帖: 15
金钱: 100 两
威望: 35 点
综合积分: 30 分
注册时间: 2009-09-16
最后登录: 2012-10-05
楼主  发表于: 2009-09-27 23:50

 mini2440 spi 驱动

請問大家, 本人是 embedded linux 的新手. 也是一個IC Designer (十多年).  

現在有一問題. 我用FriendlyARM來做一個Demo board. 把ARM的SPI和I2C 連接到FPGA. 用I2C是沒有問題.  但是SPI沒有在/dev 中看到什麼 spi*0*  或 spidev**.   請問大家怎樣成功開啟SPI !!!!

在make menuconfig 中,我已除去button driver和button demo program, MMC support也除去.
在SPI support中, 加上Utilities for bitbanging SPI master, Samsung S3C24XX series API 和 User mode SPI device driver support. 但是也看不到/dev 中有什麼 *spi* 的東西出現.

Version:
Host OS: Fedora linux 10
Embedded linux: 2.6.29
arm-linux-gcc: 4.3.2
Qtopia: 2.2.0

Thanks
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
1楼  发表于: 2009-09-28 09:55
/dev目录下没有*spi*是因为SPI驱动不是给user space应用程序使用的,因此不需要放出设备节点。这一点和I2C的dev驱动(/dev/i2c*)不同;
SPI驱动是给驱动使用的驱动,通过内核内部API供其他设备驱动使用。一个典型的例子是LCD Panel的电源管理驱动通过SPI实现LCD Panel的电源管理。
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 9064
精华: 0
发帖: 15
金钱: 100 两
威望: 35 点
综合积分: 30 分
注册时间: 2009-09-16
最后登录: 2012-10-05
2楼  发表于: 2009-09-30 08:49
謝謝。
级别: 新手上路
UID: 9064
精华: 0
发帖: 15
金钱: 100 两
威望: 35 点
综合积分: 30 分
注册时间: 2009-09-16
最后登录: 2012-10-05
3楼  发表于: 2009-10-04 13:26
我現在寫了一個 SPI 的 DRIVER, 但是用示波器一看,發現問題。用GPIO做CHIP SELECT 個信號是不受控制。
當SET CHIP SELECT 是 LOW 後,它用了幾十ms才到spi port出SPI(用了4us),再用幾十ms才SET CHIP SELECT HIGH。但是source code 中是什麼沒有(line 208)。

請問大家我少了什麼?


#include <mach/hardware.h>  // s3c2410_gpio_****
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/poll.h>
#include <linux/miscdevice.h>
//#include <linux/semaphores.h>

#include <mach/regs-gpio.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>

#define DEVICE_NAME "spi_1"
#define SPI_MAJOR 153

//------------------------------
//------------------------------
#define r_clkcon   *(volatile unsigned long*) ioremap(0x4C00000C, 4)

#define SPI_SPCON1  ioremap(0x59000020, 4)
#define SPI_SPSTA1  ioremap(0x59000024, 4)
#define SPI_SPPIN1  ioremap(0x59000028, 4)
#define SPI_SPPRE1  ioremap(0x5900002C, 4)
#define SPI_SPTDAT1 ioremap(0x59000030, 4)
#define SPI_SPRDAT1 ioremap(0x59000034, 4)

//DEFINE_MUTEX( spi_mutex);
//EXPORT_SYMBOL( spi_mutex);

//static struct semaphore lock;
static spinlock_t spi_lock;
char cs;

#define SPI1_EN0    0
#define SPI1_EN1    1
#define SPI1_EN2    2

static int s3c2440_spi_close( struct inode *inode, struct file *filp)
{
  __raw_writel( 0x00000000, SPI_SPCON1);

  printk( "s3c2440-spi close\n");
  return 0;
}

static int s3c2440_spi_open( struct inode *inode, struct file *filp)
{
  int value =0;

  cs = -1;

  printk( "s3c2440-spi open\n");
  r_clkcon |= 0x40000; // setup peri clock
  value = (int) r_clkcon;
  printk( "r_CLKcon = 0x%X\n", value);

  printk( "setup all EN signals\n");
  //---------------------------------------
  // setup EN for XXXX
  //---------------------------------------
  s3c2410_gpio_cfgpin( S3C2410_GPF5, S3C2410_GPF5_OUTP);
  s3c2410_gpio_pullup( S3C2410_GPF5, 1); // 0 = enable
  s3c2410_gpio_setpin( S3C2410_GPF5, 1);

  //---------------------------------------
  // setup EN for XXXX, XXXX
  //---------------------------------------
  s3c2410_gpio_cfgpin( S3C2410_GPG0, S3C2410_GPG0_OUTP);
  s3c2410_gpio_pullup( S3C2410_GPG0, 0); // 0 = enable
  s3c2410_gpio_setpin( S3C2410_GPG0, 1);

  s3c2410_gpio_cfgpin( S3C2410_GPG3, S3C2410_GPG3_OUTP);
  s3c2410_gpio_pullup( S3C2410_GPG3, 0); // 0 = enable
  s3c2410_gpio_setpin( S3C2410_GPG3, 1);

  //---------------------------------------
  // setup SPI1
  //---------------------------------------
  printk( "setup SPI1 port\n");

  s3c2410_gpio_cfgpin( S3C2410_GPG5, S3C2410_GPG5_SPIMISO1);
  s3c2410_gpio_cfgpin( S3C2410_GPG6, S3C2410_GPG6_SPIMOSI1);
  s3c2410_gpio_cfgpin( S3C2410_GPG7, S3C2410_GPG7_SPICLK1);

  s3c2410_gpio_pullup( S3C2410_GPG5, 1); // 0 = enable
  s3c2410_gpio_pullup( S3C2410_GPG6, 1); // 0 = enable
  s3c2410_gpio_pullup( S3C2410_GPG7, 1); // 0 = enable

  s3c2410_gpio_setpin( S3C2410_GPG5, 1);
  s3c2410_gpio_setpin( S3C2410_GPG6, 1);
  s3c2410_gpio_setpin( S3C2410_GPG7, 1);

  __raw_writel( 0x00000000, SPI_SPPIN1);

  __raw_writel( 0x00000007, SPI_SPPRE1); // SPI baudrate prescaler, Baudrate = PCLK/2/(Prescaler value +1)
  __raw_writel( 0x00000018, SPI_SPCON1); // enable SPI0

  printk( "Open SPI completed\n");
  return 0;
}


static ssize_t s3c2440_spi_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
  switch( cmd)
  {
    case SPI1_EN0:
      cs = 0;
      break;
    case SPI1_EN1:
      cs = 1;
      break;
    case SPI1_EN2:
      cs = 2;
      break;
    default:
      cs = -1;
      break;
  }

  printk( "SPI1 IO_Ctl (%d)\n", cs);
  return 0;
}

static ssize_t s3c2440_spi_read( struct file *filp, char __user *buf, size_t count,
                                  loff_t *f_ops)
{
  unsigned char *dataRx;
  int x = 0;

  if( cs == -1)
    return -EFAULT;

  if( count > 1024)
    count = 1024;

  dataRx = kmalloc( count, GFP_KERNEL);
  if( dataRx == NULL)
    return -ENOMEM;

  if( copy_to_user( buf, dataRx, count))
  {
    kfree( dataRx);
    return -EFAULT;
  }

  printk( "SPI1 read data\n");
  kfree( dataRx);
  return x;
}

static ssize_t s3c2440_spi_write( struct file *filp, const char __user *buf, size_t count, loff_t *f_ops)
{
  unsigned char *dataTx;
  int x = 0, y = 0;
//  unsigned long flags;

  if( cs == -1)
    return -EFAULT;

  if( count > 1024)
    count = 1024;

  dataTx = kmalloc( count, GFP_KERNEL);
  if( dataTx == NULL)
    return -ENOMEM;

  if( copy_from_user( dataTx, buf, count))
  {
    kfree( dataTx);
    return -EFAULT;
  }

//  local_irq_save( flags);
//  mutex_lock( &spi_mutex);
  //while(( spi_spsta1 & 0x01) != 0x01);
  spin_lock_irq( &spi_lock);

  for( x = 0; x < count; x++)
  {
    switch( cs)
    {
      case SPI1_EN0:
        s3c2410_gpio_setpin( S3C2410_GPF5, 0);
        break;
      case SPI1_EN1:
        s3c2410_gpio_setpin( S3C2410_GPG0, 0);
        break;
      case SPI1_EN2:
        s3c2410_gpio_setpin( S3C2410_GPG3, 0);
        break;
    }

    __raw_writel( dataTx[x], SPI_SPTDAT1);  <﹣﹣﹣﹣﹣﹣ ???

    switch( cs)
    {
      case SPI1_EN0:
        s3c2410_gpio_setpin( S3C2410_GPF5, 1);
        break;
      case SPI1_EN1:
        s3c2410_gpio_setpin( S3C2410_GPG0, 1);
        break;
      case SPI1_EN2:
        s3c2410_gpio_setpin( S3C2410_GPG3, 1);
        break;
    }
  }

//  mutex_unlock( &spi_mutex);
//  local_irq_restore( flags);
  spin_unlock_irq( &spi_lock);
  kfree( dataTx);
  return x;
}

static struct file_operations s3c2410_spi_fops = {
  .owner    = THIS_MODULE,
  .open     = s3c2440_spi_open,
  .write    = s3c2440_spi_write,
  .read     = s3c2440_spi_read,
  .ioctl    = s3c2440_spi_ioctl,
  .release  = s3c2440_spi_close,
};

static struct miscdevice misc = {
  .minor = MISC_DYNAMIC_MINOR,
  .name  = DEVICE_NAME,
  .fops  = &s3c2410_spi_fops,
};

static int __init dev_init( void)
{
  int ret;

//  init_MUTEX( &lock);
  spin_lock_init( &spi_lock);

  ret = misc_register( &misc);
  printk( DEVICE_NAME "   initialized\n");

  return 0;
}

static void __exit dev_exit( void)
{
  misc_deregister( &misc);
  printk( "Good-byte, SPI removed\n");
}

module_init( dev_init);
module_exit( dev_exit);

MODULE_LICENSE( "GPL");
MODULE_AUTHOR( "GPL");



App:


#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>

#define SPI1_EN0 0

int main(void)
{
  int fd;
  int x;
  int y;
  unsigned char data[11];
//  pthread_mutex_t lock;
//  spinlock_t spi_lock;

//  pthread_mutex_init( &lock, 0);
//  spin_lock_init( &spi_lock);

  fd = open( "/dev/spi_1", O_RDWR | O_NOCTTY);
  if( fd < 0)
  {
    return -1;
  }
  else
  {
    ioctl( fd, SPI1_EN0, 0);
    for( x = 0; x < 10; x++)
      data[x] = x;
//    spin_lock_irq( &spi_lock);
//    pthread_mutex_lock( &lock);
    write( fd, &data, 10);
//    spin_unlock_irq( &spi_lock);
//    pthread_mutex_unlock( &lock);
  }
}
级别: 新手上路
UID: 55528
精华: 0
发帖: 16
金钱: 80 两
威望: 16 点
综合积分: 32 分
注册时间: 2011-09-19
最后登录: 2017-09-13
4楼  发表于: 2011-11-10 14:37

 回 楼主(kg2007gkhk) 的帖子

您好请问后来怎么实现的呢?
级别: 新手上路
UID: 55528
精华: 0
发帖: 16
金钱: 80 两
威望: 16 点
综合积分: 32 分
注册时间: 2011-09-19
最后登录: 2017-09-13
5楼  发表于: 2011-11-10 14:38

 回 1楼(kasim) 的帖子

引用第1楼kasim于2009-09-28 09:55发表的  :
/dev目录下没有*spi*是因为SPI驱动不是给user space应用程序使用的,因此不需要放出设备节点。这一点和I2C的dev驱动(/dev/i2c*)不同;
SPI驱动是给驱动使用的驱动,通过内核内部API供其他设备驱动使用。一个典型的例子是LCD Panel的电源管理驱动通过SPI实现LCD Panel的电源管理。


版主您好!请问如果应用程序用到spi的话,怎么实现DEV下有SPI*呢?不重写内核驱动的话能够实现吗?
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
6楼  发表于: 2011-11-10 15:50

 回 5楼(xyzxyz) 的帖子

内核配置的时候必须包含"User mode SPI device driver support". (看起来是我没有看仔细楼主的说明)
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 55528
精华: 0
发帖: 16
金钱: 80 两
威望: 16 点
综合积分: 32 分
注册时间: 2011-09-19
最后登录: 2017-09-13
7楼  发表于: 2011-11-12 15:55

 回 6楼(kasim) 的帖子

谢谢版主回复!假如在一个现有的做好的系统上修改,而原有系统中dev/下没有SPI*,而内核又不能再重新编译,还有什么办法能使DEV/下有SPI*吗?能通过改动内核的某些参数实现吗?
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
8楼  发表于: 2011-11-12 22:38

 回 7楼(xyzxyz) 的帖子

如果内核里确实没有spidev(可以通过cat /proc/devices确认),那必须重新编译内核镜像或者将spidev编译成模块动态加载。
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 55528
精华: 0
发帖: 16
金钱: 80 两
威望: 16 点
综合积分: 32 分
注册时间: 2011-09-19
最后登录: 2017-09-13
9楼  发表于: 2011-11-14 11:09

 回 8楼(kasim) 的帖子

多谢版主热心回复!下面是结果:
# cat /proc/devices
Character devices:
  1 mem
  2 pty
  3 ttyp
  4 /dev/vc/0
  4 tty
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
10 misc
13 input
14 sound
29 fb
66 fsl-usb2-otg
81 video4linux
89 i2c
90 mtd
108 ppp
116 alsa
128 ptm
136 pts
166 ttyACM
180 usb
188 ttyUSB
189 usb_device
207 ttymxc
216 rfcomm
247 earphone_dev
248 honmax_3g
249 ilitek_file
250 mxc_enable
251 gsl_kmod
252 mxc_vpu
253 mxc_ipu
254 rtc

Block devices:
  1 ramdisk
259 blkext
  7 loop
  8 sd
31 mtdblock
65 sd
66 sd
67 sd
68 sd
69 sd
70 sd
71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
254 device-mapper
#
里面没有spidev,您说的将spidev编译成模块动态加载是编译内核时的配置吗?
  • «
  • 1
  • 2
  • »
  • Pages: 1/2     Go