core: Added a new ELF tag with AVR->simavr command path
[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 enum {
44         AVR_MMCU_TAG = 0,
45         AVR_MMCU_TAG_NAME,
46         AVR_MMCU_TAG_FREQUENCY,
47         AVR_MMCU_TAG_LFUSE,
48         AVR_MMCU_TAG_HFUSE,
49         AVR_MMCU_TAG_EFUSE,
50         AVR_MMCU_TAG_SIGNATURE,
51         AVR_MMCU_TAG_SIMAVR_COMMAND,
52         AVR_MMCU_TAG_VCD_FILENAME,
53         AVR_MMCU_TAG_VCD_PERIOD,        
54         AVR_MMCU_TAG_VCD_TRACE,
55 };
56
57 enum {
58         SIMAVR_CMD_NONE = 0,
59         SIMAVR_CMD_VCD_START_TRACE,
60         SIMAVR_CMD_VCD_STOP_TRACE,
61         SIMAVR_CMD_UART_LOOPBACK,
62 };
63
64 #if __AVR__
65
66 #define _MMCU_ __attribute__((section(".mmcu")))
67 struct avr_mmcu_long_t {
68         uint8_t tag;
69         uint8_t len;
70         uint32_t val; 
71 } __attribute__((__packed__));
72
73 struct avr_mmcu_string_t {
74         uint8_t tag;
75         uint8_t len;
76         char string[]; 
77 } __attribute__((__packed__));
78
79 struct avr_mmcu_addr_t {
80         uint8_t tag;
81         uint8_t len;
82         void * what;
83 } __attribute__((__packed__));
84
85 struct avr_mmcu_vcd_trace_t {
86         uint8_t tag;
87         uint8_t len;
88         uint8_t mask;
89         void * what;
90         char name[]; 
91 } __attribute__((__packed__));
92
93 #define AVR_MCU_STRING(_tag, _str) \
94 const struct avr_mmcu_string_t _##_tag _MMCU_ = {\
95         .tag = _tag,\
96         .len = sizeof(_str),\
97         .string = _str,\
98 }
99
100 #define AVR_MCU_LONG(_tag, _val) \
101 const struct avr_mmcu_long_t _##_tag _MMCU_ = {\
102         .tag = _tag,\
103         .len = sizeof(uint32_t),\
104         .val = _val,\
105 }
106
107 #define AVR_MCU_BYTE(_tag, _val) \
108 const uint8_t _##_tag _MMCU_ = { _tag, 1, _val }
109
110 #define AVR_MCU_VCD_SYMBOL(_name) \
111         .tag = AVR_MMCU_TAG_VCD_TRACE, \
112         .len = sizeof(struct avr_mmcu_vcd_trace_t) - 2 + sizeof(_name),\
113         .name = _name
114
115 // specified the name and wanted period (usec) for a VCD file
116 // thid is not mandatory, a default one will be created if
117 // symbols are declared themselves
118 #define AVR_MCU_VCD_FILE(_name, _period) \
119         AVR_MCU_STRING(AVR_MMCU_TAG_VCD_FILENAME, _name);\
120         AVR_MCU_LONG(AVR_MMCU_TAG_VCD_PERIOD, _period)
121
122 // It is possible to send "commands" to simavr from the
123 // firmware itself. For this to work you need to specify
124 // an IO register that is to be used for a write-only
125 // bridge. A favourite is one of the usual "GPIO register"
126 // that most (all ?) AVR have
127 #define AVR_MCU_SIMAVR_COMMAND(_register) \
128         const struct avr_mmcu_addr_t _simavr_command_register _MMCU_ = {\
129                 .tag = AVR_MMCU_TAG_SIMAVR_COMMAND,\
130                 .len = sizeof(void *),\
131                 .what = (void*)_register, \
132         }
133
134 /*
135  * This the has to be used if you want to add other tags to the .mmcu section
136  * the _mmcu symbol is used as an anchor to make sure it stays linked in.
137  */
138 #define AVR_MCU(_speed, _name) \
139         const uint8_t _mmcu[2] _MMCU_ = { AVR_MMCU_TAG, 0 }; \
140         AVR_MCU_STRING(AVR_MMCU_TAG_NAME, _name);\
141         AVR_MCU_LONG(AVR_MMCU_TAG_FREQUENCY, _speed)
142
143 #endif /* __AVR__ */
144
145
146 #endif