new file mode 100644
@@ -0,0 +1,292 @@
+/*
+ * STM32 Cortex-M device emulation.
+ *
+ * Copyright (c) 2014 Liviu Ionescu
+ * Copyright (c) 2010 Andre Beckus
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/arm/stm32-mcu.h"
+
+#if defined(CONFIG_VERBOSE)
+#include "verbosity.h"
+#endif
+
+/* ----- Private ----------------------------------------------------------- */
+
+/**
+ * Create children GPIO nodes. Public names are "/machine/stm32/gpio[%c]".
+ */
+static void create_gpio(STM32MCUState *state, stm32_gpio_index_t index,
+ const STM32Capabilities *capabilities)
+{
+ DeviceState *dev;
+ STM32SysBusDevice *sbd;
+ STM32GPIOState *gdev;
+
+ dev = qdev_create(NULL, TYPE_STM32_GPIO);
+ sbd = STM32_SYS_BUS_DEVICE_STATE(dev);
+ sbd->capabilities = capabilities;
+
+ gdev = STM32_GPIO_STATE(dev);
+ gdev->port_index = index;
+ gdev->rcc = STM32_RCC_STATE(state->rcc);
+
+ state->gpio[index] = dev;
+
+ char child_name[10];
+ snprintf(child_name, sizeof(child_name), "gpio[%c]", 'a' + index);
+
+ object_property_add_child(state->container, child_name, OBJECT(dev), NULL);
+}
+
+/**
+ * Constructor for all STM32 devices, based on capabilities.
+ *
+ * Alias the flash memory to 0x08000000.
+ *
+ * TODO: define the special CCM region for the models that include it.
+ */
+static void stm32_mcu_construct_callback(Object *obj,
+ const STM32Capabilities *capabilities,
+ const CortexMCapabilities *core_capabilities, const int flash_size_kb,
+ const int sram_size_kb, MachineState *machine)
+{
+ qemu_log_function_name();
+
+ /* Call parent constructor */
+ CORTEXM_MCU_GET_CLASS(obj)->construct(obj, core_capabilities, flash_size_kb,
+ sram_size_kb, machine);
+
+ STM32MCUState *state = STM32_MCU_STATE(obj);
+ assert(capabilities != NULL);
+ state->capabilities = capabilities;
+
+ const char *family;
+ switch (capabilities->family) {
+ case STM32_FAMILY_F1:
+ family = "F1";
+ break;
+ case STM32_FAMILY_F2:
+ family = "F2";
+ break;
+ case STM32_FAMILY_F3:
+ family = "F3";
+ break;
+ case STM32_FAMILY_F4:
+ family = "F4";
+ break;
+ case STM32_FAMILY_L1:
+ family = "L1";
+ break;
+ default:
+ family = "unknown";
+ }
+ qemu_log_mask(LOG_TRACE, "STM32 Family: %s\n", family);
+
+ /* Devices will be addressed below "/machine/stm32". */
+ state->container = container_get(qdev_get_machine(), "/stm32");
+
+ DeviceState *dev;
+ STM32SysBusDevice *sbd;
+
+ /* RCC */
+ {
+ state->rcc = qdev_create(NULL, TYPE_STM32_RCC);
+ dev = DEVICE(state->rcc);
+
+ /* Copy capabilities into internal objects. */
+ sbd = STM32_SYS_BUS_DEVICE_STATE(state->rcc);
+ sbd->capabilities = capabilities;
+
+ /* Copy internal oscillator frequencies from capabilities. */
+ qdev_prop_set_uint32(dev, "hsi-freq-hz",
+ sbd->capabilities->hsi_freq_hz);
+ qdev_prop_set_uint32(dev, "lsi-freq-hz",
+ sbd->capabilities->lsi_freq_hz);
+
+ /* Alias RCC properties to MCU, to hide internal details. */
+ object_property_add_alias(obj, "hse-freq-hz", OBJECT(dev),
+ "hse-freq-hz", NULL);
+ object_property_add_alias(obj, "lse-freq-hz", OBJECT(dev),
+ "lse-freq-hz", NULL);
+
+ /* RCC will be named "/machine/stm32/rcc" */
+ object_property_add_child(state->container, "rcc", OBJECT(state->rcc),
+ NULL);
+ }
+
+ /* FLASH */
+ {
+ state->flash = qdev_create(NULL, TYPE_STM32_FLASH);
+ sbd = STM32_SYS_BUS_DEVICE_STATE(state->flash);
+ sbd->capabilities = capabilities;
+
+ /* FLASH will be named "/machine/stm32/flash" */
+ object_property_add_child(state->container, "flash",
+ OBJECT(state->flash), NULL);
+ }
+
+ /* GPIOA */
+ if (capabilities->has_gpioa) {
+ create_gpio(state, STM32_GPIO_PORT_A, capabilities);
+ }
+
+ /* GPIOB */
+ if (capabilities->has_gpiob) {
+ create_gpio(state, STM32_GPIO_PORT_B, capabilities);
+ }
+
+ /* GPIOC */
+ if (capabilities->has_gpioc) {
+ create_gpio(state, STM32_GPIO_PORT_C, capabilities);
+ }
+
+ /* GPIOD */
+ if (capabilities->has_gpiod) {
+ create_gpio(state, STM32_GPIO_PORT_D, capabilities);
+ }
+
+ /* GPIOE */
+ if (capabilities->has_gpioe) {
+ create_gpio(state, STM32_GPIO_PORT_E, capabilities);
+ }
+
+ /* GPIOF */
+ if (capabilities->has_gpiof) {
+ create_gpio(state, STM32_GPIO_PORT_F, capabilities);
+ }
+
+ /* GPIOG */
+ if (capabilities->has_gpiog) {
+ create_gpio(state, STM32_GPIO_PORT_G, capabilities);
+ }
+
+ /* TODO: add more devices. */
+}
+
+static void stm32_mcu_realize_callback(DeviceState *dev, Error **errp)
+{
+ qemu_log_function_name();
+
+ /* Call the parent realize(). */
+ DeviceClass *parent_class = DEVICE_CLASS(
+ object_class_get_parent(object_class_by_name(TYPE_STM32_MCU)));
+ Error *local_err = NULL;
+ parent_class->realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ STM32MCUState *state = STM32_MCU_STATE(dev);
+
+ /* Propagate realize() to children. */
+
+ /* RCC */
+ qdev_realize(DEVICE(state->rcc));
+
+ /* FLASH */
+ qdev_realize(DEVICE(state->flash));
+
+ /* GPIO[A-G] */
+ for (int i = 0; i < STM32_MAX_GPIO; ++i) {
+ /* Realize all initialised GPIOs */
+ if (state->gpio[i]) {
+ qdev_realize(DEVICE(state->gpio[i]));
+ }
+ }
+}
+
+/**
+ * Virtual function, overriding (in fact extending) the Cortex-M code.
+ */
+static void stm32_mcu_memory_regions_create_callback(DeviceState *dev)
+{
+ qemu_log_function_name();
+
+ /* Create the parent (Cortex-M) memory regions */
+ CortexMClass *parent_class = CORTEXM_MCU_CLASS(
+ object_class_by_name(TYPE_CORTEXM_MCU));
+ parent_class->memory_regions_create(dev);
+
+ /**
+ * The STM32 family stores its Flash memory at some base address in memory
+ * (0x08000000 for medium density devices), and then aliases it to the
+ * boot memory space, which starts at 0x00000000 (the "System Memory" can
+ * also be aliased to 0x00000000, but this is not implemented here).
+ * The processor executes the code in the aliased memory at 0x00000000.
+ * We need to make a QEMU alias so that reads in the 0x08000000 area
+ * are passed through to the 0x00000000 area. Note that this is the
+ * opposite of real hardware, where the memory at 0x00000000 passes
+ * reads through the "real" flash memory at 0x08000000, but it works
+ * the same either way.
+ */
+ CortexMState *cm_state = CORTEXM_MCU_STATE(dev);
+ int flash_size = cm_state->flash_size_kb * 1024;
+
+ /* Allocate a new region for the alias */
+ MemoryRegion *flash_alias_mem = g_malloc(sizeof(MemoryRegion));
+
+ /* Initialise the new region */
+ memory_region_init_alias(flash_alias_mem, NULL, "stm32-mem-flash-alias",
+ &cm_state->flash_mem, 0, flash_size);
+ memory_region_set_readonly(flash_alias_mem, true);
+
+ /* Alias it as the STM specific 0x08000000 */
+ memory_region_add_subregion(get_system_memory(), 0x08000000,
+ flash_alias_mem);
+}
+
+static Property stm32_mcu_properties[] = {
+ /* TODO: add STM32 specific properties */
+ DEFINE_PROP_END_OF_LIST(), /**/
+};
+
+static void stm32_mcu_class_init_callback(ObjectClass *klass, void *data)
+{
+ STM32MCUClass *st_class = STM32_MCU_CLASS(klass);
+ st_class->construct = stm32_mcu_construct_callback;
+
+ CortexMClass *cm_class = CORTEXM_MCU_CLASS(klass);
+ cm_class->memory_regions_create = stm32_mcu_memory_regions_create_callback;
+
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->realize = stm32_mcu_realize_callback;
+ dc->props = stm32_mcu_properties;
+}
+
+static const TypeInfo stm32_mcu_type_info = {
+ .abstract = true,
+ .name = TYPE_STM32_MCU,
+ .parent = TYPE_CORTEXM_MCU,
+ .instance_size = sizeof(STM32MCUState),
+ .class_init = stm32_mcu_class_init_callback,
+ .class_size = sizeof(STM32MCUClass) /**/
+};
+
+/* ----- Type inits. ----- */
+
+static void stm32_type_init()
+{
+ type_register_static(&stm32_mcu_type_info);
+}
+
+#if defined(CONFIG_GNU_ARM_ECLIPSE)
+type_init(stm32_type_init);
+#endif
+
+/* ------------------------------------------------------------------------- */
+
new file mode 100644
@@ -0,0 +1,479 @@
+/*
+ * STM32 Cortex-M devices emulation.
+ *
+ * Copyright (c) 2014 Liviu Ionescu
+ * Copyright (c) 2010 Andre Beckus
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/arm/stm32-mcus.h"
+#include "hw/arm/cortexm-mcu.h"
+#include "exec/address-spaces.h"
+#include "qemu/error-report.h"
+#include "sysemu/sysemu.h"
+
+#if defined(CONFIG_VERBOSE)
+#include "verbosity.h"
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Define all STM32 MCUs, based on table capabilities.
+ *
+ * To easily reuse the definitions, each line includes a pointer
+ * to the core capabilities and a pointer to the stm32 capabilities.
+ * This greatly simplify adding definition that differ only in memory size.
+ */
+
+/*
+ * - Low-density devices are STM32F101xx, STM32F102xx and STM32F103xx
+ * microcontrollers where the Flash memory density ranges between 16
+ * and 32 Kbytes.
+ * - Medium-density devices are STM32F101xx, STM32F102xx and STM32F103xx
+ * microcontrollers where the Flash memory density ranges between 64
+ * and 128 Kbytes.
+ * - High-density devices are STM32F101xx and STM32F103xx microcontrollers
+ * where the Flash memory density ranges between 256 and 512 Kbytes.
+ * - XL-density devices are STM32F101xx and STM32F103xx microcontrollers
+ * where the Flash memory density ranges between 768 Kbytes and 1 Mbyte.
+ * - Connectivity line devices are STM32F105xx and STM32F107xx
+ * microcontrollers.
+ */
+
+/*
+ * Interrupts:
+ *
+ * - F1
+ * - CL: 68
+ * - [LMHX]D: 60
+ * - F4
+ * - TBD
+ */
+
+/*
+ * STM32 pin count and package encoding (first char after number):
+ *
+ * I = BGA/LQFP 176
+ * V = LQFP/UFBGA 100
+ * Z = LQFP/UFPGA/UFBGA 144, WLCSP 143
+ * B = LQFP 208
+ * R = LQFP 64
+ * N = TFBGA
+ * A = UFBGA 169, WLCSP 168
+ * C = UFQFPN 48, WLCSP 49
+ * M = WLCSP 81
+ * O = WLCSP 90
+ */
+
+/*
+ * STM32 Flash sizes encoding (second char after number):
+ *
+ * 8 = 64K
+ * B = 128K
+ * C = 256K
+ * E = 512K
+ * F = 768K
+ * G = 1024K
+ * I = 2048K
+ */
+
+static const STM32Capabilities stm32f103x8b = {
+
+ .family = STM32_FAMILY_F1,
+ .f1 = {
+ .is_md = true },
+
+ .hsi_freq_hz = 8000000,
+ .lsi_freq_hz = 40000,
+ .has_rcc = true,
+ .has_pwr = true,
+ .has_rtc = true,
+ .num_bkp = 20,
+
+ .has_crc = true,
+ .has_exti = true,
+ .has_dma1 = true,
+ .num_dma1 = 7,
+ .has_ac_tim1 = true,
+ .has_gp1_tim2 = true,
+ .has_gp1_tim3 = true,
+ .has_gp1_tim4 = true,
+ .has_iwdg = true,
+ .has_wwdg = true,
+ .has_i2c1 = true,
+ .has_i2c2 = true,
+ .has_usart1 = true, /* 4.5Mb/s */
+ .has_usart2 = true, /* 2.25 Mb/s */
+ .has_usart3 = true, /* 2.25 Mb/s */
+ .has_spi1 = true,
+ .has_spi2 = true,
+ .has_bx_can1 = true,
+ .has_usb_fs = true,
+
+ .has_gpioa = true,
+ .has_gpiob = true,
+ .has_gpioc = true,
+ .has_gpiod = true,
+ .has_gpioe = true,
+
+ .has_adc1 = true, /* 12-bits, 16-ch */
+ .has_adc2 = true, /* 12-bits, 16-ch */
+
+ .has_ts = 1, /* ADC12_IN16 */
+};
+
+static const STM32Capabilities stm32f10_57_xx = {
+
+ .family = STM32_FAMILY_F1,
+ .f1 = {
+ .is_cl = true },
+
+ .hsi_freq_hz = 8000000,
+ .lsi_freq_hz = 40000,
+ .has_rcc = true,
+ .has_pwr = true,
+ .has_rtc = true,
+
+ .has_crc = true,
+ .has_exti = true,
+ .num_exti = 20,
+ .has_dma1 = true,
+ .num_dma1 = 7,
+ .has_dma2 = true,
+ .num_dma2 = 5,
+ .has_ac_tim1 = true,
+ .has_gp1_tim2 = true,
+ .has_gp1_tim3 = true,
+ .has_gp1_tim4 = true,
+ .has_gp1_tim5 = true,
+ .has_bc_tim6 = true,
+ .has_bc_tim7 = true,
+ .has_iwdg = true,
+ .has_wwdg = true,
+ .has_i2c1 = true,
+ .has_i2c2 = true,
+ .has_usart1 = true,
+ .has_usart2 = true,
+ .has_usart3 = true,
+ .has_uart4 = true,
+ .has_uart5 = true,
+ .has_spi1 = true,
+ .has_spi2 = true,
+ .has_spi3 = true,
+ .has_i2s1 = true,
+ .has_i2s2 = true,
+ .has_eth = true, /* 107 only */
+ .has_can1 = true,
+ .has_can2 = true,
+ .has_usb_otg_fs = true,
+ .has_gpioa = true,
+ .has_gpiob = true,
+ .has_gpioc = true,
+ .has_gpiod = true,
+ .has_gpioe = true,
+ .has_adc1 = true,
+ .has_adc2 = true,
+ .has_dac1 = true,
+ .has_dac2 = true,
+ .has_ts = true, /* ADC1_IN16 */
+};
+
+static const STM32Capabilities stm32l15_12_xd = {
+
+ .family = STM32_FAMILY_L1,
+
+ .hsi_freq_hz = 16000000,
+ .lsi_freq_hz = 37000,
+ .has_rcc = true,
+ .has_rtc = true,
+ .eeprom_size_kb = 12,
+ .num_bkp = 128,
+
+ .has_gpioa = true,
+ .has_gpiob = true,
+ .has_gpioc = true,
+ .has_gpiod = true,
+ .has_gpioe = true,
+ .has_gpiof = true,
+ .has_gpiog = true,
+ .has_gpioh = true,
+ .has_exti = true,
+ .num_exti = 24,
+ .has_fsmc = true,
+ .has_dma = true,
+ .num_dma = 12,
+ .has_adc = true, /* 12-bits, 40-ch */
+ .has_ts = true, /* ADC_IN16 */
+ .has_dac1 = true,
+ .has_dac2 = true,
+ .has_gp1_tim2 = true,
+ .has_gp1_tim3 = true,
+ .has_gp1_tim4 = true,
+ .has_gp1_tim5 = true,
+ .has_bc_tim6 = true,
+ .has_bc_tim7 = true,
+ .has_gp2_tim9 = true,
+ .has_gp3_tim10 = true,
+ .has_gp3_tim11 = true,
+ .has_iwdg = true,
+ .has_wwdg = true,
+ .has_i2c1 = true,
+ .has_i2c2 = true,
+ .has_usart1 = true,
+ .has_usart2 = true,
+ .has_usart3 = true,
+ .has_uart4 = true,
+ .has_uart5 = true,
+ .has_spi1 = true,
+ .has_spi2 = true,
+ .has_spi3 = true,
+ .has_i2s1 = true,
+ .has_i2s2 = true,
+ .has_sdio = true,
+ .has_usb_fs = true,
+ .has_crc = true,
+
+/*
+ * +LCD
+ * + comparators
+ * + touch sensing
+ */
+};
+
+static const CortexMCapabilities stm32f0xx_core = {
+ .cortexm_model = CORTEX_M0,
+ .has_mpu = false, /* itm? irqs? */
+ .nvic_bits = 4, /**/
+};
+
+static const CortexMCapabilities stm32f100_core = {
+ .cortexm_model = CORTEX_M3,
+ .has_mpu = true,
+ .has_itm = true,
+ .num_irq = 60,
+ .nvic_bits = 4, /**/
+};
+
+static const CortexMCapabilities stm32f1xx_core = {
+ .cortexm_model = CORTEX_M3,
+ .has_mpu = true,
+ .has_itm = true, /* no ETM? */
+ .num_irq = 44,
+ .nvic_bits = 4 /**/
+};
+
+static const CortexMCapabilities stm32f1cl_core = {
+ .cortexm_model = CORTEX_M3,
+ .has_mpu = true,
+ .has_etm = true,
+ .has_itm = true,
+ .num_irq = 68,
+ .nvic_bits = 4, /**/
+};
+
+static const CortexMCapabilities stm32f152_core = {
+ .cortexm_model = CORTEX_M3,
+ .has_mpu = true,
+ .has_itm = true, /* TODO: check */
+ .has_etm = true,
+ .num_irq = 57, /* TODO: check */
+ .nvic_bits = 4, /**/
+};
+
+static const CortexMCapabilities stm32f2xx_core = {
+ .cortexm_model = CORTEX_M3,
+ .has_mpu = true,
+ .has_itm = true,
+ .nvic_bits = 4, /**/
+};
+
+static const CortexMCapabilities stm32f3xx_core = {
+ .cortexm_model = CORTEX_M4F,
+ .has_mpu = true,
+ .has_itm = true,
+ .nvic_bits = 4, /**/
+};
+
+static const CortexMCapabilities stm32f4xx_core = {
+ .cortexm_model = CORTEX_M4F,
+ .has_mpu = true,
+ .has_itm = true,
+ .nvic_bits = 4, /**/
+};
+
+static const STM32PartInfo stm32_mcus[] = {
+ {
+ .name = TYPE_STM32F051R8,
+ .flash_size_kb = 64,
+ .sram_size_kb = 8,
+ .core = &stm32f0xx_core, /* TODO: Add .stm32 */
+ },
+ {
+ .name = TYPE_STM32F100RB,
+ .flash_size_kb = 128,
+ .sram_size_kb = 8,
+ .core = &stm32f100_core, /* TODO: Add .stm32 */
+ },
+ {
+ .name = TYPE_STM32F103RB, /* STM32F103x[8B] */
+ .flash_size_kb = 128,
+ .sram_size_kb = 20,
+ .core = &stm32f1xx_core,
+ .stm32 = &stm32f103x8b, /**/
+ },
+ {
+ .name = TYPE_STM32F107VC,
+ .flash_size_kb = 256,
+ .sram_size_kb = 64,
+ .core = &stm32f1cl_core,
+ .stm32 = &stm32f10_57_xx, /**/
+ },
+ {
+ .name = TYPE_STM32L152RE,
+ .flash_size_kb = 384, /* 384+12 EEPROM */
+ .sram_size_kb = 48,
+ .core = &stm32f152_core,
+ .stm32 = &stm32l15_12_xd, /**/
+ },
+ {
+ .name = TYPE_STM32F205RF,
+ .flash_size_kb = 768,
+ .sram_size_kb = 128, /* No CCM */
+ .core = &stm32f2xx_core, /* TODO: Add .stm32 */
+ },
+ {
+ .name = TYPE_STM32F303VC,
+ .flash_size_kb = 256,
+ .sram_size_kb = 40,
+ .core = &stm32f3xx_core, /* TODO: Add .stm32 */
+ },
+ {
+ .name = TYPE_STM32F334R8,
+ .flash_size_kb = 64,
+ .sram_size_kb = 12,
+ .core = &stm32f3xx_core, /* TODO: Add .stm32 */
+ },
+ {
+ .name = TYPE_STM32F405RG,
+ .flash_size_kb = 1024,
+ .sram_size_kb = 128, /* 64K CCM not counted */
+ .core = &stm32f4xx_core, /* TODO: Add .stm32 */
+ },
+ {
+ .name = TYPE_STM32F407VG,
+ .flash_size_kb = 1024,
+ .sram_size_kb = 128, /* 64K CCM not counted */
+ .core = &stm32f4xx_core, /* TODO: Add .stm32 */
+ },
+ {
+ .name = TYPE_STM32F407ZG,
+ .flash_size_kb = 1024,
+ .sram_size_kb = 128, /* 64K CCM not counted */
+ .core = &stm32f4xx_core, /* TODO: Add .stm32 */
+ },
+ {
+ .name = TYPE_STM32F411RE,
+ .flash_size_kb = 512,
+ .sram_size_kb = 128, /* No CCM */
+ .core = &stm32f4xx_core, /* TODO: Add .stm32 */
+ },
+ {
+ .name = TYPE_STM32F429ZI,
+ .flash_size_kb = 2048,
+ .sram_size_kb = 192, /* 64K CCM not counted */
+ .core = &stm32f4xx_core, /* TODO: Add .stm32 */
+ },
+ {
+ .name = 0 /* End of array. */
+ } /**/
+};
+
+/* ------------------------------------------------------------------------- */
+
+static void stm32_mcus_construct_callback(Object *obj, MachineState *machine)
+{
+ qemu_log_function_name();
+
+ STM32DeviceClass *st_class = STM32_DEVICE_GET_CLASS(obj);
+
+ STM32PartInfo *part_info = st_class->part_info;
+ STM32_MCU_GET_CLASS(obj)->construct(obj, part_info->stm32, part_info->core,
+ part_info->flash_size_kb, part_info->sram_size_kb, machine);
+}
+
+static void stm32_mcus_realize_callback(DeviceState *dev, Error **errp)
+{
+ qemu_log_function_name();
+
+ /* Call the parent realize(). */
+ DeviceClass *parent_class = DEVICE_CLASS(
+ object_class_by_name(TYPE_STM32_MCU));
+ Error *local_err = NULL;
+ parent_class->realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+}
+
+static Property stm32_mcus_properties[] = {
+ /* TODO: add STM32 specific properties */
+ DEFINE_PROP_END_OF_LIST(), /**/
+};
+
+static void stm32_mcus_class_init_callback(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ STM32DeviceClass *st_class = (STM32DeviceClass *) (klass);
+
+ dc->realize = stm32_mcus_realize_callback;
+ dc->props = stm32_mcus_properties;
+
+ st_class->construct = stm32_mcus_construct_callback;
+
+ /*
+ * Copy the 'data' param, pointing to a ParamInfo, to the class
+ * structure, to be retrieved by the constructor.
+ */
+ st_class->part_info = data;
+}
+
+/**
+ * Register all devices described in the table.
+ * Pass the pointer to the table element as .class_data
+ * to the .class_init.
+ */
+static void stm32_mcus_types_init()
+{
+
+ for (int i = 0; stm32_mcus[i].name; ++i) {
+
+ TypeInfo ti = {
+ .name = stm32_mcus[i].name,
+ .parent = TYPE_STM32_MCU,
+ .instance_size = sizeof(STM32DeviceState),
+ .class_init = stm32_mcus_class_init_callback,
+ .class_size = sizeof(STM32DeviceClass),
+ .class_data = (void *) &stm32_mcus[i] };
+ type_register(&ti);
+ }
+}
+
+#if defined(CONFIG_GNU_ARM_ECLIPSE)
+type_init(stm32_mcus_types_init);
+#endif
+
+/* ------------------------------------------------------------------------- */
new file mode 100644
@@ -0,0 +1,191 @@
+/*
+ * STM32 capabilities definitions.
+ *
+ * Copyright (c) 2015 Liviu Ionescu
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef STM32_CAPABILITIES_H_
+#define STM32_CAPABILITIES_H_
+
+#include <stdint.h>
+
+/**
+ * This file defines the members used in the structure used to describe
+ * the capabilities of the STM32 MCUs.
+ *
+ * STM32 MCUs are grouped by families and sub-families.
+ */
+
+/**
+ * The family is the main differentiator for STM32 MCUs.
+ */
+typedef enum {
+ STM32_FAMILY_UNKNOWN,
+ STM32_FAMILY_F0,
+ STM32_FAMILY_F1,
+ STM32_FAMILY_F2,
+ STM32_FAMILY_F3,
+ STM32_FAMILY_F4,
+ STM32_FAMILY_L1,
+} stm32_family_t;
+
+#define STM32_MAX_GPIO (8)
+
+typedef struct {
+
+ stm32_family_t family;
+
+ /*
+ * Properties common to all families
+ */
+ uint32_t hsi_freq_hz;
+ uint32_t lsi_freq_hz;
+
+ unsigned int eeprom_size_kb;
+
+ /*
+ * Peripherals common to all families.
+ */
+ unsigned int has_rcc :1;
+ unsigned int has_pwr :1;
+
+ /* GPIOs */
+ unsigned int has_gpioa :1;
+ unsigned int has_gpiob :1;
+ unsigned int has_gpioc :1;
+ unsigned int has_gpiod :1;
+ unsigned int has_gpioe :1;
+ unsigned int has_gpiof :1;
+ unsigned int has_gpiog :1;
+ unsigned int has_gpioh :1;
+ /* EXTI */
+ unsigned int has_exti :1;
+ /* DMA */
+ unsigned int has_dma :1;
+ unsigned int has_dma1 :1;
+ unsigned int has_dma2 :1;
+
+ /* Advanced control timers */
+ unsigned int has_ac_tim1 :1;
+ unsigned int has_ac_tim8 :1;
+ /* General-purpose timers */
+ unsigned int has_gp1_tim2 :1;
+ unsigned int has_gp1_tim3 :1;
+ unsigned int has_gp1_tim4 :1;
+ unsigned int has_gp1_tim5 :1;
+ /* General-purpose timers */
+ unsigned int has_gp2_tim9 :1;
+ unsigned int has_gp2_tim12 :1;
+ /* General-purpose timers */
+ unsigned int has_gp3_tim10 :1;
+ unsigned int has_gp3_tim11 :1;
+ unsigned int has_gp3_tim13 :1;
+ unsigned int has_gp3_tim14 :1;
+ /* Basic timers */
+ unsigned int has_bc_tim6 :1;
+ unsigned int has_bc_tim7 :1;
+ /* Watchdogs */
+ unsigned int has_iwdg :1;
+ unsigned int has_wwdg :1;
+
+ /* I2C */
+ unsigned int has_i2c :1;
+ unsigned int has_i2c1 :1;
+ unsigned int has_i2c2 :1;
+
+ /* Universal synchronous/asynchronous */
+ unsigned int has_usart1 :1;
+ unsigned int has_usart2 :1;
+ unsigned int has_usart3 :1;
+ /* Universal asynchronous */
+ unsigned int has_uart4 :1;
+ unsigned int has_uart5 :1;
+
+ /* SPI */
+ unsigned int has_spi1 :1;
+ unsigned int has_spi2 :1;
+ unsigned int has_spi3 :1;
+
+ /* I2S */
+ unsigned int has_i2s1 :1;
+ unsigned int has_i2s2 :1;
+
+ /* Memory */
+ unsigned int has_fsmc :1;
+
+ /* SDIO */
+ unsigned int has_sdio :1;
+
+ /* Ethernet */
+ unsigned int has_eth :1;
+ /* CAN */
+ unsigned int has_bx_can1 :1;
+ unsigned int has_bx_can2 :1;
+ unsigned int has_can1 :1;
+ unsigned int has_can2 :1;
+ /* ADC */
+ unsigned int has_adc :1;
+ unsigned int has_adc1 :1;
+ unsigned int has_adc2 :1;
+ /* DAC */
+ unsigned int has_dac :1;
+ unsigned int has_dac1 :1;
+ unsigned int has_dac2 :1;
+ /* USB */
+ unsigned int has_usb_fs :1;
+ unsigned int has_usb_otg_fs :1;
+
+ /* RTC */
+ unsigned int has_rtc :1;
+
+ /* CRC */
+ unsigned int has_crc :1;
+
+ /* Temperature sensor */
+ unsigned int has_ts :1;
+
+ /* Keep them together */
+ unsigned char num_exti;
+ unsigned char num_dma1;
+ unsigned char num_dma2;
+ unsigned char num_dma;
+
+ /* Number of backup bytes */
+ unsigned int num_bkp;
+
+ /*
+ * Note: the family definitions are mutual exclusive, and could
+ * be packed in a union, but this makes writing the definitions
+ * more complicated and was discarded.
+ * The memory penalty is not significant.
+ */
+ struct {
+ unsigned int is_ld :1; /* is low density */
+ unsigned int is_md :1; /* is medium density */
+ unsigned int is_hd :1; /* is high density */
+ unsigned int is_xd :1; /* is extra density */
+ unsigned int is_cl :1; /* is Connectivity Line */
+ unsigned int is_ldvl :1; /* is low density */
+ unsigned int is_mdvl :1; /* is medium density */
+ unsigned int is_hdvl :1; /* is high density */
+
+ } f1;
+
+ /* TODO: add other families that have sub-families. */
+
+} STM32Capabilities;
+
+#endif /* STM32_CAPABILITIES_H_ */
new file mode 100644
@@ -0,0 +1,89 @@
+/*
+ * STM32 Cortex-M devices emulation.
+ *
+ * Copyright (c) 2014 Liviu Ionescu
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef STM32_MCU_H
+#define STM32_MCU_H
+
+#include "hw/boards.h"
+#include "hw/arm/cortexm-mcu.h"
+#include "hw/misc/stm32-rcc.h"
+#include "hw/misc/stm32-flash.h"
+#include "hw/gpio/stm32-gpio.h"
+
+/* ------------------------------------------------------------------------- */
+
+#define TYPE_STM32_MCU "stm32-mcu"
+
+#define STM32_MCU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(STM32MCUClass, (obj), TYPE_STM32_MCU)
+#define STM32_MCU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(STM32MCUClass, (klass), TYPE_STM32_MCU)
+
+typedef struct STM32MCUClass {
+ /*< private >*/
+ CortexMClass parent_class;
+ /*< public >*/
+
+ void (*construct)(Object *obj, const STM32Capabilities* capabilities,
+ const CortexMCapabilities *core_capabilities,
+ const int param_flash_size_kb, const int param_sram_size_kb,
+ MachineState *machine);
+
+} STM32MCUClass;
+
+#define STM32_MCU_STATE(obj) \
+ OBJECT_CHECK(STM32MCUState, (obj), TYPE_STM32_MCU)
+
+typedef struct STM32MCUState {
+ /*< private >*/
+ CortexMState parent_obj;
+ /*< public >*/
+
+ /* Specific STM32 capabilities; Cortex-M capabilities are separate. */
+ const STM32Capabilities *capabilities;
+
+ Object *container;
+
+ DeviceState *rcc;
+ DeviceState *flash;
+ DeviceState *gpio[STM32_MAX_GPIO];
+} STM32MCUState;
+
+/* ------ Public ----------------------------------------------------------- */
+
+/*
+ * Might be deprecated in the future; peripherals are named and can be
+ * obtained by name.
+ */
+
+G_INLINE_FUNC DeviceState *stm32_mcu_get_rcc_dev(DeviceState *dev)
+{
+ return DEVICE((STM32_MCU_STATE(dev)->rcc));
+}
+
+G_INLINE_FUNC DeviceState *stm32_mcu_get_gpio_dev(DeviceState *dev,
+ int port_index)
+{
+ assert(port_index < STM32_MAX_GPIO);
+ return DEVICE((STM32_MCU_STATE(dev)->gpio[port_index]));
+}
+
+/* ------------------------------------------------------------------------- */
+
+#endif /* STM32_MCU_H */
new file mode 100644
@@ -0,0 +1,89 @@
+/*
+ * STM32 Cortex-M devices emulation.
+ *
+ * Copyright (c) 2014 Liviu Ionescu
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef STM32_MCUS_H
+#define STM32_MCUS_H
+
+#include "hw/arm/stm32-mcu.h"
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * For compatibility with some development tools, it is
+ * strongly recommended to use the CMSIS names.
+ */
+#define TYPE_STM32F051R8 "STM32F051R8"
+#define TYPE_STM32F100RB "STM32F100RB"
+#define TYPE_STM32F103RB "STM32F103RB"
+#define TYPE_STM32F107VC "STM32F107VC"
+#define TYPE_STM32L152RE "STM32L152RE"
+#define TYPE_STM32F205RF "STM32F205RF"
+#define TYPE_STM32F303VC "STM32F303VC"
+#define TYPE_STM32F334R8 "STM32F334R8"
+#define TYPE_STM32F405RG "STM32F405RG"
+#define TYPE_STM32F407VG "STM32F407VG"
+#define TYPE_STM32F407ZG "STM32F407ZG"
+#define TYPE_STM32F411RE "STM32F411RE"
+#define TYPE_STM32F429ZI "STM32F429ZI"
+
+/*
+ * Warning, this cast does not check the type!
+ */
+#define STM32_DEVICE_GET_CLASS(obj) \
+ ((STM32DeviceClass *)object_get_class(OBJECT(obj)))
+
+/**
+ * Structure to define the specifics of each MCU. Capabilities are
+ * split between core & stm32; they care processed by parent class
+ * constructors.
+ */
+typedef struct {
+
+ const char *name; /* CMSIS device name */
+
+ const unsigned int flash_size_kb; /* size of main program area, in KB */
+ const unsigned int sram_size_kb; /* size of main RAM area, in KB */
+
+ const CortexMCapabilities *core;
+ const STM32Capabilities *stm32;
+
+} STM32PartInfo;
+
+typedef struct {
+ /*< private >*/
+ STM32MCUClass parent_class;
+ /*< public >*/
+
+ /**
+ * Constructor. Must be called manually after allocation.
+ */
+ void (*construct)(Object *obj, MachineState *machine);
+ STM32PartInfo *part_info;
+} STM32DeviceClass;
+
+typedef struct {
+ /*< private >*/
+ STM32MCUState parent_class;
+ /*< public >*/
+
+} STM32DeviceState;
+
+/* ------------------------------------------------------------------------- */
+
+#endif /* STM32_MCUS_H */