完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在上一章节中我们介绍了主要介绍了ClassB软件的作用、框架和流程等,本章节将给大家介绍CPU寄存器检测实现方法。
01 CPU寄存器自检 R0 ~ R12我们称为通用寄存器,其中寄存器R0 ~ R7我们称为低寄存器,寄存器R8 ~ R12我们称为高寄存器,可用于数据操作。 在对R0 ~ R12寄存器进行操作时需要注意:绝大多数 16 位 Thumb 指令只能访问 R0‐R7,而 32 位 Thumb‐2 指令可以访问所有寄存器。 R13作为堆栈指针 SP,SP有两个: 主堆栈指针(MSP):复位后缺省使用的堆栈指针,用于操作系统内核以及异常处理例程(包括中断服务例程)。 进程堆栈指针(PSP):由用户的应用程序代码使用。 R14连接寄存器:当呼叫一个子程序时,由 R14 存储返回地址。 CPU自检在启动时和运行时都会进行,在启动时,所有寄存器(R0~R12,PSP,MSP)和标记的功能测试都会进行一次自检;运行时,周期性自检,不检测R13,R14,仅检测寄存器R0~R12。 02 CPU寄存器测试原理 在mm32_cpu_startKeil.s与mm32_cpu_runKeil.s文件中会对CPU寄存器进行测试,其中mm32_cpu_startKeil.s文件中的测试为启动过程中对CPU寄存器进行的测试,mm32_cpu_runKeil.s文件中的测试为运行自检流程中的CPU寄存器测试,其原理为对寄存器每一位写0和写1操作,对比是否有错误。 具体实现:分别写入0xAAAAAAAA和0x55555555再进行比较是否为写入的值。 03 CPU寄存器测试实现 以启动时CPU自检程序为例进行分析,将conAA数据定义为0xAAAAAAAA,将con55定义为0x55555555,并使用EXPORT指令进行声明。 conAA DCD 0xAAAAAAAA con55 DCD 0x55555555 con80 DCD 0x80000000 conA8 DCD 0xAAAAAAA8 con54 DCD 0x55555554 EXPORT conAA EXPORT con55 声明函数ClassB_StartUpCPUTest函数,并进行CPU寄存器中的R1寄存器的检测,先将conAA的数据赋值给R0寄存器,然后赋值给R1寄存器,然后比较R0与R1寄存器的数据,如果两者的数据相同则将con55分别赋值给R1与R0寄存器进行比较,否则会跳转执行CPUTestFail函数,如果两者的数据相同则将0x01赋值给R1寄存器,否则将会跳转到CPUTestFail函数中。 ; Register R1 LDR R0, =conAA LDR R1,[R0] LDR R0,[R0] CMP R0,R1 BNE CPUTestFail LDR R0, =con55 LDR R1,[R0] LDR R0,[R0] CMP R0,R1 BNE CPUTestFail MOVS R1, #0x1 ; For ramp test 在汇编程序中大家可以看到,如果检测失败,会跳转到CPUTestFail函数执行,如果检测成功则进行下一步的检测。 依次针对R2 ,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12寄存器进行与R1一样的操作,在上述的寄存器比较完成以后相应的寄存器会被赋予新的数据。 Class_StartUpCPUTest PROC EXPORT Class_StartUpCPUTest PUSH {R4-R6} ; Safe critical registers MOVS R0, #0x00 UXTB R0,R0 ADDS R0,#0 ; Set Z(ero) Flag BNE CPUTestFail ; Fails if Z clear BMI CPUTestFail ; Fails if N is set SUBS R0,#1 ; Set N(egative) Flag BPL CPUTestFail ; Fails if N clear ADDS R0,#2 ; Set C(arry) Flag and do not set Z BCC CPUTestFail ; Fails if C clear BEQ CPUTestFail ; Fails if Z is set BMI CPUTestFail ; Fails if N is set LDR R0,=con80 ; Prepares Overflow test LDR R0,[R0] ADDS R0, R0, R0 ; Set V(overflow) Flag BVC CPUTestFail ; Fails if V clear ; This is for control flow test (ENTRY point) LDR R0,=CtrlFlowCnt LDR R1,[R0] ADDS R1,R1,#0x3 ; CtrlFlowCnt += OxO3 STR R1,[R0] ; Register R1 LDR R0, =conAA LDR R1,[R0] LDR R0,[R0] CMP R0,R1 BNE CPUTestFail LDR R0, =con55 LDR R1,[R0] LDR R0,[R0] CMP R0,R1 BNE CPUTestFail MOVS R1, #0x1 ; For ramp test ; Register R2 LDR R0, =conAA LDR R2,[R0] LDR R0,[R0] CMP R0,R2 BNE CPUTestFail LDR R0, =con55 LDR R2,[R0] LDR R0,[R0] CMP R0,R2 BNE CPUTestFail MOVS R2, #0x2 ; For ramp test ; Register R3 LDR R0, =conAA LDR R3,[R0] LDR R0,[R0] CMP R0,R3 BNE CPUTestFail LDR R0, =con55 LDR R3,[R0] LDR R0,[R0] CMP R0,R3 BNE CPUTestFail MOVS R3, #0x3 ; For ramp test ; Register R4 LDR R0, =conAA LDR R4,[R0] LDR R0,[R0] CMP R0,R4 BNE CPUTestFail LDR R0, =con55 LDR R4,[R0] LDR R0,[R0] CMP R0,R4 BNE CPUTestFail MOVS R4, #0x4 ; For ramp test ; Register R5 LDR R0, =conAA LDR R5,[R0] LDR R0,[R0] CMP R0,R5 BNE CPUTestFail LDR R0, =con55 LDR R5,[R0] LDR R0,[R0] CMP R0,R5 BNE CPUTestFail MOVS R5, #0x5 ; For ramp test ; Register R6 LDR R0, =conAA LDR R6,[R0] LDR R0,[R0] CMP R0,R6 BNE CPUTestFail LDR R0, =con55 LDR R6,[R0] LDR R0,[R0] CMP R0,R6 BNE CPUTestFail MOVS R6, #0x6 ; For ramp test ; Register R7 LDR R0, =conAA LDR R7,[R0] LDR R0,[R0] CMP R0,R7 BNE CPUTestFail LDR R0, =con55 LDR R7,[R0] LDR R0,[R0] CMP R0,R7 BNE CPUTestFail MOVS R7, #0x7 ; For ramp test ; Register R8 LDR R0, =conAA LDR R0,[R0] MOV R8,R0 CMP R0,R8 BNE CPUTestFail LDR R0, =con55 LDR R0,[R0] MOV R8,R0 CMP R0,R8 BNE CPUTestFail MOVS R0, #0x08 ; For ramp test MOV R8,R0 BAL CPUTstCont CPUTestFail BLAL FailSafePOR CPUTstCont ; Register R9 LDR R0, =conAA LDR R0,[R0] MOV R9,R0 CMP R0,R9 BNE CPUTestFail LDR R0, =con55 LDR R0,[R0] MOV R9,R0 CMP R0,R9 BNE CPUTestFail MOVS R0, #0x09 ; For ramp test MOV R9,R0 ; Register R10 LDR R0, =conAA LDR R0,[R0] MOV R10,R0 CMP R0,R10 BNE CPUTestFail LDR R0, =con55 LDR R0,[R0] MOV R10,R0 CMP R0,R10 BNE CPUTestFail MOVS R0, #0x0A ; For ramp test MOV R10,R0 ; Register R11 LDR R0, =conAA LDR R0,[R0] MOV R11,R0 CMP R0,R11 BNE CPUTestFail LDR R0, =con55 LDR R0,[R0] MOV R11,R0 CMP R0,R11 BNE CPUTestFail MOVS R0, #0x0B ; For ramp test MOV R11,R0 ; Register R12 LDR R0, =conAA LDR R0,[R0] MOV R12,R0 CMP R0,R12 BNE CPUTestFail LDR R0, =con55 LDR R0,[R0] MOV R12,R0 CMP R0,R12 BNE CPUTestFail MOVS R0, #0x0C ; For ramp test MOV R12,R0 LDR R0, =CPUTstCont R1~R12寄存器比较完成以后会在Ramp中做进一步的判断,判断R1寄存器的数值是否为0x01,R2寄存器的数值是否为0x02,依次判断到R12寄存器,如果以上的判断都是正确的则说明R1~R12寄存器验证通过。 ; Ramp pattern verification (R0 is not tested) CMP R1, #0x01 BNE CPUTestFail CMP R2, #0x02 BNE CPUTestFail CMP R3, #0x03 BNE CPUTestFail CMP R4, #0x04 BNE CPUTestFail CMP R5, #0x05 BNE CPUTestFail CMP R6, #0x06 BNE CPUTestFail CMP R7, #0x07 BNE CPUTestFail MOVS R0, #0x08 CMP R0,R8 BNE CPUTestFail MOVS R0, #0x09 CMP R0,R9 BNE CPUTestFail MOVS R0, #0x0A CMP R0,R10 BNE CPUTestFail MOVS R0, #0x0B CMP R0,R11 BNE CPUTestFail MOVS R0, #0x0C CMP R0,R12 BNE CPUTestFail 对R13的自检功能与通用寄存器的操作不同,需要先保存堆栈到R0,操作如下: ; Process Stack pointer (banked Register R13) MRS R0,PSP ; Save process stack value LDR R1, =conA8 ; Test is different (PSP is word aligned, 2 LSB cleared) LDR R1,[R1] MSR PSP,R1 ; load process stack value MRS R2,PSP ; Get back process stack value CMP R2,R1 ; Verify value BNE CPUTestFail LDR R1, =con54 ; Test is different (PSP is word aligned, 2 LSB cleared) LDR R1,[R1] MSR PSP,R1 ; load process stack value MRS R2,PSP ; Get back process stack value CMP R2,R1 ; Verify value BNE CPUTestFail MSR PSP, R0 ; Restore process stack value ; Stack pointer (Register R13) MRS R0,MSP ; Save stack pointer value LDR R1, =conA8 ; Test is different (SP is word aligned, 2 LSB cleared) LDR R1,[R1] MSR MSP,R1 ; load SP value MRS R2,MSP ; Get back SP value CMP R2,R1 ; Verify value BNE CPUTestFail LDR R1, =con54 LDR R1,[R1] ; load SP value MSR MSP,R1 ; Get back SP value MRS R2,MSP ; Verify value CMP R2,R1 BNE CPUTestFail MSR MSP,R0 ; Restore stack pointer value ; Control flow test (EXIT point) LDR R0,=CtrlFlowCntInv LDR R1,[R0] SUBS R1,R1,#0x3 ; CtrlFlowCntInv -= OxO3 STR R1,[R0] POP {R4-R6} ; Restore critical registers ; If next instruction is not executed, R0 will hold a value different from 0 MOVS R0, #0x1 ; CPUTEST_SUCCESS BX LR ; return to the caller ALIGN ENDP END 以上代码是在启动时CPU寄存器自检的汇编代码,在运行时CPU寄存器自检功能与启动自检的代码原理相同,只是对寄存器操作个数有差异,运行时不用对R1314进行操作。 在汇编程序中我们会使用CMP指令进行判断,后面会跟着BNE指令,其作用就是判断如果CMP判断的两个寄存器不相等,则直接执行BNE指令后面的CPUTestFail函数,直接提醒错误报警,或可以添加对应的处理机制。 |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
2249个成员聚集在这个小组
加入小组灵动微电子MM32全系列MCU产品应用手册,库函数和例程和选型表
11703 浏览 3 评论
【MM32 eMiniBoard试用连载】+基于OLED12864的GUI---U8G2
5930 浏览 1 评论
【MM32 eMiniBoard试用连载】移植RT-Thread至MM32L373PS
10965 浏览 0 评论
【MM32 eMiniBoard测评报告】+ 开箱 + 初探
4577 浏览 1 评论
灵动微课堂(第106讲) | MM32 USB功能学习笔记 —— WinUSB设备
4302 浏览 1 评论
[MM32软件] MM32F002使用内部flash存储数据怎么操作?
981浏览 1评论
806浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-27 22:02 , Processed in 0.576667 second(s), Total 38, Slave 31 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号