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 -> int
ret = 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-fmsh
CURRENT_DIR := $(shell pwd)
obj-m :=miscbeep.o
all:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` clean
因为开发板上没有beep,所以就不进行测试了。