在我看来,Cotex-M3内核的首要包含:嵌套向量中止操控器(NVIC),取值单元,指令译码器,管用逻辑单元(ALU),寄存器组,存储器映射(4GB一致编址各区域功用的区分与界定),关于开发者而言,其实首要重视的首要分为三大块:
1、寄存器组2、地址功用区分映射3、中止机制(NVIC)。
1)寄存器组
Cortex-M3内核共有19组32位寄存器:
R0——R12(通用寄存器);
低寄存器组R0——R7
32位Thumb-2指令与16位Thumb指令均可拜访
高寄存器组R8——R12
32位Thumb-2指令与极少数16位Thumb指令可拜访
R13(仓库指针寄存器);
主仓库寄存器MSP(main-SP)/进程仓库寄存器PSP(Process-SP)同一时刻只能运用其间一个。MSP供操作体系内核及中止(反常)处理子程序运用,PSP只供用户的运用程序代码运用(详细运用详见3、嵌套向量中止操控器(NVIC)的总结)。
仓库指针是4字节对齐的,故最低两位永远是00;
R14(衔接寄存器)
用于存储程序回来的地址及PC的回来地址;
R15(程序寄存器)指向当时程序碑文的地址;
2)特别功用寄存器组
xPSR(程序状况字寄存器组),32位,可分为三个寄存器别离进行拜访,也能够PSR或xPSR的姓名直接组合拜访。
运用程序PSR(APSR)
中止号PSR(IPSR)
碑文PSR (EPSR)
中止屏蔽寄存器
PRIMASK单一比特位,置位后,除NMI与硬fault外,其他中止都不呼应;
FAULTMASK单一比特位,置位后,除NMI外,其他中止都不呼应;
BASEPRI共有9位,中止号小于等于该寄存器设置值的中止都不呼应;
操控寄存器control
Control[0]0决议特权级线程形式;1用户级线程形式;
Control[1]0主仓库;1进程仓库;
操控寄存器只能在特权级形式下改写,handler形式永远是特权级,且只允许运用主仓库MSP
复位后,处理器进入特权级+线程形式下;
2、地址功用区分映射
Cortex-m3是一个32位处理器,其地址总线、数据总线都是32位的,故可在4G的地址范围上资源寻址。Cortex-m3内核把4G空间划定了根本的结构,界说不同的运用用处。
0x0000 0000 —-0x1FFF FFFF (512MB)该区域为code区(flash区),供指令总线与数据总线取指取数运用;能够碑文指令;
0x2000 0000 —-0x3FFF FFFF (512MB)该区域为片上SRAM区,芯片制造商可在此布设RAM,能够将代码复制到此处运转,该区域也是能够碑文指令code的;低1MB空间可位寻址,经过位带别号可扩展为32Mb的位寻址。
0x4000 0000 —-0x5FFF FFFF (512MB)该区域为“片上外设”区 ,首要为片上外设的相关寄存器,即特别功用寄存器区,同理低1MB也可位寻址;该区域不行碑文代码;
0x6000 0000 —-0x9FFF FFFF(1G)该区域为片外RAM区,该区域可碑文代码;
0xA000 0000 —-0xDFFF FFFF(1G)该区域为片外外设区,该区域不行碑文代码;
0xE000 0000 —-0xFFFF FFFF(1G)该区域为体系区,该区域不行碑文代码;
所以不同地址片段的开端地址可简记为:0,2,4,6,10,E,
该体系区又分为两部分:
内部私有外设区0xE000 0000 —-0xE003 FFFF(256KB)首要有NVIC,FPB,DWT,ITM等
外部私有外设区0xE004 0000 —-0xE00F FFFF(512+256=768KB)有ROM表,ETM,TPIU等
数据的巨细端形式:CM-3既支撑大端形式也支撑小端形式,其间关于大端形式,ARM7中运用的是字不变大端形式,CM3中则为字节不变大端形式。观赏巨细端形式都支撑,但依然主张在绝大多数状况下运用小端形式,假如一些外设是大端形式,能够经过REV/REVH指令便可轻松完结端形式的转化。
3、中止机制(NVIC)
已然称之为MCU而非MPU,那么便是以操控为主,操控的一个要害目标便是实时性,能够及时对改动的状况作出反应,而这首要是经过中止机制来完结的,能够说除却运算功能,cortex-M3内核的首要修为都表现在操控的实时性上——也即中止的即时呼应机制。
CM3对中止是怎样界说的呢?
一个是CM3内核反常导致当时运转程序的中止,一个是外部事情引进导致的。
体系反常首要是CM3内核层面的,复位,NMI,硬fault,这三者优先级固定且最高,此外还有总线fault、内存办理fault、用法fault等,svc体系调用服务、systick等的优先级能够经过编程来设定;这些都放在一个向量表里,存储的是中止服务函数的进口地址,32位,共256项,前16个是体系内的中止,万古流芳保存位,体系中止共有16-5-1=10个,剩余240个外部中止IRQ,其间有三个的优先级是固定的:复位,NMI,硬fault,中止号别离为-3,-2,-1,中止号越小,优先级也就越高,其他优先级都是可编程的。此外,关于复位发动进程,M3内核的MCU与传统的单片机复位是不一样的,传统的单片机是直接从地址0处开端运转,然后再碑文地址0处的跳转指令,跳转到设定的程序开端段;而CM3复位后首要是在地址零处0x0000 0000取出主仓库MSP的初始值,(我们CM3的仓库是向下成长型的,所以这个初始值一般设为RAM区的末地址+1,以确保仓库足够大,再烦琐下,比方说RAM区为0x2000 0000——0x3FFF FFFF那么初始值就设置为0x4000 0000);然后经过复位中止号找到寄存复位程序进口地址的地址单元(0x00000004),地址单元(0x00000004)寄存着榜首条指令碑文的地址(0x0000 0100)并赋给PC,PC就从这个地址里寄存的指令顺次碑文。关于指令碑文的地址需求严峻萍水相逢:CM3运转在thumb状况,所以加载到PC中的值的最低位LSB有必要置1,以差异ARM状况(ARM为偶数),所以若想指向0x0000 0100的地址值,中止向量表中存的复位程序进口地址应为0x0000 0101,用0x0000 0101一共0x0000 0100,这儿不要把存储数据的地址和PC的指向地址搞混,只要PC的碑文地址LSB不能等于0,其他总线拜访地址则没有此约束。(为了把问题解说清楚,烦琐的我自己都受不了了)为什么要首要初始化仓库MSP呢?我们在复位的进程中也可能发生中止,例如NMI,硬fault等。
中止从发生到完毕首要需求经过以下这么几个进程:1捕获并呼应中止,2现场维护,3中止程序进口,4回来。下面就依据这个头绪来总结cortexM3在进步中止呼应速度方面所触及的重要知识点(这个解说次序针对已具有必定的根底人员):
提到中止必触及到优先级、触及到嵌套,在CM3顶用8位来编程中止的优先级数,可完结256级优先级,其间这8位又分为两段,一段决议抢占优先级的级数,一个决议亚优先级的级数,其间规则抢占优先级不得少于3位(8级优先级),亚优先级最少不得少于1位,所以抢占优先级在M3中最多128级,在哪一位开端分组由NVIC中的寄存器中(运用程序中止及复位操控寄存器)的PRIGROUP来决议;但实践中,芯片制造商一般只运用最高几位,比方5位,高三位(7,6,5)编程抢占优先级,剩余的两个次高位(4,3)用来决议亚优先级,从第4位处作为亚优先级的分组,这儿经过一个分组寄存器来决议从哪一位做亚优先级分组。
优先级确认好了,那么在许多不同优先级的中止面前,CM3又是以什么样的机制来进步呼应速度的呢?这就需求表一表在呼应之前,处理器有必要要做的作业——现场维护即维护当时的程序运转环境,顺次入栈以下8个寄存器:程序状况寄存器XPSR,程序计数器PC,回来地址寄存器LR(衔接寄存器),R12,R0——R3,这些都是硬件主动完结的。假如当时正在运用仓库,则压入相应的仓库寄存器MSP/PSP值,当时在用PSP就压入PSP,反之则压入MSP,进入中止服务程序就将一向用MSP了;好了,请注意,进步中止的呼应速度就在这些寄存器的入栈次序上,咱们知道,仓库是建立在片上RAM中的,经过体系总线(system code)来操作(为什么要建立在RAM上,我们仓库需求不停地做出栈、入栈等动作,需求不断改动存储的值,而flash或rom只在烧写的时分写入数据),指令是寄存在flash中的即code区经过指令总线(code bus)来操作,所以在入栈的时分先压入xPSR的值,再压入PC的值,压入PC的值后,就能够经过指令总线,依据中止向量号取出中止服务函数的地址赋给PC新的指令地址,进行指令的预取,而仓库依然能够经过体系总线持续压入其他寄存器的值,与取指令操作双管齐下,互不搅扰,加速了中止的呼应速度。相关寄存器可查询威望手册。
在呼应中止前所做的预备作业都做好了,那么当许多中止前来叫门时,应该如何故最短的延时处理一系列的中止呢?榜首级中止自不必说,依据中止号来进行裁定,当发生中止嵌套的时分,CM3中的一些呼应机制就能加速整个中止呼应进程的速度了,低优先级我们高优先级中止的抢占而处于挂起状况,当高优先级中止处理完毕,依照传统的嵌套中止处理流程,高优先级中止处理完结后应该出栈弹出内容,然后再入栈压入从前弹出的内容,再处理被挂起的低优先级中止,按书中所说,这便是砸锅炼铁再铸锅的进程,彻底没有必要,所以CM3内核在处理一系列嵌套的中止时,一共只碑文一次入栈,出栈作业,这样处理接连的几个嵌套中止时,就削减了许多环节,缩短了时刻,尤其是嵌套等级计较深的时分,尤为显着。可是要注意的是:不要嵌套太深,我们每嵌套一级就至少入栈8个32位的寄存器值(32B),假如自身便是中止进程,当时代码正在运用仓库,还要将仓库的值再入栈,这样无疑加大了仓库的存储压力,假如用穿仓库,发生溢出,程序十有八九就跑飞了,是很风险的,所以在运用中,要尽量减小中止的嵌套深度。
之前的中止呼应机制发生在府第中止打断低优先级中止完结呼应之后,译者将其名曰:咬尾中止;下面的中止则发生在高优先级中止打断低优先级中止预备呼应之时,当高优先级中止还没来的时分,低优先级中止现已把前期预备作业给做完了,这时分高优先级中止来了,那么此刻高优先级中止会直接运用低优先级中止的前期作业效果,直接开端呼应,进入服务中止服务程序,而之前的初级中止则被逼挂起,为他人做嫁衣了,没办法,内核便是这样规则的,译者将其译为“晚到(的高优先级)反常”我将其名为“后发先至”中止。
中止延迟时刻:从检测到中止,到碑文中止服务程序的榜首条指令,其间所消逝的时刻。
书中云:假如存储体系足够快,入栈与取指令能够别离进行,且中止能够立刻得到呼应不被抢占,那么所消耗的时刻便是固定的12个周期(分量硬实时要求确实认性)。假如多级嵌套中止呼应,算上咬尾中止省去的收支栈时刻,每个中止可削减至6个周期。
最终再说说反常即fault,内核活动层面的东西,这个本应是需求大书特书的东西,尤其是在调试程序的时分找bug上,是表现一个人技术水平的很重要的方面,可是限于时刻与研讨深度,暂时不深究了,
就一句话吧:运转时呈现的体系过错有时分不是编程上的语法过错,假如不了解内核架构和一些运用原则,是很难发现bug在哪里,这就需求追溯到底是程序运转到哪里出了问题,导致内核运转呈现了过错,得益于CM3齐备的调试架构,许多fault的发生都会被监测到,并记载在对应的寄存器中,按图索骥就知道问题出在哪里,是哪条指令导致的,借此针对性的自查、剖析、修正。
下面将结合上面的内核架构以及内核运转机制,针对详细的根据cortex—M4内核(M4比M3内核多了DSP与FPU)的STM32F407芯片,进行硬件资源的比照。