嵌入式Linux视频笔记----驱动开发

https://www.bilibili.com/video/BV1pf4y1974n/?spm_id_from=333.788.videocard.1

基本看完了,基本只看视频没看详细的pdf,试验挑着做,一讲代码就懵逼。但还是有了基本的概念,知道驱动相关知识

 

P1 内核模块基本概念
现代内核派系:宏内核--Linux等、关键功能和服务功能均在内核、效率高、扩展性差;微内核--关键功能在内核,服务功能在用户空间、效率低、扩展性高
内核模块:加载、卸载;入口、出口;信息声明

下面两个实验都是最简单的实验,纯属教学用途,理解原理。
P2 内核模块试验1
实验环境;下载 编译内核;内核模块打印函数printk;
nfs共享;内核源码;模块编译、插入、删除

P3 内核模块试验2
设置MobaXterm长字符串显示
模块参数:定义变量、插入内核模块时带参数
符号共享:变量共享、函数共享;查看符号表cat /proc/kallsyms | grep my_add;模块自动加载 卸载;

P4 Linux内核是怎么设计字符设备的
字符设备、块设备、网络设备
字符设备使用多且简单
硬件层:类似裸机开发,实现底层操作接口
驱动层:操作接口注册到内核、主次设备号登记
文件系统层:mknod

P5 设备号的组成与哈希表
设备号:主次设备号;驱动对应1个主设备号,多个次设备号;
hash table:哈希表、散列表;数组和链表特性;哈希表=数组+链表

P6 从源码看如何管理设备号
关键数据结构:char_device_struct
__register_chrdev_region函数代码分析

P7 从源码看如何保存file_operation接口
结构体cdev、kobj_map
函数cdev_init、cdev_add

P8 如何创建一个设备文件
mknod:用法;原理--层层调用、init_special_inode函数分析

P9 open函数如何查找file_operation接口
get_unused_fd_flags、do_file_open、do_dentry_open

P10 LED字符设备驱动试验1
驱动模块=内核模块+驱动接口:内核模块配置GPIO、文件操作接口注册到内核、设备文件绑定文件操作接口、echo控制led
驱动模块初始化:寄存器映射ioremap;虚拟地址读写iowrite32
自定义file_operation接口:结构体函数指针对应的函数实现,实际仅完成写函数;拷贝数据copy_from_user

P11 LED字符设备驱动试验2
注册字符设备驱动:register_chrdev函数;也可以自己写,更灵活
操作演示:主机:make、make copy;开发板:insmod /mnt/chrdev.ko、cat /proc/devices、sudo mknod /dev/lightLED c 244 0、sudo sh -c "echo on >/dev/lightLED"

P12 Linux设备驱动模型
设备驱动模型:分类分层次、命名自由
sysfs:通过sysfs体现设备驱动模型;是虚拟文件系统;基本驱动对象kobject
设备驱动模型基本元素:kobject、kset、kobj_type
驱动模型:经典--kobject kset层层叠加;简单但无用--纯kobject

P13 kobject:驱动的基石
重点:sysfs目录项 关联 kobject对象
代码:kobject_create_and_add()、kobject_create()、kobject_init()、kobject_init_internal()、kobject_add()、kobject_add_varg()、kobject_set_name_vargs()、kobject_add_internal()、create_dir()、sysfs_create_dir_ns()、
一脸懵逼

P14 kobj_type:用户空间的法宝
重点:属性文件具体操作接口赋值;open read write函数底层机制
代码 属性文件具体操作接口赋值:sysfs_create_group(), struct attribute_group, internal_create_group(), create_files(), sysfs_add_file_mode_ns(), struct kernfs_ops, __kernfs_create_file()
代码 open read write函数底层机制:open--kernfs_init_inode(), struct kernfs_file_fops, kernfs_fop_open(), seq_open(), struct seq_file;read--kernfs_fop_read(), kernfs_of(), seq_read(), sysfs_kf_seq_show(), seq_get_buf(), sysfs_file_ops(), kobj_attr_show(),
两脸懵逼

P15 设备驱动模型试验1-kobject点灯
内核模块+led驱动+kobject+kobj_attribute
foo_show(), foo_store(), kstrtoint(), led_show(), led_store(),
主机:make、make copy;开发板:insmod /mnt/kobject_led.ko、ls /sys、sudo sh -c "echo 'on' >/sys/led_kobject/led"
相比P11,不需要mknod,路径更深1层,路径从dev换为sys

P16 kset:驱动的骨架
体现设备驱动层次关系
kset_create_and_add(), kset_create(), kset_register(), kset_init(), kobject_uevent(), 
演示:相比P15,多了1层kset。路径更深1层

P17 uevent:内核消息的快递包
内核空间kobject对象通过uevent机制向用户空间发信息
内核消息发送:kobject_uevent(), kobject_uevent_env(), 
演示:udevadm monitor &,插入模块时传递消息

P18 class:设备的大管家
分类管理硬件设备;配合udev自动创建设备文件
创建class:宏class_create、device_create()
演示:属性文件路径 /sys/class/xxx/my_led/dev、自动创建/dev/my_led

P19 xbus:打造自属的驱动总线
驱动总线:软硬件代码分离,提高复用性;device--硬件代码;driver_devices--软件代码;bus_type--软硬件匹配
总线管理:buses_init()内核启动默认执行、/sys/bus
总线注册:bus_register()添加新的总线类型、/sys/bus/xbus/devices drivers
设备注册:device_register()添加设备、/sys/bus/xbus/devices/设备名
驱动注册:driver_register()关联软件代码/sys/bus/xbus/drivers/驱动名
设备驱动模型框图
试验:代码分析;生成3个.ko;依次插入内核模块xbus xdev xdrv,最后一个自动调用其他函数

P20 platform:虚拟的平台总线
platform_device继承device;platform_driver继承device_driver;platform类似bus_type
平台总线注册:内核上电自动执行platform_bus_init()
匹配规则:platform_match() 设备树、id_table、名称匹配
平台设备注册:platform_device_regiter()、resource结构体
平台驱动注册:platform_driver_register宏
平台驱动获取资源:platform_get_resource() 寄存器地址

P21 设备驱动模型试验2--代码分离
试验:代码分析;生成2个.ko;依次插入内核模块platform_device platform_driver,后者自动调用led_probe;控制LED亮灭 sudo sh -c "echo 'on'>/dev/my_led"

P22 DTS设备树源码:硬件资源说明书1
设备树:uboot加载到内存,内核使用;设备树源文件编译为二进制设备树;
编译:内核编译、手工编译
设备树框架:imx6ull.dtsi 通用且常用的设备树;设备主体、子节点追加内容;
节点命名:基本方法、节点标签、别名子节点批量申请别名

P23 DTS:硬件资源说明书2
常见节点属性:compatible 字符串 芯片厂商及驱动名;model 字符串 板卡型号;status 字符串 运行状态;reg 值类型 寄存器地址和长度;address-cells size-cells 值类型 子节点寄存器地址和长度的数量;
查看设备树:ls /sys/firmware/devicetree/base  ls /proc/device-tree
设备树源文件与linux目录项对应关系
添加子节点:修改源文件、编译、复制、替换、sync、查看新设备树

P24 获取DTS属性信息
节点-->属性
节点表示:DTB-->结构体device_node-->platform_device
查节点:路径--of_find_node_by_path();类型--of_find_node_by_type();名字--of_find_node_by_name();compatible属性--of_find_node_by_node()
查节点属性:节点+属性--of_find_property();of_property_read_u32();of_property_read_u32_array();of_property_read_string();
演示:代码分析;insmod /mnt/get_dts_info.ko、ls /dev/get_dts_info、sudo sh -c "echo 1>/dev/get_dts_info"

P25 设备树实现RGB灯驱动
设备树添加节点信息:内核--设备树文件dts增加代码、编译并替换设备树;驱动--代码分析、make、insmod、ls /dev/rgb_led、sudo sh -c "echo '7'>/dev/rgb_led"

P26 Device Tree Overlays:“插件”设备树
设备树:传统--批量、僵化;“插件”--扩展语法、灵活
使用前提:内核配置、挂载ConfigFS
案例说明:语法
使用方式:编译命令;内核加载、通用但步骤略复杂;uboot加载,简单,野火;

P27 插件设备树实现RGB驱动
编写插件设备树文件、ls /home/pi/build/scripts/dtc/、dtc编译/home/pi/build/scripts/dtc/dtc -I dts -O dtb -o rgb.dtbo led.dts、复制sudo cp rgb.dtbo ~/workdir/nfsdir/、恢复原来的设备树、sudo mkdir /sys/kernel/config/device-tree/overlays/xxx、lsattr rgb.dtbo
lsattr: Permission denied While reading flags on rgb.dtbo试验失败

P28 iomuxc节点:pinctrl子系统初窥
iomuxc节点汇总引脚配置信息,pinctrl子系统预存iomuxc节点信息
iomuxc节点:imx6ull.dtsi、详细分析imx6ull-seeed-npi.dts
节点配置信息记录:懵逼

P29 imx_pinctrl和pinctrl_dev引脚名字和编号该存在哪里 上
pinctrl子系统需要预先确定引脚的数量和名字
imx6ul_pinctrl_probe()懵逼

P30 imx_pinctrl和pinctrl_dev引脚名字和编号该存在哪里 中
pinctrl_desc:pinctrl_register_and_init(), pinctrl_init_controller(),

P31 imx_pinctrl和pinctrl_dev引脚名字和编号该存在哪里 下
初始化基数树、pinctrl_register_pins()、pinctrl_register_one_pin()、pin_desc_get()、

P32 pin function和pin group: iomuxc节点解析始末 上
设备树iomuxc节点层次:pinctrl子系统的设备树节点iomuxc、外设功能function/group、功能和IO组的标识属性fsl,pins
imx_pinctrl_probe_dt()、imx_pinctrl_dt_is_flat_functions()

P33 pin function和pin group: iomuxc节点解析始末 中
imx_pinctrl_parse_functions()、pinmux_generic_get_function()、imx_pinctrl_parse_groups()

P34 pin function和pin group: iomuxc节点解析始末 下
imx_pinctrl_parse_pin_mem()、

P35 pin state:pinctrl-names的真相
pinctrl_enable()-->create_pinctrl()-->pinctrl_dt_to_map()

P36 pinctl_map:引脚三千,只取一瓢 上
pinctl_map数组:0--所有引脚复用;1~n--单个引脚属性
imx_dt_node_to_map()、imx_pinctrl_find_group_by_name()、pinctrl_generic_get_group()、pin_get_name()、pin_desc_get()

P37 pinctl_map:引脚三千,只取一瓢 下
dt_remember_or_free_map()、pinctrl_register_map()、pinmux_validate_map()、pinconf_validate_map()

P38 pinctl_setting:如何统一管理pin state 上
pinctl_map保存了所有pin state所需要的pin group 引脚组 信息;pinctl_setting把pin group信息按pin state分类保存
for_each_maps()宏、add_setting()、find_state()、create_state()、pinmux_map_to_setting()、pinmux_func_name_to_selector()

P39 pinctl_setting:如何统一管理pin state 下
pinmux_generic_get_function_name()、pinmux_generic_get_function_groups()、pinctrl_get_group_selector()、pinctrl_generic_get_group_name()

P40 pinctrl子系统的引脚设置接口
状态查询pinctrl_lookup_state、状态设置pinctrl_select_state
pinctrl_commit_state()、pinmux_enable_setting()、imx_pmx_set()、imx_pmx_set_one_pin_mem()

P41 pinctrl子系统试验:RGB灯引脚初始化--相当于利用内核中的寄存器信息
platform设备引脚初始化:注册时配对成功自动执行really_probe()-->pinctrl_bind_pins()配置引脚
RGB灯引脚状态初始化:更改代码
试验:去掉内核模块io相关硬件寄存器代码后make copy、增加内核设备树并编译 替换 重启、加载ko、sudo sh -c "echo '7'>/dev/rgb_led"

P42 gpio1节点:GPIO子系统初窥
设备树gpio1节点包含GPIO1控制器的寄存器基地址,类似的还有gpio2~5
gpio1节点属性解释;新增rgb_led节点,使用gpio子系统 rgb_led_red = <&gpio1 4 GPIO_ACTIVE_LOW &gpio1 10 GPIO_ACTIVE_LOW>;
常用函数:of_find_node_by_path()获取rgb_led指针;of_get_named_gpio()获取GPIO编号;gpio_request() gpio_free()配对使用;gpio_direction_output()设置为输出及默认电平、gpio_direction_input()输入;gpio_get_value() gpio_set_value()读输入 写输出

P43 GPIO子系统试验:IO引脚高低电平控制
P42函数使用
更改内核设备树并编译 替换 重启、加载ko、sudo sh -c "echo '7'>/dev/rgb_led"

P44 十面埋伏的并发1:硬件同步原语
并发根源:多线程、多进程、中断
硬件同步原语:原子操作
原子整型操作接口:ATOMIC_INIT定义 赋初值;atomic_set()赋值;atomic_read()读;atomic_add()/atomic_sub() atomic_inc()/atomic_dec();
位原子操作函数:set_bit() clear_bit() 
演示:代码分析

P45 十面埋伏的并发2:自旋锁
原子操作:简单易用,保护范围小
自旋锁:多核场合、短时轻量加锁、加锁失败忙等待pause指令、开销小
加锁步骤:查看锁状态,为空则持有;CAS函数将其变为原子指令;
自旋锁API:定义、初始化、获取、尝试获取、释放
试验:类似P44

P46 十面埋伏的并发3:信号量
计数器、获取失败触发上下文调度、开销大、适用长期资源占用
API:定义、初始化、获取、尝试获取、释放
试验:类似P44

P47 十面埋伏的并发4:互斥锁
信号量与互斥锁:信号量--强调同步、生产消费模型;互斥锁--强调互斥、资源独占;均触发上下文调度
自旋锁与互斥锁:自旋锁--开销低、保持cpu使用权;互斥锁--开销高、加锁失败释放cpu
API:定义、初始化、获取、尝试获取、释放
试验:类似P44

P48 IIC驱动框架简介
物理总线:SCL SDA
框架图:I2C核心--硬件无关代码;I2C 总线驱动--读写时序;I2C设备驱动--i2c_driver和i2c_client
核心数据结构:i2c_adapter--NXP构建并且注册;i2c_algorithm--master_xfer产生I2C通信时序 NXP实现;i2c_client--;i2c_driver--probe i2c设备和i2c驱动匹配后,回调该函数指针
I2C 总线驱动分析:i2c总线注册--内核启动执行i2c_init();i2c总线定义--结构体i2c_bus_type;i2c设备和i2c驱动匹配规则--i2c_device_match();
设备树节点:compatible、reg;i2c_imx_probe()、结构体变量i2c_imx_algo、i2c_imx_xfer()

P49 IIC核心函数与“万能”驱动   上
注册一个i2c适配器:i2c_add_adapter()
注册一个i2c驱动:i2c_add_driver()
收发iic消息:i2c_transfer();i2c_msg结构体--iic设备地址、消息传输方向、消息数据的长度、消息缓冲区;i2c_master_send()、i2c_master_recv()、i2c_transfer_buffer_flags();
"万能"的i2c驱动:i2c-dev.c分析;内核集成i2c_dev驱动模块,开机自动加载、为每个i2c_adapter生成一个设备文件;

P50 IIC核心函数与“万能”驱动   下
i2c_dev_init()、i2cdev_attach_adapter()。。。。
i2cdev_fops:i2cdev_open()、i2cdev_read()、i2cdev_write()
讲代码总是一脸懵逼,应该在课堂笔记代码上多多加中文注释

P51 IIC驱动试验:读取mpu6050数据 上
MPU6050:空间运动传感器芯片
设备树节点:iomuxc子节点、i2c1子节点 地址由芯片决定
pinctrl对设备树插件支持不完善,试验使用传统设备树

P52 IIC驱动试验:读取mpu6050数据 下
芯片手册决定配置地址和命令
读取芯片信息

P53 设备驱动的非阻塞IO:O_NONBOOCK
IO操作:数据读写;用户空间-->内核空间-->file_operation
阻塞操作--系统默认,进入休眠,等待资源可用;非阻塞操作--不可用则返回错误码
O_NONBLOCK用法演示

P54 设备驱动的阻塞IO:等待队列
等待队列头 初始化 元素:wait_queue_head、init_waitqueue_head()、wait_queue_entry
添加 移除:add_wait_queue()、remove_wait_queue()
等待事件:wait_event() wait_event_interruptible() wait_event_timeout()
等待唤醒:wake_up() wake_up_interruptible()
试验:先调用wait_event进入等待状态,后唤醒

P55 POLL机制基本概念
file_operations->poll
同步阻塞--单文件读写;异步阻塞--多文件轮询
poll函数:监视多个文件的指定事件;试验

P56 POLL底层机制剖析  上
系统调用接口sys_poll、timespec64结构体
do_sys_poll()函数:复制用户空间pollfd数组到内核空间--分配静态数组内存(一个poll_list结构体)、动态分配内存(一组poll_list结构体)

P57 POLL底层机制剖析  下
do_sys_poll()函数:poll_initwait();do_poll()--确保线程/进程被唤醒后,继续执行1次循环体内容、遍历1组poll_list、遍历1个poll_list中的1组pollfd;
驱动层poll底层接口:poll_wait()、poll_get_entry()

对于不熟的人来说,看视频不能开倍速,不能走神
P58 彻底掌握POLL机制:动手设计一个POLL试验
主要调用3个函数:APP的main、驱动的poll和write
详细看md笔记

P59 Completion机制基本概念
信号量/互斥量:进程/线程没有优先级
完成量:一个线程的运行依赖另一个线程
completion结构体:
初始化completion:init_completion()
completion休眠:wait_for_completion()、wait_for_completion_timeout()、wait_for_completion_interruptible()
complete唤醒:complete()、complete_all()
实验现象类似P58

P60 kthread_worker:怎么把内核线程当工人
驱动传输数据 :低速数据--驱动传输;高速数据--内核传输
定义变量:kthread_worker、kthread_work、task_struct
初始化:kthread_init_worker()、kthread_init_work()
创建内核线程:kthread_run()
启动工作:kthread_queue_work(&hi_worker, &hi_work);
模块退出:kthread_flush_worker(&hi_worker); kthread_stop(kworker_task);
通过内核线程点灯

P61 彻底掌握kthread_worker队列化机制--讲代码
kthread_worker_fn()、kthread_init_work()、kthread_queue_work()、kthread_flush_worker()

P62 SPI物理总线
信号线:SCK、MOSI、MISO、CS;一主多从,全双工,上百MHz
spi时序:起始信号、停止信号、上升沿输出下降沿采样
spi通信模式:CPOL=1, SCK空闲状态为高电平; CPHA=1,在 SCK “偶数边沿”采样;组合出4大模式
常见spi设备:EEPROM、FLASH、实时时钟、AD转换器

P63 SPI驱动框架简介
SPI框架图:实际挂载到SPI总线,但因为使用设备树,包装为platform总线;SPI核心层--提供SPI控制器驱动和设备驱动的注册方法、注销方法、SPI通信硬件无关接口;SPI主机驱动--产生SPI 读写时序、spi_master(spi_controller);SPI设备驱动--通过SPI主机驱动与CPU交换数据、spi_device和spi_driver
核心数据结构:spi_controller对应1个SPI总线;使用异步传输方式;spi_register_master()
spi_device:代表1个具体设备;通过modalias配对
spi_driver:spi_register_driver()
spi 总线注册:spi_init开机运行、bus_register()、class_register()
spi控制器驱动:设备树节点、module_platform_driver() module_driver()

P64 SPI主控制器驱动和核心函数
spi_imx_probe()函数:获取设备树节点信息,初始化spi时钟、dma...;保存spi寄存器起始地址,填充spi控制器回调函数;代码详解
spi_bitbang_start()函数:spi_register_master()
核心函数:spi_setup()函数--设置spi设备的片选信号、传输单位、最大传输速率...;spi_imx_setup()函数--spi_imx_chipselect()函数高低有效设置;spi_message结构体包含多个spi_transfer结构体内的消息、spi_message_init()、spi_message_init_no_memset()、spi_message_add_tail();发送--spi_sync()函数、spi_async()函数

P65 SPI数据传输剖析:同步、异步
如果把笔记中的代码加上详细注释,讲课效果应该会好很多
spi_register_controller()、spi_controller_initialize_queue()
spi_init_queue()函数-- 初始化内核线程工人、初始化内核具体工作; spi_start_queue()函数--启动内核具体工作;spi_pump_messages()函数--内核工作具体处理;__spi_pump_messages()函数
spi_sync()函数--阻塞当前线程;__spi_sync()函数;__spi_queued_transfer()函数、spi_transfer_one_message()函数、spi_finalize_current_message()函数
spi_async()函数--异步传输数据、__spi_async()函数、spi_queued_transfer()函数、__spi_queued_transfer()函数

P66 pidev:SPI万能驱动 上
万能:Linux内核开放的相对通用的驱动;内核集成spidev驱动模块
设备树节点:pinctrl子节点、spidev子节点
spidev_init()函数、spidev_fops文件操作接口--unlocked_ioctl ioctl()函数底层操作接口(32位系统)、compat_ioctl ioctl()函数底层操作接口(64位系统)
spidev_probe()函数:创建字符设备、次设备号按位图分配、设备文件名后缀数字的含义 spi控制器编号+spi设备片选信号编号

P67 pidev:SPI万能驱动 下
spidev_fops文件操作接口
spidev_open()函数--为tx_buffer、rx_buffer分配4096字节内存;
spidev_read()函数--spidev_sync_read()函数、spidev_sync()函数
spidev_ioctl()函数--文件控制命令

P68 SPI驱动试验 上
SPI回写试验
全双工:使用spidev_ioctl()函数default分支;spi_ioc_transfer结构体、spi_ioc_transfer()函数;spidev_message()函数
SPI驱动实验:SPI 3的 MIOS与MOSI引脚使用跳线帽短接;spi3引脚与uart2存在引脚复用;

P69 SPI驱动试验 下
编译替换设备树、spi_app代码介绍 编译、屏蔽系统3个设备树插件、重启运行app

P70 Linux中断基础概念
回顾:裸机开发通用中断控制器(GIC)
GIC中断控制器节点:初始化中断控制器、设置其他中断控制器节点的描述格式
外设中断控制器节点:管理某一种具体中断
其他设备使用中断节点:使用某一种具体中断
常用函数:申请中断 request_irq();释放中断 free_irq();使能中断 enable_irq();禁止中断,等待中断执行完毕 disable_irq();禁止中断,不等待中断执行完 disable_irq_nosync();禁止处理器中断 local_irq_disable();开处理器中断 local_irq_enable()

P71 Linux按键中断实验
设备树节点:iomuxc子节点、自定义按键节点
代码讲解:irq_of_parse_and_map()。。。

P72 软中断和tasklet基础概念
中断上下半部机制:上半部--传统的中断处理函数、快速任务处理、硬件信号控制;下半部--非中断处理函数,由上半部设置工作任务、数据读取 复制 包装 转发 计算
软中断:实现中断下半部的一种机制;注册一个软中断open_softirq();主动触发指定软中断raise_softirq()
tasklet机制:基于软中断实现的下半部机制;tasklet_struct结构体、tasklet_init()、调度执行tasket对象tasklet_schedule()、注销tasket对象tasklet_kill()

P73 tasklet试验
通过打印不同字符区分中断上下半部

P74 工作队列试验
tasklet机制:软中断环境下执行、不允许休眠、降低系统实时性
工作队列机制:类似于kthread_worker;进程上下文环境执行、允许休眠、不影响实时性
创建工作队列:alloc_workqueue();内核默认创建1个,用户一般不需要创建
使用工作队列:work_struct、schedule_work()
实验现象类似P73

P75 输入input子系统基础概念
统一管理外部输入设备:按键、键盘、鼠标、触摸屏
分层模型:核心层、事件处理层
创建input设备类:input_init()函数 开机自动运行
input_dev结构体
注册/销毁输入设备:input_allocate_device()、input_register_device()、input_unregister_device()、input_free_device()
上报输入事件:input_event()--input_report_key()、input_report_rel()、input_report_abs()、input_sync()

P76 输入input子系统试验
通用输入设备(evdev.c)识别:/dev/input/event*  难以识别;查看输入设备名和event对应关系 cat /proc/bus/input/devices
BIT_MASK宏 常用且不会溢出
input_set_capability()

P77 电容触摸屏驱动简介
硬件接口:IIC接口、触摸信号中断、RST信号
驱动核心:i2c驱动框架、中断机制、input子系统、多点触摸协议
多点触摸(Multi-touch) 协议:TypeB优于TypeA;多点触摸事件类型;TypeB设备上报时序
API:初始化 input_mt_init_slots();上报触摸点的序号 input_mt_slot();为触摸点分配ID input_mt_report_slot_state();上报触摸点坐标信息 input_report_abs()、touchscreen_report_pos();上报时序案例
多点触摸屏驱动框架:I2C驱动入口;yyy_probe()中devm_request_threaded_irq函数无需手动释放中断

P78 电容触摸屏驱动试验 上
设备树节点:omuxc子节点--IIC 复位引脚;iomuxc_snvs子节点--触摸中断;i2c1子节点--触摸屏4个接口引脚
GT9157触摸芯片介绍:上电时序与 I2C设备地址;寄存器配置
电容触摸屏驱动:linux自带;goodix_ts_data结构体;goodix_chip_data结构体
试验:代码基于Linux源码移植;

P79 电容触摸屏驱动试验 下
代码讲解: goodix_request_irq(ts)、goodix_ts_irq_handler(int irq, void *dev_id)、goodix_process_events(struct goodix_ts_data *ts)、 goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)
试验:编译替换设备树;编译代码、加入驱动模块、触摸并查看二进制文件
hexdump命令:二进制文件查看工具
触摸屏数据显示格式说明

P80 PWM驱动试验
相关寄存器
设备树节点:pwm3子节点、iomuxc子节点、red_led_pwm子节点
pwm_device结构体;pwm_state结构体--- period、duty_cycle、polarity、enable;
获取pwm_device:devm_of_pwm_get()函数--解析pwm设备树节点信息,生成pwm_device对象
配置pwm频率和占空比pwm_config();配置pwm极性pwm_set_polarity();使能 禁止pwm输出pwm_enable() pwm_disable()
试验:编译替换设备树;编译代码、加入驱动模块、红灯亮10%

P81 LCD驱动框架分析
framebuffer机制:帧缓冲、显示图像信息、设备文件 /dev/fbx(x=0~n)
分层模型:核心层--drivers/video/fbdev/core/fbmem.c、linux内核实现、创建graphics设备类,占据主设备号29、为不同的显示设备提供文件通用处理接口;硬件设备层--驱动人员实现、提供显示时序、显存、像素格式等硬件信息、提供显示设备的私有文件操作接口、创建lcd设备文件/dev/fbx(x=0~n)
核心层分析:fbmem_init(void) 开机自动执行--FB_MAJOR宏、fb_fops文件操作接口
硬件设备层分析:fb_info 结构体--时序、显存、像素格式、fbops显示设备的私有文件操作接口
注册 register_framebuffer()、do_register_framebuffer()、fb_open()

老师的英语发音需要好好练习了

P82 LCD驱动试验
设备树节点:iomuxc子节点、backlight子节点、lcdif节点、lcd设备节点
试验:编译替换设备树;三色+图片循环显示
位图转换器 SEGGER:图片转化c文件


 

你可能感兴趣的:(LINUX,ARM,linux,驱动程序)