硬件基础
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精简指令集处理器执行指令时采用的机制。
三级流水线:
1. 取指令。从寄存器装载一条指令。
2. 译码。识别装载的指令。并从寄存器组中读取操作数。
3. 执行。处理指令并将结果写回寄存器。
三级流水线的内核一般是冯诺伊曼架构。一条总线分时处理数据和指令。
五级流水线:
1. 取指令。从寄存器装载一条指令。
2. 译码。识别装载的指令。并从寄存器组中读取操作数。
3. 执行。
4. 缓冲。如果需要则访问数据存储器,否则 ALU 只是简单地缓冲 1 个时钟周期。
5. 回写。将指令的结果回写到寄存器堆,包括任何从寄存器读出的数据。
五级流水线的内核一般是改进哈佛结构,指令和数据分开存储和处理。
在执行的过程中,通过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类:
1. 用于 初始化协处理器的指令。
2. 用于 ARM处理器的寄存器和协处理器的寄存器间的数据传送。
3. 用于 协处理器和内存之间的数据传送。
中断与异常
中断与异常的区别
中断是由外部事件向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。片选信号线。用来选择通信的从设备。
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应答
停止信号
读操作
起始信号
设备地址+读/写操作
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。
可执行映像文件通常由三个部分构成。
- 一个或多个代码段,代码段的属性为只读。
- 零个或多个包含初始化数据的数据段,数据段的属性为可读写。
- 零个或多个不包含初始化数据的数据段,数据段的属性为可读写。