core+elf: Add fields for the MCU voltages
[simavr] / include / avr_mcu_section.h
index c7a6a2e..bce65e8 100644 (file)
@@ -23,7 +23,7 @@
 #define __AVR_MCU_SECTION_H__
 
 /*
- * This structure is used to pass "parameters" to the programmer or the simulator,
+ * This header is used to pass "parameters" to the programmer or the simulator,
  * it tags the ELF file with a section that contains parameters about the physical
  * AVR this was compiled for, including the speed, model, and signature bytes.
  *
 
 #include <stdint.h>
 
-struct avr_mcu_t
-{
-       uint32_t  f_cpu;                        // avr is little endian
-       uint32_t  reserved;
-       uint8_t mid[4];                         // signature bytes
-       uint8_t fuse[4];                        // optional
-       char name[16];
+enum {
+       AVR_MMCU_TAG = 0,
+       AVR_MMCU_TAG_NAME,
+       AVR_MMCU_TAG_FREQUENCY,
+       AVR_MMCU_TAG_VCC,
+       AVR_MMCU_TAG_AVCC,
+       AVR_MMCU_TAG_AREF,
+       AVR_MMCU_TAG_LFUSE,
+       AVR_MMCU_TAG_HFUSE,
+       AVR_MMCU_TAG_EFUSE,
+       AVR_MMCU_TAG_SIGNATURE,
+       AVR_MMCU_TAG_SIMAVR_COMMAND,
+       AVR_MMCU_TAG_VCD_FILENAME,
+       AVR_MMCU_TAG_VCD_PERIOD,        
+       AVR_MMCU_TAG_VCD_TRACE,
+};
+
+enum {
+       SIMAVR_CMD_NONE = 0,
+       SIMAVR_CMD_VCD_START_TRACE,
+       SIMAVR_CMD_VCD_STOP_TRACE,
+       SIMAVR_CMD_UART_LOOPBACK,
+};
+
+#if __AVR__
+
+#define _MMCU_ __attribute__((section(".mmcu")))
+struct avr_mmcu_long_t {
+       uint8_t tag;
+       uint8_t len;
+       uint32_t val; 
 } __attribute__((__packed__));
 
-#define AVR_MCU(_speed, _name) \
-const struct avr_mcu_t _mmcu __attribute__((section(".mmcu"))) = {\
-       .f_cpu = _speed, \
-       .mid = {SIGNATURE_0, SIGNATURE_1, SIGNATURE_2}, \
-       .name = _name,\
+struct avr_mmcu_string_t {
+       uint8_t tag;
+       uint8_t len;
+       char string[]; 
+} __attribute__((__packed__));
+
+struct avr_mmcu_addr_t {
+       uint8_t tag;
+       uint8_t len;
+       void * what;
+} __attribute__((__packed__));
+
+struct avr_mmcu_vcd_trace_t {
+       uint8_t tag;
+       uint8_t len;
+       uint8_t mask;
+       void * what;
+       char name[]; 
+} __attribute__((__packed__));
+
+#define AVR_MCU_STRING(_tag, _str) \
+const struct avr_mmcu_string_t _##_tag _MMCU_ = {\
+       .tag = _tag,\
+       .len = sizeof(_str),\
+       .string = _str,\
+}
+
+#define AVR_MCU_LONG(_tag, _val) \
+const struct avr_mmcu_long_t _##_tag _MMCU_ = {\
+       .tag = _tag,\
+       .len = sizeof(uint32_t),\
+       .val = _val,\
 }
 
+#define AVR_MCU_BYTE(_tag, _val) \
+const uint8_t _##_tag _MMCU_ = { _tag, 1, _val }
+
+#define AVR_MCU_VCD_SYMBOL(_name) \
+       .tag = AVR_MMCU_TAG_VCD_TRACE, \
+       .len = sizeof(struct avr_mmcu_vcd_trace_t) - 2 + sizeof(_name),\
+       .name = _name
+
+// specified the name and wanted period (usec) for a VCD file
+// thid is not mandatory, a default one will be created if
+// symbols are declared themselves
+#define AVR_MCU_VCD_FILE(_name, _period) \
+       AVR_MCU_STRING(AVR_MMCU_TAG_VCD_FILENAME, _name);\
+       AVR_MCU_LONG(AVR_MMCU_TAG_VCD_PERIOD, _period)
+
+// It is possible to send "commands" to simavr from the
+// firmware itself. For this to work you need to specify
+// an IO register that is to be used for a write-only
+// bridge. A favourite is one of the usual "GPIO register"
+// that most (all ?) AVR have
+#define AVR_MCU_SIMAVR_COMMAND(_register) \
+       const struct avr_mmcu_addr_t _simavr_command_register _MMCU_ = {\
+               .tag = AVR_MMCU_TAG_SIMAVR_COMMAND,\
+               .len = sizeof(void *),\
+               .what = (void*)_register, \
+       }
+
+/*
+ * This the has to be used if you want to add other tags to the .mmcu section
+ * the _mmcu symbol is used as an anchor to make sure it stays linked in.
+ */
+#define AVR_MCU(_speed, _name) \
+       const uint8_t _mmcu[2] _MMCU_ = { AVR_MMCU_TAG, 0 }; \
+       AVR_MCU_STRING(AVR_MMCU_TAG_NAME, _name);\
+       AVR_MCU_LONG(AVR_MMCU_TAG_FREQUENCY, _speed)
+
+#define AVR_MCU_VOLTAGES(_vcc, _avcc, _aref) \
+       AVR_MCU_LONG(AVR_MMCU_TAG_VCC, (_vcc));\
+       AVR_MCU_LONG(AVR_MMCU_TAG_AVCC, (_avcc));\
+       AVR_MCU_LONG(AVR_MMCU_TAG_AREF, (_aref));
+
+#endif /* __AVR__ */
+
+
 #endif