本文以RA6 MCU为例,介绍如何使用自诊断软件对MCU进行自检。
1
使用的环境
2
自检软件介绍
瑞萨提供了针对RA系列MCU的诊断软件,涵盖了对MCU的CPU core,ROM,RAM的永久性故障诊断,CPU的斩断覆盖率达90%,RAM的诊断覆盖率达90%,ROM的诊断覆盖率达99%,满足SIL3的认证要求。本文档使用的自检软件包RTK0EF0090F60001SJ_Ver.1.01适用于cortex M4架构的RA6系列MCU。
2.1
CPU诊断软件
CPU诊断软件通过采用主要基于指令的诊断方法来验证 CPU的正确功能,从而检测CPU内核的永久性硬件故障。针对处理器内核,有20项的测试内容。
2.2
CPU诊断软件API
void coreTest(uint8_t steps, const uint8_t forceFail, uint32_t *result),通过设置参数forceFail,可以实现故障注入从而返回错误。
2.3
RAM诊断软件
RAM诊断软件是检测MCU RAM内存,将要检测的内存大小MUTSize分成numberOfBUT块,那么每块内存大小就是MUTSize/numberOfBUT.调用RAM诊断API对每块内存进行检测,返回两个结果resultTestRam1和resultTestRam2,如果都为1,则表示检测通过,否则检测失败。
2.4
RAM诊断软件API
void testRAM(unsigned int index, unsigned int selectAlgorithm, unsigned int destructive),参数 selectAlgorithm是设置RAM自检算法,支持Extended March C-和WALPAT两种算法,参数destructive是设置RAM自检模式,0表示非破坏性模式,需要使用新buffer保存被检RAM区的数据做备份,1表示po破坏性检测,该模式会模式会清楚RAM区数据初始化为0。
2.5
ROM诊断软件
RAM诊断软件是检测MCU ROM,通过选定ROM起始地址和终止地址来确认检测的内存块范围,调用ROM诊断软件API对ROM内存块进行相应CRC计算,返回值与参考checksum(由IAR链接器预先计算产生)进行比较,如果不一致,则表示有错误。
2.5
ROM诊断软件
RAM诊断软件是检测MCU ROM,通过选定ROM起始地址和终止地址来确认检测的内存块范围,调用ROM诊断软件API对ROM内存块进行相应CRC计算,返回值与参考checksum(由IAR链接器预先计算产生)进行比较,如果不一致,则表示有错误。
2.6
ROM诊断软件API
void crcHwSetup(unsigned int crc)
uint16_t crcComputation(unsigned int checksumBegin,unsigned int checksumEnd,unsigned int incrMode)
以上是诊断软件的介绍,详细的细节可以查阅诊断软件的用户手册。
3
RA6开发板测试
3.1 使用RASC创建基于IAR的FSP工程,点击Generate Project Content生成代码。
3.2 打开新创建的IAR工程,从RTK0EF0090F60001SJ_Ver.1.01代码包中,拷贝自检代码添加到工程中src目录下。
3.3
工程设置
C/C++ Compiler->Preprocessor添加对应文件路径
Assembler->Preprocessor添加对应文件路径
3.4
应用功能实现
编辑hal_entry.c文件,实现对CPU,RAM,ROM每隔0.5秒的循环检测,同时EK-RA6M4按下S1按钮,故障输入,从而实现CPU错误检测,红色led灯闪烁,参考ek_ra6m4_selftest样例程序。
1.主函数入口代码:
void hal_entry(void)
{
/* TODO: add your own code here */
uint32_t ver;
uint8_t cnt = 0;
ver = R_CPU_Diag_GetVersion();
// printf("CPU diag software version = %d.%02d\n",ver >>16u,ver & 0xFFFF);
ver = R_RAM_Diag_GetVersion();
// printf("RAM diag software version = %d.%02d\n",ver >>16u,ver & 0xFFFF);
ver = R_ROM_Diag_GetVersion();
// printf("ROM diag software version = %d.%02d\n",ver >>16u,ver & 0xFFFF);
/* Setup Registers */
setup_diag();
/* Holds level to set for pins */
bsp_io_level_t pin_level = BSP_IO_LEVEL_LOW;
while(1)
{
int32_t result = 0;
cnt = cnt % 3;
/* Blue LED blinks */
led_change(0, pin_level);
/* Diagnostic */
switch (cnt)
{
case 0:
result = cpu_test_sample();
break;
case 1:
result = ram_test_sample();
break;
case 2:
result = rom_test_sample();
break;
}
cnt++;
if (0 == result){
/* Red LED lights off */
led_change(2, BSP_IO_LEVEL_LOW);
}else{
/* Red LED lights up */
led_change(2, BSP_IO_LEVEL_HIGH);
}
/* Toggle level for next write */
if (BSP_IO_LEVEL_LOW == pin_level)
{
pin_level = BSP_IO_LEVEL_HIGH;
}
else
{
pin_level = BSP_IO_LEVEL_LOW;
}
/* Delay (500ms) */
R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS);
}
/* Enter non-secure code */
R_BSP_NonSecureEnter();
}
2. cpu_test_sample()函数实现了CPU TEST代码:
/***********************************************************************************************************************
* CPU TEST
**********************************************************************************************************************/
int32_t cpu_test_sample(void)
{
uint32_t forceFail = 1; /* Force fail:Disable */
int32_t result;
uint32_t index;
/* Check SW 'S1' */
if (R_PFS->PORT[0].PIN[5].PmnPFS_b.PIDR == 0)
{
forceFail = 0;
asm("NOP");
}
else{
asm("NOP");
}
for (index = 0; index <= CPU_DIAG_MAX_INDEX; index++)
{
result = 0;
R_CPU_Diag(index, forceFail, &result);
if (result != 1) {
return -1;
}
}
return 0;
}
3. ram_test_sample()函数实现了RAM TEST代码:
/***********************************************************************************************************************
* RAM TEST
**********************************************************************************************************************/
int32_t ram_test_sample(void)
{
uint32_t area = 0;
uint32_t index;
uint32_t algorithm = RAM_ALG_MARCHC;
uint32_t destructive;
for (index = 0; index < numberOfBUT0; index++) {
if (index == 0) { /* Buffer block */
destructive = RAM_MEM_DT;
} else {
destructive = RAM_MEM_NDT;
}
/* Call API */
R_RAM_Diag(area, index, algorithm, destructive);
/* Check API result */
if ( (RramResult1 != 1) || (RramResult2 != 1) ) {
return -1;
}
}
return 0;
}
4.rom_test_sample()函数实现了ROM TEST代码:
/***********************************************************************************************************************
* ROM TEST
**********************************************************************************************************************/
/* Area where the expected CRC checksum values of each ROM block are aggregated. */
__root const uint16_t expChecksum[NUM_OB_ROM_BLOCK] @ CHECKSUM_BLOCK_ADDRESS;
int32_t rom_test_sample(void)
{
uint32_t start;
uint32_t end;
uint32_t mode;
uint16_t calChecksum;
/* ROM Test: Block0 (4KB) */
start = 0x00001000;
end = 0x00001FFF;
mode = 0;
calChecksum = R_ROM_Diag(start, end, mode);
if (calChecksum != expChecksum[0]) {
return -1;
}
/* ROM Test: Block1 (4KB, 4time-wise split) */
/* Block1, Group1 (1KB) */
start = 0x00002000;
end = 0x000023FF;
mode = 0;
calChecksum = R_ROM_Diag(start, end, mode);
/* Block1, Group2 (1KB) */
start = 0x00002400;
end = 0x000027FF;
mode = 1;
calChecksum = R_ROM_Diag(start, end, mode);
/* Block1, Group3 (1KB) */
start = 0x00002800;
end = 0x00002BFF;
calChecksum = R_ROM_Diag(start, end, mode);
/* Block1, Group4 (1KB) */
start = 0x00002C00;
end = 0x00002FFF;
calChecksum = R_ROM_Diag(start, end, mode);
if (calChecksum != expChecksum[1]) {
return -1;
}
return 0;
}
如您在使用瑞萨MCU/MPU产品中有任何问题,可识别下方二维码或复制网址到浏览器中打开,进入瑞萨技术论坛寻找答案或获取在线技术支持。
https://community-ja.renesas.com/zh/forums-groups/mcu-mpu/
1
END
1
推荐阅读
EZ-CUBE3用户手册[4-2]如何在RA微控制器上使用EZ-CUBE3(3)
瑞萨RA家族精品RA6T2产品介绍
X-IPM RA6T2 AC/DC三相无桥PFC数字电源解决方案研讨会回顾之方案介绍篇