写一个linux uart driver驱动框架
时间: 2024-04-29 09:20:54 浏览: 109
下面是一个简单的Linux UART驱动程序的框架:
```c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/serial.h>
#define DRIVER_NAME "my_uart"
// 定义字符设备结构体
struct my_uart_dev {
struct cdev cdev;
struct class *class;
struct device *device;
dev_t devno;
struct uart_port uart;
};
static int my_uart_open(struct inode *inode, struct file *filp)
{
struct my_uart_dev *dev = container_of(inode->i_cdev, struct my_uart_dev, cdev);
filp->private_data = dev;
// 初始化串口
uart_config(&dev->uart);
return 0;
}
static ssize_t my_uart_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
struct my_uart_dev *dev = filp->private_data;
ssize_t ret;
// 从串口读取数据到buf中
ret = uart_read(&dev->uart, buf, count);
return ret;
}
static ssize_t my_uart_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
struct my_uart_dev *dev = filp->private_data;
ssize_t ret;
// 将buf中的数据写入到串口中
ret = uart_write(&dev->uart, buf, count);
return ret;
}
static const struct file_operations my_uart_fops = {
.owner = THIS_MODULE,
.open = my_uart_open,
.read = my_uart_read,
.write = my_uart_write,
};
static int __init my_uart_init(void)
{
int ret;
struct my_uart_dev *dev;
// 分配设备结构体的内存
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
ret = -ENOMEM;
goto err_alloc_dev;
}
// 初始化串口
uart_init_port(&dev->uart);
// 注册字符设备
dev->devno = MKDEV(0, 0);
ret = alloc_chrdev_region(&dev->devno, 0, 1, DRIVER_NAME);
if (ret < 0) {
goto err_alloc_chrdev_region;
}
cdev_init(&dev->cdev, &my_uart_fops);
dev->cdev.owner = THIS_MODULE;
ret = cdev_add(&dev->cdev, dev->devno, 1);
if (ret < 0) {
goto err_cdev_add;
}
// 创建设备节点
dev->class = class_create(THIS_MODULE, DRIVER_NAME);
if (IS_ERR(dev->class)) {
ret = PTR_ERR(dev->class);
goto err_class_create;
}
dev->device = device_create(dev->class, NULL, dev->devno, NULL, DRIVER_NAME);
if (IS_ERR(dev->device)) {
ret = PTR_ERR(dev->device);
goto err_device_create;
}
return 0;
err_device_create:
class_destroy(dev->class);
err_class_create:
cdev_del(&dev->cdev);
err_cdev_add:
unregister_chrdev_region(dev->devno, 1);
err_alloc_chrdev_region:
kfree(dev);
err_alloc_dev:
return ret;
}
static void __exit my_uart_exit(void)
{
struct my_uart_dev *dev = container_of(&my_uart_fops, struct my_uart_dev, cdev);
// 删除设备节点
device_destroy(dev->class, dev->devno);
class_destroy(dev->class);
// 注销字符设备
cdev_del(&dev->cdev);
unregister_chrdev_region(dev->devno, 1);
// 释放设备结构体的内存
kfree(dev);
}
module_init(my_uart_init);
module_exit(my_uart_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your name");
MODULE_DESCRIPTION("My UART driver");
```
需要注意的地方:
1. 在字符设备结构体`my_uart_dev`中,有一个`struct uart_port uart`成员,用来保存串口的状态。
2. 在驱动初始化函数`my_uart_init`中,需要分配`my_uart_dev`结构体的内存,并初始化`struct uart_port uart`成员。
3. 在驱动初始化函数`my_uart_init`中,需要注册字符设备,并创建设备节点。
4. 在驱动退出函数`my_uart_exit`中,需要删除设备节点,并注销字符设备。
阅读全文