[PATCH] STM32F100: add support for external memory via FSMC
Add support for FSMC on high-density STM32F100 devices and enable mapping of additional memory via the `-m SIZE` command-line option. FSMC Bank1 can address up to 4x64MB of PSRAM memory at 0x6000. RCC is needed to enable peripheral clock for FSMC; this commit implements support for RCC through the MMIO interface. Last, high-density devices support up to 32KB of static SRAM, so adjust SRAM_SIZE accordingly. Signed-off-by: Lucas C. Villa Real --- docs/system/arm/stm32.rst| 12 ++- hw/arm/Kconfig | 1 + hw/arm/stm32f100_soc.c | 102 +++- hw/arm/stm32f1_generic.c | 12 +++ hw/misc/Kconfig | 3 + hw/misc/meson.build | 1 + hw/misc/stm32f1xx_fsmc.c | 155 +++ include/hw/arm/stm32f100_soc.h | 24 - include/hw/misc/stm32f1xx_fsmc.h | 62 + 9 files changed, 368 insertions(+), 4 deletions(-) create mode 100644 hw/misc/stm32f1xx_fsmc.c create mode 100644 include/hw/misc/stm32f1xx_fsmc.h diff --git a/docs/system/arm/stm32.rst b/docs/system/arm/stm32.rst index d0a3b1a7eb..40de58ed04 100644 --- a/docs/system/arm/stm32.rst +++ b/docs/system/arm/stm32.rst @@ -40,6 +40,8 @@ Supported devices * SPI controller * System configuration (SYSCFG) * Timer controller (TIMER) + * Reset and Clock Controller (RCC) + * Flexible static memory controller (FSMC) Missing devices --- @@ -57,7 +59,6 @@ Missing devices * Power supply configuration (PWR) * Random Number Generator (RNG) * Real-Time Clock (RTC) controller - * Reset and Clock Controller (RCC) * Secure Digital Input/Output (SDIO) interface * USB OTG * Watchdog controller (IWDG, WWDG) @@ -78,4 +79,11 @@ to select the device density line. The following values are supported: .. code-block:: bash - $ qemu-system-arm -M stm32f1-generic -global stm32f100-soc.density=medium ... \ No newline at end of file + $ qemu-system-arm -M stm32f1-generic -global stm32f100-soc.density=medium ... + +High-density devices can also enable up to 256 MB of external memory using +the `-m SIZE` option. The memory is mapped at address 0x6000. Example: + +.. code-block:: bash + + $ qemu-system-arm -M stm32f1-generic -m 64M ... \ No newline at end of file diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 822441945c..dd48068108 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -433,6 +433,7 @@ config RASPI config STM32F100_SOC bool select ARM_V7M +select STM32F1XX_FSMC select STM32F2XX_USART select STM32F2XX_SPI diff --git a/hw/arm/stm32f100_soc.c b/hw/arm/stm32f100_soc.c index c157ffd644..a2b863d309 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 "qemu/log.h" #include "hw/arm/boot.h" #include "exec/address-spaces.h" #include "hw/arm/stm32f100_soc.h" @@ -40,9 +41,85 @@ static const uint32_t usart_addr[STM_NUM_USARTS] = { 0x40013800, 0x40004400, 0x40004800 }; static const uint32_t spi_addr[STM_NUM_SPIS] = { 0x40013000, 0x40003800, 0x40003C00 }; +static const uint32_t fsmc_addr = 0xA000; static const int usart_irq[STM_NUM_USARTS] = {37, 38, 39}; static const int spi_irq[STM_NUM_SPIS] = {35, 36, 51}; +static const int fsmc_irq = 48; + +static uint64_t stm32f100_rcc_read(void *h, hwaddr offset, unsigned size) +{ +STM32F100State *s = (STM32F100State *) h; +switch (offset) { +case 0x00: +return s->rcc.cr; +case 0x04: +return s->rcc.cfgr; +case 0x08: +return s->rcc.cir; +case 0x0C: +return s->rcc.apb2rstr; +case 0x10: +return s->rcc.apb1rstr; +case 0x14: +return s->rcc.ahbenr; +case 0x18: +return s->rcc.apb2enr; +case 0x1C: +return s->rcc.apb1enr; +case 0x20: +return s->rcc.bdcr; +case 0x24: +return s->rcc.csr; +case 0x2C: +return s->rcc.cfgr2; +default: +qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, offset); +} +return 0; +} + +static void stm32f100_rcc_write(void *h, hwaddr offset, uint64_t value64, +unsigned size) +{ +STM32F100State *s = (STM32F100State *) h; +uint32_t value = value64 & 0x; + +switch (offset) { +case 0x00: +s->rcc.cr = value; +case 0x04: +s->rcc.cfgr = value; +case 0x08: +s->rcc.cir = value; +case 0x0C: +s->rcc.apb2rstr = value; +case 0x10: +s->rcc.apb1rstr = value; +case 0x14: +s->rcc.ahbenr = value; +case 0x18: +s->rcc.apb2enr = value; +case 0x1C: +s->rcc.apb1enr = value; +case 0x20: +s->rcc.bdcr = value; +case 0x24: +s->rcc.csr = value; +case 0x2C: +s->rcc.cfgr2 = value; +default: +
[PATCH] STM32F100: add support for external memory via FSMC
Add support for FSMC on high-density STM32F100 devices and enable mapping of additional memory via the `-m SIZE` command-line option. FSMC Bank1 can address up to 4x64MB of PSRAM memory at 0x6000. RCC is needed to enable peripheral clock for FSMC; this commit implements support for RCC through the MMIO interface. Last, high-density devices support up to 32KB of static SRAM, so adjust SRAM_SIZE accordingly. Signed-off-by: Lucas C. Villa Real --- docs/system/arm/stm32.rst| 12 ++- hw/arm/Kconfig | 1 + hw/arm/stm32f100_soc.c | 102 +++- hw/arm/stm32f1_generic.c | 12 +++ hw/misc/Kconfig | 3 + hw/misc/meson.build | 1 + hw/misc/stm32f1xx_fsmc.c | 155 +++ include/hw/arm/stm32f100_soc.h | 24 - include/hw/misc/stm32f1xx_fsmc.h | 62 + 9 files changed, 368 insertions(+), 4 deletions(-) create mode 100644 hw/misc/stm32f1xx_fsmc.c create mode 100644 include/hw/misc/stm32f1xx_fsmc.h diff --git a/docs/system/arm/stm32.rst b/docs/system/arm/stm32.rst index d0a3b1a7eb..40de58ed04 100644 --- a/docs/system/arm/stm32.rst +++ b/docs/system/arm/stm32.rst @@ -40,6 +40,8 @@ Supported devices * SPI controller * System configuration (SYSCFG) * Timer controller (TIMER) + * Reset and Clock Controller (RCC) + * Flexible static memory controller (FSMC) Missing devices --- @@ -57,7 +59,6 @@ Missing devices * Power supply configuration (PWR) * Random Number Generator (RNG) * Real-Time Clock (RTC) controller - * Reset and Clock Controller (RCC) * Secure Digital Input/Output (SDIO) interface * USB OTG * Watchdog controller (IWDG, WWDG) @@ -78,4 +79,11 @@ to select the device density line. The following values are supported: .. code-block:: bash - $ qemu-system-arm -M stm32f1-generic -global stm32f100-soc.density=medium ... \ No newline at end of file + $ qemu-system-arm -M stm32f1-generic -global stm32f100-soc.density=medium ... + +High-density devices can also enable up to 256 MB of external memory using +the `-m SIZE` option. The memory is mapped at address 0x6000. Example: + +.. code-block:: bash + + $ qemu-system-arm -M stm32f1-generic -m 64M ... \ No newline at end of file diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 822441945c..dd48068108 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -433,6 +433,7 @@ config RASPI config STM32F100_SOC bool select ARM_V7M +select STM32F1XX_FSMC select STM32F2XX_USART select STM32F2XX_SPI diff --git a/hw/arm/stm32f100_soc.c b/hw/arm/stm32f100_soc.c index c157ffd644..a2b863d309 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 "qemu/log.h" #include "hw/arm/boot.h" #include "exec/address-spaces.h" #include "hw/arm/stm32f100_soc.h" @@ -40,9 +41,85 @@ static const uint32_t usart_addr[STM_NUM_USARTS] = { 0x40013800, 0x40004400, 0x40004800 }; static const uint32_t spi_addr[STM_NUM_SPIS] = { 0x40013000, 0x40003800, 0x40003C00 }; +static const uint32_t fsmc_addr = 0xA000; static const int usart_irq[STM_NUM_USARTS] = {37, 38, 39}; static const int spi_irq[STM_NUM_SPIS] = {35, 36, 51}; +static const int fsmc_irq = 48; + +static uint64_t stm32f100_rcc_read(void *h, hwaddr offset, unsigned size) +{ +STM32F100State *s = (STM32F100State *) h; +switch (offset) { +case 0x00: +return s->rcc.cr; +case 0x04: +return s->rcc.cfgr; +case 0x08: +return s->rcc.cir; +case 0x0C: +return s->rcc.apb2rstr; +case 0x10: +return s->rcc.apb1rstr; +case 0x14: +return s->rcc.ahbenr; +case 0x18: +return s->rcc.apb2enr; +case 0x1C: +return s->rcc.apb1enr; +case 0x20: +return s->rcc.bdcr; +case 0x24: +return s->rcc.csr; +case 0x2C: +return s->rcc.cfgr2; +default: +qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, offset); +} +return 0; +} + +static void stm32f100_rcc_write(void *h, hwaddr offset, uint64_t value64, +unsigned size) +{ +STM32F100State *s = (STM32F100State *) h; +uint32_t value = value64 & 0x; + +switch (offset) { +case 0x00: +s->rcc.cr = value; +case 0x04: +s->rcc.cfgr = value; +case 0x08: +s->rcc.cir = value; +case 0x0C: +s->rcc.apb2rstr = value; +case 0x10: +s->rcc.apb1rstr = value; +case 0x14: +s->rcc.ahbenr = value; +case 0x18: +s->rcc.apb2enr = value; +case 0x1C: +s->rcc.apb1enr = value; +case 0x20: +s->rcc.bdcr = value; +case 0x24: +s->rcc.csr = value; +case 0x2C: +s->rcc.cfgr2 = value; +default: +
[PATCH] STM32F100: support different density lines
This patch adds support for the emulation of different density lines (low, medium, and high). A new class property stm32f100-soc.density= has been introduced to allow users to state the desired configuration. That property is recognized by a new machine, stm32f1-generic. The SOC is configured according to the following: density=low 32 KB FLASH, 2 SPIs density=medium 128 KB FLASH, 2 SPIs density=high 512 KB FLASH, 3 SPIs With this code change we should be able to introduce richer features to STM32F100, such as support for FSMC (so that a machine with more RAM capacity can be properly emulated). FSMC is supported on high density line devices only. Signed-off-by: Lucas C. Villa Real --- configs/devices/arm-softmmu/default.mak | 1 + docs/system/arm/stm32.rst | 14 hw/arm/Kconfig | 6 ++ hw/arm/meson.build | 1 + hw/arm/stm32f100_soc.c | 92 + hw/arm/stm32f1_generic.c| 70 +++ hw/arm/stm32vldiscovery.c | 3 +- include/hw/arm/stm32f100_soc.h | 18 - 8 files changed, 189 insertions(+), 16 deletions(-) create mode 100644 hw/arm/stm32f1_generic.c diff --git a/configs/devices/arm-softmmu/default.mak b/configs/devices/arm-softmmu/default.mak index 980c48a7d9..4f0f2e99c0 100644 --- a/configs/devices/arm-softmmu/default.mak +++ b/configs/devices/arm-softmmu/default.mak @@ -19,6 +19,7 @@ CONFIG_ARM_VIRT=y # CONFIG_NSERIES=n # CONFIG_STELLARIS=n # CONFIG_STM32VLDISCOVERY=n +# CONFIG_STM32F1_GENERIC=n # CONFIG_REALVIEW=n # CONFIG_VERSATILE=n # CONFIG_VEXPRESS=n diff --git a/docs/system/arm/stm32.rst b/docs/system/arm/stm32.rst index d7265b763d..d0a3b1a7eb 100644 --- a/docs/system/arm/stm32.rst +++ b/docs/system/arm/stm32.rst @@ -10,6 +10,12 @@ The STM32F1 series is based on ARM Cortex-M3 core. The following machines are based on this chip : - ``stm32vldiscovery`` STM32VLDISCOVERY board with STM32F100RBT6 microcontroller +- ``stm32f1-generic`` Generic STM32F1 board supporting low, medium and high +density devices. Low-density emulates a 32KB FLASH; +medium-density emulates a 128KB FLASH; high-density +emulates a 512KB FLASH. The density also affects the +number of peripherals exposed by QEMU for the emulated +device. See ``Boot options`` below for more details. The STM32F2 series is based on ARM Cortex-M3 core. The following machines are based on this chip : @@ -65,3 +71,11 @@ firmware. Example: .. code-block:: bash $ qemu-system-arm -M stm32vldiscovery -kernel firmware.bin + +Additionally, the ``stm32f1-generic`` board supports the ``density`` option +to select the device density line. The following values are supported: +``low``, ``medium``, ``high``. Example: + +.. code-block:: bash + + $ qemu-system-arm -M stm32f1-generic -global stm32f100-soc.density=medium ... \ No newline at end of file diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 2159de3ce6..822441945c 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -301,6 +301,12 @@ config STM32VLDISCOVERY depends on TCG && ARM select STM32F100_SOC +config STM32F1_GENERIC +bool +default y +depends on TCG && ARM +select STM32F100_SOC + config STRONGARM bool select PXA2XX diff --git a/hw/arm/meson.build b/hw/arm/meson.build index 870ec67376..f88b5fe3c8 100644 --- a/hw/arm/meson.build +++ b/hw/arm/meson.build @@ -23,6 +23,7 @@ arm_ss.add(when: 'CONFIG_REALVIEW', if_true: files('realview.c')) arm_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa-ref.c')) arm_ss.add(when: 'CONFIG_STELLARIS', if_true: files('stellaris.c')) arm_ss.add(when: 'CONFIG_STM32VLDISCOVERY', if_true: files('stm32vldiscovery.c')) +arm_ss.add(when: 'CONFIG_STM32F1_GENERIC', if_true: files('stm32f1_generic.c')) arm_ss.add(when: 'CONFIG_COLLIE', if_true: files('collie.c')) arm_ss.add(when: 'CONFIG_VERSATILE', if_true: files('versatilepb.c')) arm_ss.add(when: 'CONFIG_VEXPRESS', if_true: files('vexpress.c')) diff --git a/hw/arm/stm32f100_soc.c b/hw/arm/stm32f100_soc.c index f7b344ba9f..c157ffd644 100644 --- a/hw/arm/stm32f100_soc.c +++ b/hw/arm/stm32f100_soc.c @@ -38,10 +38,11 @@ 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 spi_addr[STM_NUM_SPIS] = { 0x40013000, 0x40003800, +0x40003C00 }; static const int usart_irq[STM_NUM_USARTS] = {37, 38, 39}; -static const int spi_irq[STM_NUM_SPIS] = {35, 36}; +static const int spi_irq[STM_NUM_SPIS] = {35, 36, 51}; static void stm32f100_soc_initfn(Object *obj) { @@ -50,17 +51,21 @@ static void stm32f100_soc_initfn(Object *obj) object_initialize_child(obj, "armv7m", >armv7m, TYPE_ARMV7M); +/* + * All
[PATCH] stm32vldiscovery: allow overriding of RAM size
stm32vldiscovery comes with 8KB of SRAM, which may be too low when running some workloads on QEMU. The command line argument "-m mem_size" is not recognized by the current implementation, though, so one cannot easily override the default memory size. This patch fixes that by adding a memory subregion according to the value provided on that command line argument. If absent, the default value of 8KB still applies. Signed-off-by: Lucas Villa Real --- hw/arm/stm32vldiscovery.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/hw/arm/stm32vldiscovery.c b/hw/arm/stm32vldiscovery.c index 67675e952f..7ca3ba029e 100644 --- a/hw/arm/stm32vldiscovery.c +++ b/hw/arm/stm32vldiscovery.c @@ -29,6 +29,7 @@ #include "hw/qdev-properties.h" #include "hw/qdev-clock.h" #include "qemu/error-report.h" +#include "exec/address-spaces.h" #include "hw/arm/stm32f100_soc.h" #include "hw/arm/boot.h" @@ -42,6 +43,9 @@ static void stm32vldiscovery_init(MachineState *machine) DeviceState *dev; Clock *sysclk; +/* Allow overriding the emulated board's RAM size */ +memory_region_add_subregion(get_system_memory(), SRAM_BASE_ADDRESS, machine->ram); + /* This clock doesn't need migration because it is fixed-frequency */ sysclk = clock_new(OBJECT(machine), "SYSCLK"); clock_set_hz(sysclk, SYSCLK_FRQ); @@ -60,6 +64,8 @@ static void stm32vldiscovery_machine_init(MachineClass *mc) { mc->desc = "ST STM32VLDISCOVERY (Cortex-M3)"; mc->init = stm32vldiscovery_init; +mc->default_ram_id = "stm32vldiscovery.ram"; +mc->default_ram_size = SRAM_SIZE; } DEFINE_MACHINE("stm32vldiscovery", stm32vldiscovery_machine_init) -- 2.37.1 (Apple Git-137.1)