嵌入式学习(四)——嵌入式Linux设备驱动开发(一)

姓名:李萌怡  学号:19020100103  学院:电子工程学院

转自:https://blog.csdn.net/light_in_dark/article/details/73321105

【嵌牛导读】:对于嵌入式系统的学习来说,学习嵌入式Linux驱动开发是十分重要的环节。本文对嵌入式linux设备系统开发作以简要总结。

【嵌牛鼻子】:寄存器  结构体

【嵌牛提问】:字符设备驱动开发流程有哪些?

【嵌牛正文】

一、Linux设备的分类

字符设备、块设备、网络设备,三种设备之间的区别是数据的交互模式,分别为:

字节流、数据块、数据包。

二、VFS核心结构体

VFS核心结构体定义在”linux/fs.h”头文件中。

1、struct inode结构体

记录文件的属主、访问时间等信息。当第一次打开文件的时候由VFS创建并初始化。当文件的所有引用都退出后,释放inode; 如果用户态有多个人同时打开一个文件,则VFS只需要分配一个inode。

2、struct file结构体

对应用户态的open操作。如果多次打开同一个文件,内核会生成多个file。file中记录文件的打开方式,文件内部指针等。当文件彻底关闭时,释放file。

3、struct file_operations结构体

该结构体包含若干函数指针,这些函数由驱动来实现,并集中到file_operations中,注册到VFS。

驱动一般要实现的函数有:

open

release

read

write

unlocked_ioctl

驱动可能会实现的有:

poll

mmap

fasync

flush

llseek

三、字符设备驱动开发流程

(1)确定硬件信息

要确定硬件的数量,物理地址,中断号等信息;

(2)为要支持的设备准备一个私有结构体

内核并不要求必须有私有结构体,但如果驱动支持多个设备,最好设计一个。私有结构体完全由驱动人员自行设计,一般来说,会把和设备相关的信息写入该结构体,比如设备的地址等。

(3)为要支持的每个设备分配对应的设备号

设备号由char驱动分配,要求唯一。一般来说,如果char驱动可支持多个类似的设备,则应该为这些设备选择一个主设备号,然后为每个设备选择一个特定的次设备号。尽量挑选和其他驱动不一样的主设备号。可以看/proc/devices,文件中记录了其他驱动选择的主设备号;也可以向内核申请,由内核分配一个主设备号。

#define DEV_MAJOR  50

...

dev_id = MKDEV(DEV_MAJOR, 0);

(4)准备file_operations结构体

函数集中包括open/release/read/write/unlocked_ioctl等函数,如果驱动支持多个设备,在函数中必须能区分自己访问的是哪个设备。

static struct file_operations mem_fops = {

    .owner = THIS_MODULE,

    .open = mem_open,

    .release = mem_release,

    .read = mem_read,

    .write = mem_write,

    .unlocked_ioctl = mem_ioctl,

};

(5)注册设备

方法一:

利用cdev结构体,将设备号和file_operations注册到VFS。一般来说,将cdev结构体包含到私有结构体中。采用cdev注册的设备,不会自动创建设备文件。

cdev_init(&mem_cdev, &mem_fops);

cdev_add(&mem_cdev, dev_id, 1);

cdev_del(&mem_cdev);  //注销cdev 

方法二:

注册miscdevice(用misc代替cdev注册,可以自动创建设备文件)

这种情况下不需要定义主设备号,即省去#define DEV_MAJOR 50,同时需要用头文件”linux/miscdevice.h”代替”linux/cdev.h”头文件。

static struct miscdevice mem_miscdev = {

    .minor  = MISC_DYNAMIC_MINOR,

    .name  = "mem",    //对应/dev/mem设备文件

    .fops  = &mem_fops,

};

ret = misc_register(&mem_miscdev); //注册miscdevice

misc_deregister(&mem_miscdev);    //注销miscdevice

cdev和miscdevice比较:

(1)cdev可以实现同一个驱动对应多个设备,而miscdevice只能实现一个驱动对应一个设备;

(2)cdev不能实现设备文件的自动创建,而miscdevice可以实现设备文件的自动创建。

上述的过程比较适合较简单的设备,比如看门狗,led灯,各种传感器等。较复杂设备的char驱动,常常要利用内核提供的驱动子系统代码进行设计。

四、如何在linux驱动中访问寄存器(SFR)

1、片内外设(pripheral)

(1)基于三总线访问

(2)用寄存器控制

(3)寄存器有物理地址,可通过手册查到,不可更改

2、片外外设

(1)很少通过三总线相连,一般是通过UART,CAN,I2C,USB,SPI,MIPI,I2S,AC97等总线相连。主芯片内部必须提供对应的控制器:内部的控制器 <–> 外部的外设

(2)片外外设基本都是智能设备(不但有硬件,还有软件)

(3)有些片外外设通过寄存器控制,有些则通过命令控制

(4)如果用寄存器控制,寄存器没有物理地址,只有偏移。

(5)要控制片外外设,需要首先了解对应的总线

3、访问寄存器的流程

由于linux使能了MMU,因此对于驱动来说,不能直接使用寄存器的物理地址,必须将其映射为虚拟地址才可以使用。

(1)定义寄存器物理基地址以及寄存器的偏移

#define GPIO_BASE  0x11000000

#define GPIO_SIZE  0x1000  //0x8

#define GPM4CON    0x2E0  //偏移地址

#define GPM4DAT    0x2E4  //偏移地址

GPIO_SIZE为寄存器的范围,可以按照使用的寄存器的总大小进行计算,比如用了两个寄存器,范围是0x8;但由于地址映射的最小单位是4K,因此小于4K的值都是可以的。

(2)将寄存器物理地址映射到虚拟地址,如果映射不成功,则无法访问寄存器

static void __iomem *vir_base;

vir_base = ioremap(GPIO_BASE, GPIO_SIZE);

if (!vir_base) {

    printk("Cannot ioremap\n");

    return -EIO;

(3)访问寄存器,一般采用基地址加偏移的模式,内核根据寄存器的大小,提供了一系列函数

8位寄存器的访问

char value;

value = readb(vir_base + offset);

writeb(value, (vir_base + offset));

16位寄存器的访问

short value;

value = readw(vir_base + offset);

writew(value, (vir_base + offset));

32位寄存器的访问

int value;

value = readl(vir_base + offset);

writel(value, (vir_base + offset));

64位寄存器的访问

u64 value;

value = readq(vir_base + offset);

writeq(value, (vir_base + offset));

(4)取消寄存器的映射

iounmap(vir_base);

————————————————

版权声明:本文为CSDN博主「light_in_dark」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/light_in_dark/article/details/73321105

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容