硬件笔记整理(硬件调试中要控制变量、换设备做对比)

1. 蜂鸣器

(1)定义

        蜂鸣器分有源和无源蜂鸣器

        (1)有源蜂鸣器

                蜂鸣器内部自带震荡电路,只需通过电源即可发声

                内部频率固定

        (2)无源蜂鸣器

                需要提供一定频率的脉冲信号才能发声

                改变频率能够调节蜂鸣器音调,产生不同音色、音调

                改变输出电平的高低电平占空比,可以改变蜂鸣器的声音大小

2. 中断

        

        

3. 通信方式

(1)根据数据传送方式可分为

        串行通信和并行通信

(2)按照通信的数据同步方式

        分为异步通信和同步通信

(3)按照数据的传输方向分为单工、半双工、全双工

4. 波特率

        如果一个码元只能表示0和1两种状态,波特率表示每秒传输的位数

5. ADC

(1)ADC转化步骤

        采样、保持、量化、编码

(2)逐次比较型ADC

(3)分辨率(ADC的精度)

        10位ADC分辨率是2的10次方(1024离散级别)

(4)基准电压

        ADC(模数转换器)的基准电压是用于将模拟信号转换为数字信号的参考电压

        基准电压决定了ADC的最大输入电压范围,即ADC能够准确测量的电压范围

6. ARM

(1) ARM定义

        ARM(Advanced RISC Machine,先进精简指令集计算机)是一种广泛应用的处理器架构,由英国的ARM公司(原名Acorn RISC Machine)设计。ARM架构是一种基于RISC(精简指令集计算机)的微处理器架构,它通过优化的指令集实现高效、低功耗的计算性能

        ARM是一种广泛应用的低功耗、高性能RISC(精简指令集)架构处理器

(2)ARM920T

        ARM920T是基于ARMv4T架构、ARM9系列的一款嵌入式处理核

        具有MMU、高速缓存、和高性能、低功耗等特性

7. 用户态和内核态

        用户态是应用程序运行的状态,而内核态是操作系统运行的状态。用户态只能执行部分指令,而内核态可以访问所有硬件资源。在用户态和内核态之间进行切换需要通过系统调用,其中系统调用号用于标识要执行的操作。切换过程涉及参数传递、系统调用映射表等步骤

        (1)printf调用了系统函数write,write是glibc封装的系统函数

(2)write系统调用通过syscall指令将用户态陷入内核态

(3)系统映射表在操作系统启动时就构建好了

8. ARM的七个工作模式

(1)User

(2)IRQ    

(3)FIQ

(4)Supervisor

(5)Abort

(6)Undef

(7)System

9. arm汇编指令(51默认大端、ARM默认小端,也可以配置为大端)ARM满减栈

(1)学习arm汇编的主要目的是为了编写arm启动代码,启动代码启动后,引导程序到c语言环境下运行。启动代码的主要任务有

                1. 初始化异常向量表

                2. 初始化各工作模式的栈指针寄存器

                3. 开启arm内核中断允许

                4. 将工作模式设置为user

                5. 完成上述工作后,引导程序进入c语言主函数执行

(2)mov指令

        加载12位立即数到寄存器或转移一个寄存器的值到另一个寄存器

(3)add

        将两个操作数相加

(4)sub

        将一个操作数从另一个操作数中减去

(5)12位立即数判断条件

        1. 如果某个数的数值范围在0~255之间,那么它一定是一个立即数

        2. 把这个数展开成二进制,这个数的最高位1到最低位1之间的二进制序列位数不能超过八位

        3. 这个二进制数末尾1的右边必须为偶数个连续的0

(6)ldr

        寄存器加载指令,作用是将一个值从内存加载到寄存器

(7)bic

        指定位清零指令

(8)orr

        指定位置位操作

(9)cmp

        用于比较两个寄存器的值或者比较一个寄存器和立即数的值

(10)b(类似c语言中的goto)

        跳转指令,跳转时需要一个lable,表示要跳转到哪去

(11)栈的实现结构(arm满减)

        1. 入栈做法

        (1)空增:先写入数据,栈指针自增

        (2)空减:先写入数据,栈指针自减

        (3)满增:先让栈指针自增,再写入数据

        (4)满减:先让栈指针自减,再写入数据

(12)stmfd

        入栈保护指令

(13)ldmfd

        出栈恢复指令

	preserve8
	area reset, code, readonly
	code32
	entry

	ldr pc, =start
	nop
	nop
	nop
	nop
	nop					   
	ldr pc, =interrupt_handler
	nop
		
start
	ldr sp, =0x40001000 //满减栈,从0x40000000到0x40000fff

	mrs r0, cpsr
	bic r0, r0, #0x1F
	orr r0, r0, #0x12;IRQ
	bic r0, r0, #(1 << 7);打开IRQ中断允许
	msr cpsr_c, r0
	ldr sp, =0x40001000
	sub sp, sp, #1024

	mrs r0, cpsr
	bic r0, r0, #0x1F
	orr r0, r0, #0x10 ;User
	msr	cpsr_c, r0
	ldr sp, =0x40001000
	sub sp, sp, #2048

	import main
	b main

interrupt_handler
	sub lr, lr, #4	
	stmfd sp!, {r0-r12, lr}
	import do_interrupt
	bl do_interrupt
	ldmfd sp!, {r0-r12, pc}^

finished
	b finished

	end

(1)

preserve8
area reset, code, readonly
code32
entry
	preserve8
  //确保代码在8字节对齐边界
	area reset, code, readonly
  //区域  复位   代码    只读不写
	code32
  //每个代码的指令占比特数为32
	entry
  //入口,相对于c的左花括号    entry到end之间是汇编代码

(2)

ldr pc, =start
nop
nop
nop
nop
nop
ldr pc, =interrupt_handler
nop

  ldr pc, =start:将程序计数器pc加载到标签start指向的地址,从而跳转到start标签位置开始执行

  nop:无操作指令,用于延时或占位

     ldr pc, =interrupt_handler:将pc加载到interrupt_handler地址,跳转到中断处理程序

10. ARM裸机程序

(1)start.s

        1. 定义

        start.s文件通常是一个汇编语言编写的启动代码文件

        2. 作用

        主要任务是在系统上电或复位时执行一些必要的初始化工作,确保程序能够正确运行

        (1)设置堆栈指针

        (2)初始化硬件设备

        (3)清除BBS段

        (4)设置向量表

        (5)跳转到主程序入口

        3. 代码

	preserve8//
	area reset, code, readonly
  //区域  复位   代码    只读不写
	code32
  //每个代码的指令占比特数为32
	entry//入口,相对于c的左花括号    entry到end之间是汇编代码

	ldr pc, =start
	nop
	nop
	nop
	nop
	nop					   
	ldr pc, =interrupt_handler
	nop
		
start
	ldr sp, =0x40001000

	mrs r0, cpsr
	bic r0, r0, #0x1F
	orr r0, r0, #0x12;IRQ
	bic r0, r0, #(1 << 7);打开IRQ中断允许
	msr cpsr_c, r0
	ldr sp, =0x40001000
	sub sp, sp, #1024

	mrs r0, cpsr
	bic r0, r0, #0x1F
	orr r0, r0, #0x10 ;User
	msr	cpsr_c, r0
	ldr sp, =0x40001000
	sub sp, sp, #2048

	import main
	b main

interrupt_handler
	sub lr, lr, #4	
	stmfd sp!, {r0-r12, lr}
	import do_interrupt
	bl do_interrupt
	ldmfd sp!, {r0-r12, pc}^

finished
	b finished

	end//结束,相当于c的右花括号

11. ROM和RAM

(1)ROM(非易失性存储器、掉电数据不丢失)

        1. ROM

        2. PROM

        3. EPOM

        4. EEPROM(电可擦写可编程存储器)

        5. 闪存

        (1)nor flash   (可寻址)

        (2)nand flash(不可寻址)

(2)RAM(易失性存储器、掉电数据丢失)

        1. SRAM(静态、晶体管)

        2. DRAM(动态、电容)

        3. SDRAM(同步动态)

        4. IRAM(集成在soc内部的SRAM、晶体管)

12. norflash和nandflash

(1)norflash(可寻址)

        1. 定义

        基于nor门逻辑结构的闪存,每个存储单元都直接与字线和位线连接,使得每个单元都可以独立访问,可寻址

        2. 特点

        (1)随机访问能力强

        (2)读取速度块,可快速读取任意地址的数据

        (3)可靠性高      

        (4)编程和擦除速度慢  

(2)nandflash(不可寻找)

        1. 定义

        基于nand门逻辑,每个存储单元排列成一个串联阵列,每个单元通过串行访问进行操作

        2. 特点

        (1)高精度、低成本

        (2)顺序读取快

        (3)编程和擦除速度快

        (4)擦写耐久性较低:相对norflash,nandflash的擦写耐久性较低,通常在一万次左右

(3)区别

        1. 结构

        norfalsh采用并行结构,每个存储单元独立连接,

        nandflash采用串行结构,存储单元串联

        2. 访问方式

        norflash可寻址随机访问

        nandflash不可寻址,主要支持顺序访问

        3. 读取速度

        norflash读取速度较快

        nandflash顺序读取性能高,但随机访问性能差

        4. 写入擦除速度

        norflash写入擦除速度较慢

        nandflash写入擦除速度较快

        5. 成本

        norflash成本高

        nandflash成本低

        6. 应用场景

        norflash应用于需要快速读取的小容量数据

        nandflash应用于大容量数据存储(SSD、USB闪存)

13. 看门狗定时器(2440默认使能)

(1)定义

        一种定时器,用于在一定时间内未收到系统重置信号时,触发系统复位或产生中断。主要主要作用是防止系统进入无响应状态(死循环、程序挂起)

(2)工作原理

        1. 系统上电或复位后,看门狗定时器开始计时

        2. 正常情况下,系统在固定时间周期内会给看门狗定时器发送时间重置信号,清除计时器

        3. 若系统在设定时间内未能给定时器发送时间重置信号,看门狗定时器会触发预定的系统复位或中断操作

14. 频率

(1)51单片机:主频12M,每个指令周期是12分频,实际工作频率为1M

(2)2440:主频400M(fclk、hclk、pclk)

        1.PCLK:给APB总线低速设备

        2. HCLK:用于AHB总线高速设备

        3. FCLK(主频):CPU

(3)2440内部的分频和倍频是由锁相环(PPL)和时钟管理器实现的

        1. 倍频:锁相环

        2. 分频:分频器

15. PWM(Pulse Width Modulation,脉冲宽度调制调制)

(1)定义

        通过改变脉冲信号的占空比(即脉冲的高电平时间与周期的比值)来调节电能传输的方法。PWM 广泛应用于电机控制、LED 调光、音频信号生成和通信等领域

(2)原理

        利用数字信号达到模拟信号的效果,例如用方波脉冲信号实现正弦信号

        利用微处理器的数字输出来对模拟电路进行控制的一种技术

        PWM通过固定频率周期信号,调节每个周期内高电平的持续时间(也称脉宽),从而控制输出信号的平均功率

        1. 周期:一个完整的高低电平时间(电平从高电平到低电平再到高电平的时间为一个周期)

                      一秒钟内的周期数为PWM的频率

        2. 占空比:高电平占整个周期的百分比

                          占空比 = (高电平时间 / 周期) * 100%

(3)应用场景

        1. 直流电机转速控制

        2. LED灯光亮度调节(呼吸灯)

        3. 音频信号产生

        4. 电源调节

15. 定时器(减定时器)(2440上的定时器都为16位   0~65535)

(1)

16. DAM

(1)定义

        DMA 控制器是一种硬件模块,它允许外设和内存之间直接传输数据,而无需通过 CPU 的干预。这种方式显著提升了数据传输的效率,减轻了 CPU 的负担,从而让 CPU 可以专注于其他任务处理

(2)

17. IIC(Inter-Integrated Circuit)集成电路总线

        时钟源来自PCLK

        SCL在空闲时没有时钟脉冲,只有在通信开始后,SCL才会有周期性的时钟脉冲信号

        IIC会产生中断的几种情况

        (1)主设备或从设备完成一次数据传输时会触发一次中断

        IIC锁死或异常情况产生原因

        1. 主从设备在传输过程中出现断电或设备异常等情况,总线会保持一种未完成的状态,使得总线一直处于忙的状态,导致总线被锁死

        2. 从设备未应答情况下会,总线会一直等待

        3. 时序管理不当,导致总线混乱异常

(1)定义

        它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板嵌入式系统手机用以连接低速周边设备而发展,同步、半双工、串行通信协议

(2)特点

        1. 双线制

        SCL(串行时钟线):用于同步数据传输的时钟信号

        SDA(串行数据线):用于发送和接收数据

        2.  多主控、多从设备

        IIC总线上可以有多个主设备和多个从设备,但在同一时刻只能有一个主设备控制总线

        3. 寻址方式

        每个从设备都有唯一的7位或10位地址,主设备通过发送地址来选择特定的从设备进行通信

        4. 数据速率

        标准模式(100 kbps)、快速模式(400 kbps)、高速模式(3.4 Mbps)和超高速模式(5 Mbps)

        5. 仲裁和同步

        当多个主设备同时试图控制总线时,总线仲裁机制确保只有一个主设备获得总线控制权

(3)IIC组网模式

        作为一种通信方式,IIC总线在某一时刻,总线只允许有一个设备处于发送状态,所发出的数据被总线上所有的设备所接收。IIC通信协议包含有设备地址,只有发送方携带的地址与某个接收方的地址相同时,接收方才真正执行相关的指令

        IIC总线规定,设备在空闲时,两根总线都处于高电平状态。为保证这种状态,数据线SDA和时钟线SCL都要外接上拉电阻。上拉电阻的阻值一般位4.7~10K。。I2C 总线标准模式下速度可以达到 100Kb/S,快速模式下可以达到 400Kb/S

(4)IIC协议时序

        1. 起始位(主设备拉低电平)

        空闲时,SDA和SCL都是高电平状态,每次通信前,发送方首先发送一个起始信号,即SCL为高电平时,发送方将电平拉低(SDA发送一个低电平)。当其他设备接收到整个信号后,将进行一次总线仲裁,意思是除了发送方之外,其他设备都将处于聆听状态

        2. 数据位(高位先行)

        IIC总线进行数据传输时,时钟线(SCL)上的信号为高电平期间,数据线(SDA)上的数据必须保持稳定(电平不能跳变)。只有在时钟线(SCL)为低电平时,数据线(SDA)上的高低电平才允许变化。数据输出到数据线(SDA)上的每个字节必须是8位。数据传输时,先传送最高位(MSB),最后传送最低位(LSB)

        3. 应答位(从设备控制电平)

        主机在每发送完一个字节(8bit)数据后,在第9个时钟脉冲之前释放数据总线(电平被拉高处于空闲状态),由接收器反馈一个应答信号。应答信号分为有效应答(ACK)和无效应答(NACK)。

        在第9个SCL拉高之前,从机将SDA拉低,为有效应答,表示接收器已经成功接收到该数据(一个字节数据);数据线SDA一直保持高电平,为非应答信号,表示接收器没有成功接收该字节数据

        4. 停止位(主设备拉高电平)

        发送方发送完一个字节数据后,需要发送一个结束标志来终止整个通信过程。当时钟线SCL为高电平时,主设备将数据线SDA由低电平拉高为高电平

        5. 一个字节数据的完整发送图

(6)IIC的设备地址

        IIC上面挂载的每个设备都有一个唯一的地址。IIC每次启动通信后的第一个字节前七位为设备地址,第八位为0表示主设备要往从设备写数据,第八位为1表示主设备要向从设备读数据

        例如:IIC设备地址为0xA0,主机发送0xA0时表示要向地址为0xA0的设备写入数据,当主机发送0xA1时表示主设备要读取该设备的数据

(7)IIC单个字节(8bit)写时序

        1. 主机发送起始信号(主机在时钟信号为高电平之前将数据线SDA电平拉低)

        2. 主机发送一个字节(8位)的信号,前7位是设备地址,第八位是写标志位0(0写1读)

        3. 在发送前8位结束后,在第9个时钟信号位高电平之前,从机发送应答位ACK,将数据线SDA拉低

        

        4. 主机重新发送起始信号,将电平拉低

        5. 主机发送要写入设备的寄存器地址

        6. 从机发送ACK应答信号,将数据线SDA拉低

        7. 主机发送要写入设备寄存器的数据

        8. 从机发送ACK应答信号(将数据线SDA电平拉低

        

        9. 停止信号,时钟信号为高电平时,数据位由低电平变为高电平

(8)IIC单字节读时序

        1. 主机发送起始信号

        2. 主机发送要读取的IIC从设备地址(7bit)以及写标志(1bit),此时主机要往从设备发送数据,因此刚开始是写信号

        3. 从机发送ACK(从机将电平拉低)

        4. 主机发送起始信号

        5. 主机发送要读取从机的寄存器地址

        6. 从机发送ACK应答信号

        

        7. 主机发送起始信号

        8. 重新发送要读取从设备的地址(7bit)和读标志位(1bit),表示接下来要从IIC从设备中读取数据

        9. 从机发送ACK应答信号

        10. 从IIC器件中读取到数据(8bit)

        11. 主机发送NOACK信号(即NACK,主机拉高SDA电平)表示读取完成,不需要从机再发送ACK信号

        12. 主机发送STOP信号,停止IIC通信

18. AT24C08

(1)AT24C08 是一款常见的 EEPROM(Electrically Erasable Programmable Read-Only Memory)芯片,具有8KB的存储容量,支持IIC总线协议

18. DM9000

        DM9000 是一款全双工的以太网控制器芯片

19. 内核的启动、裁剪、移植流程

Linux内核的启动、移植、裁剪是开发嵌入式系统或定制操作系统时的关键步骤。这些过程涉及内核的初始化、适应特定硬件平台的修改,以及根据需求定制内核的大小和功能。以下是详细的流程和原理介绍。

一、Linux内核的启动流程

Linux内核的启动过程可以分为以下几个主要阶段:

  1. 引导加载程序(Bootloader)阶段

    • 引导加载程序(如GRUB、U-Boot):这是启动Linux的第一步,它负责从非易失性存储设备(如硬盘、闪存)中加载内核到内存中。引导程序可以执行一些基本的硬件初始化工作,并将内核映像传递给下一个阶段。
    • 加载内核:引导加载程序将内核映像加载到内存,并准备好传递给内核的启动参数。
  2. 内核初始化阶段

    • 启动架构特定的代码:一旦内核映像加载到内存,处理器开始执行内核入口点代码。这个代码通常是与体系结构相关的,它负责进一步初始化硬件和设置CPU的状态。
    • 内存管理初始化:在架构特定的初始化之后,内核会设置页表,启用虚拟内存,并初始化内存管理子系统。
    • 设备初始化:内核接着会初始化各种设备和驱动程序,包括中断控制器、时钟设备、串行设备等。
    • 启动用户空间:在所有硬件初始化完成后,内核会启动init进程,进入用户空间,开始执行用户空间的程序,如/sbin/init
  3. 用户空间初始化

    • 启动用户空间程序init进程是用户空间的第一个进程,它根据系统配置(如/etc/inittabsystemd配置)启动其他用户空间服务。
    • 启动守护进程和服务:系统会根据配置文件启动各种守护进程和服务,从而完成整个系统的启动过程。

二、Linux内核的移植流程

将Linux内核移植到新的硬件平台或架构上通常涉及以下步骤:

  1. 选择合适的内核版本:首先需要选择一个适合目标硬件平台的Linux内核版本,通常会选择最新的长期支持版(LTS)。

  2. 配置内核(make config)

    • 使用合适的配置工具(如make menuconfig)配置内核,确保启用了目标平台的支持选项,如处理器架构、板级支持包(BSP)、特定硬件驱动等。
  3. 修改架构特定代码

    • 如果移植到一个全新的架构或硬件平台,可能需要编写或修改架构特定的代码,包括启动代码(bootloader)和硬件抽象层(HAL)。
  4. 添加或修改设备驱动

    • 根据目标硬件的需求,添加或修改设备驱动程序,以支持新的硬件外设。
  5. 编译内核

    • 配置完成后,使用make命令编译内核和模块。
  6. 调试和验证

    • 编译成功后,将内核加载到目标硬件上,进行调试和测试,确保内核能够正常启动并运行。

三、Linux内核的裁剪流程

裁剪Linux内核的目的是减少内核大小以适应资源有限的嵌入式系统。裁剪流程如下:

  1. 确定裁剪目标

    • 明确系统需求,确定哪些内核功能和驱动是必需的,哪些可以移除。
  2. 使用内核配置工具

    • 通过make menuconfigmake xconfig等配置工具,手动禁用不需要的内核功能、模块和驱动。例如:
      • 禁用不需要的文件系统支持(如ext4、XFS)。
      • 禁用不需要的网络协议栈(如IPv6、IPsec)。
      • 禁用不需要的调试和开发选项(如内核调试器、魔数保护等)。
  3. 编译和测试

    • 配置完成后,编译裁剪后的内核,并在目标硬件上进行测试,确保裁剪不会影响系统的正常运行。
  4. 进一步优化

    • 根据测试结果,进一步优化内核配置,移除更多的冗余功能,达到最优的内核体积和性能。

四、内核裁剪的原理

Linux内核的裁剪依赖于模块化和配置化的设计。通过Kconfig配置文件,开发者可以在编译前选择要包含的功能和模块。内核编译工具链会根据这些配置生成精简的内核映像。每个配置项通常都对应一个或多个源代码文件,这些文件会被编译进最终的内核映像或者作为可加载模块进行编译。

总结

Linux内核的启动、移植和裁剪是定制嵌入式系统或操作系统时不可避免的步骤。通过理解内核的启动流程,掌握移植的方法和技巧,以及利用内核配置工具进行裁剪,可以有效地为特定硬件平台打造高效的操作系统。

20. 内核启动原理

(1)2440启动后都进行了哪些初始化操作

(2) bootloader 原理及流程

(3)bootloader 向内核传递参数都有哪些

(4)Linux 内核驱动初始化在哪个阶段完成的?

(5)Linux 内核配置的基本原理是什么?

(6)你的文件系统都包括哪些内容,是如何制作的?

21. 内核启动具象化问题

(1)你板子启动Linux都需要哪些软件?

        1. J-Link驱动 + J-FlashV7.56

                烧入 U-boot

        2. VMware(创建和管理虚拟机)+ Ubuntu18.04(Linux操作系统)

        3. minicom(专门用于Llnux的串口调试工具)

                利用串口实现PC与开发板通信

        4. tftp

        5. nfs

        

22. uboot启动

(1)选择norflas和nandflash的区别

        1. norflash启动,此时norfalsh的首字节地址就是0x00000000,第一条指令直接从norflash取

        2. 如果选择nandflash启动,此时soc内部iram首字节地址为0x00000000,此时2440在运行iram中的程序之前,要把nandflash中的前4kb数据拷入iram中

(2)把开发板启动选择开关拨到norflash,下载uboot原码压缩包u-boot-2012.04.01.tar,解压压缩包,编译成最终程序u-boot.bin,启动j-flash,打开创建好的工程文件s3c2440.jflash,之后,连接设备,烧入uboot。

        完成使用j-flash下载u-boot到nor-flash中

(3)u-boot的一个功能是能够设置、保存一些参数,这些参数被称为环境变量,为键值对的方式

        1. printenv   打印出所有的环境变量

        2. setenv     设置环境变量

        3. saveenv   保存环境变量

(4)uboot中的环境变量

        1. baudrate

  • 描述:设置串行控制台的波特率,用于配置 U-Boot 与串行终端通信的速率。
  • 示例baudrate=115200

        2. bootargs

        传递给操作系统内核的命令行参数,通常用于设置内核的启动参数,如根文件系统的位置、控制台参数等

        console  定义控制台设备和波特率

        3, bootcmd

        uboot启动时执行的默认命令,未中断启动过程,U-Boot 将执行该命令以启动操作系统

        4. bootdelay

        指定 U-Boot 等待用户中断自动引导过程的时间

        5. ipaddr(2440ip地址)

        配置设备的 IP 地址,在 U-Boot 网络引导或通过 TFTP 下载文件时使用

        6. serverip(tftp服务器io地址)

        设置 TFTP 服务器的 IP 地址,用于从网络服务器下载文件

        7. stdin, stdout, stderr

        分别指定标准输入、标准输出和标准错误的设备。通常设置为 `serial`,表示通过串行端口与用户交互。

23. 开发阶段,通过tftp把linux内核下载到开发板内存中,2440引导linux启动

(1)复制已经编译好的linux内核文件Uimage到tftp根目录

(2)用tftp命令下载这个文件到开发板:tftp 0x30008000 uImage

(3)下载完成后使用u-boot命令bootm 0x30008000启动linux操作
系统

        linux启动后会自动去挂载根文件系统

24. 根文件系统(制作bsy-box)

        为一个文件夹,是linux的系统根目录。

        根文件系统是linux系统所不可或缺的,是linux内核启动以后要挂载的第一个文件系统。这个文件系统中包含有linux的各种命令,系统init进程等关键信息

        根文件系统一般应该放在nandflash,为了从电脑想2440传递文件方便,在开发阶段我们一般都使用nfs网络文件系统

        (1)使用已经编译好的根文件系统rootfs111.tar,直接把这个压缩文件在nfs服务器文件夹中解压缩即可

        (2)设置bootargs环境变量,在执行bootm传递给linux内核,使linux内核清楚去哪里找跟根文件系统

        (1)root=/dev/nfs 表示根文件系统是nfs即网络文件系统

                如果使用nand-flash作为根文件系统载体,则root=/dev/mtdblockx

        (2)nfsroot=192.168.1.100:/home/linux/nfs/rootfs 表示网络文件系统挂载的具体位置

        (3)ip=192.168.1.105 linux启动以后的ip地址

        (4)console=ttySAC0,115200 linux系统启动以后控制台是串口0,波特率115200

        (5)init=/linuxrc linux系统启动后的第一个进程在根文件系统中的位置

这么做的目的是之后的驱动开发修改linux源码或者重新
编译了Linux源码都需要重新把Linux烧写到nand-flash中去过于
费时费力了。通常的做法是开发调试阶段就是通过tftp下载
Linux内核,等一起调试停当,再固化到nand-flash中

25. 内核的启动

(1)第一阶段

        (1)把开发板启动选择开关拨到norflash

        (2)开发厂商提供定制化的uboot源码压缩包u-boot-2012.04.01.tar,解压压缩包

                进入u-boot源码顶层目录

                执行make smdk2440_config将编译目标设置为smdk2440

                make,编译出适合mini2440的u-boot.bin文件

                编译成最终程序u-boot.bin后,启动j-flash软件,打开创建好的工程文件s3c2440.jflash,之后,连接设备,将uboot烧入nor-flash中

                从arch/arm/cpu/arm920t/start.s  在40行找到了_start 之后的代码就是裸机程序中的汇编部分。一系列的设置工作模式,关闭看门狗,设置时钟,启动Icache,初始化nand等操作

(2)第二阶段(完成串口初始化、网卡初始化等卡发板外设初始化)

        从start.s第219行可以看出,u-boot把自己拷贝到sdram中去了

        这是因为之前的代码可能是在iram中,而iram只有4KB,剩下的可能还在nand中,所以u-boot干脆把自己所有的代码都拷贝到sdram中,然后在sdram中去运行,sdram中有一个board_init_r函数,完成了板载其他外设的初始化,如串口,网卡,中断等

       

        uImage是linux内核程序,通过编译linux原码得到

        (1)开发厂商提供定制化的linux原码压缩包linux-2.6.32.2-mini2440-20150709.tgz,解压安装包后得到下图

        (2)在解压的安装包目录arch/arm/configs下,找到适配的.config, mini2440_td35

        (3)之后通过图形化的make menuconfig来对.config中的文件进行配置

        (4)配置完成后make uImage,等待片刻输出Image arch/arm/boot/uImage is ready表示编译完成

        (5)编译完成后生成三个文件Image、zImage、uImage

        (6)一般uImage不能直接使用,解决方法是打开arch/arm/boot/Makefile,在64行将STARTADDR改为0x30008040。再次编译重新下载之后问题就能解决

                 Image:这个才是真正的镜像文件,大小约为4MB多一点

                 zImage:是Image压缩后的文件大小为2332580字节
                 uImage:也是Image压缩后的文件,不过它比zImage大了64字节,2332644字节

                 uimage比zimage多出来的64个字节包含了linux版本、编译时间等信息

                uImage通过tftp被下载到开发板的SDRAM 中

 26. 驱动

(1)驱动分为字符设备驱动、网络设备驱动、块设备驱动

 (2)linux下的应用程序如何调用驱动程序

        应用程序通过open、close、write、read等文件IO函数,调用库函数,库函数通过系统调用进入内核,内核通过驱动程序中的open、close、read、write操作硬件设备

        应用程序运行在用户空间,驱动程序运行在内核空间。应用程序必须通过系统调用实现用户空间陷入内核空间,实现对底层驱动的操作。

        
  27. 编写字符设备驱动程序

(1)驱动程序是被应用程序间接调用的,没有main函数

(2)操作系统内核把所有的驱动程序用一个链表管理起来,驱动程序可以被装入链表,也能被移出链表,即卸载驱动程序

(3)module_init和module_exit与c++中构造析构类似

        MODULE_LICENSE("GPL");中的PGL是GNU组织提供的公共许可

        __init和__exit与volatile类似,防止函数被优化

28. 编译驱动文件

(1)方法一

        1. 进入s3c2440/linux-2.6.32.2目录下

        2. 修改内核配置文件(为make menuconfig做准备)

                vi drivers/char/Kconfig

        

        3. make menuconfig修改配置(设置三态为M,手动加载module)

        4. vi drivers/char/Makefile

        

        5. make modules之后产生内核目标文件(frist_driver.ko)

(2)方法二(注意:在使用makefile之前,方法一必须要先执行一次,否则无法使用makefile)

        1. 直接创建一个专门存放驱动的文件夹my_driver

        2. 在文件夹里编写驱动程序,并编写一个makefile(效果与方法一相同)

KERNELDIR := /home/linux/s3c2440/linux-2.6.32.2/
CURRENT_PATH := $(shell pwd)
obj-m := mq7_adc_driver.o 
                                                  
build: kernel_modules

kernel_modules:
    $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
    $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

        make之后直接得到driver.ko文件

29. 驱动编写并加载的流程

(1)在s3c2440/linux-2.6.32.2目录下编写driver.c文件

(2)修改内核配置文件Kconfig为make menuconfig做准备

(3)修改make menuconfig,设置三态为M,手动加载module

(4)修改makefile

(5)make modules之后产生内核目标文件(frist_driver.ko)

(6)将frist_driver.ko拷贝到nfs下的rootfs里面

(7)进入arm的linux操作系统中,加载驱动模块,insmod driver.ko

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值