AXI GPIO
正点原子第41章。
要使用AXI GPIO,就要在vivado工程中,添加相关的IP。 然后dts会自动生成相关的AXi GPIO的设备树内容。
MISC
正点原子第42章。
/***************************************************************Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.文件名 : miscbeep.c作者 : Skylar版本 : V1.0描述 : MISC设备驱动框架其他 : beeper论坛 : www.openedv.com日志 : 初版V1.0 2024/10/9 创建***************************************************************/#include <linux/module.h>
#include <linux/of_gpio.h>
// #include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
// #include <linux/leds.h>
#include <linux/miscdevice.h>#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/of_address.h>
#include <linux/of.h>
#include <linux/kern_levels.h>struct mybeep_dev {struct miscdevice mdev;int gpio;
};struct mybeep_dev beep_dev;/* beep相关初始化操作* @ pdev: struct platform_device指针* platform设备指针* @ 成功返回0,失败返回负数*/
static int mybeep_init(struct platform_device *pdev)
{struct device *dev = &pdev->dev;int ret;beep_dev.gpio = of_get_named_gpio(dev->of_node, "beeper-gpio", 0);if(!gpio_is_valid(beep_dev.gpio)){dev_err(dev, "Failed t oget gpio");return -EINVAL;}ret = devm_gpio_request(dev, beep_dev.gpio, "Beep Gpio");if(ret){dev_err(dev, "Failde to request gpio");return ret;}gpio_direction_output(beep_dev.gpio, 0);return 0;
}static int mybeep_open(struct inode *inode, struct file *filp)
{return 0;
}/** @description : 向设备写数据* @param – filp : 设备文件,表示打开的文件描述符* @param – buf : 要写给设备写入的数据* @param – cnt : 要写入的数据长度* @param – offt : 相对于文件首地址的偏移* @return : 写入的字节数,如果为负值,表示写入失败*/
static ssize_t mybeep_write(struct file *filp, const char __user *buf,size_t cnt, loff_t *offt)
{int ret;char kern_buf[5];ret = copy_from_user(kern_buf, buf, cnt);if(ret < 0){printk(KERN_ERR "mybeep: Failed to copy data from user buffer\r\n");return -EFAULT;}if(kern_buf[0] == 0)gpio_set_value(beep_dev.gpio, 0);else if(kern_buf[0] == 1)gpio_set_value(beep_dev.gpio, 1);return 0;
}static struct file_operations mybeep_fops = {.owner = THIS_MODULE,.open = mybeep_open,.write = mybeep_write,
};/* platform驱动的probe函数* @ 当驱动与设备匹配成功后此函数会执行* @ pdev: platforme设备指针* @ 成功返回0, 失败返回负值*/
static int mybeep_probe(struct platform_device *pdev)
{struct miscdevice *mdev;int ret;dev_info(&pdev->dev, "Driver and beep device have been matched\n");/* 初始化beep */ret = mybeep_init(pdev);if(ret){return ret;}/* 初始化beep_data变量 */mdev = &beep_dev.mdev;mdev->name = "mybeep"; // 设备名mdev->minor = MISC_DYNAMIC_MINOR; // 动态分配次设备号mdev->fops = &mybeep_fops;/* 向linux系统misc驱动框架核心层注册beep设备 */return misc_register(mdev);
}/* platform驱动模块卸载时* 此函数i执行* @ dev: platform设备指针* @ 成功返回0, 失败返回负值*/
static int mybeep_remove(struct platform_device *pdev)
{gpio_set_value(beep_dev.gpio, 0);/* 注销MISC设备驱动 */misc_deregister(&beep_dev.mdev);dev_info(&pdev->dev, "Beep device was removed\n");return 0;
}/* 匹配列表 */
static const struct of_device_id beep_of_match[] = {{.compatible = "fmql,beep"},{/* Sentinel */}
};static struct platform_driver mybeep_driver = {.driver = {.name = "mybeep", /* platform_driver name*/.of_match_table = beep_of_match,},.probe = mybeep_probe,.remove = mybeep_remove,
};module_platform_driver(mybeep_driver);MODULE_AUTHOR("Skylar <Skylar@33.com>");
MODULE_DESCRIPTION("MISC BEEP Device");
MODULE_LICENSE("GPL");
/***************************************************************Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.文件名 : miscbeepAPP.c作者 : Skylar版本 : V1.0描述 : beep MISC其他 : 使用方法 : ./miscbeepAPP /dev/mybeep 0./miscbeepAPP /dev/mybeep 1论坛 : www.openedv.com日志 : 初版V1.0 2024/10/9 创建***************************************************************/#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
// #include <sys/ioctl.h>
// #include <poll.h>
// #include <signal.h> int main(int argc, char *argv[]
{int fd, ret;unsigned char buf[1];if(argc != 3){printf("Usage:\n""\t./miscbeepApp /dev/mybeep 0 @ close Beep\n""\t./miscbeepApp /dev/mybeep 1 @ open Beep\n");return -1;}fd = open(argv[1], O_RDWR);if(fd < 0){printf("Erroe: file %s open failed\r\n", argv[1]);return -1;}buf[0] = atoi(argv[2]); // char -> intret = write(fd, buf, sizeof(buf));if(ret < 0){close(fd);return -1;}close(fd);return 0;
})
Makefile:
KERN_DIR :=/。。。/FMQL-Linux-SDK-Prj-20230801/linux-4.14.55-fmshCURRENT_DIR := $(shell pwd)obj-m :=miscbeep.oall:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C $(KERN_DIR) M=`pwd` modulesclean:make -C $(KERN_DIR) M=`pwd` clean
因为开发板上没有beep,所以就不进行测试了。