Energy Micro IEC60355 Library Project 1.037 GCC-Version
IEC60355 Library documentation and API

iec60335_class_b_ram_test.c

Go to the documentation of this file.
00001 /***************************************************************************/
00030 #include "efm32.h"
00031 #include "iec60335_class_b.h"
00032 
00037 /* local definitions */
00038 #if     (defined (__CC_ARM))
00039 
00040 /*------------------RealView Compiler -----------------*/
00041 #define getSP()    __current_sp()
00042 
00044 #elif   (defined (__ICCARM__))
00045 
00046 /*------------------ ICC Compiler -------------------*/
00047 #define getSP()    __get_MSP()
00048 
00050 #elif   (defined (__GNUC__))
00051 
00052 /*------------------ GNU Compiler ---------------------*/
00053 #define getSP()    __get_MSP()
00054 
00055 #else
00056 #error "iec60355_class_b_interrupt_test.c: undefined compiler"
00057 #endif
00058 
00059 
00060 /* 32-bit word access macro */
00061 #define WA(ptr)    * ((volatile uint32_t *) ptr)
00062 
00063 
00064 #ifdef TESSY
00065 
00066 void TS_TessyDummy(volatile uint8_t* ts_ptr);
00067 #define __st(x)      {x;}
00068 #define MOP_R0()     __st(TS_TessyDummy(ptr); if (WA(ptr) != r0_exp) goto R0_FAULT_DETECTED;)
00069 #define MOP_R1()     __st(TS_TessyDummy(ptr); if (WA(ptr) != r1_exp) goto R1_FAULT_DETECTED;)
00070 
00071 #else
00072 /* local macros */
00073 /* March memory operations */
00074 #define __st(x)      do { x; } while (0)
00075 #define MOP_R0()     __st(if (WA(ptr) != r0_exp) goto R0_FAULT_DETECTED;)
00076 #define MOP_R1()     __st(if (WA(ptr) != r1_exp) goto R1_FAULT_DETECTED;)
00077 #endif  /* TESSY */
00078 
00079 #define MOP_W0()     __st(WA(ptr) = r0_exp;)
00080 #define MOP_W1()     __st(WA(ptr) = r1_exp;)
00081 #define MOP_DEL()    __NOP()
00082 
00083 testResult_t IEC60335_ClassB_RAMtest(uint32_t startAddrs, uint32_t size, uint8_t block_sel)
00084 {
00085   testResult_t result = IEC60335_testFailed;
00086 
00087   /* Note that function calls cannot be used from this function as the */
00088   /* stack is destroyed. */
00089 
00090   /* Use a byte pointer to increment through the RAM blocks. */
00091   /* The byte pointer is cast into 32-bit word accesses to generate both */
00092   /* aligned and unaligned accesses. The unaligned accesses are split into */
00093   /* multiple 8- and 16-bit accesses by the CM3 bus matrix. That way, we are */
00094   /* also testing for individual byte WE faults in the RAM IP and address */
00095   /* decoder faults. */
00096   register volatile uint8_t *ptr;
00097   register uint32_t         offset;
00098   volatile uint8_t          *ram_base_init;
00099   volatile uint8_t          *ram_end_init;
00100   register volatile uint8_t *ram_base;
00101   register volatile uint8_t *ram_end;
00102   register uint32_t         r0_exp;
00103   register uint32_t         r1_exp;
00104   uint32_t                  currentSP;
00105   register uint32_t         segment_size2;
00106   uint32_t                  stackSize;
00107 
00108   /* Set RAM block boundary pointers */
00109   switch (block_sel)
00110   {
00111   case BLOCK_SEL_CORE:
00112     ram_base_init    = (volatile uint8_t *) startAddrs;
00113     ram_end_init     = ram_base_init + size;
00114     r0_exp           = CORE_RAM_R0_EXP;
00115     r1_exp           = CORE_RAM_R1_EXP;
00116     break;
00117 
00118   case BLOCK_SEL_PLINK:
00119     ram_base_init    = PLINK_RAM_BASE_PTR;
00120     ram_end_init     = (volatile uint8_t *)(PLINK_RAM_BASE_ADDR + PLINK_RAM_MAX_BC);
00121     r0_exp           = PLINK_RAM_R0_EXP;
00122     r1_exp           = PLINK_RAM_R1_EXP;
00123     CMU->HFPERCLKEN0 = ~0;
00124     break;
00125 
00126   default:
00127     goto BOUNDARY_FAULT_DETECT;                               /* error condition */
00128     break;
00129   }
00130   do {
00131     segment_size2    = 0;
00132     if (block_sel == BLOCK_SEL_CORE)
00133     {
00134       currentSP = getSP();
00135       stackSize = initial_sp - currentSP;
00136       
00137       /* test boundaries */
00138       if (((uint32_t)ram_base_init < RAM_MEM_BASE)||((uint32_t)ram_end_init > (RAM_MEM_BASE + RAM_MEM_SIZE)))
00139       {
00140         goto BOUNDARY_FAULT_DETECT;
00141       }
00142       if (ram_base_init > ram_end_init)
00143       {
00144         goto BOUNDARY_FAULT_DETECT;
00145       }
00146       if ((currentSP < RAM_MEM_BASE)||(currentSP > initial_sp)||(stackSize > RAM_MEM_SIZE))
00147       {
00148         goto BOUNDARY_FAULT_DETECT;
00149       }
00150       if ((size%4 != 0) || (size == 0))
00151       {
00152         goto BOUNDARY_FAULT_DETECT;
00153       }
00154 
00155       /* check stack end in tested RAM area */
00156       if ((currentSP > (uint32_t) ram_base_init) && (currentSP < (uint32_t) ram_end_init))
00157       {
00158         /* check SP at end of tested RAM section */
00159         if (initial_sp >= ((uint32_t)ram_end_init - 0x10))
00160         {
00161           /* stack is at the end of the tested area */
00162           ram_end_init = (uint8_t*)(currentSP - IEC60335_RAM_SP_Offset);
00163           segment_size2 = 0;
00164           /* check sufficient size of tested memory */
00165           if (ram_base_init >= ram_end_init)
00166           {
00167             goto BOUNDARY_FAULT_DETECT;
00168           }
00169         }
00170         else /* there is a gap behind the stack */
00171         {
00172           segment_size2 = (uint32_t)ram_end_init - initial_sp;    /* next segment to check */
00173           ram_end_init = (uint8_t*)(currentSP - IEC60335_RAM_SP_Offset);
00174         }
00175       }
00176       /* check stack start in tested RAM area */
00177       else if ((initial_sp > (uint32_t) ram_base_init) && (initial_sp < (uint32_t) ram_end_init))
00178       {
00179         /* stack is at the start of the tested area */
00180         ram_base_init = (uint8_t*)initial_sp + 4;
00181         segment_size2 = 0;
00182         /* check sufficient size of tested memory */
00183         if (ram_base_init >= ram_end_init)
00184         {
00185           goto BOUNDARY_FAULT_DETECT;
00186         }
00187       }
00188     }
00189     for (offset = 0; offset < sizeof(uint32_t); offset++)
00190     {
00191       /* Offset the byte boundary pointer to generate all combinations of aligned and unaligned access to the Core RAM. */
00192       /* The PLINK RAM is arranged as bytes aligned to 32-bit word addresses. Hence, skip offset 1, 2 and 3 for the PLINK RAM. */
00193       if (offset != 0)
00194       {
00195         if (block_sel != BLOCK_SEL_CORE)
00196           break;
00197         ram_base = (volatile uint8_t *)((uint32_t) ram_base_init + offset);
00198         ram_end  = (volatile uint8_t *)((uint32_t) ram_end_init + offset - sizeof(uint32_t));       /* do not exceed the last byte on unaligned access */
00199       }
00200       else
00201       {
00202         ram_base = ram_base_init;
00203         ram_end  = ram_end_init;
00204       }
00205 
00206       /* March element M0: <->(w0), using -> address order */
00207       ptr = ram_base;
00208       while (ptr < ram_end)
00209       {
00210         MOP_W0();
00211         ptr = ptr + sizeof(uint32_t);
00212       }
00213 
00214       /* March element M1: ->(r0,w1) */
00215       ptr = ram_base;
00216       while (ptr < ram_end)
00217       {
00218         MOP_R0();
00219         MOP_W1();
00220         ptr = ptr + sizeof(uint32_t);
00221       }
00222 
00223       /* March element M2: <-(r1,w0,r0,w1) */
00224       ptr = (ram_end - sizeof(uint32_t));
00225       while (ptr >= ram_base)
00226       {
00227         MOP_R1();
00228         MOP_W0();
00229         MOP_R0();
00230         MOP_W1();
00231         ptr = ptr - sizeof(uint32_t);
00232       }
00233 
00234       /* March element M3: <-(r1,w0) */
00235       ptr = (ram_end - sizeof(uint32_t));
00236       while (ptr >= ram_base)
00237       {
00238         MOP_R1();
00239         MOP_W0();
00240         ptr = ptr - sizeof(uint32_t);
00241       }
00242 
00243       /* March element M4: <-(r0,w1,r1,w0) */
00244       ptr = (ram_end - sizeof(uint32_t));
00245       while (ptr >= ram_base)
00246       {
00247         MOP_R0();
00248         MOP_W1();
00249         MOP_R1();
00250         MOP_W0();
00251         ptr = ptr - sizeof(uint32_t);
00252       }
00253 
00254       /* March element M5: <-(r0) */
00255       ptr = (ram_end - sizeof(uint32_t));
00256       while (ptr >= ram_base)
00257       {
00258         MOP_R0();
00259         ptr = ptr - sizeof(uint32_t);
00260       }
00261 
00262       /* March element M6: Del */
00263       MOP_DEL();
00264 
00265       /* March element M7: <->(r0,w1,r1), using -> address order */
00266       ptr = ram_base;
00267       while (ptr < ram_end)
00268       {
00269         MOP_R0();
00270         MOP_W1();
00271         MOP_R1();
00272         ptr = ptr + sizeof(uint32_t);
00273       }
00274 
00275       /* March element M8: Del */
00276       MOP_DEL();
00277 
00278       /* March element M9: <->(r1), using <- address order */
00279       ptr = (ram_end - sizeof(uint32_t));
00280       while (ptr >= ram_base)
00281       {
00282         MOP_R1();
00283         ptr = ptr - sizeof(uint32_t);
00284       }
00285     }
00286     if (segment_size2 != 0)
00287     {
00288       ram_base_init = (volatile uint8_t *) initial_sp + 4;
00289       ram_end_init  = (volatile uint8_t *) initial_sp + segment_size2;
00290     }
00291   } while (segment_size2);
00292   /* No faults found, report OK */
00293   result = IEC60335_testPassed;
00294   goto RAM_TEST_END;
00295 
00296  /* Fault return */
00297  BOUNDARY_FAULT_DETECT:
00298   result = IEC60335_testFailed;
00299   goto RAM_TEST_END;
00300 
00301  R0_FAULT_DETECTED:
00302   result = IEC60335_testFailed;
00303   goto RAM_TEST_END;
00304 
00305  R1_FAULT_DETECTED:
00306   result = IEC60335_testFailed;
00307 
00308  RAM_TEST_END:
00309   return(result);
00310 }
00311 
00312 testResult_t IEC60335_ClassB_RAMtest_POST(void)
00313 {
00314   return ((testResult_t)IEC60335_ClassB_RAMtest(CORE_RAM_BASE_ADDR, IEC60335_RAM_SIZE, BLOCK_SEL_CORE));
00315 }
00316 
00317 testResult_t IEC60335_ClassB_RAMtest_BIST(uint32_t startAddr, uint32_t length)
00318 {
00319   uint8_t      buffer[IEC60335_RAM_buffersize];
00320   testResult_t result = IEC60335_testFailed;
00321 
00322 /* check StartAddr in RAM space */
00323   if (startAddr > (IEC60335_RAM_START + IEC60335_RAM_SIZE - 4))
00324   {
00325     return(result);
00326   }
00327   if (startAddr < IEC60335_RAM_START)
00328   {
00329     return(result);
00330   }
00331 /* limit size to buffer size */
00332   if (length > IEC60335_RAM_buffersize)
00333   {
00334     length = IEC60335_RAM_buffersize;
00335   }
00336   if (length == 0) 
00337   {
00338     return(result);
00339   }
00340 /* limit endaddress to RAM space */
00341   if ((startAddr + length) > (IEC60335_RAM_START + IEC60335_RAM_SIZE - 4))
00342   {
00343     length = IEC60335_RAM_START + IEC60335_RAM_SIZE - 4 - startAddr;
00344   }
00345 /* check buffer overlaps test area low */
00346   if (((uint32_t) &buffer[0] > startAddr) && ((uint32_t) &buffer[0] < (startAddr + length)))
00347   {
00348     return(result);
00349   }
00350 /* check buffer overlaps test area high */
00351   if (((uint32_t) &buffer[IEC60335_RAM_buffersize - 1] > startAddr) && 
00352       ((uint32_t) &buffer[IEC60335_RAM_buffersize - 1] < (startAddr + length)))
00353   {
00354     return(result);
00355   }
00356 /* save memory content */
00357   util_memcpy(&buffer[0], &startAddr, length);
00358 
00359   result = IEC60335_ClassB_RAMtest(startAddr, length, BLOCK_SEL_CORE);
00360 /* restore memory content */
00361   util_memcpy(&startAddr, &buffer[0], length);
00362   return(result);
00363 }
00364 
00369 /************************************** EOF *********************************/