硬件基础
NOR Flash 和 NAND Flash异同
NOR,Not OR,逻辑是或非门;NAND,Not AND,逻辑是与非门。
两者都是FALSH芯片,断电不丢失。FLASH只能写0不能写1,所以写前都要先擦除。
NOR FLASH 按照块 、BANK 、扇区进行内存组织。
NOR FLASH的最小擦除单位是扇区,最小读取、写入单位是字节。(可以随机访问)
NAND FALSH 按照块 、页进行内存组织。
NAND FLASH的最小擦除单位是块,最小写入、读取单位是页。
NOR FLASH读的快,NAND FLASH写的快。'
NAND FLASH寿命和可靠性更低,价格便宜,适合存储大容量数据。
NOR FALSH读写最小单位是字节,代码可以直接在 NOR FLASH 上运行,无需先加载到 SRAM中。
固态硬盘SSD使用的就是NOR FLASH或者NAND FLASH。
机械硬盘HDD不是基于闪存技术的,按块、扇区组织,。对于机械硬盘而言最小的擦除单位是扇区,最小的读写单位也是扇区。
但对于操作系统而言,不管是SSD还是HDD,都是以[块]为单位进行读写和擦除的。
CPU,MPU,MCU,SOC,SOPC联系与差别
CPU(中央处理器)
定义:冯诺依曼结构中CPU包括运算器和控制器。
功能:执行程序代码,处理数据。
MPU(内存保护单元)
定义:MPU可以限制对内存区域的访问,比如限制只读、只写、禁止访问等等。
功能:可以设置内存区域的访问权限,划分内存区域用于不同的任务。
MCU(微控制器单元)
定义:MCU是集成了运算器、控制器、输入输出单元、存储器的高集成芯片。
功能:除了基本的CPU功能外,还可能包括操作系统的支持、高级的数据处理能力等。
SoC(片上系统)
定义:芯片集成技术。用来将传统计算机组件集成到单个芯片上。
功能:CPU、GPU、内存、存储控制器、网络接口等都属于Soc。
SOPC(可编程片上系统)
定义:SoPC是一种基于FPGA(现场可编程门阵列)的SoC,允许用户配置和编程硬件。
功能:支持编程定制。
什么是交叉编译
支持交叉编译的编译器,作用就是,一个架构环境编译,另一个架构环境运行。这个编译过程就叫交叉编译。像windos平台用keil编译,然后stlink下载**.axf文件**,或者Jlink烧录hex文件,这种也属于交叉编译。x86架构上面生成arm架构的可运行程序。
基于ROM的运行方式和基于RAM的运行方式区别
RAM 是断电丢失,ROM 是断电不丢失。
RAM 运行需要先把硬盘SSD或者闪存FLASH的代码加载到RAM中。FLASH、EEPROM就属于ROM。
ROM运行代码比RAM慢,因为所有的代码和数据都需要缓存到RAM中然后执行。因此ROM运行比RAM运行多了个把执行代码搬运到RAM的过程。
ARM处理器
哈佛结构、冯诺伊曼结构
冯诺伊曼结构:
输入设备、输出设备、控制器、运算器、存储器。控制器和运算器属于CPU。
冯诺伊曼结构指令和数据放在一个存储器,一条总线分时传输指令或数据。
哈佛结构:
指令有指令总线和指令存储器,数据有数据总线和数据存储器。
哈佛改进结构:
指令存储器、数据存储器、指令数据通用存储器。
允许程序存储器和数据存储器之间直接传输数据,不经过CPU。
现在计算机大都冯诺依曼结构。 哈佛结构主要用于嵌入式计算机,运算速度和吞吐量较大。
ARM流水线技术
流水线技术通过多个功能部件并行工作缩短程序执行时间,提高处理器内核效率和吞吐率。
ARM7处理器 是 ARM v3架构使用典型三级流水线的冯诺依曼结构内核,
ARM9处理器 是 ARM v4\v5架构使用五级流水线的哈佛结构内核。
CortexM3 使用 ARM v7架构,五级流水线,改进哈佛结构内核。
CortexM4 使用 ARM v7架构,改进哈佛结构内核。CortexM4相较于CortexM3多了DSP处理功能、SIMD单指令多数据功能等。
Cortex-M4 在硬件上增加了 SIMD 指令集,允许一次操作多个数据,从而提高数据处理的效率。
流水线是 RISC精简指令集处理器执行指令时采用的机制。
三级流水线:
-
取指令。从寄存器装载一条指令。
-
译码。识别装载的指令。并从寄存器组中读取操作数。
-
执行。处理指令并将结果写回寄存器。
三级流水线的内核一般是冯诺伊曼架构。一条总线分时处理数据和指令。
五级流水线:
-
取指令。从寄存器装载一条指令。
-
译码。识别装载的指令。并从寄存器组中读取操作数。
-
执行。
-
缓冲。如果需要则访问数据存储器,否则 ALU 只是简单地缓冲 1 个时钟周期。
-
回写。将指令的结果回写到寄存器堆,包括任何从寄存器读出的数据。
五级流水线的内核一般是改进哈佛结构,指令和数据分开存储和处理。
在执行的过程中,通过R15寄存器直接访问PC的时候,必须考虑此事流水线执行过程的真实情况。程序计数器R15(PC)总是指向取指的指令,而不是指向正在执行的指令或者正在译码的指令。一般情况下,人们总是习惯把正在执行的指令作为参考点,称之为当前第1条指令,因此PC总是指向第3条指令。
对于ARM状态下指令,PC值=当前程序执行位置+8;
对于Thumb指令, PC值=当前程序执行位置+4.
题目:
若每一条指令都可以分解为取指、分析和执行三步。己知取指时间t取指=4△t,分析时间t分析=3△t,执行时间t执行=5△t。。如果按照流水方式执行,执行完100条指令需要__△t。
解答:
第一条指令取指时间4t+
max{取指令,分析时间}+
97个max{取指时间,分析时间,执行时间}+
max{分析时间,执行时间}+
最后一个执行时间5t,这个加起来就是507t。
分析:
当多条指令同时在流水线中处理时,流水线的效率取决于最慢的阶段,即影响整体速度的是最慢的阶段。
RISC 和 CISC区别
常见的CPU有两种架构,X86、ARM。前者主要用在电脑里,后者主要用在手机、平板上。
常见的指令集有两种,一种是复杂指令集(CISC),X86就属于复杂指令集;一种是精简指令集(RISC),家族成员有ARM、RISC-V、MIPS等。
1、精简指令集每条长度固定32位;由于指令位数较短,内部还有快速处理指令的电路,使得指令的译码与数据处理较快。不过必须经过编译处理才能发挥效率。
2、精简指令集不能直接操作内存数据,要用load/store命令;每个指令周期都能执行一条指令。
Thumb指令属于精简指令集,但是更精简,一条指令16位。
ARM 指令集分为几类
指令集分为复杂指令集RISC和精简指令集CISC。
ARM架构使用精简指令集,同时包括ARM指令集和Thumb指令集。ARM指令长度为32位,Thumb指令长度为16位。使得ARM既可以执行32位指令又可以执行16位指令。
ARM 处理器有几种工作状态
ARM 微处理器的工作状态有 ARM 和 Thumb 两种,两种状态可切换。
ARM 状态:此时处理器执行32位的ARM指令。
Thumb 状态:此时处理器执行16位的Thumb指令。
NVIC和位带操作
Cortex-M3内核采用嵌套中断向量控制器 NVIC,使得中断响应时间减少。
Cortex-M3采用位带操作,使得响应速度更快。
在STM32中,支持位带操作的区域称为位带区 (Bit Band regieon),而被位带区映射的地址被称为别名区 (Alias region)。
SRAM、片上外设 各有1M 处于低地址的位带区 ,分别映射到高地址的32M 的别名区。
SARM 区的最低 1M 范围位带:
0x2000_0000‐0x200F_FFFF,绑定的别名区0x2200_0000~0x23FF_FFFF。
片上外设 区的最低 1M 范围:
0x4000_0000‐0x400F_FFFF,绑定的别名区0x4200_0000~0x43FF_FFFF。
注意:映射地址的1位,对应物理地址的8位。
位带操作:
支持了位带操作以后,可以使用普通的加载/存储指令来对单一的比特进行读写。在CM3中,有两个区实现了位带。其中一个是SRAM的最低1MB范围,另一个是片上外设的最低1MB范围。这两个位带区中的地址除了可以像普通的RAM一样使用外,还有自己的"位带别名区"。
位带别名区把每个比特膨胀成一个32位的字。位带区的值等于对应位带别名区最低位的值。当通过位带别名区访问这些字的时候,就可以达到访问原始比特的目的。
位带操作的优越性:
最容易想到的就是,通过GPIO管脚来单独控制每盏LED的点亮与熄灭。也就是位带操作使得STM32具有对寄存器进行位操作的功能。
ARM 的 7种工作模式
用户模式、系统 模式、普通中断 模式、快速中断 模式、管理 模式、终止 模式、未定义模式
用户模式(USR)
用户程序的工作模式,运行在操作系统的用户态。
除非产生软中断或者异常,否则用户模式只能访问自己的数据,没有权限操作其他资源或切换到其他模式。
系统模式(SYS)
系统模式是特权模式。该模式下系统模式和用户模式共用一套寄存器,操作系统可以访问用户模式的寄存器,操作系统的特权任务可以访问受控资源。
普通中断模式(IRQ)
用于处理一般的中断请求,硬件产生中断信号之后自动进入该模式。中断模式也属于特权模式,可以自由访问系统硬件资源。
快速中断模式(FIQ)
用来处理紧急的中断请求,主要用于高速数据传输及通道中。
管理模式(SVC)
CPU上电后默认进入管理模式。管理模式主要用来做系统的初始化。软中断处理也在该模式下。当用户模式通过软中断访问硬件资源时,自动进入管理模式。
终止模式(ABT)
当用户访问非法地址时进入终止模式。linux下编程时经常抛出的segment fault都是在该模式下抛出返回的。
未定义模式(UND)
CPU在指令的译码阶段碰到不能识别的指令时进入未定义模式。抛出不能识别指令的异常。
除了用户模式外,其他六种模式,都属于特权模式。
(系统、普通中断、快速中断、管理、终止、未定义)
ARM 寄存器
ARM处理器有37个寄存器。31个通用寄存器 和 6个状态寄存器 。ARM寄存器都是32位的。
通用寄存器R15~R0、R16(程序状态寄存器CPSR)都是可访问的。
R16是程序状态寄存器CPSR*。R15是程序计数器PC,R14是链接寄存器LR,R13是堆栈指针SP。*
通用寄存器包括R0~R15,可以分为3类:
(1)未分组寄存器R0~R7
未分组寄存器在所有运行模式下都指向同一个物理寄存器。在中断、异常、模式转换时,处理器的不同运行模式均使用相同的物理寄存器,可能造成寄存器中数据的破坏。
(2)分组寄存器R8~R14
分组寄存器在不同运行模式下指向不同的物理寄存器。
分组寄存器 R8~R12,每个寄存器对应 2个不同的物理寄存器( fiq 和 usr )。当FIQ(快速中断)模式时,访问寄存器R8_fiq~R12_fiq;其他模式时,访问寄存器R8_usr~R12_usr。
分组寄存器 R13、R14 ,每个寄存器对应 6个不同的物理寄存器。其中物理寄存器 usr是用户模式与系统模式共用,另外 5个对应其他5中不同的运行模式。并采用以下记号来区分不同的物理寄存器:R13_ ; R14_ 。
其中 mode 可为:usr,irq,frq,svc,abt,und 。
处理器的每种模式都有自己对应的R13(SP堆栈寄存器),R13在用户应用程序的初始化部分初始化 ,指向该运行模式空间的栈顶。当程序的运行进入异常模式时,可以将需要保护的寄存器放入R13指向的堆栈 ,当程序从异常模式返回时,则从对应的堆栈中恢复。采用这种方式可以保证异常发生后程序的正确执行。
R14称为子程序链接寄存器LR,当执行子程序调用指令(BL)时,R14可得到R15(PC程序计数器)的备份。在每种运行模式下,都可用R14保存子程序的返回地址,当用BL或BLX指令调用子程序时,将PC的当前值(即子程序的返回地址)复制给R14,执行完子程序后,又将R14的值复制回PC,即可完成子程序的调用返回。R14也可作为通用寄存器。
(Link Register,LR) (Branch with Link,BL)
(3)程序计数器PC(R15)
寄存器R15用作程序计数器(PC)。
在ARM状态下,位[1:0]为0,位[31:2]用于保存PC。
在Thumb状态下,位[0]为0,位[31:1]用于保存PC。
由于ARM体系结构采用多级流水线技术,对于ARM指令集而言,PC总是指向当前指令的下两条指令的地址,即PC的值为当前指令的地址+8字节程序状态寄存器。(若是thumb指令集则+4字节)
3级流水线包括取值、译码、执行三步。
PC时钟始终指向当前取出的指令的地址。将正在执行得到指令作为参考点,称之为当前第一条指令,ARM状态时每条指令为4字节长度,因此PC总是指向当前执行的指令+8。
因为5级流水线使用哈佛结构,缓冲和回写属于对ALU的数据操作,数据和指令分开读写。因此 5级流水线,PC依然指向当前执行的指令+8。
从异常中断处理程序返回:
当数据访问异常发生时,如果是在ALU中发生,那么PC的值已经更新,PC指向当前指令后的第3条指令。如果不是在ALU中发生,则PC要返回发生错误的指令重新访问数据,因此PC不变。
寄存器R16(状态寄存器CPSR)
寄存器R16用作CPSR(当前程序状态寄存器),CPSR可以在任何模式下被访问。它包括条件标志位、中断禁止位、当前处理器模式标志位,以及其他一些相关的控制和状态位。每种运行模式下都有一个专用的备份程序状态寄存器CPSR。当异常发生时SPSR用于保存CPSR的当前值,从异常退出时则可由SPSR来恢复CPSR。
由于用户模式和系统模式不属于异常模式,因此没有SPSR,访问SPSR时结果未知。
SPSR(Saved Program Status Register,备份的程序状态寄存器)
ARM 系统调用函数时参数是通过哪种方式传递
当参数小于等于 4的时候是通过寄存器 r0~r3 传递,当参数大于4的时候是通过压栈的方式。
ARM 协处理器指令
协处理器用来协助中央处理器完成其无法完成的任务。中央处理器无法完成的工作有很多,比如接入设备的管理,图像和音频处理。
ARM32位架构最多支持16个协处理器(CP0~CP15)。最重要的协处理器是CP15,该协处理器提供了共计15个寄存器来配置和控制cache、MMU、保护系统、时钟模式等。
从ARMv8开始的64位架构弱化了协处理器的概念。
ARM 协处理器指令包括 3类:
-
用于 初始化协处理器的指令。
-
用于 ARM处理器的寄存器和协处理器的寄存器间的数据传送。
-
用于 协处理器和内存之间的数据传送。
中断与异常
中断与异常的区别
中断是由外部事件向CPU发送信号,请求CPU响应。
异常是CPU内部执行时发生错误,需要打断CPU的执行来处理这种不正常的情况。
中断与DMA的区别
DMA是一种无需CPU参与,就可以让外设与系统内存之间进行双向数据传输的硬件机制。
中断是外部事件向CPU发送信号,请求CPU响应,CPU暂停执行当前的程序处理突发事件,处理完再返回源程序被中断的位置继续执行。
DMA不需要CPU参与,中断需要CPU参与。
中断上下半部
当中断处理程序比较长时,linux内核会将中断处理程序分为中断上半部、中断下半部两部分。其中上半部用来标记中断,做紧急响应;下半部负责真正的中断操作。
拿网卡来举例,在linux内核中,当网卡一旦接受到数据,网卡会通过中断告诉内核处理数据,内核会在网卡中断处理函数(上半部)执行一些网卡硬件的必要设置,因为这是在中断响应后急切要干的事情。接着,内核调用对应的下半部函数来处理网卡接收到的数据,因为数据处理没必要在中断处理函数里面马上执行,可以将中断让出来做更紧迫的事情。
可以有三种方法来实现下半部:软中断、tasklet和等待队列。
tasklet 是通过软中断实现的,软中断就是软件实现的异步中断。优先级比硬中断低,比普通进程高,和硬中断一样不能休眠。
tasklet机制的引入,是为了支持SMP(对称多处理,不同tasklet可以在不同cpu上同时运行)。
tasklet属于中断上下文,因此不能被阻塞,不能睡眠,不能被打断。
workqueue机制特点是把中断下半部交给worker thead,因此下半部处于进程上下文,可以被重新调度,可以阻塞,也可以睡眠。
中断响应的执行流程是什么
CPU接受中断->
保存中断上下文->
跳转到中断处理程序->
执行中断上半部->
执行中断下半部->
恢复中断上下文
异常出现后,ARM微处理器会执行哪几步操作
1、如果异常是从ARM状态 进入,则链接寄存器LR中保存下一条指令的地址 (PC+4或PC+8)。如果异常是从Thumb状态 进入,则链接寄存器LR中保存当前PC的偏移量。
2、将程序状态寄存器CPSR复制到相应的备份状态寄存器SPSR中。
3、根据异常类型,强制设置CPSR的运行模式位。
4、强制PC从相关的异常向量地址取下一条指令执行,从而跳转到相应的异常处理程序处。
写一个中断服务函数需要注意哪些?
1、中断服务函数要快进快出。在中断服务函数尽快采集信息,处理使用tasklet或者workqueue方式。也就是中断上半部和下半部。
2、中断服务函数不能有阻塞操作。应为中断完全占用CPU,其他进程无法执行。
3、中断服务函数应该使用操作系统定义的宏作为返回值。
为什么FIQ比IRQ要快
1、FIQ模式提供了更多的banked寄存器,R8~R14,还有SPSR,而IRQ模式就没有这么多。在IRQ模式下,要自己保存R8~R12这几个寄存器 ,然后退出中断时要恢复这几个寄存器 。而FRQ模式由于这几个寄存器都有banked寄存器,模式切换时CPU自动保存这些值到banked寄存器,退出FIQ模式时自动恢复。ARM编译的时候,如果FIQ中断足够用这几个独立的寄存器来运作,就不会进行通用寄存器的压栈,节省时间。
2、FIQ比IRQ有更高优先级。
3、FIQ的入口地址是0x1c,IRQ的入口地址是0x18。也就是IRQ入口地址连续的空间只有4个字节,只能放一条指令。想放更多的就需要进行地址跳转。而FIQ的入口地址后面都是连续的,没有其他的中断向量表了。
中断和轮询哪个效率高?怎样决定是采用中断方式还是采用轮询方式去实现驱动?
中断是CPU在被动状态 下接收设备的信号,而轮询是CPU主动去查询该设备是否有请求。
如果设备频繁请求 CPU,那么轮询 的效率是比中断高。如果设备请求cpu的频率比较低 ,用中断效率要高一些。因为中断可能出现饥饿现象,请求频繁时轮询综合效率高一些。
中断
硬中断/软中断是什么?有什么区别?
硬中断
硬中断是硬件产生的,每个设备都有自己的IRQ(中断请求)。硬中断可以直接中断CPU。
对于时钟中断,内核调度代码会将当前正在运行的进程挂起,让其他的进程运行。它的存在是为了让调度器可以调度多任务。
软中断
软中断是由当前正在运行的进程产生的。
软中断通常是一些对IO的请求。对于某些设备,I/O请求需要被立即处理,而磁盘I/O请求通常可以排队并且可以稍后处理。
软中断仅与中断内核相联系。而内核主要负责对其他进程进行调度。
软中断并不会直接中断CPU。这种中断是一种需要内核为正在运行的进程去做一些事情(如I/O请求)。有一个特殊的软中断是Yield调用,它的作用是释放cpu去执行其他进程。
硬中断和软中断的区别
1、软中断是执行中断指令产生的,而硬中断是由外设引发的。
2、硬中断的中断号是由中断控制器提供的,软中断的中断号由指令直接指出。无需使用中断控制器。
3、硬中断可屏蔽,软中断不可屏蔽。
4、硬中断要快进快出,属于上半部。软中断处理硬中断未完成的工作,属于下半部。
中断为什么区分上半部和下半部
Linux中断分为硬件中断和内部中断(异常),调用过程:外部中断产生->发送中断信号到中断控制器->通知处理器产生中断的中断号。
对于中断上半部和下半部的产生,为了中断处理过程被新的中断打断,将中断一分为二,上半部登记新的中断,快速处理简单的新任务,复杂耗时的处理留给下半部。下半部处理可以被抢占,上半部处理不能被抢占。
中断下半部一般如何实现?
可以有三种方法来实现下半部:软中断、tasklet和等待队列。
tasklet 是通过软中断实现的,软中断就是软件实现的异步中断。优先级比硬中断低,比普通进程高,和硬中断一样不能休眠。
tasklet机制的引入,是为了支持SMP(对称多处理,不同tasklet可以在不同cpu上同时运行)。
tasklet属于中断上下文,因此不能被阻塞,不能睡眠,不能被打断。
workqueue机制特点是把中断下半部交给worker thead,因此下半部处于进程上下文,可以被重新调度,可以阻塞,也可以睡眠。
通信协议
什么是异步传输和同步传输
异步传输:是一种典型的基于字节的输入输出,数据传输每次一个字节,传输速度低。
同步传输:需要外界的时钟信号进行通信。同步传输一般都是按帧传输。
RS232和RS485通讯接口有什么区别
1、传输方式。RS232采取单端通信传输,RS485采取差分信号传输。单端通信指只有一个信号引脚传输信号,适用短距离传输,抗干扰能力弱。RS485两根信号线,电压差形成显性电平和隐形电平,功耗较大抗干扰能力强适合远距离传输。
2、传输距离。RS232适合本地设备通信,传输距离一般不超过20m。RS485传输距离在几十米到上千米。
3、设备数量。RS232只允许一对一通信 ,而RS485接口在总线上允许连接多达128个收发器。
4、连接方式。RS232,规定用电平表示数据 ,线路就是单线路 的,用两根线 才能达到全双工 的目的;RS485,用差分电平表示数据 ,要实现全双工 ,必须用4根线。
RS232/RS485规定了电流在什么样的线路上流动,和信号的电平表达。
SPI 协议
SPI的应用
SPI 协议,是摩托罗拉公司提出的通信协议,即串行外围设备接口。是一种高速全双工的通信总线。所谓串行通信就是一根线按位发送数据。SPI总线可以直接与各个厂家生产的多种标准外围器件相连,包括FLASH、SRAM、网络控制器、LCD、A/D转换器和MCU等。
SPI接口
MOSI,主设备输出/从设备输入引脚。
MISO,主设备输入/从设备输出引脚。
**SCLK,时钟信号线。**两设备通信速率受限于低速设备。
**SS。片选信号线。**用来选择通信的从设备。
SPI连线
MOSI、MISO、SCLK这三根线是所有从设备共用。SS是被选中的从设备使用。
SPI时序
1、通信的起始和停止
选中CS信号线由高变低,是SPI通信的起始信号。
2、数据有效性。
SPI使用 MOSI、MISO来传输数据,使用SCK信号线进行数据同步。MOSI、MISO在 SCK的每个时钟周期传输一位数据 ,且数据的输入输出可以同时进行。通常高位先行。
MOSI 及 MISO的数据在SCK的上升沿期间变化输出,在SCK的下降沿时被采样。即在SCK的下降沿时刻,MOSI 及 MISO的数据有效。
SPI每次数据传输可以8位或16位为单位,每次传输的单位数不受限制。
3、CPOL(时钟极性)/CPHA(时钟相位)及通讯模式
上图讲述的图中时序只是SPI中的一种通讯模式。SPI一共有四种通讯模式。SPI通讯模式的不同在于:总线空闲时 SCK的时钟状态以及数据采样时刻。
时钟极性 CPOL是指SPI总线空闲状态时,SCK时钟线的状态。
时钟相位 CPHA是指数据的采样时刻,SCK的奇数边沿采样还是偶数边沿采样。
时钟极性 和 时钟相位 组合起来四种状况,就是SPI的四种模式。
SPI总线空闲时SCK线是高/低电平+SCK下降沿奇数/偶数采样
IIC 协议
简介
IIC协议,两根线,时钟线SCL、数据线SDA。
IIC协议是由数据线SDA和时钟线SCL构成的串行总线,可发送和接收数据。是一个多主机的半双工通信方式。每个挂载在总线上的器件都有个唯一的地址。
IIC时序
1、空闲状态
空闲状态时,SDA和SCL同时处于高电平。
2、起始信号
SCL高电平期间,SDA由高到低跳变。起始信号只能由主机空闲状态发起。
3、停止信号
SCL高电平期间,SDA由低到高跳变。
4、传输数据格式
SCL低电平期间,SDA电平变化;SCL高电平期间,读取SDA电平,此时SDA电平必须稳定,否则就会变成起始/终止信号。如果主机在传输数据期间,碰到中断等情况,可以主动拉低SCL,使IIC进入等待状态 ,直到处理结束再释放SCL ,数据传输会继续。
5、应答信号ACK
IIC总线上的数据都是以8位数据(字节) 进行的,当发送了8个数据后,发送方 会在第9 个时钟脉冲期间释放SDA数据,存到缓冲区,当接收方接收该字节成功,便会输出一个ACK应答信号,当接收方SDA为高电平,表示无效应答信号NACK;当SDA为低电平,表示有效应答信号ACK。
6、完整的数据传输
发送起始信号 后,发送8位的设备地址 ,其中第8位是对设备的读写标志。后面紧跟的就是数据 ,直到发送停止信号终止。
当我们第一次是读操作,然后想转换成写操作时,可以再发送一个起始信号,然后发送读的设备地址,不需要停止信号就能实现不同的地址转换。
IIC传输的数据格式
写操作
起始信号
7bit设备地址+1bit读/写操作
等待ACK应答
8bit数据
等待ACK应答
停止信号
IIC写操作
读操作
起始信号
设备地址+读/写操作
ACK应答
传输数据
ACK应答
停止信号
Linux驱动
指令
常用Linux指令
怎么查看当前进程?
列出当前进程: ps
查找特定进程:ps | grep 进程名
退出shell会话:exit
ls 命令的作用?
列出指定目录中的目录,以及文件
参数
-a 显示所有文件及目录 (. 开头的隐藏文件也会列出)
-l 除文件名称外,亦将文件型态、权限、拥有者、文件大小等资讯详细列出
-t将文件依建立时间之先后次序列出
-R 若目录下有文件,则以下之文件亦皆依序列出
mkdir 命令的作用?
mkdir 文件夹 创建一个文件夹,路径不存在则报错
mkdir -p 文件夹/子文件夹() 创建一个文件夹,路径不存在则创建
创建文件用什么命令?
vi/vim touch echo less、more、cat cd >/>>
vi/vim 直接创建并打开一个文本文件
touch 创建一个文件
echo "this is a new file" > file.txt 创建文件并将字符串写入,不存在则创建文件。> 指令为覆盖。
less、more 、cat
三者都是将文件内容输出到标准输出,其中 less和 more可以分页显示。(less可以往前翻页)。cat 是显示全部。三者可以根据已经存在的文件创建新的文件。
cat/less/more 1.txt > 2.txt
cd
cd >/>> file3.txt#创建新的空文件
cd 最主要的作用是切换目录,在cd 后面跟>或>>再加上文件名就可创建一个空文件。它和echo的区别在于echo可以写文件内容,而cd不能。
复制文件用什么命令?
cp -r test/ newtest test下所有文件复制到新目录 newtest下
查看文件内容有哪些命令可以使用?
vi/vim cat more/less tail(仅查看尾部,可指定行数) head(仅查看头部,可指定行数)
怎么向屏幕输出带空格的字符串?
echo hello world
移动文件?改名?
mv
删除文件用哪个命令?删除非空目录?删除空文件夹?
rm -rf
rmdir -rf-rf代表递归强制
查找文件内容用哪个命令
#在当前目录中,查找后缀有 file 字样的文件中包含 字符串 的文件,并打印出该行
grep 字符串 *文件后缀
#找到目录中具有字符串内容的文件grep -r 字符串 目录
#找到文件名包含文件名字符串b的文件,并查找不包含字符串a的行grep -v 字符串a *文件名字符串b* -v表示反向匹配
查找文件用哪个命令
find ./ -name "*.c" #列出当前目录及子目录下所有文件后缀 .c 的文件
cat 命令
cat -n text1 #把 text1 的文档内容加上行号后输入到屏幕
cat -n text1 > text2 #把 text1 的文档内容加上行号后输入到 text2 文件里。
cat -b text1 text2 >> text3 #把text1、text2的文件内容加上行号后追加到 text3文件里。
cat /dev/null > /etc/text.txt #清空 text文档的内容
常用的GCC指令
GCC代表GNC编译器套件。
编译的流程是 预处理、编译、汇编、链接。
预处理 GCC -E -o .i文件
编译 GCC -S -o .s文件
汇编 GCC -c -o .o文件
链接 GCC xxx.o -o xxx 得到可执行文件
预处理
gcc -E test.c -o test.i#把预处理的结果导出到test.i文件
-E 代表对.c源码进行预处理(preprocess)。-o代表导出。
' .i ' 文件是指经过预处理后的源代码文件。
编译
gcc -S test.i -o test.s #编译器将test.i编译成汇编语言,导出到.s汇编文件
-S 代表对预处理后的 .i 文件进行编译(--assemble)。生成 .s 汇编文件。
汇编
gcc -c test.s -o test.o #将汇编代码编译为目标文件.o但不链接
-C 代表对汇编文件 .s 进行汇编(--compilation),生成目标文件 .o
链接
gcc test.o -o test #将目标文件test.o连接成可执行文件test
一步编译到位
gcc test.c -o test #将源文件直接 预处理、编译、汇编、链接 生成可执行文件
常用的GDB调试命令
gcc -g test.c -o test #编译时生成debug有关的程序信息
gdb test #启动调试
help #查看命令帮助,具体命令查询在gdb中输入help + 命令,简写 h
run #重新开始运行文件,简写 r
start #单步执行
list #查看原代码,list-n,从第n行查看原代码
set #设置变量的值
next #单步调试(逐过程,函数直接执行),简写n
step #单步调试(逐语句),简写s
backtrace#查看函数调用的栈帧和层级关系,简写bt
frame #切换函数的栈帧,简写f
info #查看函数内部局部变量的数值,简写i
finish #结束当前函数,返回到函数调用点
continue #继续运行,简写c
print #打印值及地址,简写p
quit #退出gdb,简写q
break+num #在第num行设置断点,简写b
info breakpoints #查看当前设置的所有断点
delete breakpoints num #删除第num个断点,简写d
display #追踪查看具体变量值
undisplay #取消追踪观察变量
watch #被设置观察点的变量发生修改时,打印显示
i watch #显示观察点
enable breakpoints #启用断点
disable breakpoints #禁用断点
x #查看内存x/20xw 显示20个单元,16进制,4字节每单元
run argv[1] argv[2] #调试时命令行传参
set follow-fork-mode child #Makefile项目管理:选择跟踪父子进程(fork())
常用的驱动开发指令
加载/卸载驱动
insmod/modprobe #加载驱动,xxx.ko文件,加载时执行驱动入口函数
rmmod #卸载驱动,卸载时执行驱动出口函数
驱动入口函数 static int __init 类型的自定义函数
驱动出口函数 staitc int __exit 类型的自定义函数
Linux驱动如何查看驱动模块中打印信息
dmesg
查看内核环形缓冲区中的所有消息
如何查看内核中已有的字符设备信息?
lsmod 和 modprobe,
lsmod可以查看模块的依赖关系。modprobe在加载模块时会加载其他模块的依赖项
如何查看正在使用的有哪些中断号?
cat /proc/interrupt
uboot
什么是bootloader
BootLoader是芯片出厂预设的小段程序,它在系统上电时开始运行,初始化时钟,看门狗,中断,SDRAM,等外设 。然后将LInux内核从FLASH拷贝到SDRAM中。最后启动Linux内核。
Bootloader和Linux的关系就像PC上的BIOS和Windos的关系一样。
uboot启动过程中做了哪些事
第一阶段
初始化时钟,关闭看门狗,关中断,启动 ICACHE,关闭 DCACHE和 TLB,关闭 MMU,初始化SDRAM,初始化NAND FLASH,重定位。
第二阶段初始化一个串口,检测系统内存映射,将把内核映像和根文件系统映像从Flash读到SDRAM空间中,为内核设置启动参数,调用内核。
CPU和主存之间存在多级高速缓存,一般分为3级,分别是L1, L2和L3。代码由指令和数据组成。L1 Cache比较特殊,每个CPU会有2个L1 Cache。分别为:
指令高速缓存(Instruction Cache,简称iCache)
数据高速缓存(Data Cache,简称dCache)
L2和L3一般不区分指令和数据,可以同时缓存指令和数据。
uboot和内核如何完成参数传递
uboot启动后已经完成了基本的硬件初始化(如:内存、串口等),接下来,它的主要任务就是加载Linux内核到SDRAM,然后跳转到Linux内核所在的地址运行。
跳转时直接修改PC寄存器的值为Linux内核所在的地址。
在跳转到内核以前,uboot需要做好三件事:
1、CPU寄存器的设置
R0 = 0
R1 = 机器类型ID;
R2 = 启动参数标记列表在RAM中起始基地址。
2、CPU工作模式必须禁止中断(IRQs和FIQs)。
CPU设置为SVC模式。
3、Cache和MMU设置MMU必须关闭。
指令Cache可以打开也可以关闭。
数据Cache必须关闭。
当参数个数不超过4个时,使用r0~r3这4个寄存器来传递参数;如果参数个数超过4个,剩余的参数通过数据栈来传递。
为什么要给内核传递参数
uboot完成对硬件的初始化,但是内核并不了解当前的硬件环境,因此需要设置硬件参数告诉内核,让内核适应开发板。
uboot 如何给内核传递参数
R1把机器ID传递给内核 ,内核通过机器ID来判断是否支持当前机器。
R2存放块内存的基地址。内存中包括内存起始地址、内存大小、内核挂载文件系统的方式等信息。由于内存中有多个参数,因此要按照双方规定的地址 和参数结构存放。
内核以标记列表(tagged_list)的形式来传递启动参数。标记,是一种数据结构;标记列表,是连续存放的多个标记。标记列表以ATAG_CORE开始,以标记ATAG_NONE结束。
标记的数据结构为tag,它由一个tag_header结构和一个联合union组成。tag_header结构表示标记的类型和长度,比如是表示内存还是表示命令行等参数。union用来描述每个传递给内核的参数信息。
为什么uboot要关掉caches?
caches是cpu内部的缓存。CPU和主存之间存在3级高速缓存 ,L1 , L2 和L3。每个CPU有两个L1,分别用来存储指令(iCache)和数据(dCache)。L2和L3都只有一个,可同时缓存指令和数据。
caches是通过协处理器CP15管理的。
上电的时候 iCache 可以不关闭,但 dCache 一定要关闭。否则可能导致刚开始的代码取数据的时候去数据缓存里面取,这时候的RAM中数据还没有缓存过来,导致数据异常。
文件系统
什么是根文件系统
根文件系统(rootfs)是内核启动时挂载的第一个文件系统,不仅具有普通文件系统存储数据文件的功能,还用来保存内核代码的映像文件。bootloader程序会在根文件系统挂载后把一些初始化脚本(如rcS,inittab)和服务加载到内存中去,里面包含Linux内核运行所必须的应用程序、库等。
文件系统和内核是完全独立的两个部分,但文件系统可用来加载内核。在嵌入式中移植的内核下载到开发板上,是没有办法真正启动Linux操作系统的,会出现无法加载文件系统的错误。
根文件系统为什么重要
根文件系统是加载其他文件系统的根。根文件系统包含系统启动时所必须的目录和关键性文件,以及使其他文件系统得以挂载(mount)所必要的文件。例如
- init进程的应用程序必须运行在根文件系统上。
- 根文件系统提供了根目录"/"。
- linux挂载分区时所依赖的信息存放于根文件系统 /etc/fstab这个文件中。
- shell命令程序必须运行在根文件系统上,譬如 ls、cs等命令。
总之:一套linux体系,只有内核本身是不能工作的,必须要rootfs根文件系统(/etc/目录下的配置文件、/bin 、/sbin等目录下的shell命令,还有**/lib目录下的库文件**等)相互配合才能工作。
可执行映像文件通常由几部分组成
可执行映像文件是一种包含可执行程序的文件。WINDOS中可执行映像文件的后缀是PE,Linux操作系统中可执行映像文件的后缀通常是ELF。
可执行映像文件通常由三个部分构成。
- 一个或多个代码段,代码段的属性为只读。
- 零个或多个包含初始化数据的数据段,数据段的属性为可读写。
- 零个或多个不包含初始化数据的数据段,数据段的属性为可读写。
Linux驱动模型
字符设备驱动模型
设备驱动模型