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  */
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)
259 
260 }
261 
262 //@}