哈喽,大家好。我终于回来了!19号刚提交完大论文,就被抓去出差了,折腾了整整一周,26号早晨,才回到学校。鸽了良久都没更新干货了。明天更新一篇对于Arm的口试面试题目,文章内容已同步更新在github。

[TOC]

ARM体系与架构

硬件根底

NAND FLASH 和NOR FLASH异同?

不同点

类别NORNAND
快 像拜访SRAM一样,能够随机拜访任意地址的数据;如:unsighed short pwAddr = (unsighed short )0x02;unisignded short wVal;wVal = *pwAddr快,有严格的时序要求,须要通过一个函数能力读取数据,先发送读命令->发送地址->判断nandflash是否就绪->读取一页数据读命令、发送地址、判断状态、读数据都是通过操作寄存器实现的,如数据寄存器NFDATA
慢,写之前须要擦除,因为写只能是1->0,擦除能够使0->1快,写之前须要擦除,因为写只能是1->0,擦除能够使0->1
擦除十分慢(5S)快(3ms)
XIP代码能够间接在NOR FLASH上运行NO
可靠性比拟高,位反转的比例小于NAND FLASH的10%比拟低,位反转比拟常见,必须有校验措施
接口与RAM接口雷同,地址和数据总线离开I/O接口
可擦除次数10000~100000100000~1000000
容量小,1MB~32MB大,16MB~512MB
主要用途罕用于保留代码和要害数据用于保留数据
价格

留神:nandflash和norflash的0地址是不抵触的,norflash占用BANK地址,而nandflash不占用BANK地址,它的0地址是外部的。

相同点

1写之前都要先擦除,因为写操作只能使1->0,而擦除动作是为了把所有位都变1
2擦除单元都以块为单位

CPU,MPU,MCU,SOC,SOPC分割与差异?

1.CPU(Central Processing Unit),是一台计算机的运算外围和管制外围。CPU由运算器、控制器和寄存器及实现它们之间分割的数据、管制及状态的总线形成。差不多所有的CPU的运作原理可分为四个阶段:提取(Fetch)、解码(Decode)、执行(Execute)和写回(Writeback)。 CPU从存储器或高速缓冲存储器中取出指令,放入指令寄存器,并对指令译码,并执行指令。所谓的计算机的可编程性次要是指对CPU的编程。

2.MPU (Micro Processor Unit),叫微处理器(不是微控制器),通常代表一个功能强大的CPU(暂且了解为增强版的CPU吧),但不是为任何已有的特定计算目标而设计的芯片。这种芯片往往是集体计算机和高端工作站的外围CPU。最常见的微处理器是Motorola的68K系列和Intel的X86系列。

3.MCU(Micro Control Unit),叫微控制器,是指随着大规模集成电路的呈现及其倒退,将计算机的CPU、RAM、ROM、定时计数器和多种I/O接口集成在一片芯片上,造成芯片级的芯片,比方51,avr这些芯片,外部除了CPU外还有RAM,ROM,能够间接加简略的外围器件(电阻,电容)就能够运行代码了,而MPU如x86,arm这些就不能间接放代码了,它只不过是增强版的CPU,所以得增加RAM,ROM

MCU MPU 最次要的区别就睡是否间接运行代码。MCU有外部的RAM ROM,而MPU是增强版的CPU,须要增加内部RAM ROM才能够运行代码。

4.SOC(System on Chip),指的是片上零碎,MCU只是芯片级的芯片,而SOC是零碎级的芯片,它既MCU(51,avr)那样有内置RAM,ROM同时又像MPU(arm)那样弱小的,不单单是放简略的代码,能够放零碎级的代码,也就是说能够运行操作系统(将就认为是MCU集成化与MPU强解决力各长处二合一)。

5.SOPC(System On a Programmable Chip)可编程片上零碎(FPGA就是其中一种),下面4点的硬件配置是固化的,就是说51单片机就是51单片机,不能变为avr,而avr就是avr不是51单片机,他们的硬件是一次性掩膜成型的,能改的就是软件配置,说白点就是改代码,原本是跑流水灯的,改下代码,变成数码管,而SOPC则是硬件配置,软件配置都能够批改,软件配置跟下面一样,没什么好说的,至于硬件,是能够本人构建的也就是说这个芯片是本人结构进去的,这颗芯片咱们叫“白片”,什么芯片都不是,把硬件配置信息下载进去了,他就是相应的芯片了,能够让他变成51,也能够是avr,甚至arm,同时SOPC是在SOC根底上来的,所以他也是零碎级的芯片,所以记得当把他变成arm时还得加外围ROM,RAM之类的,不然就是MPU了。

什么是穿插编译?

在一种计算机环境中运行的编译程序,能编译出在另外一种环境下运行的代码,咱们就称这种编译器反对穿插编译。这个编译过程就叫穿插编译。简略地说,就是在一个平台上生成另一个平台上的可执行代码

这里须要留神的是所谓平台,实际上蕴含两个概念:体系结构(Architecture)、操作系统(OperatingSystem)。同一个体系结构能够运行不同的操作系统;同样,同一个操作系统也能够在不同的体系结构上运行。举例来说,咱们常说的x86 Linux平台实际上是Intel x86体系结构和Linux for x86操作系统的统称;而x86 WinNT平台实际上是Intel x86体系结构和Windows NT for x86操作系统的简称。

为什么须要穿插编译?

有时是因为目标平台上不容许或不可能装置咱们所须要的编译器,而咱们又须要这个编译器的某些特色;有时是因为目标平台上的资源贫乏,无奈运行咱们所须要编译器;有时又是因为目标平台还没有建设,连操作系统都没有,基本谈不上运行什么编译器。

形容一下嵌入式基于ROM的运行形式和基于RAM的运行形式有什么区别?

基于RAM

  1. 须要把硬盘和其余介质的代码先加载到ram中,加载过程中个别有重定位的操作。
  2. 速度比基于ROM的快,可用RAM比基于ROM的少,因为所有的代码,数据都必须寄存在RAM中。

基于ROM

  1. 速度较基于RAM的慢,因为会有一个把变量,局部代码等从存储器(硬盘,flash)搬移到RAM的过程。
  2. 可用RAM资源比基于RAM的多;

ARM处理器

什么是哈佛构造和冯诺依曼结构?

定义

冯诺依曼结构釆用指令和数据对立编址,应用同条总线传输,CPU读取指令和数据的操作无奈重叠

哈佛构造釆用指令和数据独立编址,应用两条独立的总线传输,CPU读取指令和数据的操作能够重叠

利弊

冯诺依曼结构次要用于通用计算机领域,须要对存储器中的代码和数据频繁的进行批改,对立编址有利于节约资源

哈佛构造次要用于嵌入式计算机,程序固化在硬件中,有较高的可靠性、运算速度和较大的吞吐。

什么是ARM流水线技术?

流水线技术通 过多个性能部件并行工作来缩短程序执行工夫,进步处理器核的效率和吞吐率,从而成为微处理器设计中最为重要的技术之一。ARM7处理器核应用了典型三级流水线的冯·诺伊曼构造ARM9系列则采纳了基于五级流水线的哈佛构造。通过减少流水线级数简化了流水线各级的逻辑,进一步提高了处理器的性能。

PC代表程序计数器,流水线应用三个阶段,因而指令分为三个阶段执行:1.取指(从存储器装载一条指令);2.译码(辨认将要被执行的指令);3.执行(解决指令并将后果写回寄存器)。而R15(PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或正在“译码”的指令。一般来说,人们习惯性约定将“正在执行的指令作为参考点”,称之为以后第一条指令,因而PC总是指向第三条指令。当ARM状态时,每条指令为4字节长,所以PC始终指向该指令地址加8字节的地址,即:PC值=以后程序执行地位+8

ARM指令是三级流水线,取指,译指,执行,同时执行的,当初PC指向的是正在取指的地址(下一条指令),那么cpu正在译指的指令地址是PC-4(假如在ARM状态下,一个指令占4个字节),cpu正在执行的指令地址是PC-8,也就是说PC所指向的地址和当初所执行的指令地址相差8。

当忽然产生中断的时候,保留的是PC的地址(PC-8+4 = PC-4 下一条指令的地址)

这样你就晓得了,如果返回的时候返回PC,那么两头就有一个指令没有执行,所以用SUB pc lr-irq #4

ARM有几种工作模式?

  1. 用户模式(USR)

    用户模式是用户程序的工作模式,它运行在操作系统的用户态,它没有权限去操作其它硬件资源,只能执行解决本人的数据,也不能切换到其它模式下,要想

    拜访硬件资源或切换到其它模式只能通过软中断或产生异样。

  2. 零碎模式(SYS)

    零碎模式是特权模式,不受用户模式的限度。用户模式和零碎模式共用一套寄存器,操作系统在该模式下能够不便的拜访用户模式的寄存器,而且操作系统的

    一些特权工作能够应用这个模式拜访一些受控的资源。

    阐明:用户模式与零碎模式两者应用雷同的寄存器,都没有SPSR(Saved Program Statement Register,已保留程序状态寄存器),但零碎模式比用户模式有更高的权限,能够拜访所有系统资源。
  3. 个别中断模式(IRQ)

    个别中断模式也叫一般中断模式,用于解决个别的中断请求,通常在硬件产生中断信号之后主动进入该模式,该模式为特权模式,能够自在拜访零碎硬件资源。

  4. 疾速中断模式(FIQ)
    疾速中断模式是绝对个别中断模式而言的,它是用来解决对工夫要求比拟紧急的中断请求,次要用于高速数据传输及通道解决中。(快中断有许多(R8~R14)本人的专用寄存器,产生中断时,应用本人的寄存器就防止了保留和复原某些寄存器。如果异常中断处理程序中应用它本人的物理寄存器之外的其余寄存器,异常中断处理程序必须保留和复原这些寄存器)
  5. 管理模式(SVC)
    管理模式是CPU上电后默认模式,因而,在该模式下次要用来做零碎的初始化,软中断解决也在该模式下。当用户模式下的用户程序申请应用硬件资源时,通过软件中断进入该模式。

    阐明:零碎复位或开机、软中断时进入到SVC模式下。
  6. 终止模式(ABT)
    停止模式用于反对虚拟内存或存储器爱护,当用户程序拜访非法地址没有权限读取的内存地址时,会进入该模式,linux下编程时经常出现的segment fault通常都是在该模式下抛出返回的。
  7. 未定义模式(UND)
    未定义模式用于反对硬件协处理器的软件仿真,CPU在指令的译码阶段不能辨认该指令操作时,会进入未定义模式。
  1. 除了用户模式外,其它6种模式称为特权模式。所谓特权模式,即具备如下权力:

a. MRS(把状态寄存器的内容放到通用寄存器);

b. MSR(把通用寄存器的内容放到状态寄存器中)。

因为状态寄存器中的内容不可能扭转,因而,要先把内容复制到通用寄存器中,而后批改通用寄存器中的内容,再把通用寄存器中的内容复制给状态寄存器中,即可实现“批改状态寄存器”的工作。

  1. 剩下的六种模式中除去零碎模式外,统称为异样模式。

Arm有多少32位寄存器?

ARM处理器共有37个寄存器。它蕴含31个通用寄存器和6个状态寄存器。

Arm2440和6410有什么区别?

  1. 主频不同。2440是400M的。6410是533/667M的;
  2. 处理器版本不一样:2440是arm920T内核,6410是arm1176ZJF内核;
  3. 6410在视频解决方面比2440要强很多。外部视频解码器,包含MPEG4等视频格式;
  4. 6410反对WMV9、xvid、mpeg4、h264等格局的硬解码和编码;
  5. 6410多和很多扩大接口比方:tv-out、CF卡和S-Video输入等;
  6. spi、串口、sd接口也比那两个要丰盛;
  7. 6410采纳的是DDR内存控制器;2440采纳的是SDRam内存控制器;
  8. 6410为双总线架构,一路用于内存总线、一路用于Flash总线;
  9. 6410的启动形式更加灵便:次要包含SD、Nand Flash、Nor Flash和OneFlash等设施启动;
  10. 6410的Nand Flash反对SLC和MLC两种架构,从而大大扩充存储空间;
  11. 6410为双总线架构,一路用于内存总线、一路用于Flash总线;
  12. 6410具备8路DMA通道,包含LCD、UART、Camera等专用DMA通道;
  13. 6410还反对2D和3D的图形减速;

ARM指令集分为几类?

2类,别离为Thumb指令集,ARM指令集。ARM指令长度为32位,Thumb指令长度为16位。这种特点使得ARM既能执行16位指令,又能执行32位指令,从而加强了ARM内核的性能。

通用寄存器包含R0~R15,能够分为具体哪三类?

通用寄存器包含R0-R15,能够分为3类:

  1. 未分组寄存器R0-R7

    在所有运行模式下,未分组寄存器都指向同一个物理寄存器,他们未被零碎用作非凡的用处。因而在中断或异样解决进行异样模式转换时,因为不同的处理器运行模式均应用雷同的物理寄存器,所以可能造成寄存器中数据的毁坏

  2. 分组寄存器R8-R14

    对于分组寄存器,他们每次所拜访的物理寄存器都与以后的处理器运行模式相干

    R13罕用作寄存堆栈指针,用户也能够应用其余寄存器寄存堆栈指针,但在Thumb指令集下,某些指令强制要求应用R13寄存堆栈指针。

    R14称为链接寄存器(LR,Link Register),当执行子程序时,R14可失去R15(PC)的备份,执行完子程序后,又将R14的值复制回PC,即应用R14保留返回地址。

  3. 程序计数器PC(R15)

    寄存器R15用作程序计数器(PC),在ARM状态下,位[1:0]为0,位[31:2]用于保留PC;在Thumb状态下,位[0]为0,位[31:1]用于保留PC。

Arm处理器有几种工作状态?

从编程的角度来看,ARM微处理器的工作状态个别ARM和Thumb有两种,并可在两种状态之间切换。

  1. ARM状态:此时处理器执行32位的字对齐ARM指令,绝大部分工作在此状态。
  2. Thumb状态:此时处理器执行16位的半字对齐的Thumb指令。

ARM零碎中,在函数调用的时候,参数是通过哪种形式传递的?

当参数小于等于4的时候是通过r0-r3寄存器来进行传递的,当参数大于4的时候是通过压栈的形式进行传递。

为什么2440的内存起始地址是0x30000000?

S3C2440处理器有八个固定的内存块,只有两个是能够作为ROM,SRAM和SDRAM等存储器bank。具体如下图所示。

ARM协处理器指令包含哪3类,请形容它们的性能。

ARM协处理器指令包含以下3类:

  1. 用于ARM处理器初始化ARM协处理器的数据处理操作。
  2. 用于ARM处理器的寄存器和ARM协处理器的寄存器间的数据传送操作。
  3. 用于在ARM协处理器的寄存器和内存单元之间传送数据。

什么是PLL(锁相环)?

简略来说,输出时钟的存在是作为“参考源”。锁相环不是为了单纯产生同频同置信号,而是个别集成进某种“频率综合电路”,产生一个不同频,但锁相的信号。

有点绕,打个比方:某参考晶振10Mhz,频率综合器A应用该参考源产生了900Mhz时钟,而频率综合器B产生了1Ghz时钟。尽管两路频率不同,但因为应用的通一个参考源,他们俩依然是同源信号。相同,如果不同源,那么即使同频他们也不可能统一,因为世界上没有两个钟能做到齐全一样,总有强劲的频差,导致相位飘移。在很多事实利用中有要求同源时钟的场合,所以,锁相环被广泛应用。锁相环的另外一项衍生利用是相干解调,能够本人查查相干材料。

中断与异样

中断与异样有何区别?

中断是指内部硬件产生的一个电信号从CPU的中断引脚进入,打断CPU的运行。

异样是指软件运行过程中产生了一些必须作出解决的事件,CPU主动产生一个陷入来打断CPU的运行。异样在解决的时候必须思考与处理器的时钟同步,实际上异样也称为同步中断,在处理器执行到因编译谬误而导致的谬误指令时,或者在执行期间呈现非凡谬误,必须靠内核解决的时候,处理器就会产生一个异样。

中断与DMA有何区别?

DMA:是一种毋庸CPU的参加,就能够让外设与零碎内存之间进行双向数据传输的硬件机制,应用DMA能够使零碎CPU从理论的I/O数据传输过程中解脱进去,从而大大提高零碎的吞吐率。

中断:是指CPU在执行程序的过程中,呈现了某些突发事件时,CPU必须暂停执行以后的程序,转去解决突发事件,处理完毕后CPU又返回源程序被中断的地位并继续执行。

所以中断和DMA的区别就是:DMA不需CPU参加,而中断是须要CPU参加的。

中断能不能睡眠,为什么?下半部能不能睡眠?

  1. 中断解决的时候,不应该产生过程切换。因为在中断上下文中,惟一能打断以后中断handler的只有更高优先级的中断,它不会被过程打断。如果在中断上下文中休眠,则没有方法唤醒它,因为所有的wake_up_xxx都是针对某个过程而言的,而在中断上下文中,没有过程的概念,没有一个task_struct(这点对于softirq和tasklet一样)。因而真的休眠了,比方调用了会导致阻塞的例程,内核简直必定会死。
  2. schedule()在切换过程时,保留以后的过程上下文(CPU寄存器的值、过程的状态以及堆栈中的内容),以便当前复原此过程运行。中断产生后,内核会先保留以后被中断的过程上下文(在调用中断处理程序后复原)。

    但在中断处理程序里,CPU寄存器的值必定曾经变动了(最重要的程序计数器PC、堆栈SP等)。如果此时因为睡眠或阻塞操作调用了schedule(),则保留的过程上下文就不是以后的过程上下文了。所以,不能够在中断处理程序中调用schedule()。

  3. 2.4内核中schedule()函数自身在进来的时候判断是否处于中断上下文:
if(unlikely(in_interrupt()))BUG();

 因而,强行调用schedule()的后果就是内核BUG,但看2.6.18的内核schedule()的实现却没有这句,改掉了。

  1. 中断handler会应用被中断的过程内核堆栈,但不会对它有任何影响,因为handler应用完后会齐全革除它应用的那局部堆栈,复原被中断前的原貌。
  2. 处于中断上下文时候,内核是不可抢占的。因而,如果休眠,则内核肯定挂起。

中断的响应执行流程是什么?

中断的响应流程:cpu承受中断->保留中断上下文跳转到中断解决历程->执行中断上半部->执行中断下半部->复原中断上下文。

当一个异样呈现当前,ARM微处理器会执行哪几步操作?

  1. 将下一条指令的地址存入相应连贯寄存器LR,以便程序在解决异样返回时能从正确的地位从新开始执行。若异样是从ARM状态进入,则LR寄存器中保留的是下一条指令的地址(以后PC+4或PC+8,与异样的类型无关);若异样是从Thumb状态进入,则在LR寄存器中保留以后PC的偏移量,这样,异样处理程序就不须要确定异样是从何种状态进入的。例如:在软件中断异样SWI,指令 MOV PC,R14_svc总是返回到下一条指令,不论SWI是在ARM状态执行,还是在Thumb状态执行。
  2. 将CPSR复制到相应的SPSR中。
  3. 依据异样类型,强制设置CPSR的运行模式位。
  4. 强制PC从相干的异样向量地址取下一条指令执行,从而跳转到相应的异样处理程序处。

写一个中断服务须要留神哪些?如果中断产生之后要做比拟多的事件你是怎么做的?

  1. 写一个中断服务程序要留神快进快出,在中断服务程序外面尽量疾速采集信息,包含硬件信息,而后退出中断,要做其它事件能够应用工作队列或者tasklet形式。也就是中断上半部和下半部。
  2. 中断服务程序中不能有阻塞操作。应为中断期间是齐全占用CPU的(即不存在内核调度),中断被阻塞住,其余过程将无奈操作。
  3. 中断服务程序留神返回值,要用操作系统定义的宏做为返回值,而不是本人定义的。
  4. 如果要做的事件较多,应将这些工作放在后半段(tasklet,期待队列等)解决。

为什么FIQ比IRQ要快?

  1. ARM的FIQ模式提供了更多的banked寄存器r8到r14还有SPSR,而IRQ模式就没有那么多,R8,R9,R10,R11,R12对应的banked的寄存器就没有,这就意味着在ARM的IRQ模式下,中断处理程序本人要保留R8到R12这几个寄存器,而后退出中断解决时程序要复原这几个寄存器,而FIQ模式因为这几个寄存器都有banked寄存器,模式切换时CPU主动保留这些值到banked寄存器,退出FIQ模式时主动复原,所以这个过程FIQ比IRQ快.不要小看这几个寄存器,ARM在编译的时候,如果你FIQ中断处理程序足够用这几个独立的寄存器来运作,它就不会进行通用寄存器的压栈,这样也省了一些工夫。
  2. FIQ比IRQ有更高优先级,如果FIQ和IRQ同时产生,那么FIQ先解决。
  3. 在symbian零碎里,当CPU处于FIQ模式解决FIQ中断的过程中,预取指令异样,未定义指令异样,软件中断全被禁止,所有的中断被屏蔽。所以FIQ就会很快执行,不会被其余异样或者中断打断,所以它又比IRQ快了。而IRQ不一样,当ARM解决IRQ模式解决IRQ中断时,如果来了一个FIQ中断请求,那正在执行的IRQ中断处理程序会被抢断,ARM切换到FIQ模式去执行这个FIQ,所以FIQ比IRQ快多了。
  4. 另外FIQ的入口地址是0x1c,IRQ的入口地址是0x18。写过残缺汇编零碎的都比拟明确这点的差异,18只能放一条指令,为了不与1C处的FIQ抵触,这个中央只能跳转,而FIQ不一样,1C当前没有任何中断向量表了,这样能够间接在1C处放FIQ的中断处理程序,因为跳转的范畴限度,至多少了一条跳转指令。

中断和轮询哪个效率高?怎么决定是采纳中断形式还是采纳轮询形式去实现驱动?

中断是CPU处于被动状态下来承受设施的信号,而轮询是CPU被动去查问该设施是否有申请。

凡事都是两面性,所以,看效率不能简略的说那个效率高。如果是申请设施是一个频繁申请cpu的设施,或者有大量数据申请的网络设备,那么轮询的效率是比中断高。如果是个别设施,并且该设施申请cpu的频率比拟低,则用中断效率要高一些。次要是看申请频率。

通信协议

什么是异步传输和同步传输?

异步传输:是一种典型的基于字节的输入输出,数据按每次一个字节进行传输,其传输速度低。

同步传输:须要外界的时钟信号进行通信,是把数据字节组合起来一起发送,这种组合称之为帧,其传输速度比异步传输快。

RS232和RS485通信接口有什么区别?

  1. 传输方式不同。 RS232采取不均衡传输方式,即所谓单端通信。 而RS485则采纳均衡传输,即差分传输方式
  2. 传输间隔不同。RS232适宜本地设施之间的通信,传输间隔个别不超过20m。而RS485的传输间隔为几十米到上千米
  3. 设施数量。RS232 只容许一对一通信,而RS485 接口在总线上是容许连贯多达128个收发器
  4. 连贯形式。RS232,规定用电平示意数据,因而线路就是单线路的,两根线能力达到全双工的目标;而RS485, 应用差分电平示意数据,因而,必须用两根线能力达到传输数据的根本要求,要实现全双工,必须用4根线

 总结:从某种意义上,能够说,线路上存在的仅仅是电流,RS232/RS485规定了这些电流在什么样的线路上流动和流动的款式

SPI协定

SPI的利用

SPI(Serial Peripheral Interface)协定是由摩托罗拉公司提出的通信协定,即串行外围设备接口,是一种高速全双工的通信总线。SPI总线零碎是一种同步串行外设接口,它能够使MCU与各种外围设备以串行形式进行通信以替换信息。SPI总线可间接与各个厂家生产的多种规范外围器件相连,包含FLASH、RAM、网络控制器、LCD显示驱动器、A/D转换器和MCU等。

接口

  1. MOSI (Master Output, Slave Input)

    主设施输入/从设施输出引脚。主机的数据从这条信号线输入,从机由这条信号线读入主机发送的数据,即这条线上数据的方向为主机到从机。

  2. MISO(Master Input,, Slave Output)

    主设施输出/从设施输入引脚。主机从这条信号线读入数据,从机的数据由这条信号线输入到主机,即在这条线上数据的方向为从机到主机。

  3. SCLK (Serial Clock)

    时钟信号线,用于通信数据同步。它由通信主机产生,决定了通信的速率,不同的设施反对的最高时钟频率不一样,如 STM32 的 SPI 时钟频率最大为fpclk/2,两个设施之间通信时,通信速率受限于低速设施。

  4. SS( Slave Select)

    从设施抉择信号线,常称为片选信号线,也称为 NSS、 CS,以下用 NSS 示意。 当有多个 SPI 从设施与 SPI 主机相连时,设施的其它信号线 SCK、MOSI 及 MISO 同时并联到雷同的 SPI 总线上,即无论有多少个从设施,都独特只应用这 3 条总线;而每个从设施都有独立的这一条 NSS 信号线,本信号线独占主机的一个引脚,即有多少个从设施,就有多少条片选信号线。

    I2C 协定中通过设施地址来寻址、选中总线上的某个设施并与其进行通信;而 SPI 协定中没有设施地址,它应用 NSS 信号线来寻址,当主机要抉择从设施时,把该从设施的 NSS 信号线设置为低电平,该从设施即被选中,即片选无效,接着主机开始与被选中的从设施进行 SPI 通信。所以SPI 通信以 NSS 线置低电平为开始信号,以 NSS 线被拉高作为完结信号。

协定层

SPI 通讯设备之间的罕用连贯形式见下图:

SPI 通信的通信时序,见下图:

  1. 通信的起始和进行信号

    在图中的标号1处,NSS 信号线由高变低,是 SPI 通信的起始信号。 NSS 是每个从机各自独占的信号线,当从机检在本人的 NSS 线检测到起始信号后,就晓得本人被主机选中了,开始筹备与主机通信。在图中的标号处, NSS 信号由低变高,是 SPI 通信的进行信号,示意本次通信完结,从机的选中状态被勾销。

  2. 数据有效性

    SPI 应用 MOSI 及 MISO 信号线来传输数据,应用 SCK 信号线进行数据同步。 MOSI及 MISO 数据线在 SCK 的每个时钟周期传输一位数据,且数据输入输出是同时进行的。数据传输时, MSB 后行(高位后行)或 LSB(低位后行)后行并没有作硬性规定,但要保障两个 SPI 通讯设备之间应用同样的协定,个别都会采纳上图中的 MSB 后行(高位后行)模式。

    察看图中的2345标号处, MOSI 及 MISO 的数据在 SCK 的回升沿期间变动输入,在 SCK 的降落沿时被采样。即在 SCK 的降落沿时刻, MOSI 及 MISO 的数据无效,高电平时示意数据“1”,为低电平时示意数据“0”。在其它时刻,数据有效, MOSI 及 MISO为下一次示意数据做筹备。

    SPI 每次数据传输能够 8 位或 16 位为单位,每次传输的单位数不受限制。

  3. CPOL(时钟极性)/CPHA(时钟相位)及通信模式

    下面讲述的图中的时序只是 SPI 中的其中一种通信模式, SPI 一共有四种通信模式,它们的次要区别是:总线闲暇时 SCK 的时钟状态以及数据采样时刻。为不便阐明,在此引入“时钟极性CPOL”和“时钟相位 CPHA”的概念。

    时钟极性 CPOL 是指 SPI 通讯设备处于闲暇状态时, SCK 信号线的电平信号(即 SPI 通信开始前、 NSS 线为高电平时 SCK 的状态)。 CPOL=0 时, SCK 在闲暇状态时为低电平,CPOL=1 时,则相同。

    时钟相位 CPHA 是指数据的采样的时刻,当 CPHA=0 时, MOSI 或 MISO 数据线上的信号将会在 SCK 时钟线的“奇数边际” 被采样。当 CPHA=1 时,数据线在 SCK 的“偶数边际” 采样。

IIC协定

简介

IIC协定是由数据线SDA和时钟SCL形成的串行总线,可发送和接收数据,是一个多主机的半双工通信形式

每个挂接在总线上的器件都有个惟一的地址。位速在规范模式下可达 100kbit/s,在疾速模式下可达400kbit/s,在高速模式下可待3.4Mbit/s。

I2C总线系统结构,如下所示:

I2C时序介绍

1. 闲暇状态

当总线上的SDA和SCL两条信号线同时处于高电平,便是闲暇状态,如下面的硬件图所示,当咱们不传输数据时, SDA和SCL被上拉电阻拉高,即进入闲暇状态

2. 起始信号

SCL为高期间,SDA由高到低的跳变;便是总线的启动信号,只能由主机发动,且在闲暇状态下能力启动该信号,如下图所示:

3. 进行信号

SCL为高期间SDA由低到高的跳变;便是总线的进行信号,示意数据已传输实现,如下图所示:

4. 传输数据格式
当发了起始信号后,就开始传输数据,传输的数据格式如下图所示:

SCL为高电平时,便会获取SDA数据值,其中SDA数据必须是稳固的(若SDA不稳固就会变成起始/进行信号)。

SCL为低电平时,便是SDA的电平变动状态

若主从机在传输数据期间,须要实现其它性能(例如一个中断),能够被动拉低SCL,使I2C进入期待状态,直到解决完结再开释SCL,数据传输会持续

5. 应答信号ACK

I2C总线上的数据都是以8位数据(字节)进行的,当发送了8个数据后,发送方会在第9个时钟脉冲期间开释SDA数据,当接管方接管该字节胜利,便会输入一个ACK应答信号,当SDA为高电平,示意为非应答信号NACK,当SDA为低电平,示意为无效应答信号ACK

PS:当主机为接管方时,收到最初一个字节后,主机能够不发送ACK,间接发送进行信号来完结传输

当从机为接管方时,没有发送ACK,则示意从机可能在忙其它事、或者不匹配地址信号和不反对多主机发送,主机能够发送进行信号,再次发送起始信号启动新的传输。

6. 残缺的数据传输

如下图所示, 发送起始信号后,便发送一个8位的设施地址,其中第8位是对设施的读写标记,前面紧跟着的就是数据了,直到发送进行信号终止

PS:当咱们第一次是读操作,而后想换成写操作时,能够再次发送一个起始信号,而后发送读的设施地址,不须要进行信号便能实现不同的地址转换。

IIC传输数据的格局

1.写操作

刚开始主芯片要收回一个start信号,而后收回一个(用来确定是往哪一个芯片写数据),方向(读/写,0示意写,1示意读)。回应(用来确定这个设施是否存在),而后就能够传输数据,传输数据之后,要有一个回应信号(确定数据是否承受实现),而后再传输下一个数据。每传输一个数据,接受方都会有一个回应信号,数据发送完之后,主芯片就会发送一个进行信号

红色背景:主→从。灰色背景:从→主。

2.读操作

刚开始主芯片要收回一个start信号,而后收回一个设施地址(用来确定是从哪一个芯片读取数据),方向(读/写,0示意写,1示意读)。回应(用来确定这个设施是否存在),而后就能够传输数据,传输数据之后,要有一个回应信号(确定数据是否承受实现),而后在传输下一个数据。每传输一个数据,接受方都会有一个回应信号,数据发送完之后,主芯片就会发送一个进行信号

红色背景:主→从。灰色背景:从→主

编程

嵌人式编程中,什么是大端?什么是小端?

大端模式:低位字节存在高地址上,高位字节存在低地址上。

小端模式:高位字节存在高地址上,低位字节存在低地址上。

STM32属于小端模式,简略的说,比方u32 temp=0X12345678;假如temp地址在0X2000 0010。那么在内存外面,寄存就变成了:

地址         |            HEX     |0X2000 0010  |  78   56   43  12  |

因为是16进制的,一个数为0.5字节,所以 12 代表一个字节 34 代表一个字节。

釆用小端模式的CPU对操作数的寄存形式是从低字节到高字节,而大端模式对操作数的寄存形式是从高字节到低字节。例如,16位宽的数0x1234在小端模式CPU内存中的寄存形式(假如从地址0x4000开始寄存)见表1,而在大端模式CPU内存中的寄存形式见表2。

                      表1 0x1234在小端CPU内存中的寄存形式

内存地址寄存内容
0x40000x34
0x40010x12

                      表2 0x1234在大端CPU内存中的寄存形式

内存地址寄存内容
0x40000x12
0x40010x34

  32位宽的数0x12345678在小端模式CPU内存中的寄存形式(假如从地址0x4000开始寄存)见表3,而在大端模式CPU内存中的寄存形式见表4。

                      表3 0x12345678在小端CPU内存中的寄存形式

内存地址寄存内容
0x40000x78
0x40010x56
0x40020x34
0x40030x12

                      表4 0x12345678在大端CPU内存中的寄存形式

内存地址寄存内容
0x40000x12
0x40010x34
0x40020x56
0x40030x78

以下程序为例:

#include <stdio.h>struct mybitfields{    unsigned short a:4;    unsigned short b:5;    unsigned short c:7;}test;int main(){    int i;    test.a = 2;    test.b = 3;    test.c = 0;    i =*((short*)&test);    printf("%d\n",i);    return 0;}

程序的输入后果为 50。

上例中, sizeof( test)=2,上例的申明形式是把一个 short(也就是一块16位内存)分成3局部,各局部的大小别离是4位、5位、7位,赋值语句i*( short*)&test)就是把下面的16位内存转换成 short类型进行解释。

变量a的二进制示意为0000000000000010,取其低四位是0010.变量b的二进制示意为0000000000000011,取其低五位是00011。变量c的二进制示意为0000000000000000,取其低七位是0000000。

80x86机是小端(批改分区表时要留神)模式,单片机个别为大端模式。小端个别是低位字节在高位字节的后面,也就是低位在内存地址低的一端,能够这样记(小端→低位→在前→与失常逻辑程序相同),所以合成后失去0000000000110010,即十进制的50。

上面给出另外一个例子

#include <stdlib.h>#include <stdio.h>#include <string.h>int main(){    unsigned int uiVal_1 = 0x12345678;    unsigned int uiVal_2 = 0;    unsigned char aucVal[4] = {0x12,0x34,0x56,0x78};    unsigned short usVal_1 = 0;    unsigned short usVal_2 = 0;    memcpy(&uiVal_2,aucVal,sizeof(uiVal_2));    usVal_1 = (unsigned short)uiVal_1;//在这里截断,都获得的是低位    usVal_2 = (unsigned short)uiVal_2;//在这里截断    printf("usVal_1:%x\n",usVal_1);//在这里又转化回来    printf("usVal_2:%x\n",usVal_2);//在这里又转化回来    return 0;}

  小端模式是低地址寄存低字节,高地址寄存高字节,构造如下所示

78//低地址563412//高地址

  在内存外面测试机是小端,地址由小到大。

val1:78563412riVal2:12345678

  后果如下:

56783412

如何判断计算机处理器是大端,还是小端?

#include <stdio.h>int checkCPU(){    {        union w        {            int a;            char b;        }c;        c.a =1;        return(c.b == 1);    }}int main(){    if(checkCPU())        printf("小端\n");    else        printf("大端\n");    return 0;}

编者的处理器为ntel处理器,因为 Intel处理器个别都是小端模式,所以此时程序的输入后果为:小端

上述代码中,如果处理器是大端,则返回0;如果处理器是小端,则返回1.联合体 union的寄存程序是所有成员都从低地址开始寄存,如果可能通过改代码晓得CPU对内存是采纳小端模式读写,还是采纳大端模式读写,肯定会令面试官另眼相看。

还能够通过指针地址来判断,因为在32位计算机系统中, short占两个字节,char占1个字节,所以能够采纳如下做法实现该判断。

#include <stdio.h>int checkCPU(){    unsigned short usData = 0x1122;    unsigned char*pucData = (unsigned char*)&usData;    return (*pucData == 0x22);}int main(){    if(checkCPU())        printf("小端\n");    else        printf("大端\n");    return 0;}

程序输入的后果为:小端

如何进行大小端的转换?

int swapInt32(int intValue){    int temp = 0;    temp = ((intValue & 0x000000FF) <<24)|           ((intValue & 0x0000FF00) <<8) |           ((intValue & 0x00FF0000) >>8) |           ((intValue & 0xFF000000) >>24);    return temp;}/*short型:*/unsigned short swapShort16(unsigned short shortValue){ return ((shortValue & 0x00FF ) <<8) | ((shortValue & 0xFF00)>>8);}/*float型:*/float swapFloat32(float floatValue){         typedef union SWAP_UNION{         float unionFloat;         int   unionInt;         }SWAP_UNION;                  SWAP_UNION swapUnion;         swapUnion.unionFloat = floatValue;         swapUnion.unionInt = swapInt32(  swapUnion.unionInt);        return     swapUnion.unionFloat;}/*double型换一种写法,用一下指针,不然移位移死了……*/void swapDouble64(unsigned char *pIn, unsigned char *pOut){for( int i=0;i<8;i++)pOut[7-i] = pIn[i];}int main(){    int x = 0x12345678;    int y = swapInt32(x);    printf("%x\r\n",y);    return 0;}

如何对相对地址0x100000赋值?

(unsigned int*)0x100000 = 1234;

那么要是想让程序跳转到相对地址是0x100000去执行,应该怎么做?

*((void (*)( ))0x100000 ) ( );

首先要将0x100000强制转换成函数指针,即:

(void (*)())0x100000

而后再调用它:

*((void (*)())0x100000)();·

用typedef能够看得更直观些:

typedef void(*)() voidFuncPtr;*((voidFuncPtr)0x100000)();

分割作者

对于作者

作者在筹备秋招的过程中,凭借这份材料,最初顺利拿到了oppo,小米,兆易翻新,全志科技,海康威视等十余家家公司的offer。现将这部分材料分享进去,心愿能对大家有帮忙!

如果大家在网上看到了不错的材料,或者在口试面试中遇到了材料中没有的知识点,大家能够关注我的公众号分割我,我替大家整顿。

材料如有谬误或者不适合的中央,能够在github向我提交issues。因为精力有限,所以只会用心保护好github和公众号两个平台。材料中的勘误也会同步更新在github中。

github仓库

这份材料总共有七个局部,别离为:C/C++数据结构与算法剖析Arm体系与架构Linux驱动开发操作系统网络编程名企口试真题。所有内容均会同步更新到github仓库中。

点击跳转

微信

扫描下方二维码加我微信。微信号:LinuxDriverDev。

公众号

扫描下方二维码,关注我的公众号。

公众号有近2000G的嵌入式学习视频和10G的电子书,均能够收费获取!