AnsweredAssumed Answered

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

Question asked by pinese.lucio on Dec 23, 2015
Latest reply on Dec 24, 2015 by Clive One
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 11.3 and 17.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);
}

Outcomes