В этой статье рассказывается, как использовать среду различных устройств для написания простого драйвера кнопок, завершения написания, компиляции, установки, тестирования и других процессов, а также понимания процесса разработки драйвера различных символьных устройств.
Ниже приведены интерфейсы для различных символьных устройств:
struct miscdevice {
int minor; /*Номер вторичного устройства 10 20 */
const char *name; /*Имя узла устройства*/
const struct file_operations *fops; /*Коллекция файловых операций*/
struct list_head list; // связанный список
struct device *parent;
struct device *this_device;
const char *nodename;
umode_t mode;
};
//Регистрируем разные символьные устройства
extern int misc_register(struct miscdevice * misc);
//Отменяем регистрацию различных символьных устройств
extern int misc_deregister(struct miscdevice *misc);
Ключ должен передать значение на прикладной уровень.,Нужно использоватьcopy_to_user
функция,этотфункция Также есть соответствиеcopy_from_user
,Подробные функции и параметры этих двух функций представлены ниже:
#include <asm/uaccess.h>
unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
Функция функция: Скопируйте данные уровня драйвера на уровень приложения.
Параметры функции:
void __user *to Адрес пространства пользователя – куда идти
const void *from Адрес уровня драйвера — откуда он берется
unsigned long n размер копии
Возвращаемое значение: 0 указывает на успех. >0Указывает количество копий, которые не были успешно скопированы.。
unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
Функция функция: Скопируйте данные с уровня приложения на уровень драйвера.
Параметры функции:
void *to Адрес места на диске — куда его скопировать
const void __user *from Адрес пользовательского пространства — откуда он берется
unsigned long n размер копии
Возвращаемое значение: 0 указывает на успех. >0Указывает количество копий, которые не были успешно скопированы.。
Используйте разные устройства для регистрации драйверов ключей, а уровень приложения использует интерфейс чтения для чтения значений ключей.
Прежде чем писать драйвер, нужно найти принципиальную схему кнопки и узнать, к какому IO кнопка подключена к ЦП.
Затем проверьте таблицу данных, чтобы найти адрес регистра порта GPIO, и страницу конфигурации регистра, чтобы облегчить инициализацию и настройку порта GPIO в режиме ввода.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <asm/uaccess.h>
/* Кнопка регистрации*/
static unsigned int *GPX3CON;
static unsigned int *GPX3DAT;
static int tiny4412_open(struct inode *inode, struct file *file)
{
printk("tiny4412_open-->ok\n");
return 0;
}
/*Функции прикладного уровня:
int key_val;
read(fd,&key_val,4)
ssize_t read(int fd, void *buf, size_t count);
*/
static ssize_t tiny4412_read(struct file *file, char __user *buf, size_t size, loff_t *seek)
{
int key_val=0;
if(!(*GPX3DAT&1<<2)) //Определяем, нажата ли кнопка
{
key_val=0x1;
}
else if(!(*GPX3DAT&1<<3)) //Определяем, нажата ли кнопка
{
key_val=0x2;
}
else if(!(*GPX3DAT&1<<4)) //Определяем, нажата ли кнопка
{
key_val=0x3;
}
else if(!(*GPX3DAT&1<<5)) //Определяем, нажата ли кнопка
{
key_val=0x4;
}
/*Функция копирования данных: Присвойте значение пространству прикладного уровня — скопируйте данные уровня драйвера на прикладной уровень*/
/*copy_to_user(void __user *to, const void *from, unsigned long n)*/
int error;
error=copy_to_user(buf,&key_val,4);
if(error>0)
{
printk("Не удалось скопировать данные.\n");
}
return 0;
}
static ssize_t tiny4412_write(struct file *file, const char __user *buf, size_t size, loff_t *seek)
{
return 0;
}
static int tiny4412_release(struct inode *inode, struct file *file)
{
printk("tiny4412_release-->ok\n");
return 0;
}
static struct file_operations fops=
{
.open=tiny4412_open,
.read=tiny4412_read,
.write=tiny4412_write,
.release=tiny4412_release
};
/*
Драйвер управления ядром Linux — номер устройства
Номер устройства является беззнаковым int Переменная - 32 бита.
Номер устройства = основной номер устройства + дополнительный номер устройства.
*/
static struct miscdevice misc=
{
.minor = MISC_DYNAMIC_MINOR, /*Номер вторичного устройствозаполнение 255 означает автоматическое распределение Основной номер устройства фиксирован: 10*/
.name = "tiny4412_key", /*/Имя файла в каталоге dev*/
.fops = &fops, /*Интерфейс работы с файлами*/
};
static int __init tiny4412_key_init(void)
{
/*Преобразование физического адреса*/
GPX3CON=ioremap(0x11000C60,4);
GPX3DAT=ioremap(0x11000C64,4);
/*Настроить режим порта GPIO — настроить кнопки*/
*GPX3CON&=0xFF0000FF;
/*1. Функции регистрации для разных устройств*/
misc_register(&misc);
printk("Кнопка: Установка драйвера прошла успешно\n");
return 0;
}
static void __exit tiny4412_key_exit(void)
{
/*2. Функция выхода из системы для различного оборудования*/
misc_deregister(&misc);
/*Отменить преобразование*/
iounmap(GPX3CON);
iounmap(GPX3DAT);
printk("Кнопка: Драйвер успешно удален\n");
}
module_init(tiny4412_key_init); /*Ввод драйвера — выполняется при установке драйвера*/
module_exit(tiny4412_key_exit); /*Экспорт драйвера — выполняется при удалении драйвера*/
MODULE_LICENSE("GPL"); /*Установить лицензию модуля — GPL*/
Скомпилируйте код make-файла драйвера.
KER_DRI=/home/wbyq/work/linux-3.5/linux-3.5
all:
make -C $(KER_DRI) M=`pwd` modules
cp *.ko /home/wbyq/work/rootfs/code -f
make -C $(KER_DRI) M=`pwd` modules clean
arm-linux-gcc app.c -o app
cp app /home/wbyq/work/rootfs/code -f
rm app -f
obj-m += miscdev_key_drv.o
После компиляции и запуска передайте файл узла устройства кнопки.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char **argv)
{
if(argc!=2)
{
printf("./app <Файл узла устройства>\n");
return 0;
}
/*1. Открыть файл устройства*/
int fd=open(argv[1],O_RDWR);
if(fd<0)
{
printf("%s Не удалось открыть драйвер устройства.\n",argv[1]);
return 0;
}
/*2.Чтение и запись данных*/
int key_val;
while(1)
{
read(fd,&key_val,4);//Читаем значение ключа
если (key_val)
{
printf("%#x\n",key_val);
}
}
/*3. Закрыть файл*/
close(fd);
return 0;
}
[root@wbyq code]# ls
tiny4412_key_drv.ko
[root@wbyq code]#
[root@wbyq code]# insmod tiny4412_key_drv.ko
[ 173.340000] Тест водителя: Установка драйвера прошла успешно
[root@wbyq code]# lsmod
hello_drv 616 0 - Live 0xbf000000 (O)
[root@wbyq code]# modinfo tiny4412_key_drv.ko
filename: tiny4412_key_drv.ko
license: GPL
depends:
vermagic: 3.5.0-FriendlyARM SMP preempt mod_unload ARMv7 p2v8
[root@wbyq code]# rmmod tiny4412_key_drv.ko
[ 391.075000] Тест водителя: Драйвер успешно удален
[root@wbyq code]#