刚接触安卓嵌入式底层开发有些疑惑
对于模块驱动开发,接口是串口方式
在Linux中,应用层直接调用两个驱动文件,
而安卓驱动中,
是单独两个驱动(模块驱动和串口驱动)再通过应用层相互调用?那底层如何处理好数据再传给app呢?
还是直接写成一个设备驱动,里面包含注册串口驱动和模块驱动,再将驱动接口传给hal层呢?
在安卓嵌入式底层开发中,模块驱动和串口驱动可以分开实现。例如,我们可以在内核中实现一个模块驱动,它负责控制硬件设备,将数据从硬件读取到内核空间中,并提供一个字符设备接口,应用程序可以通过这个接口来读取数据。同时,我们也可以实现一个串口驱动,它负责将数据从内核空间发送到串口设备中,并提供一个串口设备接口,模块驱动可以通过这个接口将数据发送到串口设备中。
在底层处理数据时,模块驱动和串口驱动可以通过内核的缓冲区来进行数据传输。在模块驱动中,我们可以使用内核的缓冲区来存储从硬件设备读取到的数据。同时,我们也可以在串口驱动中使用内核的缓冲区来存储要发送到串口设备的数据。这样,模块驱动和串口驱动就可以通过内核的缓冲区来传输数据了。
以下是一个简单的例子,展示了如何在安卓平台上实现一个基本的模块驱动和串口驱动:
模块驱动:
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
static dev_t dev;
static struct cdev cdev;
static struct class *cls;
static char buffer[1024];
static int my_open(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
if (copy_to_user(buf, buffer, count))
return -EFAULT;
return count;
}
static ssize_t my_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
if (copy_from_user(buffer, buf, count))
return -EFAULT;
return count;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = my_open,
.read = my_read,
.write = my_write,
};
static int __init my_init(void)
{
int ret;
ret = alloc_chrdev_region(&dev, 0, 1, "my_dev");
if (ret < 0) {
printk("failed to allocate chrdev region\n");
return ret;
}
cdev_init(&cdev, &fops);
cdev_add(&cdev, dev, 1);
cls = class_create(THIS_MODULE, "my_class");
device_create(cls, NULL, dev, NULL, "my_dev");
return 0;
}
static void __exit my_exit(void)
{
device_destroy(cls, dev);
class_destroy(cls);
cdev_del(&cdev);
unregister_chrdev_region(dev, 1);
}
module_init(my_init);
module_exit(my_exit);
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("My Module");
MODULE_LICENSE("GPL");
串口驱动:
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/serial.h>
#include <linux/uaccess.h>
static dev_t dev;
static struct cdev cdev;
static struct class *cls;
static struct uart_driver uart_driver;
static struct uart_port uart_port;
static char buffer[1024];
static int my_open(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
if (copy_to_user(buf, buffer, count))
return -EFAULT;
return count;
}
static ssize_t my_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
if (copy_from_user(buffer, buf, count))
return -EFAULT;
uart_write(&uart_port, buffer, count);
return count;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = my_open,
.read = my_read,
.write = my_write,
};
static int my_startup(struct uart_port *port)
{
return 0;
}
static void my_shutdown(struct uart_port *port)
{
}
static void my_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old)
{
}
static void my_stop_tx(struct uart_port *port)
{
}
static void my_start_tx(struct uart_port *port)
{
}
static void my_rx_chars(struct uart_port *port)
{
int i, count;
count = uart_read(&uart_port, buffer, sizeof(buffer));
for (i = 0; i < count; i++)
uart_insert_char(&uart_port, buffer[i], UART_RX_FULL);
}
static struct uart_ops ops = {
.startup = my_startup,
.shutdown = my_shutdown,
.set_termios = my_set_termios,
.stop_tx = my_stop_tx,
.start_tx = my_start_tx,
.rx_chars = my_rx_chars,
};
static int __init my_init(void)
{
int ret;
uart_driver = (struct uart_driver) {
.owner = THIS_MODULE,
.driver_name = "my_uart",
.dev_name = "ttyMY",
.major = 0,
.minor = 0,
.nr = 1,
};
uart_port = (struct uart_port) {
.ops = &ops,
};
ret = uart_register_driver(&uart_driver);
if (ret < 0) {
printk("failed to register uart driver\n");
return ret;
}
cls = class_create(THIS_MODULE, "my_class");
device_create(cls, NULL, MKDEV(uart_driver.major, uart_driver.minor), NULL, "my_uart");
return 0;
}
static void __exit my_exit(void)
{
device_destroy(cls, MKDEV(uart_driver.major, uart_driver.minor));
class_destroy(cls);
uart_unregister_driver(&uart_driver);
}
module_init(my_init);
module_exit(my_exit);
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("My UART Driver");
MODULE_LICENSE("GPL");
在上述例子中,模块驱动和串口驱动分别实现了字符设备接口和串口设备接口,并通过内核的缓冲区来传输数据。应用程序可以通过字符设备接口和串口设备接口来读取和写入数据。