什么是驱动
驱动,即设备驱动程序,是一种可以使计算机和设备通信的特殊程序。
从作用角度来看,驱动的主要功能是将硬件设备的功能与操作系统进行连接,让操作系统能够识别并正确使用硬件设备。例如,显卡驱动能让操作系统充分发挥显卡的图形处理能力,打印机驱动能使计算机顺利地向打印机发送打印指令。
从组成结构来说,驱动通常包含了硬件设备的各种控制指令、通信协议以及与操作系统交互的接口等。它就像是一个翻译官,在硬件设备和操作系统之间进行信息的转换和传递。
什么是Linux驱动
Linux 驱动是专门为在 Linux 操作系统下使硬件设备正常工作而编写的软件程序。
在功能方面,它负责在 Linux 系统与硬件设备之间建立通信桥梁。通过驱动程序,Linux 系统能够识别硬件设备、控制其工作状态以及获取设备提供的数据等。例如,网卡驱动使得 Linux 系统能够连接网络,实现数据的收发;磁盘驱动则负责管理存储设备的读写操作。
从结构组成上看,Linux 驱动通常包含与硬件交互的底层代码、设备注册和初始化的模块、中断处理程序以及与 Linux 内核接口的部分等。它既要遵循 Linux 内核的编程规范和接口要求,又要针对特定硬件的特性进行优化设计。
什么是裸机驱动
裸机驱动是在没有操作系统的情况下,直接控制硬件设备的程序。
从功能上讲,裸机驱动主要负责初始化硬件设备、设置设备的工作模式和参数,并实现对设备的基本操作,如读写数据、控制设备状态等。它直接与硬件进行交互,不需要依赖操作系统提供的服务和接口。
在结构组成方面,裸机驱动通常由针对特定硬件的初始化代码、控制逻辑和中断处理程序等组成。由于没有操作系统的支持,裸机驱动需要更加关注硬件的细节和特性,以确保设备能够正确、高效地运行。
对于一些嵌入式系统开发或特定的硬件控制场景,裸机驱动具有重要意义。它可以提供更高效的硬件控制,减少系统资源的占用,并且能够在没有操作系统的环境下实现特定的功能需求
什么是搬移内核到内存
“搬移内核到内存” 是指在系统启动过程中,将存储在非易失性存储设备(如 NandFlash、NorFlash 等)中的 Linux 内核映像文件复制到计算机的内存中。
一、为什么要进行内核搬移
- 提高运行速度
- 内存的读写速度通常比外部存储设备快得多。将内核加载到内存中运行,可以大大提高内核的启动速度和运行效率。例如,当系统需要快速响应外部事件或执行复杂的计算任务时,内存中的内核能够更快地进行处理。
- 直接访问
- CPU 可以直接访问内存中的数据,而对于外部存储设备的访问通常需要通过特定的接口和控制器,这会增加访问的延迟。将内核搬移到内存中,使得 CPU 能够更快速地获取内核代码和数据,从而提高系统的整体性能。
二、搬移的过程
- 确定内核映像的位置
- 在启动过程中,引导加载程序(如 U-Boot)首先需要确定内核映像在存储设备中的位置。这通常是通过读取特定的配置信息或预设的地址来实现的。例如,在 NandFlash 启动方式中,引导加载程序可能会根据预先设定的地址范围来查找内核映像。
- 读取内核映像
- 一旦确定了内核映像的位置,引导加载程序会从存储设备中读取内核映像到内存中的特定位置。这个过程可能涉及到对存储设备的读写操作和数据传输。例如,通过特定的总线接口(如 SPI、I2C 等)从 NandFlash 中读取数据,并将其存储到内存的指定地址。
- 验证内核映像
- 在将内核映像搬移到内存后,引导加载程序通常会对内核映像进行验证,以确保其完整性和正确性。这可以通过校验和、数字签名等方式来实现。如果内核映像损坏或不完整,引导加载程序可能会停止启动过程并报告错误。
- 启动内核
- 当内核映像被成功搬移到内存并验证通过后,引导加载程序会将控制权转移到内存中的内核入口点,启动内核的执行。内核会进一步进行初始化和系统配置,最终启动整个操作系统。
三、不同启动方式下的内核搬移
- 从 NandFlash 启动
- 在这种启动方式下,系统上电后会自动搬移 NandFlash 前 4KB 的程序到 IRAM 中,并将 0 地址映射到 0x40000000 地址处。引导加载程序在前 4KB 代码中初始化好内存,然后将 NandFlash 中的内核映像搬移到内存的特定地址(如 0x30008000)。最后,引导加载程序启动内存中的内核。
- 从 NorFlash 启动
- 系统上电后,PC 默认指向 0 地址处,直接运行 NorFlash 中的程序。如果内核映像存储在 NorFlash 中,引导加载程序可以直接将内核从 NorFlash 搬移到内存中。或者,如果内核映像存储在其他位置(如通过网络下载),引导加载程序也可以从其他来源获取内核映像并搬移到内存中。
- 从网络启动(如通过 TFTP 和 NFS)
- 在这种启动方式下,引导加载程序通过 TFTP 服务从网络上的服务器(如 Ubuntu 服务器)下载内核映像到内存的特定地址。然后,引导加载程序启动内存中的内核,并通过 NFS 服务挂载网络上的根文件系统。
内存和flash的区别
一、性质与特点
- 内存(RAM):
- 属于易失性存储器,即当电源关闭时,其中存储的数据会立即丢失。
- 具有高速读写的特点,能够快速响应 CPU 的指令,为 CPU 提供临时的数据存储和快速的数据交换空间。
- 通常以动态随机存取存储器(DRAM)或静态随机存取存储器(SRAM)的形式存在。
- Flash:
- 是非易失性存储器,即使断电后数据也不会丢失。
- 读写速度相对较慢,但比传统的机械硬盘要快很多。
- 常用于存储长期的数据,如操作系统、应用程序和用户文件等。
二、用途
- 内存:
- 主要用于在计算机运行过程中暂时存储正在运行的程序和数据,以便 CPU 能够快速访问。
- 对于需要频繁读写和快速响应的任务,如运行大型软件、进行多任务处理等,内存的性能至关重要。
- Flash:
- 作为长期存储设备,用于保存操作系统、应用程序、文档、图片、视频等各种数据。
- 在移动设备如手机、平板电脑和数码相机中,Flash 存储器广泛应用,因为它具有体积小、功耗低和非易失性的优点。
三、存储容量与成本
- 内存:
- 通常存储容量相对较小,一般以 GB 为单位。例如,常见的个人电脑内存容量可能在 4GB 到 32GB 之间。
- 由于其高速读写的特性和复杂的制造工艺,内存的成本相对较高。
- Flash:
- 存储容量可以从几 GB 到数 TB 不等,适用于存储大量的数据。
- 随着技术的不断进步,Flash 的成本逐渐降低,但相对于内存来说,仍然较为便宜。
四、数据读写方式
- 内存:
- 可以随机访问任意地址的数据,读写速度非常快。
- CPU 可以直接对内存进行读写操作,无需经过复杂的寻址过程。
- Flash:
- 一般以块为单位进行读写操作,在写入数据之前可能需要先擦除整个块。
- 读写速度相对较慢,并且在进行大量写入操作时,可能会因为擦除和写入的过程而导致性能下降。
norflash和nandflash的区别有哪些
NorFlash 和 NandFlash 的区别主要体现在以下几个方面:
- 物理结构5:
- NorFlash:采用并行连接的存储单元结构,每个存储单元都有独立的访问线。这使得它可以直接按字节读取,就像访问传统的存储器一样,能够同时读取和写入存储器中的每个字节。
- NandFlash:采用串行连接的存储单元结构,多个存储单元被组合成一个页(page),多个页再组合成一个块(block),形成存储数组。读取和写入是以页为单位进行的,而非单个字节。
- 性能表现:
- 读取速度:NorFlash 的读取速度相对较快,可支持随机读取,适合快速获取代码指令等小数据量的随机读取操作16。NandFlash 的读取速度整体比 NorFlash 稍慢,但随着技术发展,差距在逐渐缩小。
- 写入速度:NandFlash 的写入速度比 NorFlash 快很多。NorFlash 在写入前需要先将目标块内所有的位写为 0(擦除操作),且擦除是以较大的块为单位进行,导致写入效率较低;而 NandFlash 的写入操作相对简单,擦除单元也更小14。
- 擦除速度:NandFlash 的擦除速度远快于 NorFlash。NorFlash 擦除一个块的时间可能需要 5s 左右,而 NandFlash 擦除一个块通常不超过 4ms1。
- 接口与使用方式3:
- 接口:NorFlash 带有 SRAM 接口,有足够的地址引脚来寻址,可以直接和 CPU 相连,CPU 可以直接通过地址总线对 NorFlash 进行访问,存取其内部的每一个字节,接口较为简单。NandFlash 器件使用复杂的 I/O 口来串行地存取数据,8 个引脚用来传送控制、地址和数据信息,各个产品或厂商的方法可能各不相同,接口相对复杂。
- 使用方式:NorFlash 可以在片内直接运行代码,应用程序可以直接在 NorFlash 闪存内运行,不必先把代码读到系统 RAM 中。NandFlash 不能在片内运行程序,使用时必须先写入驱动程序,才能进行其他操作3。
- 容量与成本:
- 容量:NorFlash 的容量相对较小,常见的有 128KB、256KB、1MB、2MB 等,一般在 1-16MB 左右。NandFlash 的容量较大,目前市面上的 NandFlash 产品容量可以从几 GB 到数 TB 不等23。
- 成本:NorFlash 的成本相对较高,因为其生产工艺复杂、容量小。NandFlash 由于生产过程相对简单、存储密度高,在大容量的情况下成本更低3。
- 可靠性与耐用性3:
- 可靠性:NorFlash 的可靠性较高,接口简单,数据操作少,位交换操作少,极少出现坏区块,一般用在对可靠性要求高的地方。NandFlash 的接口和操作相对复杂,位交换操作较多,出现问题的几率相对较大。
- 耐用性:NandFlash 中每个块的最大擦写次数一般是一百万次,而 NorFlash 的擦写次数是十万次左右。但是由于 NandFlash 通常是整块擦写,块内的页面中如果有一位失效整个块就会失效,而且擦写过程复杂,失败的概率相对较高14。
- 应用场景:
- NorFlash:常用于存储代码和关键数据,如用于 BIOS 芯片、嵌入式系统中存放启动代码等对数据读取速度要求高、容量需求不大且对可靠性要求高的场景5。
- NandFlash:适合于数据存储,如在固态硬盘(SSD)、U 盘、存储卡等需要大容量存储的设备中广泛应用。
Linux启动流程
Linux 的启动是一个复杂而有序的过程,主要包括启动 bootloader、启动内核以及加载(挂载)根文件系统三个关键阶段。
一、启动 bootloader
- 功能与性质:
- Bootloader 是一段裸机程序,其主要职责是为内核启动精心准备适宜的环境。一旦内核成功启动,CPU 的控制权便彻底移交至内核,此后 bootloader 不再被启动。任何具备此类功能的程序均可称为 bootloader。
- 具体操作步骤:
- 初始化 CPU:合理设置 CPU 的工作模式,确保其处于适合系统启动的最佳状态。
- 初始化堆栈:为程序的运行构建临时数据存储区域,保障程序执行过程中数据存储和调用栈的稳定运作。
- 初始化异常向量表:为系统处理各类异常情况(如中断、故障等)设定入口地址,确保在异常发生时能够准确地进行处理。
- 初始化时钟:为系统提供精准的时间基准,保证各种与时间相关的操作(如定时器设置、任务调度等)得以正常进行。
- 初始化内存:对系统内存进行检测和配置,为后续程序的加载和运行开辟可用的内存空间。
- 关看门狗:防止程序运行过程中因看门狗超时而导致系统意外复位,确保系统稳定运行。
- 关 Cache:在启动初期,为了确保对内存的直接操作准确无误,避免 Cache 可能带来的不一致性。Cache 作为一种高速缓存,能够加速 CPU 对内存的访问,但在某些特定情况下,尤其是在系统启动初期,需要直接操作物理内存,此时关闭 Cache 可以有效确保操作的准确性。
- 关 MMU:MMU(内存管理单元)负责将虚拟地址转换为物理地址。然而在启动初期,需要直接操作物理地址,因此关闭 MMU 能够避免地址转换带来的复杂性。
- 初始化相关硬件设备:包括调试串口、网口、LED 等。调试串口用于输出启动过程中的调试信息,为开发者进行问题排查提供便利;网口为系统提供网络连接功能,以便进行网络通信和文件下载等操作;LED 可以作为启动状态的指示,方便用户直观了解系统的运行情况。
- 集成相关通信协议:若要进行通信操作,必须借助通信协议来定义帧格式。例如,在网络启动过程中,可能需要集成 TCP/IP 等通信协议,以确保与其他设备进行准确的数据传输。
- 搬移内核到内存:将内核映像从存储设备(如 NandFlash 或通过网络从 Ubuntu 等服务器)搬移到内存中,以便 CPU 能够快速访问和执行内核代码。
- 向内核传参:向内核传递重要的参数,如根文件系统的位置和调试端口等。根文件系统的位置信息告知内核在哪里能够找到文件系统,以便进行加载和挂载操作;调试端口信息则用于在开发和调试过程中输出调试信息。
- 启动方式:
- 在 NandFlash 上:对于s3c2440芯片来说,系统上电后,会自动搬移 NandFlash 前 4KB 的程序到 IRAM(内部随机存取存储器)中(这是一个自动的过程,但这个过程并不是每个处理器都支持),并将 0 地址映射到 0x40000000 地址处,程序就从这个地址开始跑。如果bootloader 程序大于4KB,在这前 4KB 代码中,bootloader 初始化好内存,并将自己剩余的部分搬移到内存中运行。
- 在 NorFlash 中:系统上电后,PC(程序计数器)默认指向 0 地址处(norflash连接0地址处),直接运行 NorFlash 中的程序。
二、启动内核
- 内核的性质与功能:
- 内核(kernel)是一个复杂的程序,负责操作系统的核心功能,涵盖文件管理、进程管理、内存管理、网络管理和设备管理等多个重要方面。
- 获取、启动内核的方式:
- 在 NandFlash 上:bootloader 启动的最后阶段将 NandFlash 中的内核搬移到内存的 0x30008000 地址处(内存是被接到0x30000000地址处,从0x30000000到0x30008000之间的这一段内存放的是页表(用于记录虚拟地址和物理地址之间的关系)和参数),然后启动该地址处的内核。
- 在 Ubuntu 上:bootloader 通过 TFTP(Trivial File Transfer Protocol)服务将 Ubuntu 上的内核下载到内存的 0x30008000 地址处,随后启动该地址处的内核。 (下载:tftp 0x30008000 uImage)
三、加载(挂载)根文件系统
- 根文件系统的组成与作用:
- 根文件系统(rootfs)是一堆文件的集合,其中包括配置文件、系统命令 / 用户程序以及普通文件等。配置文件用于设置系统的各种参数和选项,如网络配置、用户权限等;系统命令和用户程序是系统运行所必需的工具和应用程序;普通文件则包含各种数据文件和文档等。
- 启动方式:
- 在 NandFlash 上:直接挂载 NandFlash 的 mtdblock3 分区(人为的对存储空间的区域划分)上的根文件系统。
- 在 Ubuntu 上:通过 NFS(Network File System)服务挂载 Ubuntu 上的根文件系统。在这种方式下,bootloader 通过网络从 Ubuntu 服务器下载内核,并将其加载到内存中启动。然后,通过 NFS 服务将 Ubuntu 上的根文件系统挂载到本地系统中,使得本地系统可以像访问本地文件系统一样访问 Ubuntu 上的文件。
以网络启动(通过 TFTP 和 NFS)的方式启动内核
首先向开发板的 NorFlash 中下载 uboot.bin。U-Boot(Universal Boot Loader)是一种广泛应用于嵌入式系统的引导加载程序,它负责初始化硬件设备、加载内核等重要任务。将 U-Boot 下载到 NorFlash 中,确保系统在启动时能够首先执行 U-Boot 程序。
在 Ubuntu 中安装 TFTP 服务并将 uImage(内核映像文件)拷贝到 TFTP 服务目录下。TFTP(Trivial File Transfer Protocol)是一种简单的文件传输协议,常用于嵌入式系统中快速传输小文件。通过 TFTP 服务,开发板可以从 Ubuntu 服务器上下载内核映像到特定的内存地址。
查看tftp服务是否已经安装
通过tftp服务,从tftpboot中下载文件到当前目录下(在哪个目录下使用tftp,文件就下载到哪个目录下)
在 Ubuntu 中安装 NFS 服务,并将 rootfs.tar.gz(根文件系统压缩包)拷贝到 NFS 服务目录下并解压。NFS(Network File System)允许网络中的计算机之间共享文件系统。在这种启动方式中,开发板将通过 NFS 挂载 Ubuntu 服务器上的根文件系统,以便访问系统运行所需的各种文件和程序。
启动 minicom,这是一个用于串口通信的工具。通过 minicom,可以查看开发板的输出信息,进行调试和交互操作。
输入 “print” 查看环境变量。环境变量包含了系统启动时的各种参数和配置信息,通过查看环境变量可以了解当前系统的设置情况。
baudrate=115200:
定义了串口通信的波特率为 115200bps。bootargs=root=/dev/nfs nfsroot=192.168.1.17:/home/linux/nfs/rootfs ip=192.168.1.100 console=ttySAC0,115200 init=/linuxrc:
root=/dev/nfs:指定根文件系统通过网络文件系统(NFS)挂载。
nfsroot=192.168.1.17:/home/linux/nfs/rootfs:指定 NFS 服务器的地址和共享的根文件系统路径。
ip=192.168.1.100:设置设备的 IP 地址。
console=ttySAC0,115200:将控制台输出重定向到串口ttySAC0,并使用与前面定义一致的波特率 115200。
init=/linuxrc:指定系统启动时执行的初始化程序为/linuxrc。bootcmd=nand read 30000000 kernel;bootm 30000000:
nand read 30000000 kernel:从 NAND 闪存读取内核到内存地址 30000000。
bootm 30000000:从内存地址 30000000 启动内核。bootdelay=5:
设置启动延迟为 5 秒,在此期间可以中断启动过程进入 U-Boot 命令行界面。ethact=dm9000:
指定网络控制器为dm9000。ethaddr=00:0c:29:4d:e4:f4:
设置设备的以太网 MAC 地址。ipaddr=192.168.1.27:
设置设备的 IP 地址,与前面bootargs中的ip参数可能有不同的用途,具体取决于系统的启动流程。mtddevname=u-boot:
指定 MTD(Memory Technology Device)设备名称为u-boot。mtddevnum=0:
设置 MTD 设备编号为 0。mtdids=nand0=jz2440-0:
定义 NAND 闪存的设备 ID,这里将其命名为nand0,对应型号为jz2440-0。
mtdparts=mtdparts=jz2440-0:256k(u-boot),128k(params),2m(kernel),-(rootfs):
定义 MTD 分区,对于jz2440-0设备,划分出不同大小的分区,分别用于存储 U-Boot(256KB)、参数(128KB)、内核(2MB)和根文件系统(剩余空间)。
netmask=255.255.255.0:
设置子网掩码为 255.255.255.0。
partition=nand0,0:
指定要使用的分区为nand0的第一个分区,可能是 U-Boot 分区。
serverip=192.168.1.17:
设置 NFS 服务器的 IP 地址。
stderr=serial、stdin=serial、stdout=serial:
将标准错误、标准输入和标准输出重定向到串口。
修改环境变量,设置启动参数。其中,“setenv bootargs root=/dev/nfs nfsroot=192.168.1.3:/home/linux/nfs/rootfs ip=192.168.1.99 console=ttySAC0,115200 init=/linuxrc” 这条命令设置了根文件系统的位置为 NFS 服务器上的特定目录,指定了开发板的 IP 地址、控制台设备和初始化程序等参数。
“ping serverip” 检查网络是否连通。确保开发板能够与 Ubuntu 服务器进行网络通信是成功启动的关键步骤之一。如果网络不通,可能会导致内核下载和根文件系统挂载失败。
“tftp 0x30008000 uImage” 下载 uImage 到内存的 0x30008000 地址处。这一步骤利用 TFTP 服务将内核映像从 Ubuntu 服务器下载到开发板的内存中,为启动内核做准备。
“bootm 0x30008000” 启动 0x30008000 地址处的内核。这是最后一步,通过引导加载程序(U-Boot)启动位于特定内存地址的内核,从而启动整个 Linux 系统。