驱动开发-day9
驱动代码:
-
-
-
-
-
-
-
-
-
-
-
-
struct cdev* cdev;
-
unsigned int major = 500;
-
unsigned int minor = 0;
-
dev_t devno;
-
struct class* cls;
-
struct device* dev;
-
struct device_node* dnode;
-
struct device_node* dnode_led;
-
unsigned int irqno;
-
unsigned int number = 0;
-
// 定义等待队列头
-
wait_queue_head_t wq_head;
-
unsigned int condition = 0;
-
// 分配对象
-
struct work_struct work;
-
char kbuf[128] = { 0 };
-
struct gpio_desc* gpiono;
-
int mycdev_open(struct inode* inode, struct file* file)
-
{
-
-
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
-
return 0;
-
}
-
ssize_t mycdev_read(struct file* file, char* ubuf, size_t size, loff_t* lof)
-
{
-
int ret;
-
-
wait_event_interruptible(wq_head, condition);
-
-
if (size > sizeof(number)) {
-
size = sizeof(number);
-
}
-
-
ret = copy_to_user(ubuf, (void*)&number, size);
-
if (ret) {
-
printk("copy_to_user filed\n");
-
return -EIO;
-
}
-
condition = 0;
-
return size;
-
}
-
ssize_t mycdev_write(struct file* file, const char* ubuf, size_t size, loff_t* lof)
-
{
-
-
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
-
return 0;
-
}
-
int mycdev_close(struct inode* inode, struct file* file)
-
{
-
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
-
return 0;
-
}
-
long mycdev_ioctl(struct file* file, unsigned int cmd, unsigned long arg)
-
{
-
return 0;
-
}
-
struct file_operations fops = {
-
.open = mycdev_open,
-
.unlocked_ioctl = mycdev_ioctl,
-
.read = mycdev_read,
-
.write = mycdev_write,
-
.release = mycdev_close,
-
};
-
-
// 中断触发函数
-
irqreturn_t myirq_handler(int irqno, void* dev_id)
-
{
-
if (!gpio_get_value(gpiono)) {
-
number = !number;
-
gpiod_set_value(gpiono, number);
-
condition = 1;
-
wake_up_interruptible(&wq_head);
-
}
-
-
return IRQ_HANDLED;
-
}
-
// 解析led设备树
-
int myled_init(void)
-
{
-
// 解析led灯的设备树节点
-
dnode_led = of_find_node_by_path("/led_key");
-
if (dnode_led == NULL) {
-
printk("解析设备led树节点失败\n");
-
return -ENXIO;
-
}
-
printk("解析设备树节点成功 \n");
-
// 根据设备树节点解析led1gpio编号
-
gpiono = gpiod_get_from_of_node(dnode_led, "led1-gpios", 0, GPIOD_OUT_LOW, NULL);
-
if (IS_ERR(gpiono)) {
-
printk("gpio编号解析失败\n");
-
return -PTR_ERR(gpiono);
-
}
-
return 0;
-
}
-
// 解析按键设备树
-
int myirq_init(void)
-
{
-
int wet;
-
dnode = of_find_node_by_name(NULL, "led_key");
-
if (dnode == NULL) {
-
printk("解析设备树key节点失败\n");
-
return -ENXIO;
-
}
-
printk("设备树节点解析成功\n");
-
// 获取软中断号
-
irqno = irq_of_parse_and_map(dnode, 0);
-
if (!irqno) {
-
printk("软中断号获取失败\n");
-
return -ENOMEM;
-
}
-
printk("软中断号获取成功irqno=%d\n", irqno);
-
// 注册中断
-
wet = request_irq(irqno, myirq_handler, IRQF_TRIGGER_FALLING, "key1-gpios", NULL);
-
if (wet) {
-
printk("注册失败\n");
-
return wet;
-
}
-
return 0;
-
}
-
static int __init mycdev_init(void)
-
{
-
int ret, i;
-
// 初始化等待队列头
-
init_waitqueue_head(&wq_head);
-
// 分配字符设备驱动对象空间
-
cdev = cdev_alloc();
-
if (cdev == NULL) {
-
printk("申请字符设备驱动空间失败\n");
-
ret = -EFAULT;
-
goto out1;
-
}
-
// 字符设备驱动对象部分初始化
-
cdev_init(cdev, &fops);
-
// 静态申请设备号
-
if (major > 0) {
-
-
ret = register_chrdev_region(MKDEV(major, minor), 3, "mykey");
-
if (ret) {
-
printk("静态指定设备号失败\n");
-
goto out2;
-
}
-
} else { // 动态申请设备号
-
ret = alloc_chrdev_region(&devno, minor, 3, "mykey");
-
if (ret) {
-
printk("动态指定设备号失败\n");
-
goto out2;
-
}
-
major = MAJOR(devno);
-
minor = MINOR(devno);
-
}
-
// 注册字符设备驱动对象
-
ret = cdev_add(cdev, MKDEV(major, minor), 3);
-
if (ret) {
-
printk("注册字符设备驱动对象失败\n");
-
goto out3;
-
}
-
printk("注册字符设备驱动对象成功\n");
-
// 向上提交目录
-
cls = class_create(THIS_MODULE, "mykey");
-
if (IS_ERR(cls)) {
-
printk("向上提交目录失败\n");
-
ret = -PTR_ERR(cls);
-
goto out4;
-
}
-
printk("向上提交目录成功\n");
-
// 向上提交设备节点
-
for (i = 0; i < 3; i ) {
-
dev = device_create(cls, NULL, MKDEV(major, i), NULL, "mykey%d", i);
-
if (IS_ERR(dev)) {
-
printk("向上提交节点信息失败\n");
-
ret = -PTR_ERR(dev);
-
goto out5;
-
}
-
}
-
printk("向上提交设备节点信息成功\n");
-
-
// 解析设备树节点
-
myled_init();
-
// 解析设备树节点
-
myirq_init();
-
return 0;
-
out5:
-
for (--i; i > 0; i--) {
-
// 销毁提交的设备信息
-
device_destroy(cls, MKDEV(major, i));
-
}
-
class_destroy(cls);
-
out4:
-
cdev_del(cdev);
-
out3:
-
unregister_chrdev_region(MKDEV(major, minor), 3);
-
out2:
-
kfree(cdev);
-
out1:
-
return ret;
-
}
-
static void __exit mycdev_exit(void)
-
{
-
// 注销中断
-
free_irq(irqno, NULL);
-
// 销毁设备信息
-
int i;
-
for (i = 0; i < 3; i ) {
-
device_destroy(cls, MKDEV(major, i));
-
}
-
// 销毁目录
-
class_destroy(cls);
-
// 注销对象
-
cdev_del(cdev);
-
// 释放设备号
-
unregister_chrdev_region(MKDEV(major, minor), 3);
-
// 释放对象空间
-
kfree(cdev);
-
}
-
module_init(mycdev_init);
-
module_exit(mycdev_exit);
-
MODULE_LICENSE("GPL");
测试代码:
-
-
-
-
-
-
-
-
-
-
int main(int argc, char const* argv[])
-
{
-
int fd;
-
-
unsigned int number;
-
-
fd = open("/dev/mykey0", O_RDWR);
-
if (fd < 0) {
-
printf("打开设备文件失败\n");
-
exit(-1);
-
}
-
-
while (1) {
-
-
read(fd, &number, sizeof(number));
-
printf("number=:%d\n", number);
-
}
-
close(fd);
-
return 0;
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgakcbf
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01