基于SPI协议的驱动开发

1、linux下的spi协议框架

一般spi-core以下的spi_master有芯片厂家开发完成。因此只需要完成SPI协议基础上的二次开发,比方说基于SPI协议实现网络数据的传输,或者SPI外围器件的控制,或者blalalala

2、代码框架

2.1、dts的配置,生成spi_master

/*配置GPIO口模式为SPI模式*/
spixxx_pins: spixxx_pins{
    anyka,pins = <15 16 25 26 >;
    anyka,function = <2 2 3 3 >;
    anyka,pull = <0x00000010>;
};

&spi1 {
    pinctrl-names = "default";
    pinctrl-0 = <&spixxx_pins>;
    cs-gpios = <&gpio 10 1>;
    status = "okay";
	spidev: my_xxx@0 {
		compatible = "test,my_xxx";
		spi-max-frequency = <12000000>;
		reg = <0>;
	};	
};

2.2、代码框架

创建一个字符设备驱动,在字符设备驱动中调用spi接口完成数据的读写

#include <linux/init.h>
#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/compat.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>

extern struct my_xxx_dev g_my_xxx_init __attribute__((weak));
struct my_xxx_dev g_my_xxx_init;

static struct my_xxx_dev *g_my_xxx_dev = NULL;

int my_xxx_open(struct inode *node, struct file *filp)
{
//	struct my_xxx_dev *my_xxx_dev = container_of(filp->private_data, struct my_xxx_dev, misc_dev);
	
    return 0;
}

int my_xxx_release(struct inode *node, struct file *filp)
{
//	struct my_xxx_dev *my_xxx_dev = container_of(filp->private_data, struct my_xxx_dev, misc_dev);

    return 0;
}

static ssize_t my_xxx_read(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
{
	char data[10] = {0x00};
	struct spi_transfer *t;
    struct spi_message m;
	struct my_xxx_dev *my_xxx_dev = container_of(filp->private_data, struct my_xxx_dev, misc_dev);
    struct spi_device *spi = (struct spi_device *)my_xxx_dev->private_data;

	mutex_lock(&my_xxx_dev->buf_lock);	
    t = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);
    if(t == NULL) {
    
        printk("kzalloc spi_transfer error!\r\n");
        return -1;
    }

	t->rx_buf	= data;
	t->len		= 10;
    spi_message_init(&m);
    spi_message_add_tail(t, &m);
    ret = spi_sync(spi, &m);
    if(ret < 0) {
        printk("spi_sync failed!\r\n");
        kfree(t);
        mutex_unlock(&my_xxx_dev->buf_lock);
        return -1;
    }
	
	if (copy_to_user(buf, (void *)data, status) {
		printk("error: copy from user\n");
        mutex_unlock(&my_xxx_dev->buf_lock);
        return -1;
    }
	
	kfree(t);
	mutex_unlock(&my_xxx_dev->buf_lock);
	
	return 0;
}

static ssize_t my_xxx_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
{
    int ret 		= 0;
	struct spi_transfer *t;
    struct spi_message m;
	struct my_xxx_dev *my_xxx_dev = container_of(filp->private_data, struct my_xxx_dev, misc_dev);
    struct spi_device *spi = (struct spi_device *)my_xxx_dev->private_data;

	mutex_lock(&my_xxx_dev->buf_lock);	
    if (copy_from_user(my_xxx_dev->data, (void *)buf, count)) {
		printk("error: copy from user\n");
        return -1;
    }

    t = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);
    if(t == NULL) {
        printk("kzalloc spi_transfer error!\r\n");
        mutex_unlock(&my_xxx_dev->buf_lock);
        return -1;
    }

    t->tx_buf 	= my_xxx_dev->data;
    t->len 		= count;
	t->tx_nbits	= my_xxx_dev->tx_nbits;
	spi->mode	= ((my_xxx_dev->tx_nbits) == 0x02) ? SPI_TX_DUAL : (((my_xxx_dev->tx_nbits) == 0x04) ? SPI_TX_QUAD : SPI_MODE_0);
    spi_message_init(&m);
    spi_message_add_tail(t, &m);
    ret = spi_sync(spi, &m);
    if(ret < 0) {
        printk("spi_sync failed!\r\n");
        kfree(t);
        mutex_unlock(&my_xxx_dev->buf_lock);
        return -1;
    }

    kfree(t);
	mutex_unlock(&my_xxx_dev->buf_lock);
	
    return 0;
}

int my_xxx_ioctl(struct file *filp, unsigned int cmd, unsigned long  int arg)
{
	unsigned long  int speed_hz = 0;
	struct my_xxx_dev *my_xxx_dev = container_of(filp->private_data, struct my_xxx_dev, misc_dev);
	struct spi_device *spi = (struct spi_device *)my_xxx_dev->private_data;

	if(copy_from_user(&speed_hz, (void *)arg, sizeof(speed_hz))) {
		printk("copy mparam data error\n");
		return -1;
	}
	
	mutex_lock(&my_xxx_dev->buf_lock); 
	switch(cmd) {
		case 0:
			spi->max_speed_hz = speed_hz;
			spi_setup(spi);
			break;
		default:
			break;
	}	
	mutex_unlock(&my_xxx_dev->buf_lock); 
	
	return 0;
}

struct file_operations my_xxx_fops = {
    .owner          = THIS_MODULE,
    .open           = my_xxx_open,
    .release        = my_xxx_release,
	.read			= my_xxx_read,
    .write 			= my_xxx_write,
    .unlocked_ioctl = my_xxx_ioctl,
};

static int my_xxx_probe(struct spi_device *spi)
{
	int ret = 0;

	printk("spi driver and device was matched!\n");

	g_my_xxx_dev = kzalloc(sizeof(struct my_xxx_dev), GFP_KERNEL);
	if (!g_my_xxx_dev) {
        printk("kmalloc stepmotor dev fail.\n");
        return -1;
    }

	memcpy(g_my_xxx_dev, &g_my_xxx_init, sizeof(struct my_xxx_dev));
	
	g_my_xxx_dev->misc_dev.minor 	= MISC_DYNAMIC_MINOR;
    g_my_xxx_dev->misc_dev.name 	= my_xxx_DEV_NAME;
    g_my_xxx_dev->misc_dev.fops  	= &my_xxx_fops;
	
    ret = misc_register(&g_my_xxx_dev->misc_dev);
    if(unlikely(ret < 0)) {
        printk("register misc fail\n");
    }
	mutex_init(&g_my_xxx_dev->buf_lock);
	
	spi->mode = SPI_MODE_0;
	spi_setup(spi);

	g_my_xxx_dev->private_data = spi; 

	return ret;
}

static int my_xxx_remove(struct spi_device *spi)
{ 
    misc_deregister(&g_my_xxx_dev->misc_dev);

	kfree(g_my_xxx_dev);
	g_my_xxx_dev = NULL;
	
    return 0;
}

static const struct spi_device_id my_xxx_id_table[] = 
{
	{
	"test,my_xxx", 0},
	{
	},
};

static const struct of_device_id my_xxx_of_match[] = 
{   
	{
	.compatible = "test,my_xxx"},
	{
	},
};

static struct spi_driver my_xxx_driver = 
{
	.probe = my_xxx_probe,
	.remove = my_xxx_remove,
	.driver = {
		.name = "my_xxx",
		.owner = THIS_MODULE,
		.of_match_table = my_xxx_of_match,
	},
	.id_table = my_xxx_id_table,
};

int my_xxx_init(void)
{
	spi_register_driver(&my_xxx_driver);
	
    printk("%s module is installed\n", __func__);

    return 0;
}

void my_xxx_exit(void)
{	
	spi_unregister_driver(&my_xxx_driver);
	
    printk("%s module is removed.\n", __func__);
	
    return;
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值