cancel
Showing results for 
Search instead for 
Did you mean: 

Problem about Full March Ram test on startup for class B safety

l239955_st
Associate II
Posted on December 23, 2015 at 11:29

Hello,

I'm writing the firmware for an application that requires class b safety for certifications. I'm using ST library and it's all ok, my micro is STM32F030C8. I have no particular problem using the library, but I have one issue with the Ram start test, below you can see the library function given for march test. It sets all the ram to 0x00 and then to 0xFF with scrambling techniques and checks the result. The strange thing is that I have an error at some point when the ram is read back for check ( at address like 0x20000840 ...ram goes from 0x20000000 to 0x20001FFF ). Investigating with the debugger I see that the first pass set correctely to 0 all ram..then start reading back to check and write the read one to 0xFF...but sometimes a byte from 00 becomes 0x01 during the read time raising an error. I know that this micro ha an hw parity check that could be enabled by fw with the option bytes and from AN3307 i know that memory should be written before to avoid accidental parity error, but I have this in either case ( hw partiy check enabled or not...) What am I doing wrong???

ErrorStatus STL_FullRamMarchC(void)
{
uint32_t *p; /* RAM pointer */
uint32_t j; /* Index for RAM physical addressing */ 
ErrorStatus Result = SUCCESS;
// uint32_t *p; /* RAM pointer */
// uint32_t j; /* Index for RAM physical addressing */
// 
#ifdef __IAR_SYSTEMS_ICC__ /* IAR Compiler */
uint32_t ra= __get_LR(); /* save return address (as it will be destryed) */
#endif /* IAR Compiler */
#ifdef __CC_ARM /* KEIL Compiler */
uint32_t ra= __return_address(); /* save return address (as it will be destryed) */
#endif /* KEIL Compiler */
/* CtrlFlowCnt not used at function entry, since it will be cleared by the
routine. CtrlFlowCntInv is written at the function exit */
/* ==============================================================================*/
/* MISRA violation of rules 3 and 4: integral casting and pointer arithmetic 
is used here to manage the RAM testing and Check Class B var integrity */
#ifdef __IAR_SYSTEMS_ICC__ /* IAR Compiler */
#pragma diag_suppress=Pm088,Pm140
#endif /* IAR Compiler */
/* ---------------------------- STEP 1 ----------------------------------- */
/* Write background with addresses increasing */
for (p = RAM_START; p <= RAM_END; p++)
{
/* Scrambling not important when there's no consecutive verify and write */
*p = BCKGRND;
}
/* ---------------------------- STEP 2 ----------------------------------- */
/* Verify background and write inverted background with addresses increasing */
for (p = RAM_START; p <= RAM_END; p += RAM_BLOCKSIZE)
{
for (j = 0u; j < 
RAM_BLOCKSIZE
; j++)
{
if ( *(p + (uint32_t)RAM_SCRMBL[j]) != BCKGRND)
// 
p
=p+RAM_SCRMBL[j];
// if (*p != 0x00000000)
{
Result
= 
ERROR
;
}
// *
p
= 
INV_BCKGRND
;
*(p + (uint32_t)RAM_SCRMBL[j]) = INV_BCKGRND;
}
}
/* ---------------------------- STEP 3 ----------------------------------- */
/* Verify inverted background and write background with addresses increasing */
for (
p
= 
RAM_START
; p <= RAM_END; p += RAM_BLOCKSIZE)
{
for (
j
= 
0u
; j < RAM_BLOCKSIZE; j++)
{
if ( *(p + (uint32_t)RAM_SCRMBL[j]) != INV_BCKGRND) 
// 
p
=p+(uint32_t)RAM_SCRMBL[j];
// if (*p != 0xFFFFFFFF)
{
Result
= 
ERROR
;
}
*(p + (uint32_t)RAM_SCRMBL[j]) = BCKGRND;
}
}
/* ---------------------------- STEP 4 ----------------------------------- */
/* Verify background and write inverted background with addresses decreasing */
for (
p
= 
RAM_END
; p > RAM_START; p -= RAM_BLOCKSIZE)
{
for (j = 0u; j < 
RAM_BLOCKSIZE
; j++)
{
if ( *(p - (uint32_t)RAM_REVSCRMBL[j]) != BCKGRND)
{
Result
= 
ERROR
;
}
*(p - (uint32_t)RAM_REVSCRMBL[j]) = INV_BCKGRND;
}
}
/* ---------------------------- STEP 5 ----------------------------------- */
/* Verify inverted background and write background with addresses decreasing */
for (
p
= 
RAM_END
; p > RAM_START; p -= RAM_BLOCKSIZE)
{
for (j = 0u; j < 
RAM_BLOCKSIZE
; j++)
{
if ( *(p - (uint32_t)RAM_REVSCRMBL[j]) != INV_BCKGRND)
{
Result
= 
ERROR
;
}
*(p - (uint32_t)RAM_REVSCRMBL[j]) = BCKGRND;
}
}
/* ---------------------------- STEP 6 ----------------------------------- */
/* Verify background with addresses increasing */
for (
p
= 
RAM_START
; p <= RAM_END; p++)
{
if (*p != BCKGRND)
{
Result
= 
ERROR
; /* No need to take into account scrambling here */
}
}
/* As all SRAM is zeroed CtrlFlowCntInv is re-initialized here to be inverse */
CtrlFlowCntInv
= 
0xFFFFFFFFuL
;
/* Restore destroyed return address back into the stack (all the content is destroyed).
Next line of code supposes the {r4-r7,pc} for Keil and {r4-r5,pc} for IAR registers
only was saved into stack by this test so their restored values are not valid: 
=> optiomizations at caller must be switched off as caller cannot relay on r4-r7 values!!! */
#ifdef __IAR_SYSTEMS_ICC__ /* IAR Compiler */
*((uint32_t *)(__get_SP()) + 2u) = ra;
#pragma diag_default=Pm088,Pm140 
#endif /* IAR Compiler */
#ifdef __CC_ARM /* KEIL Compiler */
*((uint32_t *)(__current_sp()) + 4u) = ra;
#endif /* KEIL Compiler */ 
return(Result);
}

#march-test #safety
3 REPLIES 3
Posted on December 23, 2015 at 13:51

What am I doing wrong???

Does the location of the failure correlate with where the STACK is situated?

You'd want to review the generated code and make sure all the auto/local variables in your routine are held in REGISTERS

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
l239955_st
Associate II
Posted on December 24, 2015 at 12:50

Hello Clive,

thanks for the quick answer...so my stack is defined at the end of Ram ( 0x20001FFF ) and growing up, stack size is 0x400 so is limited to ( 0x2001BFF ). Here's my .icf...

/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile=''$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml'' */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08002000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08002000 ;
define symbol __ICFEDIT_region_ROM_end__ = 0x0800FFFF;
//define symbol __ICFEDIT_region_RAM_start__ = 0x20000100;
define symbol __ICFEDIT_region_RAM_start__ = 0x200001C0;
define symbol __ICFEDIT_region_RAM_end__ = 0x20001FFF;
//define symbol __ICFEDIT_region_CLASSB_start__ = 0x20000040;
//define symbol __ICFEDIT_region_CLASSB_end__ = 0x20000100;
define symbol __ICFEDIT_region_CLASSB_start__ = 0x20000100;
define symbol __ICFEDIT_region_CLASSB_end__ = 0x200001C0;
define symbol __MY_Func_Addr__ = 0x0800AAA0;
define symbol __MY_Func_Addr1__ = 0x08005550;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x400;
define symbol __ICFEDIT_size_heap__ = 0;
define symbol __ICFEDIT_size_stack_bottom__ = 0x10;
/**** End of ICF editor section. ###ICF###*/
export symbol __ICFEDIT_region_ROM_start__;
export symbol __ICFEDIT_region_ROM_end__;
export symbol __ICFEDIT_region_RAM_start__;
export symbol __ICFEDIT_region_RAM_end__;
export symbol __ICFEDIT_region_CLASSB_start__;
export symbol __ICFEDIT_region_CLASSB_end__;
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define region My_Function = mem:[from __MY_Func_Addr__ size 0x10];
define region My_Function1 = mem:[from __MY_Func_Addr1__ size 0x10];
//define symbol __region_RUN_TIME_RAM_BUF_start__ = 0x20000004;
//define symbol __region_RUN_TIME_RAM_PNT__satrt__ = 0x20000030;
define symbol __region_RUN_TIME_RAM_BUF_start__ = 0x200000C4;
define symbol __region_RUN_TIME_RAM_PNT__satrt__ = 0x200000F0;
//define symbol __region_CLASS_B_RAM_start__ = 0x20000040;
//define symbol __region_CLASS_B_RAM_REV__satrt__ = 0x20000040;
define symbol __region_CLASS_B_RAM_start__ = 0x20000100;
define symbol __region_CLASS_B_RAM_REV__satrt__ = 0x20000100;
//define region RUN_TIME_RAM_BUF_region = mem:[from __region_RUN_TIME_RAM_BUF_start__ to 0x2000002F];
//define region RUN_TIME_RAM_PNT_region = mem:[from __region_RUN_TIME_RAM_PNT__satrt__ to 0x2000003F];
define region RUN_TIME_RAM_BUF_region = mem:[from __region_RUN_TIME_RAM_BUF_start__ to 0x200000EF];
define region RUN_TIME_RAM_PNT_region = mem:[from __region_RUN_TIME_RAM_PNT__satrt__ to 0x200000FF];
define region CLASS_B_RAM_region = mem:[from __region_CLASS_B_RAM_start__ to __ICFEDIT_region_CLASSB_end__];
define region CLASS_B_RAM_REV_region = mem:[from __region_CLASS_B_RAM_REV__satrt__ to __ICFEDIT_region_CLASSB_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
//define block STACK_TOP_B with alignment = 8, size = __ICFEDIT_size_stack_bottom__ { section STACK_TOP };
define block STACK_BOTTOM_B with alignment = 8, size = __ICFEDIT_size_stack_bottom__ { section STACK_BOTTOM };
define block stack_order with fixed order { block STACK_BOTTOM_B, block CSTACK, block HEAP };
initialize by copy { readwrite };
do not initialize { section .noinit, section STACK_BOTTOM, section RUN_TIME_RAM_BUF, section RUN_TIME_RAM_PNT,
section CLASS_B_RAM, section CLASS_B_RAM_REV };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place at address mem:__MY_Func_Addr__ { readonly section My_Function };
place at address mem:__MY_Func_Addr1__ { readonly section My_Function1 };
place in CLASS_B_RAM_region
{ readwrite data section CLASS_B_RAM }; 
place in CLASS_B_RAM_REV_region
{ readwrite data section CLASS_B_RAM_REV };
place in RUN_TIME_RAM_BUF_region
{ readwrite data section RUN_TIME_RAM_BUF }; 
place in RUN_TIME_RAM_PNT_region
{ readwrite data section RUN_TIME_RAM_PNT }; 
place in ROM_region { readonly };
place at end of ROM_region { ro section .checksum };
place at end of RAM_region { readwrite, block stack_order };

What I see with the debugger is that March Test goes in error when running normally always with the readback of a byte between 0x20000840 and 0x20000880 and i see a byte set to 0x01 and some bytes at stack bottom not set to zero...as setted before by march test...I tried going single step and it seem not happening . Local/auto variables of the readback cycle are allocated in registers correctely... Maybe an Interrupt?? But it seems to me they are all off...i will check better....
Posted on December 24, 2015 at 16:42

Perhaps you'd need to look more to when and how the code is run.

There seems to be a boot-loader involved prior to this being run, you'd want to check for DMA and IRQ activity that might still be happening, and if the vector table has been changed. Where it's stack is, and then machine context/registers when it fails.

These kinds of memory tests really need to be done in assembler code, in the reset handler, where the system state is clearly understood and controlled.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..