找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4745|回复: 1
收起左侧

M3内核点滴记录

[复制链接]
ID:60266 发表于 2014-8-18 00:50 | 显示全部楼层 |阅读模式
1:M3的系统控制块(SCB)中的VTOR(0XE000_ED08)寄存器:【7~28】向量表的起始地址,【29】向量表是在Code区(0),还是在RAM区(1);
2:在keil环境中,编译器是通过***.sct分散加载文件来组织映像文件,分散加载文件中包含加载地址、运行地址以及哪一个段的位置(启动代码中的RESET代码段就被描述放在特定的地址中);
LR_IROM1 0x08000000 0x00040000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00040000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x20000000 0x00010000  {  ; RW data
   .ANY (+RW +ZI)
  }
}
3:M3的优先级
M3的异常,包括系统异常(15个系统异常:复位、NMI、hardfault、SysTick等,编号从1~15,0表示没有异常运行)与外部中断(总共240个,编号从16~255,NVIC最多支持1~240个外部中断IRQ,芯片具体支持多少个由芯片厂商设计),支持中断嵌套,使得高优先级的异常可以抢占低优先级的中断。
其中3个系统异常(复位、NMI、hardfault)有固定的优先级且都是负数级优先级,所以他们的优先级高于其他的所有可编程的优先级(非负),除这三个系统异常外,其他的异常与中断的优先级都是可以编程的。
因此M3拥有3个固定的高优先级与最多256级可编程的优先级。
M3所有可编程优先级的异常(系统异常与外部中断)都拥有一个对应的8位的优先级寄存器,且中断优先级的值(8位)又分为两个域:抢占域与亚优先(非抢占)域;高抢占域的异常可以抢占低抢占域的异常(这时不考虑亚优先级谁高谁低),如果两个异常抢占域相同,其中一个异常已在服务中,那此时不论另一中断的亚优先级是高或低都不能抢占它,而如果这两个中断同时出现,那么系统会先响应亚优先级高的中断;如果两个异常优先级完全相同,同时出现时则会优先响应异常编号小的那个异常。
重要规则:多个中断源在它们的抢占式优先级相同的情况下,子优先级不论是否相同,如果某个中断已经在服务当中,则其它中断源都不能打断它(可以末尾连锁);只有抢占式优先级高的中断才可以打断其它抢占式优先级低的中断。优先级分组规定:亚优先级至少1位,因此抢占式优先级最多7位;
优先级分组在AIRCR(应用程序中断与复位控制寄存器(0XE000_ED00))中的[10:8]PRIGROUP位域设置(芯片的标准库函数中一般都会有相应的这样的设置函数给用户调用:如
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
void NVIC_SystemHandlerPriorityConfig(u32 SystemHandler, u8 SystemHandlerPreemptionPriority, u8 SystemHandlerSubPriority)
具体的芯片支持的M3的优先级分组情况不一样,芯片在设计时已经确定了它支持多个种分组,如我的STM32只支持0~4分组,这个具有要看芯片手册(其实查看芯片提供的相关代码就可以查出了),为了更好的支持代码的跨平台特性,优先级是以MSB对齐的(这里的对齐,比如3位抢占式优先级移植到另一款芯片变成2位,这时丢失的是最高位,如抢占式优先级5会变成1);


4:《权威指南》第一章小结
ARM处理器支持的指令集:ARM(32位,对应CPU的ARM状态)、Thumb(16,对应CPU的Thumb状态)、Thumb2(32、16);
Thumb指令在功能上时ARM指令的一个子集,它的优点是提高代码密度;Thumb2是Thumb指令的超集(16和32位的指令共存);
Cortex M3使用的就是2003年盛产的Thumb2指令集,M3支持Thumb2指令的好处:1.支持绝大多数的传统的Thumb指令,方便在只支持Thumb指令平台上写的代码的移植;2.不用进行处理器的状态切换(在一些运算复杂的地方需要Thumb<->ARM切换),提高效率。
5:《权威指南》第二章小结
CPU的寄存器:R0~R12(通用寄存器)、R13(M/P SP)、R14(LR)、R15(PC)、xPSR(程序状态字寄存器)、PRIMASK/FAULTMASK/BASEPRI(中断屏蔽寄存器)、CONTROL(控制寄存器)【最后三类为特殊功能寄存器,具体功能后面分析】
堆栈指针(R13)的最低两位永远为0,因为堆栈是4字节对齐(ARM是32位处理器,各寄存器都是32位的);
M3支持两种处理器的操作模式以及两种特权操作;
操作模式:handler mode 、thread mode (异常时处理器处于handler mode ,其他时候是thread mode)
特权操作:特权级(复位后系统默认、handler mode下总是特权级)、用户级(非特权级);这是一种安全策略,特权级是可以访问所有的存储器(有MPU,要除去MPU规定的禁区),可执行所有的指令【这是特权级与用户级的区别所在,配上MPU,就可以对特权级访问和用户级访问施加不同的限制】。
CONTROL[1]、CONTROL[0]只有在特权级模式下才允许写(从用户级到特权级的唯一路径就是异常:触发一个异常,处理器总是先切换到特权级,异常退出时,返回先前的状态,也可通过LR手动修改返回状态),特权级的线程模式可通过修改CONTROL[0]=1进入用户模式,这样就只能通过异常才能返回特权级;
Cortex M3 拥有4G的存储空间,且对这4G的存储空间进行了粗线条的规划:
0x0000_0000--0x1FFF_FFFF:代码区。         0x2000_0000--0x3FFF_FFFF:用于片上静态RAM。
0x4000_0000--0x5FFF_FFFF:片上外设空间。   0x6000_0000--0x9FFF_FFFF:扩展外部存储器。
0xA000_0000--0xDFFF_FFFF:扩展片外外设。  0xE000_0000--0xFFFF_FFFF:系统控制空间(NVIC、SCB等)
处于最高地址的系统级存储区包括NVIC、MPU、SCB、调试组件等,且所有这些控制模块的寄存器地址是固定的,不随芯片厂家的不同而发生改变,这样就方便移植了。
MPU:MPU保护内存是按region(区)来管理的,当检测到访问犯规时,MPU会产生一个异常,进入对应的异常服务程序。最常见的MPU玩法是操作系统使用MPU来包含特权级代码的数据,包括操作系统本身的数据不被其他的用户程序破坏。
MRS、MSR访问特殊功能寄存器。
调试:M3不同于以往的ARM处理器,内核本身不再含有JTAG接口,取而代之的是CPU提高的DAP“调试访问接口”的总线接口,通过这个总线接口,可以访问芯片的寄存器、系统存储器等,甚至可以在内核运行时访问,而对此总线接口的使用是通过一个调试端口(DP)设备完成,DP不属于M3内核,但它是在芯片内部实现的。DP包括SWJ-DP(支持JTAG调试与串行线调试)、SW-DP(串行线调试),也可以使用JTAG-DP,具体使用哪一个由厂家选择提供给用户(通常为SWJ-DP); M3还挂载了一个ETM(嵌入式跟踪宏单元),ETM不断发出跟踪信息,这些信息通过一个被称为TPIU(跟踪端口接口单元)的模块送到内核的外部,如果再芯片外使用“跟踪信息分析仪”就可以捕捉TPIU的“已执行指令信息”,送给调试PC机。
通过WFI(等待中断指令)与WFE(等待事件指令),内核可以进入睡眠模式。
M3支持“位寻址带”操作,支持非对齐的数据访问。
6:《权威指南》第三章小结
M3中指令至少是半字对齐,所以读取PC的值时,PC的LSB总是读回0,且PC的LSB位表示的是CPU所处的状态,1表示Thumb状态,0表示ARM状态,所以无论是在直接写PC值还是使用分支指令,都必须保证加载到PC的数值是奇数(LSB=1),用以表示这是在Thumb状态下执行,若写了0,则试图转入ARM状态,CM3将产生一个异常
读取PC值时获得的数值是与CPU的流水线级数【M3的是三级:取指、译码、执行】有关的,CM3在读PC时返回的值是当前指令的地址+4,PC(取指) = PC(执行) + 4(16位的是两个字节,2*2)【这里出于对Thumb代码兼容,Thumb2既有16位的指令也包含32位的指令】
【复位序列】在离开复位状态后,CM3做的第一件事就是读取下列两个32位整数的值:
1:从地址0x0000_0000处取出MSP(默认使用MSP)的初始值
2:从地址0x0000_0004处取出PC的初始值这个值是复位向量,LSB必须是1
这与传统的ARM架构以及绝大多数的单片机不同,传统ARM架构总是从0地址开始执行第一条指令(0地址处一般总是一条跳转指令),在CM3中,0地址处提供MSP的初始值,然后紧跟的是向量表(向量表在以后还可以被移到其他的位置),向量表中存放的是32位的服务程序的地址(我们通过工具查看这些地址值时,他们的最低位都是1)
7:M3的堆栈大小如何设置?
我们可以通过查看0地址处的MSP初始值。可以知道系统最开始使用的堆栈的大小,如:0x20004430(减去RAM的起始地址就可知道大小)。那怎么设置?
Stack_Size   EQU     0x200【512个字节】
AREA    STACK(段名), NOINIT, READWRITE(两个属性), ALIGN=3(对齐)
Stack
    SPACE   Stack_Size
AREA    RESET, CODE, READONLY
        THUMB
    EXPORT  __Vectors
__Vectors                     
    DCD  Stack + Stack_Size            ; Top of Stack【堆栈是往下生长的满栈,Stack是栈底
    DCD  Reset_Handler
8:M3的fault分析
fault分为:总线fault、存储器管理fault、用法fault、硬fault;
总线fault:当AHB接口上正在传送数据时,如果回复了一个错误信号(Error Response),则会产生总线fault,产生的场合可以是:
9:M3的SVC、PendSV
SVC(系统调用)【学linux时,在带操作系统的系统中,用户空间系统调用(直接使用操作系统提供的接口函数)与C库调用,且C库调用最后会使用系统提供的系统调用接口函数(也就变为了系统调用),通过系统调用请求(通过系统调用号:对应各个系统提供的对应接口函数)从用户空间进入内核空间,C库调用接口具有很好的跨平台特性】
PendSV(可挂起的系统调用)
SVC异常 通过 执行SVC指令来产生,如SVC 0X3 //0X3是系统调用号
不能再SVC服务例程中嵌套使用SVC指令(因为同优先级的异常不能抢占自身,都是系统调用异常),否则会产生一个用法fault;同样也不能在NMI服务例程中使用SVC,否则会导致hardfault【因为执行SVC指令后,如因优先级不比当前正在处理的高,或是其他原因使之无法响应,则将造成hardfault】.
PendSV可以像普通的中断一样被挂起(不像SVC一样会上访hardfault),OS可以利用它缓期执行一个异常,直到其他重要的任务完成后才执行动作,为了能让其他很重要的任务优先完成,PendSV的优先级可以调到最低。
通过向PendSV挂起寄存器中写1,可以手工挂起PendSV,挂起后,如果优先级不够高,则将缓期执行。
PendSV的典型使用场合是上下文切换;





回复

使用道具 举报

ID:26188 发表于 2014-8-21 20:46 来自手机 | 显示全部楼层
写得很好,不过说起来真是悲剧啊!单片机都发展到了这个程度,我们还在天天学习8051
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表