
driver
文章平均质量分 72
Huskar_Liu
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
bootargs常用属性项
bootargs可以在DTS中生成,chosen里有属性项bootargs,启动linux时,内核会使用chosen中定义的bootargs,如果没有定义bootargs,linux会使用内核默认的bootargs。格式是由很多个键值对用空格隔开依次排列,每个参数中都是:参数名=参数值整个 Kernel command line会被内核启动时解析,解析成一个一个的参数名=参数值的字符串...原创 2019-04-11 22:05:44 · 6629 阅读 · 1 评论 -
如何基于OF系统和DTB配置文件编写设备驱动
先来看看DTB在系统中被使用的过程。setup_machine_fdt()直接在dtb中解析根节点的一些属性和子节点给系统早期使用。解析”/”节点的model”属性给machine_desc赋值;解析”/chosen”node中的”bootargs”属性给boot_command_line;解析”/”节点的”#size-cells”、”#address-cells”属性;解析”/mem...原创 2019-04-20 16:05:51 · 842 阅读 · 0 评论 -
DTC管理DTB和DTS
可以用dtc命令编译或反编译特定的dtb文件 ~/work/linux/output/arch/arm64/boot/dts/xilinx$ dtc –help 反汇编,由dtb生成dts,反之亦然 dtc -I dtb -O dts -o zynqmp-zcu102.dts zynqmp-zcu102.dtb...原创 2018-06-27 13:11:53 · 3074 阅读 · 0 评论 -
DTS那些事
(1)设备节点怎么修改?怎么移植?ARM架构下dts文件存放于arch/arm/boot/dts/目录下。那Build内核的时候是如何决定哪些dts需要被编译呢? 答案在arch/arm/boot/dts/xxxx/Makefile中,ifeq ($(CONFIG_OF),y)#include (srctree)/arch/arm/boot/dts/qcom/Makefile.boardd...原创 2019-04-08 21:16:14 · 2654 阅读 · 1 评论 -
如何为自己的zynq板子定制移植linux的DTS
移植DTS时,首先要利用SDK,生成对应版本的kernel的DTS。SDK生成DTS,主要依据的HDF文件。需要从HDF中提取出有哪些外设,以及这些外设对应的REG。SDK是根据HDF文件生成的DTS,所以这个生成的DTS,是参考的基础,它决定了有哪些硬件资源需要被开启,并生成设备节点。以2017.4版本的kernel为例。生成我们的板子system-top.dts,并和zynq-zed...原创 2019-04-10 11:29:07 · 1718 阅读 · 1 评论 -
添加内核驱动模块(8)(修改DTS)
mydriver8原创 2019-04-19 17:16:31 · 1326 阅读 · 1 评论 -
添加内核驱动模块(7)(mydriver.c+ Konfig+Makefile )
mydriver7原创 2019-04-19 12:42:49 · 346 阅读 · 1 评论 -
添加内核驱动模块(6)(mydriver.c+ Konfig+Makefile )
mydriver6原创 2019-04-19 11:34:47 · 290 阅读 · 1 评论 -
添加内核驱动模块(5)(mydriver.c+ Konfig+Makefile )
mydriver5原创 2019-04-18 21:50:22 · 336 阅读 · 1 评论 -
添加内核驱动模块(4)(mydriver.c+ Konfig+Makefile )
mydriver4原创 2019-04-18 21:47:37 · 219 阅读 · 1 评论 -
添加内核驱动模块(3)(mydriver.c+ Konfig+Makefile )
mydriver3原创 2019-04-18 20:58:21 · 305 阅读 · 1 评论 -
添加内核驱动模块(2)(mydriver.c+ Konfig+Makefile )
mydriver2原创 2019-04-18 19:42:11 · 228 阅读 · 1 评论 -
添加内核驱动模块(1)(mydriver.c+ Konfig+Makefile )
mydriver1原创 2019-04-18 18:11:54 · 461 阅读 · 1 评论 -
kernel hacking
linux标准的打印函数是printk。#define KERN_EMERG "<0>"#define KERN_ALERT "<1>"#define KERN_CRIT "<2>"#define KERN_ERR "<3>"#define KERN_WARNING "<4>"#define KERN_NOTICE "<5>"#define KERN_INFO "<6>"#define KERN_DEBUG原创 2020-05-25 16:58:50 · 429 阅读 · 0 评论 -
SOD设计思想
struct oriented design,是介于procedure oriented design 和 object oriented design之间的一种设计思想。在POD的基础上,借用了OOD的很多理念。与OOD不同的是,SOD存在大量的FunctionEntryPoint。体现为系统提供了大量的API。也就是说,可以直接硬链接API,这是基于LabelMark实现的,所以是静态流程入口(Fixed Procedure),同时,SOD中,又使用了函数指针,把对象相关的函数封装到结构体对象中去原创 2020-05-20 19:11:42 · 896 阅读 · 0 评论 -
linux驱动(第二十七课,综合实例,platform, cdev,spi, gpio)
来看一个具体的实例OLED驱动原创 2020-05-20 19:09:10 · 375 阅读 · 0 评论 -
linux驱动(第二十六课 基于DTS的系统移植)
对于系统移植者而言,主要是两种驱动方面的工作1)SOC已经提供的驱动,在DTS中进行对应修改,提供给内核板子相关的资源。2)自己实现的驱动,在DTS中进行添加,提供相关的资源。并在drivers下添加对应的目录或者文件。本文来看看,如何读懂SOC已经提供的驱动,DTS又是如何对应的。内核提供了zedboard的DTS。我们来看看内核是如何构建device_node,又是如何创建device,并和对应的driver关联起来的。本文不关注于driver的具体语句的含义,而是将重心放在权项的使用上。来原创 2020-05-20 10:12:07 · 1446 阅读 · 0 评论 -
linux驱动(第二十五课,FRAMEBUFFER)
FB是一个典型的CDEV。framebuffer是对显示区的抽象,屏蔽显示硬件的底层差异。对于帧缓冲设备而言,只要在缓冲区中写入对应的数据,对应的就会自动在屏幕上显示出来。drivers/video/fbdev/core/fbmem.c中,提供了FBCORE的功能。特定的fb_info的注册注销,fb_ops的具体函数,则是在xxxfb.c中对应实现。fb_ops中的具体函数,最终操作LCDCTRL。FBCORE中的fb_write,会调用底层提供的fb_write方法,如果没有提供fb_wri原创 2020-05-18 11:54:28 · 391 阅读 · 0 评论 -
linux驱动(第二十四课 PWM)
PWMDEV是一个典型的CDEV。内核实现了PWMCORE,向上提供一个CDEV的用户接口,向下,调用不同的PWMCONTROLLER提供服务。类似于GPIOCHIP,在kernel中,PWMCHIP就是用来控制PWMCONTROLLER的一个结构体。struct pwm_chip{ struct device* dev; const struct pwm_ops* ops; int base; unsigned int npwm; struct pwm_device* pwms; ...原创 2020-05-18 10:57:59 · 1341 阅读 · 0 评论 -
linux驱动(第二十三课 RTC)
RTC是一种典型的CDEV。drivers/rtc/rtc-dev.c实现了RTC的通用驱动层,称为RTCCORE。RTCCORE实现了FOPS,并向底层导出了一些结构体和API。分层的结果是,底层RTC驱动无需关心RTC作为CDEV的功能实现,也无需关心通用的RTC控制逻辑。只需要专注于底层操作的实现。RTCCORE定义了rtc_class_ops结构体,作为RTC的底层操作集。struct rtc_class_ops{ int (*open)(struct device*); int (*原创 2020-05-17 22:50:45 · 739 阅读 · 0 评论 -
linux驱动(第二十二课 INPUT SUBSYSTEM)
输入设备是典型的CDEV。一般的工作机制时,按键或者触摸板在产生了数据后,发送一个中断,或者内核通过TIMER进行轮询,然后CPU通过SPI,I2C,USB等BUS,读取数据,并放入一个InputBuffer,CDEV的驱动,负责管理这个INBUF。CDEV提供了文件操作接口,它是一个UADEV,所以用户程序可以通过read文件操作来读取INBUF的数据。内核设计了INPUT子系统,由INPUTCORE处理通用服务。INPUTCORE提供了服务API,struct input_dev* input原创 2020-05-17 22:18:44 · 224 阅读 · 0 评论 -
linux驱动(第二十一课,IRQ COMPLETION)
如果需要驱动进程和设备操作同步,就需要用到IRQ和 Completion。进程执行到同步点时,将自己阻塞休眠到completion这个event上,而在IRQACTION中负责唤醒阻塞休眠在对应event上的进程。例如,我们需要读取设备的数据,但是数据并不一定就准备好了,这就需要同步了。通常设备会使用IRQ来提醒CPU,资源已经可用。但是IRQ和进程是异步的。有两种情况,1)IRQ先到达,也就是说,资源已经准备好,进程后到达,这时候,进程可以不用阻塞,而直接取用资源。2)进程先到达,此时,资源原创 2020-05-16 15:58:53 · 359 阅读 · 0 评论 -
linux驱动(第二十课 TTY)
console=ttySAC0,115200这是bootargs 里最常见的一句。它被用来选择从哪个设备输出内核、驱动的printk信息。这究竟是什么意思?串行端口终端(/dev/ttySn)计算机把每个串行端口都看作是一个字符设备。这些串行端口所对应的设备名称是/dev/ttyS0,/dev/ttyS1等,设备号分别是(4,0), (4,1)等.PC上的串口一般是ttySn,板子上Linux的串口一般叫做ttySACn.控制终端(/dev/tty)如果当前进程有控制终端(Controlli原创 2020-05-16 14:48:52 · 515 阅读 · 0 评论 -
linux驱动(第十九课 MISCDEV)
linux驱动是分层设计的,所以各个具体设备都能找到归属的类型,从而套用对应的框架。这样,就只需要实现最底层的部分。但是也有一部分设备并不能确定它的类型,这时,可以使用miscdevice的框架。本质上,miscdevice也是字符设备的一种,只是对CDEV进行了二次封装。在miscdevice的misc_init函数中,regiser_chrdev(MISC_MAJOR, “misc”, &misc_fops);注册了CDEV。miscdeviece的主号固定为10,区别在于各自的次号原创 2020-05-16 13:40:36 · 778 阅读 · 0 评论 -
linux驱动(第十八课,PINCTRL,GPIO, GPIO_CHIP, IRQ_CHIP)
在linux中,pinctrl被定义为一个子系统。pinmux功能被pinctrl子系统所管理。这个功能通常有SOC厂商提供。我们需要关心的是,如何使用它的功能。pin_configuration_node 是一个多维向量,通常的组成形式是:pinctrl1:xxxxgroup_1{ xxx,pins= < PIN_FUNCTION1 PIN_SETTING1 PIN_FUNCTION2 PIN_SETTING2 PIN_FUNCTION3 PIN_SETTING3 ..原创 2020-05-16 12:25:48 · 2002 阅读 · 0 评论 -
linux驱动(第十七课,USBBUS)
USB也是主从结构的总线。整体呈树状结构。USBHOST,由它发起传输。USB设备,分为HUB和FUNCTION。我们所用的外设,就是FUNCTION。USB树中,最多能有6层。USB设备地址,是7位的。其中,地址0是一个特殊地址,SFA(special function address)。所以,理论上,USBBUS上,只有127个独立地址。USB设备,大体上可以分为物理设备和逻辑设备。一个USB物理设备,可以由一个或者多个逻辑设备组成。一个逻辑设备,体现为一个或者多个接口(Interface原创 2020-05-15 20:54:52 · 919 阅读 · 0 评论 -
linux驱动(第十六课,SPIBUS)
和I2CBUS类似,SPIBUS上的物理设备,也是分为SPIMASTER和SPISLAVE。不同的是,SPIBUS上,只能有一个MASTER。在linux中,对应定义了两种对象,spi_master 和 spi_device。类似于I2CBUS,linux驱动中,分为master驱动, core驱动,device驱动。来看看spi_device的结构体。struct spi_device{ struct device dev; char modalias[SPI_NAME_SIZE]; st原创 2020-05-15 11:17:58 · 1047 阅读 · 0 评论 -
linux驱动(第十五课,I2CBUS)
I2CBUS,在协议标准里,分为MASTER和SLAVE。linux里,I2CMASTER被称为adaptor,对应的,I2CSLAVE被称为client。为了区别于SPIBUS。I2C是可以允许多个主机的,所以叫做MASTER,显得并不合适。而且,I2C的节点,既可以作为MASTER,也可以切换为SLAVE。SPI是只有一个主机的,所以叫做MASTER。所有的访问操作,都是由MASTER发起的。I2C的驱动架构,分为I2Cclient,I2Ccore,I2Cadaptor。其中,core是内原创 2020-05-14 23:39:24 · 1408 阅读 · 0 评论 -
linux驱动(第十四课,NDEV)
NDEV是linux中的第三大类设备。linux将网络协议栈实现在内核中。网络协议栈是典型的分层架构,由于不能跨层提供服务,也不能跨层请求服务,所以被成为协议栈。与CDEV或者BDEV不同的是,NDEV并不对应于/dev下的文件。用户程序是使用socket完成网络接口通信。NDEV的驱动被分为四个层次。1)协议接口层,向网络层协议提供统一的数据包收发接口,不论是ARP还是IP,都通过dev_queue_xmit()发送,并通过netif_rx()接收。这一层使得上层协议可以独立于具体的设备。2原创 2020-05-14 18:15:43 · 1206 阅读 · 0 评论 -
linux驱动(第十三课,BDEV, eMMC)
BDEV和CDEV在IO操作上有很大的不同。CDEV是直来直去的,用户进程请求文件操作syscall,syscall调用FOPS,整个调用栈就完成了。但是BDEV要用到内核的更多机制,例如缓冲,IO调度,请求队列等。BDEV只能以block为单位,接受输入或者输出,而CDEV是以byte为单位。所以大多数设备属于CDEV,因为他们不需要块缓冲,而且size不固定。BDEV对IO请求存在对应的块缓冲,BDEV要先对IO请求进行排序,然后再按照排序后的IO请求来发起实际的IO。BDEV可以随机访问,因原创 2020-05-14 13:25:26 · 939 阅读 · 0 评论 -
linux驱动(第十二课,CDEV)
CDEV是linux中最庞大的一类设备。struct cdev{ struct list_head list; dev_t dev; unsigned int count; const struct file_operations* ops; struct kobject kobj; struct module* owner;};struct file_operations{ struct module* owner; ... (*open)(...), (*rele原创 2020-05-14 08:49:58 · 523 阅读 · 0 评论 -
linux驱动(第十一课,内核机制,驱动模块架构)
我们经常会听到一个词,support。究竟什么是support?linux是一个可裁剪的OS,所以,如果不需要某些功能,就会裁剪掉。从内核的角度讲,内核都是提供的kernel service,所谓support,也就是说,内核提供了相应的kernel service。user process是OS的使用者。使用的是OS提供的服务。那么,究竟什么是kernel service?当系统在DDR中部署完成后,DDR中存在的Data 和Instruction,就构成了系统的静态布局,包括数据布局和函数布局两原创 2020-05-13 19:14:51 · 471 阅读 · 0 评论 -
linux驱动(第十课,MM, MMIO,mmap, DMA, )
首先来看看MM。也就是我们最常见的kmalloc。用来在内核空间内分配内存。对应的,malloc是在用户空间分配内存。void* kmalloc(size_t size, int flags);void kfree(const void* ptr);flags = GFP_KERNEL | GFP_ATOMIC |GFP_USER|GFP_HIGHUSER|GFP_DMA返回的是有效的Virtual Address。如果返回NULL,则说明分配失败。类似的,还有kzalloc和kzfree。他们原创 2020-05-13 13:19:18 · 3139 阅读 · 0 评论 -
linux驱动(第九课,中断,定时器)
我们首先看看中断的执行路径。linux中,首先是__vectors_start,这是异常向量表的入口。ExceptionHandler处理后,会跳转到IRQHandler,最后跳转到Callback.在handle_irq_event_percpu函数中,会调用Callback。irqreturn_t handle_irq_event_percpu(struct irq_desc* desc, struct irqaction* action){ ... do{ res = action原创 2020-05-13 09:24:37 · 605 阅读 · 0 评论 -
linux驱动(第八课,互斥,同步,并发控制)
驱动虽然是运行在内核空间的,但是驱动是运行在进程上下文中的,当系统中有多个进程并发的请求驱动的服务时,就会导致竞态,所以驱动必须解决的问题就是对共享资源的访问。并发访问会导致竞态。当内核的多条执行路径同时访问同一个共享资源时,就会造成竞态。例如中断ISR的执行,或者多核CPU的不同CPU核的并行执行。常见的共享资源有,全局变量,共享内存,等等。解决竞态的方法是,保证对共享资源的互斥访问。访问共享资源的代码段,成为临界代码段。(critical section)linux中提供了多种实现互斥的原创 2020-05-12 19:43:26 · 568 阅读 · 0 评论 -
linux驱动(第七课,Signal Driven AIO)
signal是软件层面上对中断的一种模拟。signal是async的,所以用户进程并不知道signal何时会到来。阻塞IO意味着用户进程一直要等待IO完成,非阻塞IO中使用Poll意味着要不停的查询。而signal则可以实现内核向用户进程的发送异步通知。用户程序中,可以捕获信号。typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);这个内核服务函数,用来注册一个信号处理原创 2020-05-12 17:07:55 · 334 阅读 · 0 评论 -
linux驱动(第六课IO方式)
IO模型是APP和DRIVER协同工作方式一种架构。用来提供驱动处理来自用户进程的IO请求的判据。当用户进程打开一个FILE时,会关联到某个DEV,同时设置FILE的其他数据成员,例如buf,pos,flags,等等。从用户的角度,它只需要关注FILE,至于FILE从哪里获取数据,如何获取数据,是由内核负责提供服务的。内核负责解析来自与FILE的数据请求,并调用DRIVER进一步完成IO,内核同时也会传入FILE的句柄,让DRIVER能够进一步了解FILE的相关信息。也就是说,DRIVER的服务对象原创 2020-05-12 15:14:02 · 357 阅读 · 1 评论 -
linux驱动(第五课,DTB,DTS)
LDM的BDD架构,使得DTB成为最合适的设备信息记录文件。OF_MATCH_STYLE是推荐的platform_driver的工作方式。当一个PDEV需要和PDRV配对时,会检查compatible权项。我们知道,一个驱动模块配置了OF_MATCH_TABLE,在这个表里登记了OF_DEVICE_ID的条目。struct of_device_id{ char compatible[128]; const void *data;}来看一个例子,static const struct of原创 2020-05-09 19:37:11 · 1366 阅读 · 0 评论 -
linux驱动(第四课 驱动架构,platform)
在BDD模型下,总线设备驱动分离。总线负责匹配设备和驱动,而驱动以标准途径拿到板级硬件资源。软件分层是linux驱动的基本思想。驱动被分离为核心层,硬件层等。驱动核心层用来处理某一类驱动的公共处理部分,从而让硬件层只需要专注与硬件操作。对于PCI,USB,IIC,SPI等设备而言,他们本身挂载在一个具体的BUS上,自然不成问题。但是对于SOC,有些外设却是挂载在SOC的内部总线上。为此,...原创 2020-05-08 17:11:24 · 405 阅读 · 0 评论 -
linux驱动(第三课 SYSFS LDM )
在linux中,一切IO资源皆文件。自然的,一切设备皆文件。所以,用户程序中如果要进行IO,首先要open一个FILE,指定FILE_PATH,让内核能够找到对应的IOResource(IOR),并填充一个FileControlBlock,然后返回一个filp给用户。之后,用户可以利用filp作为句柄来操作IOR。对于用户而言,read和write总是发生在userbuf和IOR之间的。所以我...原创 2020-05-08 13:23:18 · 554 阅读 · 0 评论