Instantiate the Rust STM32F1xx GPIO device for GPIOA through GPIOE on the 
STM32F100RBT6 used by the stm32vldiscovery machine.

Use a fixed-size address table tied to STM32F100_NUM_GPIOS. When the Rust type 
is unavailable, retain the existing unimplemented-device regions so a 
--disable-rust build does not leave the GPIO windows unbacked.

Do not connect the GPIO ports directly to the NVIC because external interrupts 
are routed through the currently unmodelled EXTI.

Signed-off-by: Jack Wang <[email protected]>
---
 hw/arm/Kconfig                 |  1 +
 hw/arm/stm32f100_soc.c         | 35 ++++++++++++++++++++++++++++++-----
 include/hw/arm/stm32f100_soc.h |  2 ++
 3 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 260d2f0751..6333c0ca09 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -373,6 +373,7 @@ config STM32F100_SOC
     select ARM_V7M
     select STM32F2XX_USART
     select STM32F2XX_SPI
+    select STM32F1XX_GPIO if HAVE_RUST
 
 config STM32F205_SOC
     bool
diff --git a/hw/arm/stm32f100_soc.c b/hw/arm/stm32f100_soc.c
index 2358368dba..769f8e5ff0 100644
--- a/hw/arm/stm32f100_soc.c
+++ b/hw/arm/stm32f100_soc.c
@@ -26,6 +26,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 #include "hw/arm/boot.h"
 #include "system/address-spaces.h"
 #include "hw/arm/stm32f100_soc.h"
@@ -36,10 +37,20 @@
 
 /* stm32f100_soc implementation is derived from stm32f205_soc */
 
+#define TYPE_STM32F1XX_GPIO_RUST "stm32f1xx-gpio-rust"
+
 static const uint32_t usart_addr[STM_NUM_USARTS] = { 0x40013800, 0x40004400,
     0x40004800 };
 static const uint32_t spi_addr[STM_NUM_SPIS] = { 0x40013000, 0x40003800 };
 
+static const uint32_t gpio_addr[STM32F100_NUM_GPIOS] = {
+    0x40010800, 0x40010c00, 0x40011000, 0x40011400, 0x40011800,
+};
+
+static const char *const gpio_name[STM32F100_NUM_GPIOS] = {
+    "GPIOA", "GPIOB", "GPIOC", "GPIOD", "GPIOE",
+};
+
 static const int usart_irq[STM_NUM_USARTS] = {37, 38, 39};
 static const int spi_irq[STM_NUM_SPIS] = {35, 36};
 
@@ -149,6 +160,25 @@ static void stm32f100_soc_realize(DeviceState *dev_soc, 
Error **errp)
         sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
     }
 
+    /* GPIO interrupts are routed through the currently unmodelled EXTI. */
+    if (object_class_by_name(TYPE_STM32F1XX_GPIO_RUST)) {
+        for (i = 0; i < STM32F100_NUM_GPIOS; i++) {
+            g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i);
+
+            s->gpio[i] = qdev_new(TYPE_STM32F1XX_GPIO_RUST);
+            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]);
+        }
+    } else {
+        for (i = 0; i < STM32F100_NUM_GPIOS; i++) {
+            create_unimplemented_device(gpio_name[i], gpio_addr[i], 0x400);
+        }
+    }
+
     create_unimplemented_device("timer[2]",  0x40000000, 0x400);
     create_unimplemented_device("timer[3]",  0x40000400, 0x400);
     create_unimplemented_device("timer[4]",  0x40000800, 0x400);
@@ -165,11 +195,6 @@ static void stm32f100_soc_realize(DeviceState *dev_soc, 
Error **errp)
     create_unimplemented_device("CEC",       0x40007800, 0x400);
     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("ADC1",      0x40012400, 0x400);
     create_unimplemented_device("timer[1]",  0x40012C00, 0x400);
     create_unimplemented_device("timer[15]", 0x40014000, 0x400);
diff --git a/include/hw/arm/stm32f100_soc.h b/include/hw/arm/stm32f100_soc.h
index 4c113d6774..401794242d 100644
--- a/include/hw/arm/stm32f100_soc.h
+++ b/include/hw/arm/stm32f100_soc.h
@@ -36,6 +36,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(STM32F100State, STM32F100_SOC)
 
 #define STM_NUM_USARTS 3
 #define STM_NUM_SPIS 2
+#define STM32F100_NUM_GPIOS 5
 
 #define FLASH_BASE_ADDRESS 0x08000000
 #define FLASH_SIZE (128 * 1024)
@@ -49,6 +50,7 @@ struct STM32F100State {
 
     STM32F2XXUsartState usart[STM_NUM_USARTS];
     STM32F2XXSPIState spi[STM_NUM_SPIS];
+    DeviceState *gpio[STM32F100_NUM_GPIOS];
 
     MemoryRegion sram;
     MemoryRegion flash;

-- 
2.53.0


Reply via email to