Re: [RFC PATCH v1 3/5] hw/arm/stm32f103: instantiate and map GPIO ports
Philippe Mathieu-Daudé <[email protected]> Mon, 27 Jul 2026 09:48:52 +0200
| Newsgroups | org.nongnu.qemu-rust,org.nongnu.qemu-arm,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
On 26/7/26 16:51, Jack Wang wrote: > Create the seven GPIO ports GPIOA..GPIOG by name via qdev_new() and map > them at their APB2 base addresses, removing the corresponding > unimplemented-device stubs so the real devices back that range. > > The Rust GPIO type is only present in a Rust-enabled build, so the ports > are created behind an object_class_by_name() check; with --disable-rust > the type is absent and the range is simply left unbacked. > > Signed-off-by: Jack Wang <[email protected]> > --- > hw/arm/Kconfig | 1 + > hw/arm/stm32f103_board.c | 2 +- > hw/arm/stm32f103_soc.c | 54 +++++++++++++++++++++++++++++----- > include/hw/arm/stm32f103_soc.h | 9 ++++++ > 4 files changed, 58 insertions(+), 8 deletions(-) > +/* GPIO addresses: GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG */ > +static const uint32_t gpio_addr[] = { static const uint32_t gpio_addr[STM32F103_NUM_GPIOS] = { > + 0x40010800, 0x40010C00, 0x40011000, 0x40011400, 0x40011800, 0x40011C00, > + 0x40012000 > +}; > + > static const int usart_irq[] = { 37, 38, 39, 52, 53 }; > static const int spi_irq[] = { 35, 36, 51 }; > #define ADC_IRQ 18 > @@ -199,6 +209,37 @@ static void stm32f103_soc_realize(DeviceState *dev_soc, Error **errp) > qdev_get_gpio_in(DEVICE(&s->adc_irqs), i)); > } > > + /* > + * GPIO ports GPIOA..GPIOG. > + * > + * These are implemented by the Rust device "stm32f1xx-gpio-rust", created > + * by name with qdev_new() and mapped at its APB2 base address. On STM32F1 > + * a GPIO port has no dedicated NVIC line of its own: pin-change interrupts > + * are delivered through the EXTI controller (not yet modelled), so no > + * sysbus_connect_irq() to the NVIC is done here. > + * > + * The GPIO port is only provided by the Rust build; when QEMU is built > + * with --disable-rust the type is not registered, so skip creating the > + * ports and leave the address range unbacked. > + */ > + if (object_class_by_name(TYPE_STM32F1XX_GPIO_RUST)) { > + for (i = 0; i < STM32F103_NUM_GPIOS; i++) { > + g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i); > + s->gpio[i] = qdev_new(TYPE_STM32F1XX_GPIO_RUST); > + /* > + * Give each port a stable QOM name ("/machine/soc/gpioa"..) so > + * tests and the monitor can reach it and its gpio-out lines by > + * path. > + */ > + object_property_add_child(OBJECT(s), name, OBJECT(s->gpio[i])); > + busdev = SYS_BUS_DEVICE(s->gpio[i]); > + if (!sysbus_realize_and_unref(busdev, errp)) { > + return; > + } > + sysbus_mmio_map(busdev, 0, gpio_addr[i]); > + } > + } Please keep the UNIMP regions: else { create_unimplemented_device("GPIOA", 0x40010800, 0x400); ... create_unimplemented_device("GPIOG", 0x40012000, 0x400); } > + > /* > * Unimplemented peripherals -- STM32F103 devices that do not yet > * have QEMU models. > @@ -231,13 +272,12 @@ static void stm32f103_soc_realize(DeviceState *dev_soc, Error **errp) > /* APB2 peripherals */ > create_unimplemented_device("AFIO", 0x40010000, 0x400); > create_unimplemented_device("EXTI", 0x40010400, 0x400); > - create_unimplemented_device("GPIOA", 0x40010800, 0x400); > - create_unimplemented_device("GPIOB", 0x40010C00, 0x400); > - create_unimplemented_device("GPIOC", 0x40011000, 0x400); > - create_unimplemented_device("GPIOD", 0x40011400, 0x400); > - create_unimplemented_device("GPIOE", 0x40011800, 0x400); > - create_unimplemented_device("GPIOF", 0x40011C00, 0x400); > - create_unimplemented_device("GPIOG", 0x40012000, 0x400); > + /* > + * GPIOA..GPIOG (0x40010800..0x40012000) are real devices mapped in the > + * GPIO loop above when the Rust build is used, so they must NOT be > + * registered as unimplemented devices here: overlapping MemoryRegions at > + * the same address abort at runtime. > + */ > create_unimplemented_device("timer[1]", 0x40012C00, 0x400); > create_unimplemented_device("timer[8]", 0x40013400, 0x400); > create_unimplemented_device("timer[9]", 0x40014C00, 0x400); > diff --git a/include/hw/arm/stm32f103_soc.h b/include/hw/arm/stm32f103_soc.h > index 260f3695c0..8d78360ce0 100644 > --- a/include/hw/arm/stm32f103_soc.h > +++ b/include/hw/arm/stm32f103_soc.h > @@ -40,6 +40,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(STM32F103State, STM32F103_SOC) > #define STM32F103_NUM_USARTS 5 > #define STM32F103_NUM_SPIS 3 > #define STM32F103_NUM_ADCS 3 > +#define STM32F103_NUM_GPIOS 7