Xmega IEC60730 Class B Library  1.0
 All Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
classb_cpu_gcc.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 This file contains the function definition for a CPU register test
6  * that is compatible with AVR GCC.
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  *
20  * Copyright (C) 2012 Atmel Corporation. All rights reserved.
21  *
22  * \page License
23  *
24  * Redistribution and use in source and binary forms, with or without
25  * modification, are permitted provided that the following conditions are met:
26  *
27  * 1. Redistributions of source code must retain the above copyright notice,
28  * this list of conditions and the following disclaimer.
29  *
30  * 2. Redistributions in binary form must reproduce the above copyright notice,
31  * this list of conditions and the following disclaimer in the documentation
32  * and/or other materials provided with the distribution.
33  *
34  * 3. The name of Atmel may not be used to endorse or promote products derived
35  * from this software without specific prior written permission.
36  *
37  * 4. This software may only be redistributed and used in connection with an
38  * Atmel AVR product.
39  *
40  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
42  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
43  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
44  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
46  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
47  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
50  * DAMAGE.
51  */
52 
53 #include "avr_compiler.h"
54 #include "classb_cpu.h"
55 
56 //! \cond GCC
57 
58 /*!
59  * \brief CPU register self-diagnostic routine for AVR GCC.
60  *
61  * This function tests the CPU registers, preserving those registers specified
62  * in the AVR GCC compiler documentation. Note that if there should be a fault
63  * in a register that needs preservation, its value would not be restored.
64  *
65  * Registers are tested in this order:
66  * -# Critical registers
67  * -# Return value register: R24
68  * -# stack pointer: SPL/SPH
69  * -# register %file: R31 -- R30
70  * -# Non-critical registers
71  * -# register %file: R29 -- R25, R23 -- R0
72  * -# extended addressing registers: RAMPD/X/Y/Z, EIND
73  * -# status register: SREG (except interrupt flag)
74  *
75  * \retval false No register fault detected.
76  * \retval true Register fault detected.
77  *
78  * \note Interrupts must be disabled during this test.
79  */
81 {
82 
83  // The error flag used locally
84  register bool error asm("r24") = true;
85 
86  // Test R24 first because it is the return register!
87  CLASSB_RegSet_R_HI(R24,0x55);
88  CLASSB_RegTest_R_HI(R24,0xAA,CLASSB_ERROR_CRIT);
89  CLASSB_RegTest_R_HI(R24,0x55,CLASSB_ERROR_CRIT);
90 
91  // Then test R31 and R30 because they are used in the rest of the tests.
92  CLASSB_RegSet_R_HI(R31,0x55);
93  CLASSB_RegTest_R_HI(R31,0xAA,CLASSB_ERROR_CRIT);
94  CLASSB_RegTest_R_HI(R31,0x55,CLASSB_ERROR_CRIT);
95 
96  CLASSB_RegSet_R_HI(R30,0x55);
97  CLASSB_RegTest_R_HI(R30,0xAA,CLASSB_ERROR_CRIT);
98  CLASSB_RegTest_R_HI(R30,0x55,CLASSB_ERROR_CRIT);
99 
100  // SPH
101  CLASSB_RegStore_IO(0x3D);
102  CLASSB_RegSet_IO(0x3D,0x55);
103  CLASSB_RegTest_IO(0x3D,0xAA,CLASSB_ERROR_CRIT);
104  CLASSB_RegTest_IO(0x3D,0x55,CLASSB_ERROR_CRIT);
105  CLASSB_RegRestore_IO(0x3D);
106 
107  // SPL
108  CLASSB_RegStore_IO(0x3E);
109  CLASSB_RegSet_IO(0x3E,0x55);
110  CLASSB_RegTest_IO(0x3E,0xAA,CLASSB_ERROR_CRIT);
111  CLASSB_RegTest_IO(0x3E,0x55,CLASSB_ERROR_CRIT);
112  CLASSB_RegRestore_IO(0x3E);
113 
114  // Test R29-R28 non-destructively.
115  CLASSB_RegStore_R(R29);
116  CLASSB_RegSet_R_HI(R29,0x55);
117  CLASSB_RegTest_R_HI(R29,0xAA,CLASSB_ERROR_NON_CRIT);
118  CLASSB_RegTest_R_HI(R29,0x55,CLASSB_ERROR_NON_CRIT);
119  CLASSB_RegRestore_R(R29);
120 
121  CLASSB_RegStore_R(R28);
122  CLASSB_RegSet_R_HI(R28,0x55);
123  CLASSB_RegTest_R_HI(R28,0xAA,CLASSB_ERROR_NON_CRIT);
124  CLASSB_RegTest_R_HI(R28,0x55,CLASSB_ERROR_NON_CRIT);
125  CLASSB_RegRestore_R(R28);
126 
127  // Test R27-R25, R23-R18 destructively.
128  CLASSB_RegSet_R_HI(R27,0x55);
129  CLASSB_RegTest_R_HI(R27,0xAA,CLASSB_ERROR_NON_CRIT);
130  CLASSB_RegTest_R_HI(R27,0x55,CLASSB_ERROR_NON_CRIT);
131 
132  CLASSB_RegSet_R_HI(R26,0x55);
133  CLASSB_RegTest_R_HI(R26,0xAA,CLASSB_ERROR_NON_CRIT);
134  CLASSB_RegTest_R_HI(R26,0x55,CLASSB_ERROR_NON_CRIT);
135 
136  CLASSB_RegSet_R_HI(R25,0x55);
137  CLASSB_RegTest_R_HI(R25,0xAA,CLASSB_ERROR_NON_CRIT);
138  CLASSB_RegTest_R_HI(R25,0x55,CLASSB_ERROR_NON_CRIT);
139 
140  CLASSB_RegSet_R_HI(R23,0x55);
141  CLASSB_RegTest_R_HI(R23,0xAA,CLASSB_ERROR_NON_CRIT);
142  CLASSB_RegTest_R_HI(R23,0x55,CLASSB_ERROR_NON_CRIT);
143 
144  CLASSB_RegSet_R_HI(R22,0x55);
145  CLASSB_RegTest_R_HI(R22,0xAA,CLASSB_ERROR_NON_CRIT);
146  CLASSB_RegTest_R_HI(R22,0x55,CLASSB_ERROR_NON_CRIT);
147 
148  CLASSB_RegSet_R_HI(R21,0x55);
149  CLASSB_RegTest_R_HI(R21,0xAA,CLASSB_ERROR_NON_CRIT);
150  CLASSB_RegTest_R_HI(R21,0x55,CLASSB_ERROR_NON_CRIT);
151 
152  CLASSB_RegSet_R_HI(R20,0x55);
153  CLASSB_RegTest_R_HI(R20,0xAA,CLASSB_ERROR_NON_CRIT);
154  CLASSB_RegTest_R_HI(R20,0x55,CLASSB_ERROR_NON_CRIT);
155 
156  CLASSB_RegSet_R_HI(R19,0x55);
157  CLASSB_RegTest_R_HI(R19,0xAA,CLASSB_ERROR_NON_CRIT);
158  CLASSB_RegTest_R_HI(R19,0x55,CLASSB_ERROR_NON_CRIT);
159 
160  CLASSB_RegSet_R_HI(R18,0x55);
161  CLASSB_RegTest_R_HI(R18,0xAA,CLASSB_ERROR_NON_CRIT);
162  CLASSB_RegTest_R_HI(R18,0x55,CLASSB_ERROR_NON_CRIT);
163 
164  // Test R17-R0 non-destructively.
165  CLASSB_RegStore_R(R17);
166  CLASSB_RegSet_R_HI(R17,0x55);
167  CLASSB_RegTest_R_HI(R17,0xAA,CLASSB_ERROR_NON_CRIT);
168  CLASSB_RegTest_R_HI(R17,0x55,CLASSB_ERROR_NON_CRIT);
169  CLASSB_RegRestore_R(R17);
170 
171  CLASSB_RegStore_R(R16);
172  CLASSB_RegSet_R_HI(R16,0x55);
173  CLASSB_RegTest_R_HI(R16,0xAA,CLASSB_ERROR_NON_CRIT);
174  CLASSB_RegTest_R_HI(R16,0x55,CLASSB_ERROR_NON_CRIT);
175  CLASSB_RegRestore_R(R16);
176 
177  CLASSB_RegStore_R(R15);
178  CLASSB_RegSet_R_LO(R15,0x55);
179  CLASSB_RegTest_R_LO(R15,0xAA,CLASSB_ERROR_NON_CRIT);
180  CLASSB_RegTest_R_LO(R15,0x55,CLASSB_ERROR_NON_CRIT);
181  CLASSB_RegRestore_R(R15);
182 
183  CLASSB_RegStore_R(R14);
184  CLASSB_RegSet_R_LO(R14,0x55);
185  CLASSB_RegTest_R_LO(R14,0xAA,CLASSB_ERROR_NON_CRIT);
186  CLASSB_RegTest_R_LO(R14,0x55,CLASSB_ERROR_NON_CRIT);
187  CLASSB_RegRestore_R(R14);
188 
189  CLASSB_RegStore_R(R13);
190  CLASSB_RegSet_R_LO(R13,0x55);
191  CLASSB_RegTest_R_LO(R13,0xAA,CLASSB_ERROR_NON_CRIT);
192  CLASSB_RegTest_R_LO(R13,0x55,CLASSB_ERROR_NON_CRIT);
193  CLASSB_RegRestore_R(R13);
194 
195  CLASSB_RegStore_R(R12);
196  CLASSB_RegSet_R_LO(R12,0x55);
197  CLASSB_RegTest_R_LO(R12,0xAA,CLASSB_ERROR_NON_CRIT);
198  CLASSB_RegTest_R_LO(R12,0x55,CLASSB_ERROR_NON_CRIT);
199  CLASSB_RegRestore_R(R12);
200 
201  CLASSB_RegStore_R(R11);
202  CLASSB_RegSet_R_LO(R11,0x55);
203  CLASSB_RegTest_R_LO(R11,0xAA,CLASSB_ERROR_NON_CRIT);
204  CLASSB_RegTest_R_LO(R11,0x55,CLASSB_ERROR_NON_CRIT);
205  CLASSB_RegRestore_R(R11);
206 
207  CLASSB_RegStore_R(R10);
208  CLASSB_RegSet_R_LO(R10,0x55);
209  CLASSB_RegTest_R_LO(R10,0xAA,CLASSB_ERROR_NON_CRIT);
210  CLASSB_RegTest_R_LO(R10,0x55,CLASSB_ERROR_NON_CRIT);
211  CLASSB_RegRestore_R(R10);
212 
213  CLASSB_RegStore_R(R9);
214  CLASSB_RegSet_R_LO(R9,0x55);
215  CLASSB_RegTest_R_LO(R9,0xAA,CLASSB_ERROR_NON_CRIT);
216  CLASSB_RegTest_R_LO(R9,0x55,CLASSB_ERROR_NON_CRIT);
217  CLASSB_RegRestore_R(R9);
218 
219  CLASSB_RegStore_R(R8);
220  CLASSB_RegSet_R_LO(R8,0x55);
221  CLASSB_RegTest_R_LO(R8,0xAA,CLASSB_ERROR_NON_CRIT);
222  CLASSB_RegTest_R_LO(R8,0x55,CLASSB_ERROR_NON_CRIT);
223  CLASSB_RegRestore_R(R8);
224 
225  CLASSB_RegStore_R(R7);
226  CLASSB_RegSet_R_LO(R7,0x55);
227  CLASSB_RegTest_R_LO(R7,0xAA,CLASSB_ERROR_NON_CRIT);
228  CLASSB_RegTest_R_LO(R7,0x55,CLASSB_ERROR_NON_CRIT);
229  CLASSB_RegRestore_R(R7);
230 
231  CLASSB_RegStore_R(R6);
232  CLASSB_RegSet_R_LO(R6,0x55);
233  CLASSB_RegTest_R_LO(R6,0xAA,CLASSB_ERROR_NON_CRIT);
234  CLASSB_RegTest_R_LO(R6,0x55,CLASSB_ERROR_NON_CRIT);
235  CLASSB_RegRestore_R(R6);
236 
237  CLASSB_RegStore_R(R5);
238  CLASSB_RegSet_R_LO(R5,0x55);
239  CLASSB_RegTest_R_LO(R5,0xAA,CLASSB_ERROR_NON_CRIT);
240  CLASSB_RegTest_R_LO(R5,0x55,CLASSB_ERROR_NON_CRIT);
241  CLASSB_RegRestore_R(R5);
242 
243  CLASSB_RegStore_R(R4);
244  CLASSB_RegSet_R_LO(R4,0x55);
245  CLASSB_RegTest_R_LO(R4,0xAA,CLASSB_ERROR_NON_CRIT);
246  CLASSB_RegTest_R_LO(R4,0x55,CLASSB_ERROR_NON_CRIT);
247  CLASSB_RegRestore_R(R4);
248 
249  CLASSB_RegStore_R(R3);
250  CLASSB_RegSet_R_LO(R3,0x55);
251  CLASSB_RegTest_R_LO(R3,0xAA,CLASSB_ERROR_NON_CRIT);
252  CLASSB_RegTest_R_LO(R3,0x55,CLASSB_ERROR_NON_CRIT);
253  CLASSB_RegRestore_R(R3);
254 
255  CLASSB_RegStore_R(R2);
256  CLASSB_RegSet_R_LO(R2,0x55);
257  CLASSB_RegTest_R_LO(R2,0xAA,CLASSB_ERROR_NON_CRIT);
258  CLASSB_RegTest_R_LO(R2,0x55,CLASSB_ERROR_NON_CRIT);
259  CLASSB_RegRestore_R(R2);
260 
261  CLASSB_RegStore_R(R1);
262  CLASSB_RegSet_R_LO(R1,0x55);
263  CLASSB_RegTest_R_LO(R1,0xAA,CLASSB_ERROR_NON_CRIT);
264  CLASSB_RegTest_R_LO(R1,0x55,CLASSB_ERROR_NON_CRIT);
265  CLASSB_RegRestore_R(R1);
266 
267  CLASSB_RegStore_R(R0);
268  CLASSB_RegSet_R_LO(R0,0x55);
269  CLASSB_RegTest_R_LO(R0,0xAA,CLASSB_ERROR_NON_CRIT);
270  CLASSB_RegTest_R_LO(R0,0x55,CLASSB_ERROR_NON_CRIT);
271  CLASSB_RegRestore_R(R0);
272 
273  // Test IO registers non-destructively.
274  // RAMPD
275  #ifdef CLASSB_HAS_BIGMEM
276  CLASSB_RegStore_IO(0x38);
277  CLASSB_RegSet_IO(0x38,0x55);
278  CLASSB_RegTest_IO(0x38,0xAA,CLASSB_ERROR_NON_CRIT);
279  CLASSB_RegTest_IO(0x38,0x55,CLASSB_ERROR_NON_CRIT);
280  CLASSB_RegRestore_IO(0x38);
281  #endif
282 
283  // RAMPX
284  #ifdef CLASSB_HAS_BIGMEM
285  CLASSB_RegStore_IO(0x39);
286  CLASSB_RegSet_IO(0x39,0x55);
287  CLASSB_RegTest_IO(0x39,0xAA,CLASSB_ERROR_NON_CRIT);
288  CLASSB_RegTest_IO(0x39,0x55,CLASSB_ERROR_NON_CRIT);
289  CLASSB_RegRestore_IO(0x39);
290  #endif
291 
292  // RAMPY
293  #ifdef CLASSB_HAS_BIGMEM
294  CLASSB_RegStore_IO(0x3A);
295  CLASSB_RegSet_IO(0x3A,0x55);
296  CLASSB_RegTest_IO(0x3A,0xAA,CLASSB_ERROR_NON_CRIT);
297  CLASSB_RegTest_IO(0x3A,0x55,CLASSB_ERROR_NON_CRIT);
298  CLASSB_RegRestore_IO(0x3A);
299  #endif
300 
301  // RAMPZ
302  #if defined(CLASSB_HAS_BIGMEM) || defined(CLASSB_HAS_BIGFLASH)
303  CLASSB_RegStore_IO(0x3B);
304  CLASSB_RegSet_IO(0x3B,0x55);
305  CLASSB_RegTest_IO(0x3B,0xAA,CLASSB_ERROR_NON_CRIT);
306  CLASSB_RegTest_IO(0x3B,0x55,CLASSB_ERROR_NON_CRIT);
307  CLASSB_RegRestore_IO(0x3B);
308  #endif
309 
310  // EIND
311  #ifdef CLASSB_HAS_BIGFLASH
312  CLASSB_RegStore_IO(0x3C);
313  CLASSB_RegSet_IO(0x3C,0x55);
314  CLASSB_RegTest_IO(0x3C,0xAA,CLASSB_ERROR_NON_CRIT);
315  CLASSB_RegTest_IO(0x3C,0x55,CLASSB_ERROR_NON_CRIT);
316  CLASSB_RegRestore_IO(0x3C);
317  #endif
318 
319  // SREG (Not interrupt flag!)
320  CLASSB_RegStore_IO(0x3F);
321  CLASSB_RegSet_IO(0x3F,0x55);
322  CLASSB_RegTest_IO(0x3F,0x2A,CLASSB_ERROR_NON_CRIT);
323  CLASSB_RegTest_IO(0x3F,0x55,CLASSB_ERROR_NON_CRIT);
324  CLASSB_RegRestore_IO(0x3F);
325 
326  ASSEMBLY(
327  // Continue here if test was successful: Clear return register and return.
328  "clr %0 \n\t"
329  "jmp END \n\t"
330  "CLASSB_LABEL1: jmp CLASSB_LABEL1 \n\t"
331  // If a fault was detected, set return register.
332  "CLASSB_LABEL2: ldi %0, 0x01 \n\t"
333  "END: \n\t"
334  :"=r" (error) // Output value
335  : // No inputs
336  );
337 
338  // Handle global error. This will not be reached if there was a fault in
339  // a) critical registers and CLASSB_ERROR_CRIT was defined as CLASSB_LABEL1.
340  // b) non-critical registers and CLASSB_ERROR_NON_CRIT was defined as CLASSB_LABEL1.
341  if (error == true)
342  {
344  }
345 
346  return (error);
347 }
348 
349 //! \endcond