完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在上一章节中我们介绍了CPU寄存器检测的实现方法,本章节我们将给大家介绍RAM检测的实现方法。SRAM检测不仅检测数据区域的错误,还检测其内部地址和数据路径的错误。 检测时由于需要执行软件算法(March-C),会影响CPU的利用率,所以SRAM测试采用拓扑模式,按位阵列推进测试,阵列中的逻辑邻位(属于单字)物理上彼此分离,而带后续逻辑地址的字对在物理上却共享邻位,此时可采用按字测试的方法。 SRAM自检采用March-C算法,March-C是一种用于嵌入式芯片RAM测试的算法,是安全认证的一部分,可用于测试那些未被硬件奇偶校验覆盖的部分RAM。为了不影响MCU的运行,将RAM分成很多小块,每次测试其中一块, 先将要测试的块清零,然后按位逐位置1,每置一位,测试该位是不是1,是就继续,不是就报错;全部置完后,再逐位清0,每清一个位,测试该位清0是不是0,如果是就正确,不是就报错。如果是对工作区的RAM,数据需要保留,在RAM中开一个安全保留区,先对安全保留区March-C,然后把要测试的区的数据copy进安全区,再对要测试的工作区进行March-C,测试-- copy进安全区-- 测试-- copy进安全区...... 完成整个空间的测试。 在ClassB检测中,RAM自检也分为启动自检与运行自检两部分。 01 ClassB RAM启动自检 RAM在启动自检过程中会检测全部的RAM。算法中会用值(0x00000000)和值(0xFFFFFFFF)逐字填充,填充后读取出来比较看值是否相等。 具体的运行流程图如下:
主要有6步:
Class_FullRamMarchC PUSH {R4-R7} MOVS R4, #0x1 ; Test success status by default MOVS R3,R2 ; setup inverted background pattern RSBS R3, R3, #0 SUBS R3,R3, #1 ; *** Step 1 *** ; Write background pattern with addresses increasing MOVS R5,R0 __FULL1_LOOP CMP R5,R1 BHI __FULL_RET LDR R7,[R5, #+0] STR R2,[R5, #+0] LDR R6,[R5, #+0] CMP R2,R6 BNE __FULL_ERR STR R3,[R5, #+0] LDR R6,[R5, #+0] CMP R3,R6 BNE __FULL_ERR STR R7,[R5, #+0] ADDS R5,R5,#+4 B __FULL1_LOOP ; *** Step 2 *** ; Write background pattern with addresses decreasing MOVS R5,R1 SUBS R5,R5,#+4 __FULL2_LOOP CMP R5,R0 BLO __FULL_RET LDR R7,[R5, #+0] STR R2,[R5, #+0] LDR R6,[R5, #+0] CMP R2,R6 BNE __FULL_ERR STR R3,[R5, #+0] LDR R6,[R5, #+0] CMP R3,R6 BNE __FULL_ERR STR R7,[R5, #+0] SUBS R5,R5,#+4 B __FULL2_LOOP __FULL_ERR MOVS R4,#0 ; error result __FULL_RET MOVS R0,R4 POP {R4-R7} BX LR ; return to the caller 02 ClassB RAM运行自检程序 RAM在运行自检的过程中只检测部分RAM,不会检测全部的RAM。目前主要自检0x20000030-0x2000007B范围内的RAM以及0x20000000-0x2000001F缓冲区范围的RAM,具体的操作流程如下: ; ***************** test of the RAM slice ********************* MOVS R5, #0 ; NO - save content of the RAM slice into the backup buffer __SAVE_LOOP LDR R6,[R4, R5] ; load data offset LDR R7,[R0, R6] ; load data from RAM ADDS R5,R5,#4 ; original data are stored starting from second item of the buffer STR R7,[R1, R5] ; (first and last items are used for testing purpose exclusively) CMP R5, #20 BLE __SAVE_LOOP ; *** Step 1 *** ; Write background pattern with addresses increasing MOVS R5, #0 __STEP1_LOOP LDR R6,[R4, R5] ; load data offset STR R2,[R0, R6] ; store background pattern ADDS R5,R5,#4 CMP R5, #20 BLE __STEP1_LOOP ; *** Step 2 *** ; Verify background and write inverted background with addresses increasing MOVS R5, #0 __STEP2_LOOP LDR R6,[R4, R5] ; load data offset LDR R7,[R0, R6] ; verify background pattern CMP R7, R2 BNE __STEP_ERR STR R3,[R0, R6] ; store inverted background pattern ADDS R5,R5,#4 CMP R5, #20 BLE __STEP2_LOOP 在MDK工程的mm32_STLClassBvar.h文件中设置一些变量进行定址,并在工程配置中设定区域。 /* RAM location for temporary storage of original values at run time RAM transparent test */ EXTERN uint32_t aRunTimeRamBuf[RT_RAM_BLOCKSIZE + 2] __attribute__((section("RUN_TIME_RAM_BUF"))); /* RAM pointer for run-time tests */ EXTERN uint32_t *pRunTimeRamChk __attribute__((section("RUN_TIME_RAM_PNT"))); EXTERN uint32_t *pRunTimeRamChkInv __attribute__((section("RUN_TIME_RAM_PNT"))); EXTERN uint32_t aGAP_FOR_RAM_TEST_OVERLAY[2] __attribute__((section("RUN_TIME_RAM_PNT"))); /*Note:the zero_init forces the linker to place variables in the bsssection */ /*This allows the UNINIT directive(in scatter file)to work. On the contrary */ /* all Class B variables pairs should be initialized properly by user before using them */ /* Counter for verifying correct program execution at start */ EXTERN uint32_t CtrlFlowCnt __attribute__((section("CLASS_B_RAM"), zero_init)); EXTERN uint32_t CtrlFlowCntInv __attribute__((section("CLASS_B_RAM_REV"), zero_init)); /* Counter for verifying correct program execution in interrupt */ EXTERN uint32_t ISRCtrlFlowCnt __attribute__((section("CLASS_B_RAM"), zero_init)); EXTERN uint32_t ISRCtrlFlowCntInv __attribute__((section("CLASS_B_RAM_REV"), zero_init)); /* LSI period measurement at TIM5 IRQHandler */ EXTERN uint32_t PeriodValue __attribute__((section("CLASS_B_RAM"), zero_init)); EXTERN uint32_t PeriodValueInv __attribute__((section("CLASS_B_RAM_REV"), zero_init)); /* Sofware time base used in main program (incremented in SysTick timer ISR */ EXTERN uint32_t TickCounter __attribute__((section("CLASS_B_RAM"), zero_init)); EXTERN uint32_t TickCounterInv __attribute__((section("CLASS_B_RAM_REV"), zero_init)); /* Indicates to the main routine a 100ms tick */ EXTERN __IO uint32_t TimeBaseFlag __attribute__((section("CLASS_B_RAM"), zero_init)); EXTERN __IO uint32_t TimeBaseFlagInv __attribute__((section("CLASS_B_RAM_REV"), zero_init)); /* Indicates to the main routine a 100ms tick */ EXTERN __IO uint32_t LSIPeriodFlag __attribute__((section("CLASS_B_RAM"), zero_init)); EXTERN __IO uint32_t LSIPeriodFlagInv __attribute__((section("CLASS_B_RAM_REV"), zero_init)); /* Stores the Control flow counter from one main loop to the other */ EXTERN uint32_t LastCtrlFlowCnt __attribute__((section("CLASS_B_RAM"), zero_init)); EXTERN uint32_t LastCtrlFlowCntInv __attribute__((section("CLASS_B_RAM_REV"), zero_init)); /* Pointer to FLASH for crc32 run-time tests */ EXTERN uint32_t *pRunCrc32Chk __attribute__((section("CLASS_B_RAM"), zero_init)); EXTERN uint32_t *pRunCrc32ChkInv __attribute__((section("CLASS_B_RAM_REV"), zero_init)); /* Reference 32-bit CRC for run-time tests */ EXTERN uint32_t RefCrc32 __attribute__((section("CLASS_B_RAM"), zero_init)); EXTERN uint32_t RefCrc32Inv __attribute__((section("CLASS_B_RAM_REV"), zero_init)); EXTERN uint32_t LSI_Freq __attribute__((section("CLASS_B_RAM"), zero_init)); /* Magic pattern for Stack overflow in this array */ EXTERN __IO uint32_t aStackOverFlowPtrn[4] __attribute__((section("STACK_BOTTOM"), zero_init)); 在MDK的Options for Target 选项卡中进行如下配置: control_flow_call(STACK_OVERFLOW_TEST); aStackOverFlowPtrn[0] = 0xEEEEEEEEuL; aStackOverFlowPtrn[1] = 0xCCCCCCCCuL; aStackOverFlowPtrn[2] = 0xBBBBBBBBuL; aStackOverFlowPtrn[3] = 0xDDDDDDDDuL; control_flow_resume(STACK_OVERFLOW_TEST); /** * @Brief This function verifies that Stack didn't overflow * @param : None * @retval : ErrorStatus = (ERROR, SUCCESS) */ ErrorStatus STL_CheckStack(void) { ErrorStatus result = SUCCESS; CtrlFlowCnt += STACK_OVERFLOW_CALLEE; if ( aStackOverFlowPtrn[0] != 0xEEEEEEEEuL ) { result = ERROR; } if ( aStackOverFlowPtrn[1] != 0xCCCCCCCCuL ) { result = ERROR; } if ( aStackOverFlowPtrn[2] != 0xBBBBBBBBuL ) { result = ERROR; } if ( aStackOverFlowPtrn[3] != 0xDDDDDDDDuL ) { result = ERROR; } CtrlFlowCntInv -= STACK_OVERFLOW_CALLEE; return (result); } 以上代码是RAM自检的汇编代码,整个算法执行会花费一定时间,如果整个内存范围的测试时间太长,就会对用户应用程序造成较大的局限性,所以将其分成若干片段,这些片段与执行程序的本地区域相一致。对被测试区域进行动态修改,然后进行单独执行测试。检测出问题则会跳转后面的故障函数,可以添加对应的操作进行故障处理。 |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
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:00 , Processed in 0.733563 second(s), Total 39, Slave 31 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号