From: rmsyn <rmsync...@gmail.com>

Adds support for ATmega16u4 and ATmega32u4 MCU definitions.

Defines interrupts, memory layout, and machine types for generic
ATmega16u4 and ATmega32u4 MCUs.

Signed-off-by: rmsyn <rmsync...@gmail.com>
---
 hw/avr/arduino.c |  36 ++++++++++++++
 hw/avr/atmega.c  | 122 +++++++++++++++++++++++++++++++++++++++++++++++
 hw/avr/atmega.h  |   2 +
 3 files changed, 160 insertions(+)

diff --git a/hw/avr/arduino.c b/hw/avr/arduino.c
index 48ef478346..be04e412e6 100644
--- a/hw/avr/arduino.c
+++ b/hw/avr/arduino.c
@@ -129,6 +129,34 @@ static void arduino_mega2560_class_init(ObjectClass *oc, 
void *data)
     amc->xtal_hz    = 16 * 1000 * 1000; /* CSTCE16M0V53-R0 */
 };
 
+static void arduino_mega16u4_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+    ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc);
+
+    /*
+     * 
https://ww1.microchip.com/downloads/en/devicedoc/atmel-7766-8-bit-avr-atmega16u4-32u4_datasheet.pdf
+     */
+    mc->desc        = "Arduino Mega 16u4 (ATmega16u4)";
+    mc->alias       = "mega16u4";
+    amc->mcu_type   = TYPE_ATMEGA16U4_MCU;
+    amc->xtal_hz    = 16 * 1000 * 1000; /* CSTCE16M0V53-R0 */
+};
+
+static void arduino_mega32u4_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+    ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc);
+
+    /*
+     * 
https://ww1.microchip.com/downloads/en/devicedoc/atmel-7766-8-bit-avr-atmega16u4-32u4_datasheet.pdf
+     */
+    mc->desc        = "Arduino Mega 32u4 (ATmega32u4)";
+    mc->alias       = "mega32u4";
+    amc->mcu_type   = TYPE_ATMEGA32U4_MCU;
+    amc->xtal_hz    = 16 * 1000 * 1000; /* CSTCE16M0V53-R0 */
+};
+
 static const TypeInfo arduino_machine_types[] = {
     {
         .name          = MACHINE_TYPE_NAME("arduino-duemilanove"),
@@ -146,6 +174,14 @@ static const TypeInfo arduino_machine_types[] = {
         .name          = MACHINE_TYPE_NAME("arduino-mega-2560-v3"),
         .parent        = TYPE_ARDUINO_MACHINE,
         .class_init    = arduino_mega2560_class_init,
+    }, {
+        .name          = MACHINE_TYPE_NAME("arduino-mega-16u4"),
+        .parent        = TYPE_ARDUINO_MACHINE,
+        .class_init    = arduino_mega16u4_class_init,
+    }, {
+        .name          = MACHINE_TYPE_NAME("arduino-mega-32u4"),
+        .parent        = TYPE_ARDUINO_MACHINE,
+        .class_init    = arduino_mega32u4_class_init,
     }, {
         .name           = TYPE_ARDUINO_MACHINE,
         .parent         = TYPE_MACHINE,
diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
index a34803e642..292ad9a447 100644
--- a/hw/avr/atmega.c
+++ b/hw/avr/atmega.c
@@ -27,6 +27,17 @@ enum AtmegaPeripheral {
     GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK, GPIOL,
     USART0, USART1, USART2, USART3,
     TIMER0, TIMER1, TIMER2, TIMER3, TIMER4, TIMER5,
+    RESET,
+    INT0, INT1, INT2, INT3, INT4, INT5, INT6,
+    PCINT0,
+    USB_GEN, USB_EP,
+    WDT,
+    SPI,
+    ANALOG_COMP,
+    ADC,
+    EE_READY,
+    TWI,
+    SPM_READY,
     PERIFMAX
 };
 
@@ -98,6 +109,30 @@ static const peripheral_cfg dev168_328[PERIFMAX] = {
     [GPIOC]         = {  0x26 },
     [GPIOB]         = {  0x23 },
     [GPIOA]         = {  0x20 },
+}, dev16u4_32u4[PERIFMAX] = {
+    [POWER1]        = {  0x65 },
+    [POWER0]        = {  0x64 },
+    [TIMER4]        = {  0x4c, POWER1, 4, 0x72, 0x39, true }, 
+    [SPM_READY]     = {  0x4a },
+    [TWI]           = {  0x48 },
+    [TIMER3]        = {  0x3e, POWER1, 3, 0x71, 0x38, true },
+    [EE_READY]      = {  0x3c },
+    [ADC]           = {  0x3a },
+    [ANALOG_COMP]   = {  0x38 },
+    [USART1]        = {  0x32, POWER1, 0 },
+    [SPI]           = {  0x30 },
+    [TIMER0]        = {  0x2a, POWER0, 5, 0x6e, 0x35, true },
+    [TIMER1]        = {  0x20, POWER0, 3, 0x6f, 0x36, true },
+    [WDT]           = {  0x18 },
+    [USB_GEN]       = {  0x14 },
+    [USB_EP]        = {  0x16 },
+    [PCINT0]        = {  0x12 },
+    [INT6]          = {  0x0e },
+    [INT3]          = {  0x08 },
+    [INT2]          = {  0x06 },
+    [INT1]          = {  0x04 },
+    [INT0]          = {  0x02 },
+    [RESET]         = {  0x00 },
 };
 
 enum AtmegaIrq {
@@ -117,6 +152,17 @@ enum AtmegaIrq {
         TIMER4_COMPC_IRQ, TIMER4_OVF_IRQ,
     TIMER5_CAPT_IRQ, TIMER5_COMPA_IRQ, TIMER5_COMPB_IRQ,
         TIMER5_COMPC_IRQ, TIMER5_OVF_IRQ,
+    RESET_IRQ,
+    INT0_IRQ, INT1_IRQ, INT2_IRQ, INT3_IRQ, INT4_IRQ, INT5_IRQ, INT6_IRQ,
+    PCINT0_IRQ,
+    USB_GEN_IRQ, USB_EP_IRQ,
+    WDT_IRQ,
+    SPI_IRQ,
+    ANALOG_COMP_IRQ,
+    ADC_IRQ,
+    EE_READY_IRQ,
+    TWI_IRQ,
+    SPM_READY_IRQ,
     IRQ_COUNT
 };
 
@@ -184,6 +230,44 @@ static const uint8_t irq168_328[IRQ_COUNT] = {
     [USART3_RXC_IRQ]        = 55,
     [USART3_DRE_IRQ]        = 56,
     [USART3_TXC_IRQ]        = 57,
+}, irq16u4_32u4[IRQ_COUNT] = {
+    [RESET_IRQ]             =  1,
+    [INT0_IRQ]              =  2,
+    [INT1_IRQ]              =  3,
+    [INT2_IRQ]              =  4,
+    [INT3_IRQ]              =  5,
+    [INT6_IRQ]              =  8,
+    [PCINT0_IRQ]            = 10,
+    [USB_GEN_IRQ]           = 11,
+    [USB_EP_IRQ]            = 12,
+    [WDT_IRQ]               = 13,
+    [TIMER1_CAPT_IRQ]       = 17,
+    [TIMER1_COMPA_IRQ]      = 18,
+    [TIMER1_COMPB_IRQ]      = 19,
+    [TIMER1_COMPC_IRQ]      = 20,
+    [TIMER1_OVF_IRQ]        = 21,
+    [TIMER0_COMPA_IRQ]      = 22,
+    [TIMER0_COMPB_IRQ]      = 23,
+    [TIMER0_OVF_IRQ]        = 24,
+    [SPI_IRQ]               = 25,
+    [USART0_RXC_IRQ]        = 26,
+    [USART0_DRE_IRQ]        = 27,
+    [USART0_TXC_IRQ]        = 28,
+    [ANALOG_COMP]           = 29,
+    [ADC_IRQ]               = 30,
+    [EE_READY_IRQ]          = 31,
+    [TIMER3_CAPT_IRQ]       = 32,
+    [TIMER3_COMPA_IRQ]      = 33,
+    [TIMER3_COMPB_IRQ]      = 34,
+    [TIMER3_COMPC_IRQ]      = 35,
+    [TIMER3_OVF_IRQ]        = 36,
+    [TWI_IRQ]               = 37,
+    [SPM_READY_IRQ]         = 38,
+    [TIMER4_COMPA_IRQ]      = 39,
+    [TIMER4_COMPB_IRQ]      = 40,
+    [TIMER4_COMPC_IRQ]      = 41,
+    [TIMER4_OVF_IRQ]        = 42,
+    /*[TIMER4_FPF_IRQ]        = 43,*/
 };
 
 static void connect_peripheral_irq(const AtmegaMcuClass *k,
@@ -427,6 +511,36 @@ static void atmega2560_class_init(ObjectClass *oc, void 
*data)
     amc->dev = dev1280_2560;
 };
 
+static void atmega16u4_class_init(ObjectClass *oc, void *data)
+{
+    AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc);
+
+    amc->cpu_type = AVR_CPU_TYPE_NAME("avr5");
+    amc->flash_size = 16 * KiB;
+    amc->eeprom_size = 512;
+    amc->sram_size = KiB + 256;
+    amc->io_size = 64;
+    amc->gpio_count = 32;
+    amc->adc_count = 12;
+    amc->irq = irq16u4_32u4;
+    amc->dev = dev16u4_32u4;
+};
+
+static void atmega32u4_class_init(ObjectClass *oc, void *data)
+{
+    AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc);
+
+    amc->cpu_type = AVR_CPU_TYPE_NAME("avr5");
+    amc->flash_size = 32 * KiB;
+    amc->eeprom_size = KiB;
+    amc->sram_size = 2 * KiB + 512;
+    amc->io_size = 64;
+    amc->gpio_count = 32;
+    amc->adc_count = 12;
+    amc->irq = irq16u4_32u4;
+    amc->dev = dev16u4_32u4;
+};
+
 static const TypeInfo atmega_mcu_types[] = {
     {
         .name           = TYPE_ATMEGA168_MCU,
@@ -444,6 +558,14 @@ static const TypeInfo atmega_mcu_types[] = {
         .name           = TYPE_ATMEGA2560_MCU,
         .parent         = TYPE_ATMEGA_MCU,
         .class_init     = atmega2560_class_init,
+    }, {
+        .name           = TYPE_ATMEGA16U4_MCU,
+        .parent         = TYPE_ATMEGA_MCU,
+        .class_init     = atmega16u4_class_init,
+    }, {
+        .name           = TYPE_ATMEGA32U4_MCU,
+        .parent         = TYPE_ATMEGA_MCU,
+        .class_init     = atmega32u4_class_init,
     }, {
         .name           = TYPE_ATMEGA_MCU,
         .parent         = TYPE_SYS_BUS_DEVICE,
diff --git a/hw/avr/atmega.h b/hw/avr/atmega.h
index a99ee15c7e..37d36b9b69 100644
--- a/hw/avr/atmega.h
+++ b/hw/avr/atmega.h
@@ -22,6 +22,8 @@
 #define TYPE_ATMEGA328_MCU  "ATmega328"
 #define TYPE_ATMEGA1280_MCU "ATmega1280"
 #define TYPE_ATMEGA2560_MCU "ATmega2560"
+#define TYPE_ATMEGA16U4_MCU "ATmega16U4"
+#define TYPE_ATMEGA32U4_MCU "ATmega32U4"
 
 typedef struct AtmegaMcuState AtmegaMcuState;
 DECLARE_INSTANCE_CHECKER(AtmegaMcuState, ATMEGA_MCU,
-- 
2.38.4

Reply via email to