| Xmega IEC60730 Class B Library 1.0 |

All Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
classb_sram.c
Go to the documentation of this file.
1 /* This file has been prepared for Doxygen automatic documentation generation.*/
2 /**
3 * \file
4 *
5 * \brief
6 * SRAM test based on the March X algorithm.
7 *
8 * \par Application note:
9 * AVR1610: Guide to IEC60730 Class B compliance with XMEGA
10 *
11 * \par Documentation
12 * For comprehensive code documentation, supported compilers, compiler
13 * settings and supported devices see readme.html
14 *
15 * \author
16 * Atmel Corporation: http://www.atmel.com \n
17 * Support email: avr@atmel.com
18 *
19 * Copyright (C) 2012 Atmel Corporation. All rights reserved.
20 *
21 * \page License
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions are met:
25 *
26 * 1. Redistributions of source code must retain the above copyright notice,
27 * this list of conditions and the following disclaimer.
28 *
29 * 2. Redistributions in binary form must reproduce the above copyright notice,
30 * this list of conditions and the following disclaimer in the documentation
31 * and/or other materials provided with the distribution.
32 *
33 * 3. The name of Atmel may not be used to endorse or promote products derived
34 * from this software without specific prior written permission.
35 *
36 * 4. This software may only be redistributed and used in connection with an
37 * Atmel AVR product.
38 *
39 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
40 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
41 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
42 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
43 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
45 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
46 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
48 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
49 * DAMAGE.
50 */
51
52 #include "avr_compiler.h"
53 #include "classb_sram.h"
54 #include "error_handler.h"
55
56 //!\ingroup classb_sram
57 //@{
58
59 #if defined(__ICCAVR__)
60 #pragma location=INTERNAL_SRAM_START
61 __no_init uint8_t classb_buffer[CLASSB_SEC_SIZE+CLASSB_OVERLAP_SIZE];
62 #elif defined(__GNUC__)
63 static uint8_t classb_buffer[CLASSB_SEC_SIZE+CLASSB_OVERLAP_SIZE] __attribute__ ((section (".classb_sram_buffer")));
64 #elif defined(__DOXYGEN__)
65 //! @cond IAR
66
67 //! \internal
68
69 //! @endcond
70
71 //! \brief Buffer of SRAM memory that is used to store the information from
72 //! sections that are tested.
73 //!
74 //! The buffer is placed in the beginning of SRAM (see \c INTERNAL_SRAM_START). The size
75 //! in bytes should be \c INTERNAL_SRAM_SIZE/CLASSB_NSECS+CLASSB_OVERLAP_SIZE. As an example, let us
76 //! suppose the device has \c INTERNAL_SRAM_SIZE=4096 Bytes of SRAM, \ref CLASSB_NSECS = 8 and
77 //! \ref CLASSB_OVERLAP=25. Given that the number of sections is a divisor of \c INTERNAL_SRAM_SIZE,
78 //! there would be in principle exactly 8 sections, each with a size of 512 Bytes. For 25%
79 //! overlap we need to extend the first section (the buffer) by 128 Bytes, and the second
80 //! section is shortened accordingly. Therefore, we would have to reserve 512+128=640 Bytes for
81 //! the buffer.
82 //!
83 //! The implementation depends on the compiler:
84 //! For IAR it is easy because variables can be placed in a specific address using the a location
85 //! pragma directive.
86 //! For GCC the following steps should be followed:
87 //! - Firstly, it is necessary to define in <em> AVR/GNU C linker > Memory settings </em> a section
88 //! that starts at \c INTERNAL_SRAM_START, for example:
89 //! <tt> .classb_sram_buffer=0x2000</tt>.
90 //! - Secondly, the buffer variable has to be placed in that memory section. This can be done
91 //! appending this to the definition of the variable:
92 //! <tt> __attribute__ ((section(".classb_sram_buffer")))</tt>.
93 //! - Thirdly, the <tt>.data</tt> section has to be moved so that there is no overlap:
94 //! the start should be <tt>INTERNAL_SRAM_START + buffer_size</tt>. For example
95 //! 640=0x280 and then we would set
96 //! <tt> .data=0x2280</tt>.
97 uint8_t classb_buffer[CLASSB_SEC_SIZE+CLASSB_OVERLAP_SIZE];
98 #endif
99
100
101 /*! \brief This function executes March X test for a memory section at a time.
102 *
103 * The test behaves as follows for a general section:
104 * - The size of the section is \c CLASSB_SEC_SIZE.
105 * - In order to have overlap between sections, the total number of bytes to be tested
106 * is <tt>CLASSB_SEC_SIZE + CLASSB_OVERLAP_SIZE</tt>.
107 * - The algorithm is set to start \c CLASSB_OVERLAP_SIZE bytes before the start of the current section,
108 * thus overlapping \c CLASSB_OVERLAP_SIZE bytes with the previous section.
109
110 * Special cases of memory sections are:
111 * - The first section to test is the buffer segment, which starts at \c INTERNAL_SRAM_START
112 * and ends at <tt>CLASSB_SEC_SIZE + CLASSB_OVERLAP_SIZE</tt>. In this case there is no previous segment, so no
113 * overlap is necessary. The total number of bytes tested is then the size of the buffer.
114 * - The second section to test is the first "data" memory section (i.e. the one after
115 * the buffer). The size of this section is <tt> CLASSB_SEC_SIZE - CLASSB_OVERLAP_SIZE</tt> (i.e. the size of
116 * this section was reduced in \c CLASSB_OVERLAP_SIZE bytes in order to expand the buffer by the
117 * same size). The test starts \c CLASSB_OVERLAP_SIZE bytes before the beginning of the section, and
118 * the total number of bytes tested is then \c CLASSB_SEC_SIZE.
119 * - The "remainder" segment, if any. This section has a size of \c CLASSB_SEC_REM, so the total
120 * number of bytes will be <tt>CLASSB_SEC_REM + CLASSB_OVERLAP_SIZE</tt>.
121 */
122 void classb_sram_test()
123 {
124
125 // This variable keeps track of the section to test.
126 static uint8_t current_section = 0;
127
128 switch (current_section)
129 {
130 case 0:
131 // Test the buffer, which starts at INTERNAL_SRAM_START and ends at CLASSB_SEC_SIZE + CLASSB_OVERLAP_SIZE. There is no overlap with previous segments.
132 classb_marchX((uint8_t *)INTERNAL_SRAM_START, classb_buffer, CLASSB_SEC_SIZE + CLASSB_OVERLAP_SIZE);
133 break;
134 case 1:
135 // Test the first section, which size shrunk from below by the buffer when there is overlap.
136 // In order to overlap with the buffer, we simply start at INTERNAL_SRAM_START + CLASSB_SEC_SIZE.
137 classb_marchX((uint8_t *)INTERNAL_SRAM_START + CLASSB_SEC_SIZE, classb_buffer, CLASSB_SEC_SIZE);
138 break;
139 case CLASSB_NSECS:
140 // We test the last section of size SRAM_SIZE % CLASSB_NSECS
141 // Limit size to the amount of memory remaining when dividing SRAM_SIZE with CLASSB_NSECS.
142 classb_marchX((uint8_t *)INTERNAL_SRAM_START + CLASSB_NSECS * CLASSB_SEC_SIZE - CLASSB_OVERLAP_SIZE, classb_buffer, CLASSB_SEC_REM + CLASSB_OVERLAP_SIZE);
143 break;
144 default:
145 // Sections in the middle. We start CLASSB_OVERLAP_SIZE before the segment and test CLASSB_SEC_SIZE+CLASSB_OVERLAP_SIZE bytes
146 classb_marchX((uint8_t *)INTERNAL_SRAM_START + current_section * CLASSB_SEC_SIZE - CLASSB_OVERLAP_SIZE, classb_buffer, CLASSB_SEC_SIZE + CLASSB_OVERLAP_SIZE);
147 break;
148 }
149
150 // Increase section count for next iteration, or reset if all memory is tested.
151 current_section++;
152 if (current_section > CLASSB_NSEC_TOTAL-1)
153 current_section = 0;
154
155 }
156
157
158 /*! \internal\brief This function executes the the March X algorithm in a section of
159 * SRAM memory.
160 *
161 * The following steps are followed:
162 * -# The content of the area to be tested is copied to the buffer. This does not
163 * apply when the buffer is tested.
164 * -# The March X algorithm is applied to the section to test for coupling faults.
165 * -# Memory content is copied back from the buffer. This does not apply when the
166 * buffer is tested.
167 *
168 * This function requires that all variables are placed in registers by the compiler.
169 * This is achieved by using the \c register specifier (probably not necessary if the right
170 * level of optimization is chosen).
171 *
172 * If there should be an error in SRAM a local variable (implemented in a register)
173 * would be flagged. This would lead to the error handler \ref CLASSB_ERROR_HANDLER_SRAM()
174 * being called.
175 *
176 * \param p_sram Pointer to first byte in memory area to be tested
177 * \param p_buffer Pointer to first byte in the buffer
178 * \param size Size of area to be tested in bytes.
179 */
180 void classb_marchX(register volatile uint8_t * p_sram, register volatile uint8_t * p_buffer, register uint16_t size)
181 {
182 register uint16_t i = 0;
183 register uint8_t error = 0;
184
185 // Save content of the section: copy to buffer unless we test the buffer
186 if (p_buffer != p_sram)
187 for (uint16_t i = 0; i < size; i++)
188 *(p_buffer+i) = *(p_sram+i);
189
190
191 // Test phase 1: write 0 to all bit locations.
192 for (i = 0; i < size; i++)
193 *(p_sram+i) = 0x00;
194
195
196 // Test phase 2: read 0, write FF.
197 for (i = 0; i < size; i++)
198 {
199 if (*(p_sram+i) != 0x00)
200 error = 1;
201 else
202 *(p_sram+i) = 0xFF;
203 }
204
205
206 // Test phase 3: read FF, write 0 (reverse order).
207 for(i = size ; i>0; i--)
208 {
209 if (*(p_sram+i-1) != 0xFF)
210 error = 1;
211 else
212 *(p_sram+i-1) = 0x00;
213 }
214
215
216 // Test phase 4: read 0.
217 for (i = 0; i < size; i++)
218 if (*(p_sram+i) != 0x00)
219 error = 1;
220
221
222 #ifdef CLASSB_SRAM_INTRAWORD_TEST
223 // Intra-word march test.
224 for (i = 0; i < size; i++) {
225 *(p_sram+i) = 0x55;
226 if (*(p_sram+i) != 0x55)
227 error = 1;
228
229 *(p_sram+i) = 0xAA;
230 if (*(p_sram+i) != 0xAA)
231 error = 1;
232
233 *(p_sram+i) = 0x33;
234 if (*(p_sram+i) != 0x33)
235 error = 1;
236
237 *(p_sram+i) = 0xCC;
238 if (*(p_sram+i) != 0xCC)
239 error = 1;
240
241 *(p_sram+i) = 0xF0;
242 if (*(p_sram+i) != 0xF0)
243 error = 1;
244 *(p_sram+i) = 0x0F;
245 if (*(p_sram+i) != 0x0F)
246 error = 1;
247 }
248
249 #endif
250
251 // Restore content of the section: copy from buffer, unless buffer is tested
252 if (p_buffer != p_sram)
253 for (i = 0; i < size; i++)
254 *(p_sram+i) = *(p_buffer+i);
255
256 // Call the error handler if there was an error.
257 if (error)
258 CLASSB_ERROR_HANDLER_SRAM();
259
260 }
261
262 //@}