ARM9 ADS8344 SPI驱动移植 (一)

     近期做毕业设计,移植了一个ARM9,AD38344 SPI驱动。现在我慢慢把我经历写出来。对于驱动我是个小白,如果

有什么写错的,望各位指正。期间参考了 国嵌和 http://my.csdn.net/weiqing1981127 博客的大量资料。


目标板:TQ2440开发板 cpu:s3c2440 linux内核:2.6.30


     网上有很多关于SPI驱动的移植,当是很少拿一个真正的SPI外设作讲解,显得不过生动。AD38344是8通道16位AD,基于spi通信协议。SPI子系统中,包含两类设备驱动。一类称之为.SPI主控设备驱动,用于驱动SPI主控设备,以和SPI总线交互,读写通信数据。另一类称之为SPI接口设备驱动,用于解析SPI主控设备驱动读取的i数据,形成有意义的协议数据。我们所写的ADS8344驱动属于SPI接口设备驱动。而SPI接口设备驱动是基于 总线设备驱动模型的。我们所写的ADS8344驱动是这个模型的驱动。spi总线在内核代码将会注册(如果你在编译内核时在勾选上spi选项)。SPI的设备信息需要你在机器配置文件当中添加(机器配置文件一般在arch/arm/mach-s3c2440/中。不同的内核,机器配置文件将会不同。我的2.6.30内核是采用天嵌科技资料包内提供的内核。故我的机器配置文件为mach-tq2440.c)。

   我先将ADS8344驱动的代码贴出,稍后进行分析。

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>

#include <linux/delay.h>
#include <linux/device.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/spi/spi.h>
#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <linux/cache.h>
#include <linux/mutex.h>
#include <linux/spi/spi.h>

#define AVERAGETIMES 4
static int send2user=0;

static struct {
    struct spi_device *spi;
    struct class   *ads8344_class;
    int     major;
    struct mutex  lock;
} ads38344_data;


static inline int spi_nor_setup(struct spi_device *spi, u8 bst_len)
{
 spi->bits_per_word = bst_len << 3;
 return spi_setup(spi);
}


static ssize_t ads8344_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
    char __user readResult[2];
    readResult[0] =(char __user)(send2user&0XFF);
    readResult[1] =(char __user)((send2user>>8)&0XFF);
    copy_to_user(buf,readResult,sizeof(readResult));
    return sizeof(readResult);
 }

static ssize_t ads8344_write(struct file *file, const char __user *data,
                                   size_t len, loff_t *ppos)
{
 return 0;
}

static int ads8344_open(struct inode *inode, struct file *file)
{
 return 0;
}

static int ads8344_release(struct inode *inode, struct file *file)
{
 return 0;
}

static int ads8344_ioctl(struct inode *inode, struct file *file,
       unsigned int cmd, unsigned long arg)
{
    send2user=0X00000000;
    u8 channel,revData[AVERAGETIMES][3];
    u8 control_word;
    int ret = 0, i,k,z;
    int temp[AVERAGETIMES][3]; 
    pr_debug("ioctl cmd %d is issued...\n", cmd);

    if((cmd>7)||(cmd<0))
    return -EINVAL;

    switch (cmd) {
         case 0: channel = 0; break;
         case 1: channel = 4; break;
         case 2: channel = 1; break;
         case 3: channel = 5; break;
         
         case 4: channel = 2; break;
         case 5: channel = 6; break;
         case 6: channel = 3; break;
         case 7: channel = 7; break;
         
        default: channel = 0; break;
    }

    mutex_lock(&ads8344_data.lock);

    for (i = 0; i < AVERAGETIMES; i++) {
            control_word = (1u << 7)|(channel << 4)|(1u << 2)|0x3;
            ret = spi_write_then_read(ads8344_data.spi, &control_word, 1,revData[i],3);
            if (ret)
            break;
    }

    mutex_unlock(&ads8344_data.lock);

    if (ret)
    return -EIO;

    for(k=0;k<AVERAGETIMES;k++)
    {
        temp[k][0]=(int)revData[k][0];
        temp[k][1]=(int)revData[k][1];
        temp[k][2]=(int)revData[k][2];
    }

    for(z=0;z<AVERAGETIMES;z++)
    {
        send2user += ((temp[z][0]<<16)|(temp[z][1]<<8)|temp[z][2])>>7;
    }

    send2user= send2user>>2;
    send2user &=0xffff; 
    return ret;
}

//设备文件访问操作接口
static const struct file_operations ads8344_fops = {
 .owner  = THIS_MODULE,
 .read  = ads8344_read,
 .write  = ads8344_write,
 .open  = ads8344_open,
 .release = ads8344_release,
 .ioctl  = ads8344_ioctl,
};

static int ads8344_probe(struct spi_device *spi) //监测系统是否有ads8344设备,并进行设备注册
{
 printk("we has find spi dev\n");
 int ret = 0;
 struct device *dev;
 printk("we find spi dev! \n");
 mutex_init(&ads8344_data.lock); //初始化lock信号量
 ads8344_data.spi = spi_dev_get(spi); //获取SPI设备
 aads8344_data.major = 0; //定义主设备号

 ret = register_chrdev(ads8344_data.major, "ads8344", &ads8344_fops);//注册字符设备
 if (ret < 0)
  return ret;


 if (ads8344_data.major == 0)

 {
  ads8344_data.major = ret;
  printk(KERN_INFO "ads8344: major number %d\n", ads8344_data.major);
 }


 ad7490_data.ads8344_class = class_create(THIS_MODULE, "ads8344");        //创建ad7490设备类
 if (IS_ERR(ads8344_data.ads8344_class))

 {
  dev_err(&ads8344_data.spi->dev, "ads8344: failed to create ads8344 class\n");
  goto char_dev_remove;
 }

 dev = device_create(ads8344_data.ads8344_class, NULL,
       MKDEV(ads8344_data.major, 0), NULL, "ads8344");//创建设备节点
 if (IS_ERR(dev)) {
  dev_err(&ads8344_data.spi->dev,
   "ads8344: failed to create class device\n");
  goto class_remove;
 }
 return 0;

class_remove:
 class_destroy(ads8344_data.ads8344_class);
char_dev_remove:
 unregister_chrdev(ads8344_data.major, "ads8344");//注销字符设备
 return -ENODEV;
}


static int __devexit ads8344_remove(struct spi_device *spi)
{
 device_destroy(ads8344_data.ads8344_class, MKDEV(ads8344_data.major, 0));
 class_destroy(ads8344_data.ads8344_class);
 unregister_chrdev(ads8344_data.major, "ads8344");

 return 0;
}


static struct spi_driver ads8344_driver = {
 .driver = {
  .name  = "ads8344",
  .owner  = THIS_MODULE,
 },
 .probe  = ads8344_probe,
 .remove  = __devexit_p(ads8344_remove),
};

static int __init ads8344_init(void)
{
    printk("ads8344_init\n");
 return spi_register_driver(&ads8344_driver);
}
module_init(ads8344_init);


static void __exit ads8344_exit(void)
{
    printk("ads8344_exit\n");
 spi_unregister_driver(&ads8344_driver);
}
module_exit(ads8344_exit);

MODULE_DESCRIPTION("Driver for ads8344");
MODULE_AUTHOR("Electronics, Inc");
MODULE_LICENSE("GPL");
MODULE_ALIAS("spi:ads8344");




现在讲解如何进行SPI移植。

 step1: 

           在 arch/arm/mach-s3c2440/mach-tq2440.c中添加以下信息

#include <linux/spi/spi.h>  

#include <mach/spi.h> 

 

然后加入如下代码:

static struct spi_board_info s3c2410_spi0_board[] =  

{  

        [0] = {  

                .modalias = "ads8344",   //设备的名称用来和驱动进行匹配,一定要和ADS8344驱动中 ads8344_driver中的名字相同,

                .bus_num = 0,    //总线的编号,实际指对应的SPI寄存器

                .chip_select = 0,   //反映了这个芯片是不是被连接到SPI上

                .irq = IRQ_EINT9,    //设备的中断号

                .max_speed_hz = 500 * 1000,   //SPI的最大速率

                }  

};  


static struct s3c2410_spi_info s3c2410_spi0_platdata = {  

        .pin_cs = S3C2410_GPG(2),  

       .num_cs = 1,     //所有的片选信号

        .bus_num = 0,    //SPI多对应的总线编号

        .gpio_setup = s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,   //引脚设置函数

};  


Step2:

在tq2440_devices[]平台数组中添加如下代码:

&s3c_device_spi0,


Step3:

最后在tq2440_machine_init函数中加入如下代码:

s3c_device_spi0.dev.platform_data= &s3c2410_spi0_platdata;  

spi_register_board_info(s3c2410_spi0_board, ARRAY_SIZE(s3c2410_spi0_board));  


Step4:

最后需要修改arch/arm/plat-s3c24xx/KConfig文件

找到

config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13  

        bool 

        help  

         SPI GPIO configuration code for BUS0 when connected to  

         GPE11, GPE12 and GPE13.  


config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13  

        bool "S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13"  

        help  

         SPI GPIO configuration code for BUS0 when connected to  

         GPE11, GPE12 and GPE13.  


Step5:到内核代码当中输入 make menuconfig ARCH=arm ,进入内核配置菜单

将System Type->S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13

    Device Drivers->SPI support勾选上~

(贴图)




 然后重新编译内核。


step6:

将ADS8344驱动编译成内核模块加载到内核当中。这样一个完整的ADS833驱动就移植好了。我将在下一讲中对代码进行详解

       




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值