Reviewed-by: Michael Rolnik <mrol...@gmail.com> On Sun, May 14, 2023 at 12:54 AM ~rmsyn <rm...@git.sr.ht> wrote:
> 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 > -- Best Regards, Michael Rolnik