嵌入式Linux编程 课件 第7、8章 Linux高性能网络编程、Linux驱动程序开发_第1页
嵌入式Linux编程 课件 第7、8章 Linux高性能网络编程、Linux驱动程序开发_第2页
嵌入式Linux编程 课件 第7、8章 Linux高性能网络编程、Linux驱动程序开发_第3页
嵌入式Linux编程 课件 第7、8章 Linux高性能网络编程、Linux驱动程序开发_第4页
嵌入式Linux编程 课件 第7、8章 Linux高性能网络编程、Linux驱动程序开发_第5页
已阅读5页,还剩91页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第7讲高性能网络编程主讲:学习目标及要求学会TCP协议服务器端和客户端工作流程。掌握基于套接字的网络编程方法。掌握多进程、多线程、线程池和高效I/O多路复用网络服务器的设计。掌握高性能网络服务器编程。能力目标和要求

嵌入式终端通常需要与外部通信,接收控制指令,传输运行状态和采集的数据。嵌入式Linux系统能够驱动各种网络设备,并通过网络协议实现通信。每一位嵌入式软件工程师,都需要熟练掌握网络通信编程方法。项目导入目录:7.1网络编程基本知识7.2基于套接字的网络编程7.3高性能网络服务器编程7.4

基于多路复用的网络通信7.5项目实录7.1网络编程基本知识41.TCP/IP分层模型7.1网络编程基本知识5(2)

网络层(InternetLayer)网络层负责在主机之间的通信中选择数据报的传输路径,即路由。当网络层接收到传输层的请求后,传输某个具有目的地址信息的分组。该层把分组封装在IP数据报中,填入数据报的首部,使用路由算法来确定是直接交付数据报,还是把它传递给路由器,然后把数据报交给适当的网络接口进行传输。(1)

网络接口层(NetworkInterfaceLayer)网络接口层是TCP/IP协议软件的最底层,负责将二进制流转换为数据帧,并进行数据帧的发送和接收。数据帧是网络传输的基本单元。7.1网络编程基本知识6(3)

传输层(TransportLayer)传输层负责提供应用程序之间的通信服务。这种通信又称为端到端通信。传输层要系统地管理信息的流动,还要提供可靠的传输服务,以确保数据到达无差错、无乱序。为了达到这个目的,传输层协议软件要进行协商,让接收方回送确认信息及让发送方重发丢失的分组。传输层协议软件把要传输的数据流划分为分组,把每个分组连同目的地址交给网络层去发送。7.1网络编程基本知识7(4)应用层(ApplicationLayer)应用层是分层模型的最高层,在这个最高层中,用户调用应用程序通过TCP/IP互联网来访问可行的服务。与各个传输层协议交互的应用程序负责接收和发送数据。每个应用程序选择适当的传输服务类型,把数据按照传输层的格式要求封装好向下层传输。7.1网络编程基本知识82.TCP/IP模型边界特性7.2

基于套接字的网络编程93.讨论(1)TCP和UDP的最大区别是什么?分别应用于什么场合?(2)socket是什么?套接字是什么?目录:7.1网络编程基本知识7.2基于套接字的网络编程7.3高性能网络服务器编程7.4

基于多路复用的网络通信7.5项目实录7.2

基于套接字的网络编程111.网络编程——套接字套接字(Socket)是一种特殊的I/O接口,可以使网络中不同主机上的应用实现双向通信。套接字提供了一套访问底层TCP/IP通信服务的标准API接口,在嵌入式Linux系统中应用十分广泛。利用二元组<IP,Port>来描述一个套接字。套接字的类型主要有以下三种:7.2

基于套接字的网络编程12(1)流式套接字(SOCK_STREAM)流式套接字提供可靠的、面向连接的通信流;它使用TCP协议,从而保证了数据传输的可靠性和顺序性。(2)数据报套接字(SOCK_DGRAM)数据报套接字定义了一种无可靠、面向无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议UDP。(3)原始套接字(SOCK_RAW)原始套接字允许对底层协议如IP或ICMP进行直接访问,它功能强大但使用较为不便,主要用于一些协议的开发。7.2

基于套接字的网络编程132.工作流程7.2

基于套接字的网络编程14(1)

socket()函数语法:7.2

基于套接字的网络编程15(2)

bind()函数语法:7.2

基于套接字的网络编程16(3)listen()函数语法:7.2

基于套接字的网络编程17(4)

accept()函数语法:7.2

基于套接字的网络编程18(5)

connect()函数语法:7.2

基于套接字的网络编程19(6)send()函数语法:7.2

基于套接字的网络编程20(7)

recv()函数语法:7.2

基于套接字的网络编程21(8)

recvfrom()函数语法:7.2

基于套接字的网络编程22(9)

sendto()函数语法:233.简单的服务器与客户端(代码讲解):教师演示学生训练7.2

基于套接字的网络编程7.2

基于套接字的网络编程244.讨论本节的服务器实例只能顺序处理客户的服务请求,而不能并发处理多客户的同时任务请求,无法满足多任务、实时的应用场景。(1)你所知道的提高网络服务器性能的方法有哪些?(2)服务器具有哪些特性是高性能?目录:7.1网络编程基本知识7.2基于套接字的网络编程7.3高性能网络服务器编程7.4

基于多路复用的网络通信7.5项目实录7.3高性能网络服务器编程26在Linux软件开发领域,高性能的网络服务器是开发的重点。实现高性能的网络服务器需要从底层的网络协议到操作系统对服务器性能进行优化。我们可以应用哪些操作系统运行机制进行高性能网络服务器的开发?1.高性能网络服务器编程7.3高性能网络服务器编程27如何应用以下操作系统运行机制进行高性能网络服务器的开发?(1)多进程、(2)多线程、(3)线程池2.讨论7.3高性能网络服务器编程283.基于多线程的网络通信示例在基于多线程的高性能服务器实现中,通过accept()函数接收来自客户端的连接请求后,需要创建新的线程。在新的线程中,接收来自客户端的数据,并进行数据处理,最后将处理结果返回客户端。7.3高性能网络服务器编程293.运行结果7.3高性能网络服务器编程30运行中的模拟客户端314.高性能网络服务器编程(代码讲解):教师演示学生训练7.3高性能网络服务器编程目录:7.1网络编程基本知识7.2基于套接字的网络编程7.3高性能网络服务器编程7.4

基于多路复用的网络通信7.5项目实录7.4基于多路复用的网络通信33高性能的服务器往往通过I/O多路复用服务大量客户端的连接请求,并为客户提供数据服务。我们可以应用哪些I/O多路复用技术实现高性能网络服务器的开发?它们之间有什么不同?

1.讨论7.4基于多路复用的网络通信341)基于select机制的网络服务器

虽然select能够监控输入文件描述符集合、输出文件描述符集合以及错误处理文件描述符集合,但本示例程序将所有的网络通信的套接字放入输入文件描述符集合进行监控。7.4基于多路复用的网络通信352)基于poll机制的网络服务器

在基于poll机制的网络服务器中,将服务器套接字和accept函数返回的套接字封装成相对应的输入或输出事件。然后,通过poll函数对事件进行监控,一旦事件发生,Linux内核将设置结构体structpollfd的成员revents。最后,循环扫描结构体structpollfd数组并对发生对应事件的套接字进行处理7.4基于多路复用的网络通信363)基于epoll机制的网络服务器

epoll是Linux内核为处理大批量句柄而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著减少程序在大量并发连续中只有少量活跃的情况下的系统CPU利用率。7.4基于多路复用的网络通信37通过以下I/O多路复用技术实现高性能网络通信:(1)基于select机制的网络服务器(2)基于poll机制的网络服务器(3)基于epoll机制的网络服务器

2.学生练习:38该代码文件名network_select.c,通过gcc将其编译为可执行程序network_select。在测试过程中,两个客户端连接的服务器均为192.168.3.166,其端口号为4321。两个客户端均能够连接到select的服务器,并能够实现数据的收发工作,运行稳定。7.4.1基于select机制的网络服务器3.运行结果39运行中的模拟客户端7.4.1基于select机制的网络服务器401.基于多路复用的网络通信服务器(代码讲解):教师演示学生训练7.4基于多路复用的网络通信思考题411.在网络通信中,流式和数据报两种套接字类型有什么不同?2.在基于套接字的网络通信实例中,关闭服务器程序,并再次运行服务器时,可能出现绑定IP和端口错误,地址已经被占用的提示信息,试分析原因并给与解决。3.简述使用TCP协议的网络通信流程。4.在TCP服务器程序中,accept函数的作用?5.在本章介绍的几种并发服务器中性能最好、传输效率最高的是哪个服务器,是什么导致了它具备优势?目录:7.1网络编程基本知识7.2基于套接字的网络编程7.3高性能网络服务器编程7.4

基于多路复用的网络通信7.5项目实录7.5项目实录43基于多线程方法实现具有并发多任务处理能力的网络服务器,并利用客户端测试。客户端任务发送文件,服务器接收文件,文件传输完毕断开网络连接。第八章嵌入式Linux驱动程序开发主讲:学习目标及要求理解Linux内核模块执行机理并熟悉常用概念。掌握相关平台设备驱动程序的编写。养成嵌入式开发的系统思维。能力目标和要求

随着信息技术的发展,新的设备层出不穷,现代化的操作系统需要能够对设备进行有效地操作和管理。设备驱动程序能够使操作系统与硬件设备进行直接通信。从操作系统的角度来看,设备驱动程序包含设备信息,并将设备功能统一到设备驱动程序的接口函数中,进而能够屏蔽不同硬件设备的差异。项目导入目录8.1Linux设备驱动8.2Linux内核模块8.3字符设备驱动编程8.4Linux平台设备驱动8.5Linux设备树8.6工程实战8.1Linux设备驱动Linux设备驱动:设备驱动程序是一种操作系统与硬件设备进行通信的特殊程序。在Linux系统中,设备文件代表硬件设备,并且应用程序打开设备文件,通过对设备文件的读写操作,实现对硬件设备数据读写。Linux设备驱动分类:(1)字符设备驱动程序(2)块设备驱动程序(3)网络设备驱动程序字符设备驱动程序字符设备驱动程序以字节为单位对设备进行读写操作。由于字符设备数量最多,因此该类驱动程序占比最大。从最简单的Led灯、蜂鸣器、按键到I2C设备、SPI设备以及ADC设备,均属于字符设备。驱动这些设备的驱动程序,被称为字符设备驱动程序。块设备驱动程序块设备驱动程序主要以块为单位对设备进行读写操作。在计算机中,存储设备大多属于块设备,像硬盘、光盘、SD卡、U盘等。网络设备驱动程序网络设备驱动程序没有对应的设备文件,使用内部设备名访问,主要用于对网络硬件设备进行操作和管理。由于网络硬件设备的运行依赖于网络套接字机制,因此网络设备驱动程序运行不需要使用设备结点。8.1Linux设备驱动8.1Linux设备驱动8.2Linux内核模块8.3字符设备驱动编程8.4Linux平台设备驱动8.5Linux设备树8.6工程实战目录8.2Linux内核模块Linux宏内核结构Windows操作系统是微内核操作系统的代表,仅实现关键核心部分,其他功能模块单独编译加载,不同功能模块之间通过微内核通信机制进行交互。Linux操作系统采用宏内核的结构,即将所有内核功能进行整体编译,得到单独的内核镜像文件。宏内核通过函数调用进行不同功能模块之间的交互,因此执行效率极高。使用内核模块驱动外设Linux操作系统需要驱动各种各样的外设,如果每次修改外设驱动模块都将Linux内核进行重新编译加载,开发人员将无法忍受如此低的效率。所以,外设驱动程序一般以内核模块的形式存在于系统内核。内核模块基本组成一个Linux内核模块主要由模块加载函数、模块卸载函数、许可证声明以及简单描述信息组成。

module_init宏指定的模块加载函数hello_init,模块加载时执行该函数。例:staticint__inithello_init(void){printk("Thisisasimplelinuxkernelmodule!\r\n");return0;}简单内核模块的示例module_exit宏指定的模块卸载函数hello_exit,模块卸载时执行该函数。例:staticvoid__exithello_exit(void){ printk("Nowthesimplemoduleexitsfromthe system!!!\n");}8.2Linux内核模块MODULE_LICENSE用于指定模块的许可权限,该内核模块遵守GPL的许可权限。例:MODULE_LICENSE("GPL");MODULE_AUTHOR用于指定模块的开发人员。例:MODULE_AUTHOR("JASON");简单内核模块的示例8.2Linux内核模块8.1Linux设备驱动8.2Linux内核模块8.3字符设备驱动编程8.4Linux平台设备驱动8.5Linux设备树8.6工程实战目录字符设备:字符设备即以一个字节一个字节进行读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后顺序进行。字符设备是面向字节流的设备,常见的字符设备如鼠标、键盘、串口、控制台、LED等。LED灯控制工程示例下面通过LED灯控制为例,给出传统字符设备驱动开发的过程。工程案例的目标为:编写并编译字符设备驱动程序,以控制PA14管脚对应的LED灯每隔10s进行亮灭循环。8.3字符设备驱动编程PA14管脚对应的LED灯硬件原理图该LED灯的硬件原理图如图所示。由LED灯原理图可知,当PA14输出为高电平时,LED灯处于灭的状态;当PA14输出为低电平时,LED灯处于亮的状态。8.3字符设备驱动编程驱动模块入口函数在入口函数中,主要完成LED灯的初始化工作。首先,将GPIO口相关寄存器的物理地址映射为虚拟地址;然后,配置GPIO口相关寄存器,使管脚工作于输出模式,以便输出高低电平,控制LED灯的亮灭。步骤①:通过ioremap函数实现将端口A(GPIOA)的控制寄存器、数据寄存器以及状态寄存器的物理地址映射到Linux操作系统的虚拟地址,并用指针pgpioa_regs指向该虚拟地址的起始位置。

步骤②:将寄存器RCC_MP_AHB4ENSETR的物理地址映射到虚拟地址空间,用指针pRCC_MP_AHB4ENSETR指向起始地址。ARM处理器通过时钟控制不同功能部件的工作状态,并通过关闭对应部件的时钟,使其处于关闭状态,以达到低功耗运行的目的。步骤③:使能GPIOA的时钟,在该工程实例中,通过控制处理器管脚PA14输出高低电平,实现LED灯的亮灭。在ARM处理器中,通过合理配置相关寄存器使IO口正常工作,主要包括:模式寄存器(GPIOx_MODER)、输出类型寄存器(GPIOx-OTYPER)、上拉/下拉寄存器(GPIOx_PUPDR)等。8.3字符设备驱动编程时钟使能

RCC_MP_AHB4ENSETR寄存器的功能是使能GPIO组相关控制器。该寄存器主要控制端口A到端口K的时钟使能,对应位置1,使能对应端口的时钟,并使其进入工作状态。该代码主要将该寄存器第0位置1,使能端口A的时钟,使其处于工作状态。时钟总线寄存器地址RCC_MP_AHB4ENSETR地址:基地址+偏移地址。例如:基地址+偏移地址=0x5000A28,使能GPIO组,将第四位置一,使其处于工作状态,时钟总线寄存器地址如图所示。8.3字符设备驱动编程工作模式输入模式(0x00)通用输出模式(0x01)复用功能模式(0x10)模拟模式(0x11)工作模式寄存器地址

在工作中可以通过改变相应位的寄存器数值,实现模式的切换。例如:在该工程实例中,将寄存器位28和29设置为0x01,管脚PA14工作于通用输出模式,工作模式寄存器地址如图所示。8.3字符设备驱动编程输出模式推挽输出(0x0)开漏输出(0x1)其中推挽输出的驱动能力强,而开漏输出的驱动能力较弱。可以通过改变寄存器位值从而实现输出模式的切换。输出类型寄存器地址由于需要驱动LED灯,因此将管脚PA14设置为推挽输出,即将端口输出类型寄存器的位14设置为0,如图所示。8.3字符设备驱动编程端口属性配置寄存器①端口输出速度寄存器②端口上下拉寄存器③端口位设置/复位寄存器端口输出速度寄存器低速(0x00)中速(0x01)高速(0x10)超高速(0x11)

通过改变寄存器位值实现速度的选择,将寄存器位28与位29设置为0x11,使PA14工作于超高速状态。8.3字符设备驱动编程端口上下拉寄存器无上拉和下拉(0x00)上拉(0x01)下拉(0x10)预留(0x11)端口上下拉寄存器位信息如图所示。在代码中,将寄存器位28和29设置为0x01,PA14将工作于上拉状态。8.3字符设备驱动编程端口位设置/复位寄存器高电平(寄存器对应位置1)低电平(寄存器对应位置0)

位0-位15设置为1对应管脚将输出高电平,设置0无效;位16-位31设置为1对应管脚将输出低电平,设置0无效,如图所示。例如:在代码中,将位30设置为1,因此PA14输出低电平,LED灯处于亮的状态。8.3字符设备驱动编程驱动模块出口函数其中在驱动模块出口函数中,释放驱动程序运行过程中所申请的资源。在Linux操作系统中,地址空间也属于系统资源,使用完毕及时释放。

Iounmap函数即把映射过来的物理地址还原,释放掉虚拟地址。驱动模块写函数在LED灯字符设备驱动程序中,Linux内核需要获取应用程序传递过来的控制命令,进而实现LED灯的控制。8.3字符设备驱动编程驱动模块写函数的实例8.3字符设备驱动编程字符设备驱动程序编译、测试及验证

与应用程序编译和测试相比,字符设备驱动程序编译测试更加复杂。首先,字符设备驱动程序运行于Linux内核,需要与宿主内核版本保持一致;然后,单独编译的字符设备驱动模块需要通过专用命令加载和运行;最后,测试结果无法实时显示,只能通过调试日志进行查看。下面将给出上述LED灯字符设备驱动程序编译、测试和验证过程。8.3字符设备驱动编程字符设备驱动程序编译字符设备驱动程序编译过程复杂,需要融入相关内核文件,该字符设备驱动程序编译过程中采用的Makefile文件如图所示。按照Makefile文件进行编译,生成stm32_pa14_led.ko文件,如图所示。

8.3字符设备驱动编程测试应用程序编译该测试应用程序非常简单,可以直接通过命令进行编译生成,生成可执行文件test。命令如图所示:加载字符设备驱动程序模块

Linux操作系统提供命令insmod,能够将单独编译的内核模块链接到正在运行的内核中。通过insmod命令将stm32_pa14_led.ko内核模块链接到当前内核中运行,命令如下:root@stm32mp-dk1#insmodstm32_pa14_led.ko

8.3字符设备驱动编程创建设备文件在Linux操作系统中,设备文件是硬件设备驱动程序的接口。应用程序能够通过标准I/O系统调用访问设备驱动程序,进而实现与硬件设备的交互。将设备驱动内核模块加载到Linux内核后,用户可以通过命令mknod创建设备文件,命令如下:root@stm32mp-dk1#mknod/dev/stm32paledc1590

执行应用程序

在开发板Linux操作系统中,输入./test执行测试应用程序,执行情况如图所示。LED灯亮10秒钟,然后灭10秒钟,循环10次,达到设计预期。8.3字符设备驱动编程8.1Linux设备驱动8.2Linux内核模块8.3字符设备驱动编程8.4Linux平台设备驱动8.5Linux设备树8.6工程实战目录8.4Linux平台设备驱动基于内核模块的驱动有缺陷

目前,Linux操作系统所管理的外围设备越来越多,设备驱动程序的代码在Linux内核中比重越来越大。同类外围设备仅部分参数不同,每种外围设备均开发驱动程序,并将驱动程序加载进Linux内核,将会使Linux操作系统越来越臃肿。Linux平台设备

为了实现Linux驱动程序有序管理,Linux操作系统的维护团队提出设备驱动模型,采用分层思想解决复杂的工程问题。在该模型中,主要有总线、设备、驱动三部分构成。

在计算机系统中,有些外围设备并未挂载到某一总线上。为了便于统一管理,Linux操作系统提出平台虚拟总线(Platform总线),实现该类设备统一操作。同样,该类设备称为平台设备,设备驱动被称为平台驱动。平台总线

在Linux内核中,总线由结构体bus_type来表示,该结构体位于文件include/linux/device.h中。在该结构体中,最重要的函数是match函数,主要完成设备与驱动匹配工作。当新的设备注册到Linux内核,总线match函数将搜索与之配对的驱动。同样,当新的驱动加载到系统,总线match函数也会被调用,搜索与之配对的设备。8.4Linux平台设备驱动基本结构:structplatform_device{ constchar*name; intid; u32num_resources; structresource*resource; …}name是平台设备的名称,后续工作中将通过该字段匹配相应的驱动。num_resources是设备资源的数量。resource指针指向设备所占用的资源。8.4Linux平台设备驱动resource指针基本结构:

structresource{ resource_size_tstart; resource_size_tend; constchar*name; unsignedlongflags; … }start表示设备占用资源的起始值。end表示设备占用资源的终止值。name表示资源的名称。flags表示资源的类型。8.4Linux平台设备驱动平台设备注册函数:intplatform_device_register(structplatform_device*pdev);参数:pdev 指向平台设备的指针dev 字符设备所使用的设备号Count 本次添加的字符设备数量Name 指定设备的名称返回值:返回0表示注册成功;返回负数表示注册失败。平台设备注销函数:voidplatform_device_unregister(structplatform_device*pdev);参数:pdev指向平台设备的指针8.4Linux平台设备驱动平台设备驱动结构:structplatform_driver{

int(*probe)(structplatform_device*);

int(*remove)(structplatform_device*); …}probe函数用于完成传统字符设备驱动程序中模块加载的工作;remove函数将执行字符设备注销的工作,执行与probe函数相反的动作。8.4Linux平台设备驱动8.1Linux设备驱动8.2Linux内核模块8.3字符设备驱动编程8.4Linux平台设备驱动8.5Linux设备树8.6工程实战目录设备树的定义与作用

设备树的定义:描述设备硬件信息的一种数据结构,它通过bootloader将硬件资源传给内核,使得内核和硬件资源描述相对独立。设备树的作用:设备树就是代替了device文件,将硬件信息从内核中剥离出来,我们通过内核提供的接口获取设备树的节点和属性。8.5Linux设备树DTS(Device

Tree

Source)设备树

硬件的相应信息都会写在.dts为后缀的文件中,每一款硬件可以单独写一份xxx.dts,一般在Linux源码中存在大量的dts文件,对于arm架构可以在arch/arm/boot/dts找到相应的dts,一个dts文件对应一个ARM的machie。DTC(Device

Tree

Compiler)设备树编译器dtc是编译dts的工具,可以在Ubuntu系统上通过指令apt-get

install

device-tree-compiler安装dtc工具,不过在内核源码scripts/dtc路径下已经包含了dtc工具。DTB(Device

Tree

Blob)设备树二进制文件

dts经过dtc编译之后会得到dtb文件,dtb通过Bootloader引导程序加载到内核。所以Bootloader需要支持设备树才行;Kernel也需要加入设备树的支持。8.5Linux设备树设备节点的命名格式

例:lable:node-name@unit-addressnode-name表示结点名字,除根结点外,其他结点均有名字;unit-address表示结点所表示设备占有的寄存器或内存起始地址,如果设备没有相关地址,可以为空;label表示的标号,可以在设备树的其他位置通过标号引用该结点。设备树的主要标准属性

在面向对象程序设计中,通过属性对对象进行描述。在设备树,也是通过设备属性对设备节点进行描述。设备树中的属性主要包括标准属性和用户自定义属性。设备树中主要标准属性有以下几个:

8.5Linux设备树compatible属性compatible属性即“兼容性”属性,该属性的值为字符串列表。Linux内核通过该属性实现设备和驱动的配对。该属性值的格式如下:compatible=“manufacture,model”

其中,manufacture表示设备生产厂商,而model对应驱动中的名字。compatible属性为字符串列表,当存在多个字符串时,通过第一个字符串查找与之匹配的驱动,如果没有找到,则通过第二个字符串继续查找,以此类推。model属性model属性值也用字符串表示,用于指定设备模块名字信息。以开发板stm32mp157a-dk1为例,其model属性表示为model="STMicroelectronicsSTM32MP157A-DK1DiscoveryBoard"。8.5Linux设备树reg属性reg属性表示该设备节点所代表设备占有的地址空间资源,属性值形式为地址和长度数对。

如reg=<0x400000000x400>表示寄存器地址从0x40000000开始,地址空间的长度为0x400。#address-cells和#size-cells属性

这两个属性指定该设备结点的子节点中reg属性的地址和长度信息所占用的字长。当设备结点的#address-cells和#size-cells的属性值分别为1和0,表示地址的数为32位的整数,没有长度信息,因此其子结点timer@1的reg的属性值为<1>。8.5Linux设备树案例代码分解#include"stm32mp157c.dtsi"#include"stm32mp157c-m4-srm.dtsi"#include"stm32mp157cac-pinctrl.dtsi"#include<dt-bindings/input/input.h>#include<dt-bindings/mfd/st,stpmic1.h>

该设备树文件引用了stm32mp157c.dtsi,该文件给出主控芯片STM32MP1硬件资源,像CPU、内存、片上外设等。两个设备树文件中都有“/”结点,但在编译后生成的.dtb文件中两个“/”结点将合并成为一个根结点。8.5Linux设备树案例代码分解model="STMicroelectronicsSTM32MP157A-DK1DiscoveryBoard";compatible="st,stm32mp157a-dk1","st,stm32mp157";

整个开发板stm32mp157a-dk1设备树的根结点有两个属性model和compatible。属性model给出开发板的名称,即STMicroelectronicsSTM32MP157A-DK1DiscoveryBoard;属性compatible,即“兼容性”属性,值的类型为字符串,通过该属性能够在Linux内核中搜索与之相匹配的驱动。8.5Linux设备树案例代码分解aliases{ ethernet0=ðernet0; serial0=&uart4; serial1=&usart3; serial2=&uart7;}; aliases结点,即“别名”结点,并不表示具体的设备,仅给出设备标号的别名,像串口4的别名为serial0。8.5Linux设备树案例代码分解chosen{ stdout-path="serial0:115200n8";};chosen结点并不代表开发板上的硬件,而是保存传递给Linux内核的参数,并且在系统启动的过程中,uboot能够修改该结点,以便向Linux内核传递配置参数。8.5Linux设备树案例代码分解memory@c0000000{ reg=<0xc00000000x20000000>;};

根据设备树结点reg属性的命令格式,设备结点memory@c0000000中,节点名字为memory,内存的首地址为0xc0000000,地址空间的长度为0x20000000。8.5Linux设备树操作设备节点的of函数of_find_node_by_path函数

该函数将根据用户提供的路径来查找设备节点。函数原型如表8.1所示。类别描述函数structdevice_node*of_find_node_by_path(constchar*path)参数path从根节点开始的设备节点的路径返回值设备节点的信息表8.1of_find_node_by_path函数原型8.5Linux设备树of_find_property函数

该函数用于返回设备结点指定的属性。函数原型如表8.2所示。类别描述函数structproperty*of_find_property(conststructdevice_node*np,constchar*name,int*lenp)参数Np设备节点Name属性名字Lenp属性值的字节数返回值设备节点中指定的属性表8.2of_find_property函数原型8.5Linux设备树of_property_read_string函数

该函数用

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论