![]() |
Energy Micro IEC60355 Library Project 1.037 GCC-Version
IEC60355 Library documentation and API
|
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 *********************************/