编写SPI DAC驱动程序

参考资料:用户态调用spidev操作DAC模块

一、修改设备树

&spi0 {
    dac:dac@00{               
        compatible = "100ask,dac";     
        reg = <0>;
        spi-max-frequency = <10000000>;
        status="okay";
    };
};

二、编写驱动程序

#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <asm/uaccess.h>
#include <linux/device.h>
#include <linux/of.h>

static struct spi_device *dac;
static int major;

static long
spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	int val;
	int err;
	int old_val = 0;

	unsigned char tx_buf[2];
	unsigned char rx_buf[2];

	struct spi_message msg;
	struct spi_transfer xfer[1];
	int status;

	memset(&xfer[0], 0, sizeof(xfer));

	err = copy_from_user(&val, (const void __user *)arg, sizeof(int));
	printk(KERN_ERR"copy from user %d \n", val);

	val <<= 2;
	val &= 0xFFC;			//只发送8位

	tx_buf[0] = (val>>8) & 0xff;		//低位在前
	tx_buf[1] = val & 0xff;

	xfer[0].tx_buf = tx_buf;
	xfer[0].rx_buf = rx_buf;
	xfer[0].len = 2;

	spi_message_init(&msg);
	spi_message_add_tail(&xfer[0], &msg);

	status = spi_sync(dac, &msg);
	printk(KERN_ERR"spi_sync %d \n", status);

	old_val = (rx_buf[0]<<8) | (rx_buf[1]);		//把读到的数据返回给应用层
	old_val >>= 2;
	err = copy_to_user((void __user*)arg, &old_val, sizeof(int));

	return 0;
}

static const struct file_operations spidev_fops = {
	.owner = THIS_MODULE,
	.unlocked_ioctl = spidev_ioctl,
};

static struct class *spidev_class;

static const struct of_device_id spidev_dt_ids[] = {
	{ .compatible = "100ask,dac" },
	{},
};

static int spidev_probe(struct spi_device *spi)
{
	dac = spi;

	major = register_chrdev(0, "100ask_dac", &spidev_fops);
	spidev_class = class_create(THIS_MODULE, "100ask_dac");
	device_create(spidev_class, NULL, MKDEV(major, 0), NULL, "100ask_dac");

	return 0;
}

static int spidev_remove(struct spi_device *spi)
{
	device_destroy(spidev_class, MKDEV(major, 0));
	class_destroy(spidev_class);
	unregister_chrdev(major, "100ask_dac");

	return 0;
}

static struct spi_driver spidev_spi_driver = {
	.driver = {
		.name = "100ask_spi_dac_drv",
		.of_match_table = of_match_ptr(spidev_dt_ids),
	},
	.probe = spidev_probe,
	.remove = spidev_remove,
};

static int __init spidev_init(void)
{
	int status;

	status = spi_register_driver(&spidev_spi_driver);
	if(status < 0) {
		printk(KERN_ERR"spidev_spi_driver error\n");
	}

	return status;
}
module_init(spidev_init);

static void __exit spidev_exit(void)
{
	spi_unregister_driver(&spidev_spi_driver);
}
module_exit(spidev_exit);

MODULE_LICENSE("GPL");

三、编写应用程序

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

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <linux/types.h>

#define SPI_IOC_WR 123

int main(int argc, char **argv)
{
	int fd;
	unsigned int val;
	int status;

	unsigned char tx_buf[2];
	unsigned char rx_buf[2];

	if(argc != 3) {
		printf("Usage: %s /dev/100ask_dac <val>\n", argv[0]);
		return 0;
	}

	fd = open(argv[1], O_RDWR);
	if(fd < 0) {
		printf("can not open %s\n", argv[1]);
		return 1;
	}

	val = strtoul(argv[2], NULL, 0);

	status = ioctl(fd, SPI_IOC_WR, &val);
	if(status < 0) {
		printf("SPI_IOC_WR\n");
		return -1;
	}

	printf("Pre val = %d\n", val);

	return 0;
}

四、操作过程和结果

[root@firefly-rk3288:/home/picture/spi/dac_drv]# insmod dac_drv.ko
[  456.955496] dac_drv: loading out-of-tree module taints kernel.
[root@firefly-rk3288:/home/picture/spi/dac_drv]# ./dac_test /dev/
100ask_dac          loop2               stderr              tty33               tty61
ashmem              loop3               stdin               tty34               tty62
block/              loop4               stdout              tty35               tty63
bus/                loop5               tty                 tty36               tty7
char/               loop6               tty0                tty37               tty8
console             loop7               tty1                tty38               tty9
cpu_dma_latency     mali0               tty10               tty39               ttyFIQ0
dht11               mapper/             tty11               tty4                ttyS0
disk/               mem                 tty12               tty40               ttyS1
dri/                memory_bandwidth    tty13               tty41               ttyS2
ds18b20             mmcblk0             tty14               tty42               ttyS3
fb0                 mmcblk0p1           tty15               tty43               ttyS4
fd/                 mmcblk0p2           tty16               tty44               uhid
full                mmcblk2             tty17               tty45               uinput
fuse                mmcblk2boot0        tty18               tty46               urandom
hdmi_hdcp1x         mmcblk2boot1        tty19               tty47               usbmon0
hevc-service        mmcblk2rpmb         tty2                tty48               usbmon1
hwrng               net/                tty20               tty49               usbmon2
i2c-0               network_latency     tty21               tty5                usbmon3
i2c-2               network_throughput  tty22               tty50               usbmon4
i2c-3               null                tty23               tty51               v4l/
i2c-4               ppp                 tty24               tty52               vcs
i2c-6               ptmx                tty25               tty53               vcs1
iio:device0         pts/                tty26               tty54               vcsa
input/              ram0                tty27               tty55               vcsa1
irda                random              tty28               tty56               vendor_storage
kmsg                rfkill              tty29               tty57               vhci
log                 rtc                 tty3                tty58               video0
loop-control        rtc0                tty30               tty59               vpu-service
loop0               shm/                tty31               tty6                zero
loop1               snd/                tty32               tty60               zram0
[root@firefly-rk3288:/home/picture/spi/dac_drv]# ./dac_test /dev/100ask_dac 0
[  472.618281] copy from user 0
[  472.622078] spi_sync 0
Pre val = 0
[root@firefly-rk3288:/home/picture/spi/dac_drv]# ./dac_test /dev/100ask_dac 500
[  475.983460] copy from user 500
[  475.987103] spi_sync 0
Pre val = 0
[root@firefly-rk3288:/home/picture/spi/dac_drv]# ./dac_test /dev/100ask_dac 1000
[  479.009154] copy from user 1000
[  479.013211] spi_sync 0
Pre val = 500
[root@firefly-rk3288:/home/picture/spi/dac_drv]# ./dac_test /dev/100ask_dac 200
[  482.198009] copy from user 200
[  482.201851] spi_sync 0
Pre val = 1000
[root@firefly-rk3288:/home/picture/spi/dac_drv]# ./dac_test /dev/100ask_dac 300
[  484.559005] copy from user 300
[  484.562844] spi_sync 0
Pre val = 200
[root@firefly-rk3288:/home/picture/spi/dac_drv]# ./dac_test /dev/100ask_dac 400
[  486.566507] copy from user 400
[  486.570157] spi_sync 0
Pre val = 300
[root@firefly-rk3288:/home/picture/spi/dac_drv]# ./dac_test /dev/100ask_dac 500
[  489.214435] copy from user 500
[  489.218095] spi_sync 0
Pre val = 400
[root@firefly-rk3288:/home/picture/spi/dac_drv]#

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

习惯就好zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值