1 /* 2 * QEMU Arduino boards 3 * 4 * Copyright (c) 2019-2020 Philippe Mathieu-Daudé 5 * 6 * This work is licensed under the terms of the GNU GPLv2 or later. 7 * See the COPYING file in the top-level directory. 8 * SPDX-License-Identifier: GPL-2.0-or-later 9 */ 10 11 /* TODO: Implement the use of EXTRAM */ 12 13 #include "qemu/osdep.h" 14 #include "qapi/error.h" 15 #include "hw/boards.h" 16 #include "atmega.h" 17 #include "boot.h" 18 19 typedef struct ArduinoMachineState { 20 /*< private >*/ 21 MachineState parent_obj; 22 /*< public >*/ 23 AtmegaMcuState mcu; 24 } ArduinoMachineState; 25 26 typedef struct ArduinoMachineClass { 27 /*< private >*/ 28 MachineClass parent_class; 29 /*< public >*/ 30 const char *mcu_type; 31 uint64_t xtal_hz; 32 } ArduinoMachineClass; 33 34 #define TYPE_ARDUINO_MACHINE \ 35 MACHINE_TYPE_NAME("arduino") 36 #define ARDUINO_MACHINE(obj) \ 37 OBJECT_CHECK(ArduinoMachineState, (obj), TYPE_ARDUINO_MACHINE) 38 #define ARDUINO_MACHINE_CLASS(klass) \ 39 OBJECT_CLASS_CHECK(ArduinoMachineClass, (klass), TYPE_ARDUINO_MACHINE) 40 #define ARDUINO_MACHINE_GET_CLASS(obj) \ 41 OBJECT_GET_CLASS(ArduinoMachineClass, (obj), TYPE_ARDUINO_MACHINE) 42 43 static void arduino_machine_init(MachineState *machine) 44 { 45 ArduinoMachineClass *amc = ARDUINO_MACHINE_GET_CLASS(machine); 46 ArduinoMachineState *ams = ARDUINO_MACHINE(machine); 47 48 object_initialize_child(OBJECT(machine), "mcu", &ams->mcu, amc->mcu_type); 49 object_property_set_uint(OBJECT(&ams->mcu), "xtal-frequency-hz", 50 amc->xtal_hz, &error_abort); 51 sysbus_realize(SYS_BUS_DEVICE(&ams->mcu), &error_abort); 52 53 if (machine->firmware) { 54 if (!avr_load_firmware(&ams->mcu.cpu, machine, 55 &ams->mcu.flash, machine->firmware)) { 56 exit(1); 57 } 58 } 59 } 60 61 static void arduino_machine_class_init(ObjectClass *oc, void *data) 62 { 63 MachineClass *mc = MACHINE_CLASS(oc); 64 65 mc->init = arduino_machine_init; 66 mc->default_cpus = 1; 67 mc->min_cpus = mc->default_cpus; 68 mc->max_cpus = mc->default_cpus; 69 mc->no_floppy = 1; 70 mc->no_cdrom = 1; 71 mc->no_parallel = 1; 72 } 73 74 static void arduino_duemilanove_class_init(ObjectClass *oc, void *data) 75 { 76 MachineClass *mc = MACHINE_CLASS(oc); 77 ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc); 78 79 /* https://www.arduino.cc/en/Main/ArduinoBoardDuemilanove */ 80 mc->desc = "Arduino Duemilanove (ATmega168)", 81 mc->alias = "2009"; 82 amc->mcu_type = TYPE_ATMEGA168_MCU; 83 amc->xtal_hz = 16 * 1000 * 1000; 84 }; 85 86 static void arduino_uno_class_init(ObjectClass *oc, void *data) 87 { 88 MachineClass *mc = MACHINE_CLASS(oc); 89 ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc); 90 91 /* https://store.arduino.cc/arduino-uno-rev3 */ 92 mc->desc = "Arduino UNO (ATmega328P)"; 93 mc->alias = "uno"; 94 amc->mcu_type = TYPE_ATMEGA328_MCU; 95 amc->xtal_hz = 16 * 1000 * 1000; 96 }; 97 98 static void arduino_mega_class_init(ObjectClass *oc, void *data) 99 { 100 MachineClass *mc = MACHINE_CLASS(oc); 101 ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc); 102 103 /* https://www.arduino.cc/en/Main/ArduinoBoardMega */ 104 mc->desc = "Arduino Mega (ATmega1280)"; 105 mc->alias = "mega"; 106 amc->mcu_type = TYPE_ATMEGA1280_MCU; 107 amc->xtal_hz = 16 * 1000 * 1000; 108 }; 109 110 static void arduino_mega2560_class_init(ObjectClass *oc, void *data) 111 { 112 MachineClass *mc = MACHINE_CLASS(oc); 113 ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc); 114 115 /* https://store.arduino.cc/arduino-mega-2560-rev3 */ 116 mc->desc = "Arduino Mega 2560 (ATmega2560)"; 117 mc->alias = "mega2560"; 118 amc->mcu_type = TYPE_ATMEGA2560_MCU; 119 amc->xtal_hz = 16 * 1000 * 1000; /* CSTCE16M0V53-R0 */ 120 }; 121 122 static const TypeInfo arduino_machine_types[] = { 123 { 124 .name = MACHINE_TYPE_NAME("arduino-duemilanove"), 125 .parent = TYPE_ARDUINO_MACHINE, 126 .class_init = arduino_duemilanove_class_init, 127 }, { 128 .name = MACHINE_TYPE_NAME("arduino-uno"), 129 .parent = TYPE_ARDUINO_MACHINE, 130 .class_init = arduino_uno_class_init, 131 }, { 132 .name = MACHINE_TYPE_NAME("arduino-mega"), 133 .parent = TYPE_ARDUINO_MACHINE, 134 .class_init = arduino_mega_class_init, 135 }, { 136 .name = MACHINE_TYPE_NAME("arduino-mega-2560-v3"), 137 .parent = TYPE_ARDUINO_MACHINE, 138 .class_init = arduino_mega2560_class_init, 139 }, { 140 .name = TYPE_ARDUINO_MACHINE, 141 .parent = TYPE_MACHINE, 142 .instance_size = sizeof(ArduinoMachineState), 143 .class_size = sizeof(ArduinoMachineClass), 144 .class_init = arduino_machine_class_init, 145 .abstract = true, 146 } 147 }; 148 149 DEFINE_TYPES(arduino_machine_types) 150