赞
踩
这篇文章来简单介绍一下NXP针对core test为S32K3设计的SCST(core self-test code)软件,并且将描述如何将SCST集成在自己的工程中并将其应用起来。
SCST的原理如下:
SCST说白了就是针对S32K3的M7核的RTL模式,架构,指令集等等特征设计出可以测试M7核是否正常运行的一段汇编代码,这段代码里面无外乎就是主动去触发和响应中断呀,去做一些整型和浮点型计算,反正就是去干一些核经常干的事情,验证一下核的功能是否正常,此为SCST。
编译器选项 | options |
---|---|
GreenHills | -preprocess_assembly_files |
GCC | -x assembler-with-cpp |
IAR | 无需添加 |
除此之外,个别core test会用到一个reserved的地址M7_DEVICE_RESERVED_ADDR,所以需要在assembly的预宏定义中定义这个宏,如下:
修改链接文件将一些段链接到合适的位置,这些段应该所链接位置以及这些段的内容具体如下:
sector | 链接位置 | 描述 |
---|---|---|
.m7_scst_test_code | FLASH | 包含了SCST的所有测试代码 |
.m7_scst_test_branch_code0 | FLASH | 分支测试代码0 |
.m7_scst_test_branch_code1 | FLASH | 分支测试代码1 |
.m7_scst_test_shell_code | FLASH | 调用测试的接口函数 |
.m7_scst_vector_table | FLASH | SCST自定义中断向量表 |
.m7_scst_rom_data | FLASH | 常量 |
.m7_scst_ram_data | RAM | 全局变量 |
.m7_scst_test_shell_data | RAM | 调用测试的接口函数所用的全部变量 |
.m7_scst_ram_data_target0 | RAM | 恢复现场所用的数据0 |
.m7_scst_ram_data_target1 | RAM | 恢复现场所用的数据1 |
.m7_scst_ram_test_code | RAM | 给fetch test使用的变量 |
FLASH部分如下:
RAM的sram_data部分如下:
到此,移植准备工作全部完成了。
SCST一共提供了50项测试,对应的测试项ID为0~49,截取一部分如下(其他请参考《M7_S32K3xx_SCST_User_Manual.pdf》):
表中详细列出了每一测试项的测试ID(测试项索引), 参考签名值(当前测试项的正确返回值,如果测试项返回结果不等于参考签名值,那么标定该测试项未通过),用户中断阻塞时间(测试过程中,会更换中断向量表,从而让用户ISR堵塞),测试执行时间(整个测试项所用的时间),所用栈大小(使用的栈为编译器所划的Stack)。那么怎么在代码中实现这些测试呢?
启动SCST的测试项非常简单,只牵扯到一个函数,三个变量。其中一个函数为:
m7_scst_uint32_t m7_scst_execute_core_tests(m7_scst_uint32_t start, m7_scst_uint32_t end)
可以通过这个函数来启动SCST测试项,形参start为起始测试项ID,形参end为结束测试ID。举个例子,如果如下调用:
test_result = m7_scst_execute_core_tests(0,49);//启动第1测试项到第49测试项,依次进行
test_result = m7_scst_execute_core_tests(0,0);//测试第0测试项
test_result = m7_scst_execute_core_tests(1,1);//测试第1测试项
三个变量如下:
/*保存了最后一次测试项的ID,如果一次性启动所有测试项,中间有测试项出现错误未通过,
导致测试终止,那么则可以读取这个值来确定是哪个测试项未通过*/
extern m7_scst_uint32_t m7_scst_last_executed_test_number;
/*记录了最后一次测试项的返回值,如果一次性启动所有测试项,中间有测试项出现错误未通过,
导致测试终止,那么则可以读取这个值来了解未通过测试项的错误返回值*/
extern m7_scst_vuint32_t m7_scst_accumulated_signature;
/*指定注入错误通道,可以在启动测试项之前,通过指定这个参数来向指定测试项注入错误,
注入错误会导致测试未通过*/
extern m7_scst_uint32_t m7_scst_fault_inject_test_index;
SCST50项测试有13项测试是针对FPU的,可以在m7_scst_configuration.h中配置是否使能FPU相关的core test选项,如下:
#define M7_SCST_SPFPU_TESTS 1U
另外,如果激活了FPU测试,那么就需要在编译选项中激活单精度FPU硬件,如下:
其他编译器对应编译选项如下:
编译器选项 | options |
---|---|
GreenHills | -fpu=vfpv3_d16 |
GCC | -mfpu=fpv5-d16 |
IAR | –cpu Cortex-M7.fp.sp |
如果在应用代码中使能了MPU配置,那么其中49号测试项m7_scst_loadstore_test7对MPU的配置也有要求,具体要求以及MPU配置代码如下:
void MPU_config() { /*------------------------------------------------------------------------*/ /* MPU region 0 */ /*------------------------------------------------------------------------*/ *MPU_RNR = 0x00000000; /* Configure MPU region 0 base address to SCST_RAM_TARGET0 */ *MPU_RBAR = (m7_scst_uint32_t)&SCST_RAM_TARGET0; /* Configure MPU region 0 - XN: Not executable - AP: S:RW U:RW Full access - TEX: 0 - S: Not shareable - C: Not cacheable - B: Not bufferable - SRD: 0b00000000 - SIZE: 32 B - EN: Enabled */ *MPU_RASR = 0x13000009; /*------------------------------------------------------------------------*/ /* MPU region 1 */ /*------------------------------------------------------------------------*/ *MPU_RNR = 0x00000001; /* Configure MPU region 1 base address to SCST_RAM_TARGET1 */ *MPU_RBAR = (m7_scst_uint32_t)&SCST_RAM_TARGET1; /* Configure MPU region 1 - XN: Not executable - AP: S:RW U:-- Privileged access only - TEX: 0 - S: Not shareable - C: Not cacheable - B: Not bufferable - SRD: 0b00000000 - SIZE: 32 B - EN: Enabled */ *MPU_RASR = 0x11000009; /* Enable MPU - PRIVDEFENA: 1 (Use default memory map as region -1 for privileged access) - HFNMIENA: 0 (Disable MPU for handlers with priority less than 0) - ENABLE: 1 */ *MPU_CTRL = 0x00000005; }
当然了,如果你没有使能MPU,那么就没有什么影响。
在50个测试中,0 ~ 5号测试项比较特殊,如果在Handle模式下启动0 ~ 5号测试项的话,那么就需要在m7_scst_configuration.h中配置一些宏,将其由默认值改为以下值:
#define M7_SCST_EXECUTION_MODE M7_SCST_HANDLER
#define M7_SCST_SVC_EXCEPTION_LOW 1U
#define M7_SCST_PENDSV_EXCEPTION_LOW 1U
#define M7_SCST_SYSTICK_EXCEPTION_LOW 1U
如果systick中断被使能了,那么还需要修改这个宏,如下:
#define M7_SCST_SYSTICK_IS_RUNNING 1U
相关测试代码如下:
void SCST_example(void) { //给第10号测试项注入错误 m7_scst_fault_inject_test_index = 10; //启动0~27号测试项 m7_scst_execute_core_tests(0, 27); //判断最后一次测试项ID是否为10 if(m7_scst_last_executed_test_number != 10) { while(1); } //再次启动0~27号测试项 m7_scst_execute_core_tests(0, 27); //判断最后一次测试项ID是否为35 if(m7_scst_last_executed_test_number != 27) { while(1); } //判断最后一次测试项返回值是否为35号测试的参考签名值 if(m7_scst_accumulated_signature == 0x7F0BF5A3U) { while(1); } //启动29~49号测试项 m7_scst_execute_core_tests(29, 49); //判断最后一次测试项ID是否为48 if(m7_scst_last_executed_test_number != 49) { while(1); } //判断最后一次测试项返回值是否为49号测试的参考签名值 if(m7_scst_accumulated_signature == 0x2F6AB216U) { while(1); } //m7_scst_execute_core_tests(28, 28); //28号测试项暂时有问题,待解决 }
注意①:SCST测试项是可以在应用程序中周期性启动的。
注意②:在测试代码中,我跳过了第28号测试项,因为在测试过程中,发现该项测试无法通过,发现死在了一条STREX指令,这是因为这条指令是给FLASH的一个地址执行写操作,但是在MCAL代码中SystemInit中有一个配置MPU的操作,默认是将FALSH配置成了禁止写性所以我们有两种方法让第28测试项通过,第一种就是将FLASH的读写属性改成可写,第二种就是直接Disable MPU,具体如下:
/*配置FLASH区域为可写*/
rasr[2]=0x020B002BUL;
/*Disable MPU*/
S32_MPU->CTRL &= (~S32_MPU_CTRL_ENABLE_MASK);
个人觉得这应该是条bug,看官方是否会在后面将其修复。
至此,关于SCST的应用就全部介绍完毕了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。