interrupts: Do not clear raised bit twice
[simavr] / include / avr_mcu_section.h
1 /*
2         avr_mcu_section.h
3
4         Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #ifndef __AVR_MCU_SECTION_H__
23 #define __AVR_MCU_SECTION_H__
24
25 /*
26  * This header is used to pass "parameters" to the programmer or the simulator,
27  * it tags the ELF file with a section that contains parameters about the physical
28  * AVR this was compiled for, including the speed, model, and signature bytes.
29  *
30  * A programmer software can read this and verify fuses values for example, and a
31  * simulator can instanciate the proper "model" of AVR, the speed and so on without
32  * command line parameters.
33  *
34  * Exemple of use:
35  *
36  * #include "avr_mcu_section.h"
37  * AVR_MCU(F_CPU, "atmega88");
38  *
39  */
40
41 #include <stdint.h>
42
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46
47 enum {
48         AVR_MMCU_TAG = 0,
49         AVR_MMCU_TAG_NAME,
50         AVR_MMCU_TAG_FREQUENCY,
51         AVR_MMCU_TAG_VCC,
52         AVR_MMCU_TAG_AVCC,
53         AVR_MMCU_TAG_AREF,
54         AVR_MMCU_TAG_LFUSE,
55         AVR_MMCU_TAG_HFUSE,
56         AVR_MMCU_TAG_EFUSE,
57         AVR_MMCU_TAG_SIGNATURE,
58         AVR_MMCU_TAG_SIMAVR_COMMAND,
59         AVR_MMCU_TAG_SIMAVR_CONSOLE,
60         AVR_MMCU_TAG_VCD_FILENAME,
61         AVR_MMCU_TAG_VCD_PERIOD,        
62         AVR_MMCU_TAG_VCD_TRACE,
63 };
64
65 enum {
66         SIMAVR_CMD_NONE = 0,
67         SIMAVR_CMD_VCD_START_TRACE,
68         SIMAVR_CMD_VCD_STOP_TRACE,
69         SIMAVR_CMD_UART_LOOPBACK,
70 };
71
72 #if __AVR__
73
74 #define _MMCU_ __attribute__((section(".mmcu")))
75 struct avr_mmcu_long_t {
76         uint8_t tag;
77         uint8_t len;
78         uint32_t val; 
79 } __attribute__((__packed__));
80
81 struct avr_mmcu_string_t {
82         uint8_t tag;
83         uint8_t len;
84         char string[]; 
85 } __attribute__((__packed__));
86
87 struct avr_mmcu_addr_t {
88         uint8_t tag;
89         uint8_t len;
90         void * what;
91 } __attribute__((__packed__));
92
93 struct avr_mmcu_vcd_trace_t {
94         uint8_t tag;
95         uint8_t len;
96         uint8_t mask;
97         void * what;
98         char name[]; 
99 } __attribute__((__packed__));
100
101 #define AVR_MCU_STRING(_tag, _str) \
102         const struct avr_mmcu_string_t _##_tag _MMCU_ = {\
103                 .tag = _tag,\
104                 .len = sizeof(_str),\
105                 .string = _str,\
106         }
107
108 #define AVR_MCU_LONG(_tag, _val) \
109         const struct avr_mmcu_long_t _##_tag _MMCU_ = {\
110                 .tag = _tag,\
111                 .len = sizeof(uint32_t),\
112                 .val = _val,\
113         }
114
115 #define AVR_MCU_BYTE(_tag, _val) \
116         const uint8_t _##_tag _MMCU_ = { _tag, 1, _val }
117
118 /*!
119  * This Macro allows you to specify traces for the VCD file output
120  * engine. This specifies a default header, and let you fill in the
121  * relevant bits.
122  * Example:
123  *      const struct avr_mmcu_vcd_trace_t _mytrace[]  _MMCU_ = {
124  *              { AVR_MCU_VCD_SYMBOL("UDR0"), .what = (void*)&UDR0, },
125  *              { AVR_MCU_VCD_SYMBOL("UDRE0"), .mask = (1 << UDRE0), .what = (void*)&UCSR0A, },
126  *      };
127  * This structure will automatically tell simavr to add a VCD trace
128  * for the UART register, and the UDRE0 bit, so you can trace exactly
129  * the timing of the changed using gtkwave.
130  */
131 #define AVR_MCU_VCD_SYMBOL(_name) \
132         .tag = AVR_MMCU_TAG_VCD_TRACE, \
133         .len = sizeof(struct avr_mmcu_vcd_trace_t) - 2 + sizeof(_name),\
134         .name = _name
135
136 /*!
137  * Specifies the name and wanted period (in usec) for a VCD file
138  * this is not mandatory for the VCD output to work, if this tag
139  * is not used, a VCD file will still be created with default values
140  */
141 #define AVR_MCU_VCD_FILE(_name, _period) \
142         AVR_MCU_STRING(AVR_MMCU_TAG_VCD_FILENAME, _name);\
143         AVR_MCU_LONG(AVR_MMCU_TAG_VCD_PERIOD, _period)
144
145 /*!
146  * It is possible to send "commands" to simavr from the
147  * firmware itself. For this to work you need to specify
148  * an IO register that is to be used for a write-only
149  * bridge. A favourite is one of the usual "GPIO register"
150  * that most (all ?) AVR have.
151  * See definition of SIMAVR_CMD_* to see what commands can
152  * be used from your firmware.
153  */
154 #define AVR_MCU_SIMAVR_COMMAND(_register) \
155         const struct avr_mmcu_addr_t _simavr_command_register _MMCU_ = {\
156                 .tag = AVR_MMCU_TAG_SIMAVR_COMMAND,\
157                 .len = sizeof(void *),\
158                 .what = (void*)_register, \
159         }
160 /*!
161  * Similar to AVR_MCU_SIMAVR_COMMAND, The CONSOLE allows the AVR code
162  * to declare a register (typically a GPIO register, but any unused
163  * register can work...) that will allow printing on the host's console
164  * without using a UART to do debug.
165  */
166 #define AVR_MCU_SIMAVR_CONSOLE(_register) \
167         const struct avr_mmcu_addr_t _simavr_command_register _MMCU_ = {\
168                 .tag = AVR_MMCU_TAG_SIMAVR_CONSOLE,\
169                 .len = sizeof(void *),\
170                 .what = (void*)_register, \
171         }
172
173 /*!
174  * This tag allows you to specify the voltages used by your board
175  * It is optional in most cases, but you will need it if you use
176  * ADC module's IRQs. Not specifying it in this case might lead
177  * to a divide-by-zero crash.
178  * The units are Volts*1000 (millivolts)
179  */
180 #define AVR_MCU_VOLTAGES(_vcc, _avcc, _aref) \
181         AVR_MCU_LONG(AVR_MMCU_TAG_VCC, (_vcc));\
182         AVR_MCU_LONG(AVR_MMCU_TAG_AVCC, (_avcc));\
183         AVR_MCU_LONG(AVR_MMCU_TAG_AREF, (_aref));
184
185 /*!
186  * This the has to be used if you want to add other tags to the .mmcu section
187  * the _mmcu symbol is used as an anchor to make sure it stays linked in.
188  */
189 #define AVR_MCU(_speed, _name) \
190         const uint8_t _mmcu[2] _MMCU_ = { AVR_MMCU_TAG, 0 }; \
191         AVR_MCU_STRING(AVR_MMCU_TAG_NAME, _name);\
192         AVR_MCU_LONG(AVR_MMCU_TAG_FREQUENCY, _speed)
193
194 #endif /* __AVR__ */
195
196 #ifdef __cplusplus
197 };
198 #endif
199
200 #endif