[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: [PATCH] hw/arm/stm32f405: Add preliminary flash interface emulation
From: |
Stephanos Ioannidis |
Subject: |
RE: [PATCH] hw/arm/stm32f405: Add preliminary flash interface emulation support |
Date: |
Fri, 6 Mar 2020 01:07:57 +0000 |
> I think a lot of comments from your other patch apply to this patch as well
> (about bit fields and splitting the patch specifically).
Certainly does, I will send the v2 for this as well.
Stephanos
-----Original Message-----
From: Alistair Francis <address@hidden>
Sent: Friday, March 6, 2020 8:08 AM
To: Stephanos Ioannidis <address@hidden>
Cc: Peter Maydell <address@hidden>; Alistair Francis <address@hidden>; open
list:All patches CC here <address@hidden>; open list:ARM TCG CPUs
<address@hidden>
Subject: Re: [PATCH] hw/arm/stm32f405: Add preliminary flash interface
emulation support
On Sun, Mar 1, 2020 at 12:47 AM Stephanos Ioannidis <address@hidden> wrote:
>
> The flash interface (FLASHIF) peripheral provides a control interface
> for the SoC embedded flash memory on the STM32F4xx series devices.
>
> This commit adds preliminary support for the flash interface
> peripheral emulation, in order to support proper emulation of the
> firmware images that use the STM32Cube driver, which configures and
> validates the FLASH_ACR register during system initialisation.
>
> Signed-off-by: Stephanos Ioannidis <address@hidden>
Hey Stephanos,
I think a lot of comments from your other patch apply to this patch as well
(about bit fields and splitting the patch specifically).
Do you mind sending a v2 addressing those comments?
Alistair
> ---
> hw/arm/Kconfig | 1 +
> hw/arm/stm32f405_soc.c | 15 +-
> hw/misc/Kconfig | 3 +
> hw/misc/Makefile.objs | 1 +
> hw/misc/stm32f4xx_flashif.c | 215 ++++++++++++++++++++++++++++
> hw/misc/trace-events | 4 +
> include/hw/arm/stm32f405_soc.h | 2 +
> include/hw/misc/stm32f4xx_flashif.h | 144 +++++++++++++++++++
> 8 files changed, 384 insertions(+), 1 deletion(-) create mode 100644
> hw/misc/stm32f4xx_flashif.c create mode 100644
> include/hw/misc/stm32f4xx_flashif.h
>
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index
> 3d86691ae0..179696ec91 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -314,6 +314,7 @@ config STM32F205_SOC config STM32F405_SOC
> bool
> select ARM_V7M
> + select STM32F4XX_FLASHIF
> select STM32F4XX_SYSCFG
> select STM32F4XX_EXTI
>
> diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c index
> 9bcad97853..72b16910c7 100644
> --- a/hw/arm/stm32f405_soc.c
> +++ b/hw/arm/stm32f405_soc.c
> @@ -30,6 +30,7 @@
> #include "hw/arm/stm32f405_soc.h"
> #include "hw/misc/unimp.h"
>
> +#define FLASHIF_ADDR 0x40023C00
> #define SYSCFG_ADD 0x40013800
> static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
> 0x40004C00, 0x40005000,
> 0x40011400, @@ -59,6 +60,9 @@ static void stm32f405_soc_initfn(Object *obj)
> sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> TYPE_ARMV7M);
>
> + sysbus_init_child_obj(obj, "flashif", &s->flashif, sizeof(s->flashif),
> + TYPE_STM32F4XX_FLASHIF);
> +
> sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> TYPE_STM32F4XX_SYSCFG);
>
> @@ -130,6 +134,16 @@ static void stm32f405_soc_realize(DeviceState *dev_soc,
> Error **errp)
> return;
> }
>
> + /* Flash interface */
> + dev = DEVICE(&s->flashif);
> + object_property_set_bool(OBJECT(&s->flashif), true, "realized", &err);
> + if (err != NULL) {
> + error_propagate(errp, err);
> + return;
> + }
> + busdev = SYS_BUS_DEVICE(dev);
> + sysbus_mmio_map(busdev, 0, FLASHIF_ADDR);
> +
> /* System configuration controller */
> dev = DEVICE(&s->syscfg);
> object_property_set_bool(OBJECT(&s->syscfg), true, "realized",
> &err); @@ -261,7 +275,6 @@ static void stm32f405_soc_realize(DeviceState
> *dev_soc, Error **errp)
> create_unimplemented_device("GPIOI", 0x40022000, 0x400);
> create_unimplemented_device("CRC", 0x40023000, 0x400);
> create_unimplemented_device("RCC", 0x40023800, 0x400);
> - create_unimplemented_device("Flash Int", 0x40023C00, 0x400);
> create_unimplemented_device("BKPSRAM", 0x40024000, 0x400);
> create_unimplemented_device("DMA1", 0x40026000, 0x400);
> create_unimplemented_device("DMA2", 0x40026400, 0x400);
> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index
> bdd77d8020..e333a955b2 100644
> --- a/hw/misc/Kconfig
> +++ b/hw/misc/Kconfig
> @@ -79,6 +79,9 @@ config IMX
> select SSI
> select USB_EHCI_SYSBUS
>
> +config STM32F4XX_FLASHIF
> + bool
> +
> config STM32F2XX_SYSCFG
> bool
>
> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index
> da993f45b7..1aea0b9bb9 100644
> --- a/hw/misc/Makefile.objs
> +++ b/hw/misc/Makefile.objs
> @@ -58,6 +58,7 @@ common-obj-$(CONFIG_RASPI) += bcm2835_thermal.o
> common-obj-$(CONFIG_SLAVIO) += slavio_misc.o
> common-obj-$(CONFIG_ZYNQ) += zynq_slcr.o
> common-obj-$(CONFIG_ZYNQ) += zynq-xadc.o
> +common-obj-$(CONFIG_STM32F4XX_FLASHIF) += stm32f4xx_flashif.o
> common-obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
> common-obj-$(CONFIG_STM32F4XX_SYSCFG) += stm32f4xx_syscfg.o
> common-obj-$(CONFIG_STM32F4XX_EXTI) += stm32f4xx_exti.o diff --git
> a/hw/misc/stm32f4xx_flashif.c b/hw/misc/stm32f4xx_flashif.c new file
> mode 100644 index 0000000000..d280fc5b2c
> --- /dev/null
> +++ b/hw/misc/stm32f4xx_flashif.c
> @@ -0,0 +1,215 @@
> +/*
> + * STM32F4xx FLASHIF
> + *
> + * Copyright (c) 2020 Stephanos Ioannidis <address@hidden>
> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a copy
> + * of this software and associated documentation files (the
> +"Software"), to deal
> + * in the Software without restriction, including without limitation
> +the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense,
> +and/or sell
> + * copies of the Software, and to permit persons to whom the Software
> +is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> +included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
> +SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
> +OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> +ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> +DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "trace.h"
> +#include "hw/irq.h"
> +#include "migration/vmstate.h"
> +#include "hw/misc/stm32f4xx_flashif.h"
> +
> +static void stm32f4xx_flashif_reset(DeviceState *dev) {
> + STM32F4xxFlashIfState *s = STM32F4XX_FLASHIF(dev);
> +
> + /* Initialise states */
> + s->cr_key_index = 0;
> + s->optcr_key_index = 0;
> +
> + /* Initialise register values */
> + s->flash_acr.reg = 0x00000000;
> + s->flash_keyr.reg = 0x00000000;
> + s->flash_optkeyr.reg = 0x00000000;
> + s->flash_sr.reg = 0x00000000;
> + s->flash_cr.reg = 0x80000000;
> + s->flash_optcr.reg = 0x0FFFAAED;
> +}
> +
> +static uint64_t stm32f4xx_flashif_read(void * opaque, hwaddr addr,
> + unsigned int size) {
> + STM32F4xxFlashIfState *s = opaque;
> +
> + trace_stm32f4xx_flashif_read(addr);
> +
> + switch (addr) {
> + case FLASH_ACR:
> + return s->flash_acr.reg;
> + case FLASH_SR:
> + return s->flash_sr.reg;
> + case FLASH_CR:
> + return s->flash_cr.reg;
> + case FLASH_OPTCR:
> + return s->flash_optcr.reg;
> + default:
> + qemu_log_mask(
> + LOG_GUEST_ERROR,
> + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
> + return 0;
> + }
> +}
> +
> +static void flash_acr_write(STM32F4xxFlashIfState *s, FlashAcrType
> +val) {
> + /* Set latency */
> + s->flash_acr.latency = val.latency;
> + /* Set prefetch status */
> + s->flash_acr.prften = val.prften;
> + /* Set instruction cache status */
> + s->flash_acr.icen = val.icen;
> + /* Set data cache status */
> + s->flash_acr.dcen = val.dcen;
> +}
> +
> +static void flash_cr_write(STM32F4xxFlashIfState *s, FlashCrType val)
> +{
> + /* Lock FLASH_CR if lock bit is set */
> + if (val.lock) {
> + s->flash_cr.lock = 1;
> + s->cr_key_index = 0;
> + return;
> + }
> +}
> +
> +static void flash_optcr_write(STM32F4xxFlashIfState *s,
> +FlashOptcrType val) {
> + /* Lock FLASH_OPTCR if lock bit is set */
> + if (val.optlock) {
> + s->flash_optcr.optlock = 1;
> + s->optcr_key_index = 0;
> + return;
> + }
> +}
> +
> +static void stm32f4xx_flashif_write(void *opaque, hwaddr addr,
> + uint64_t val64, unsigned int
> +size) {
> + STM32F4xxFlashIfState *s = opaque;
> + uint32_t value = val64;
> +
> + trace_stm32f4xx_flashif_write(value, addr);
> +
> + switch (addr) {
> + case FLASH_ACR:
> + flash_acr_write(s, (FlashAcrType)value);
> + return;
> + case FLASH_KEYR:
> + if (s->cr_key_index == 0 && value == 0x45670123) {
> + s->cr_key_index = 1;
> + } else if (s->cr_key_index == 1 && value == 0xCDEF89AB) {
> + /* Valid key; unlock FLASH_CR */
> + s->flash_cr.lock = 0;
> + s->cr_key_index = 0;
> + } else {
> + /* Invalid key; permanently lock FLASH_CR until reset */
> + s->flash_cr.lock = 1;
> + s->cr_key_index = -1;
> + }
> + return;
> + case FLASH_OPTKEYR:
> + if (s->optcr_key_index == 0 && value == 0x08192A3B) {
> + s->optcr_key_index = 1;
> + } else if (s->optcr_key_index == 1 && value == 0x4C5D6E7F) {
> + /* Valid key; unlock FLASH_OPTCR */
> + s->flash_optcr.optlock = 0;
> + s->optcr_key_index = 0;
> + } else {
> + /* Invalid key; lock FLASH_OPTCR until reset */
> + s->flash_optcr.optlock = 1;
> + s->optcr_key_index = -1;
> + }
> + return;
> + case FLASH_SR:
> + if (s->flash_sr.eop) s->flash_sr.eop = 0;
> + if (s->flash_sr.operr) s->flash_sr.operr = 0;
> + if (s->flash_sr.wrperr) s->flash_sr.wrperr = 0;
> + if (s->flash_sr.pgaerr) s->flash_sr.pgaerr = 0;
> + if (s->flash_sr.pgperr) s->flash_sr.pgperr = 0;
> + if (s->flash_sr.pgserr) s->flash_sr.pgserr = 0;
> + return;
> + case FLASH_CR:
> + flash_cr_write(s, (FlashCrType)value);
> + return;
> + case FLASH_OPTCR:
> + flash_optcr_write(s, (FlashOptcrType)value);
> + return;
> + default:
> + qemu_log_mask(
> + LOG_GUEST_ERROR,
> + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
> + }
> +}
> +
> +static const MemoryRegionOps stm32f4xx_flashif_ops = {
> + .read = stm32f4xx_flashif_read,
> + .write = stm32f4xx_flashif_write,
> + .endianness = DEVICE_NATIVE_ENDIAN };
> +
> +static void stm32f4xx_flashif_init(Object *obj) {
> + STM32F4xxFlashIfState *s = STM32F4XX_FLASHIF(obj);
> +
> + memory_region_init_io(&s->mmio, obj, &stm32f4xx_flashif_ops, s,
> + TYPE_STM32F4XX_FLASHIF, 0x400);
> + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); }
> +
> +static const VMStateDescription vmstate_stm32f4xx_flashif = {
> + .name = TYPE_STM32F4XX_FLASHIF,
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .fields = (VMStateField[]) {
> + VMSTATE_UINT32(flash_acr.reg, STM32F4xxFlashIfState),
> + VMSTATE_UINT32(flash_keyr.reg, STM32F4xxFlashIfState),
> + VMSTATE_UINT32(flash_optkeyr.reg, STM32F4xxFlashIfState),
> + VMSTATE_UINT32(flash_sr.reg, STM32F4xxFlashIfState),
> + VMSTATE_UINT32(flash_cr.reg, STM32F4xxFlashIfState),
> + VMSTATE_UINT32(flash_optcr.reg, STM32F4xxFlashIfState),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> +static void stm32f4xx_flashif_class_init(ObjectClass *klass, void
> +*data) {
> + DeviceClass *dc = DEVICE_CLASS(klass);
> +
> + dc->reset = stm32f4xx_flashif_reset;
> + dc->vmsd = &vmstate_stm32f4xx_flashif; }
> +
> +static const TypeInfo stm32f4xx_flashif_info = {
> + .name = TYPE_STM32F4XX_FLASHIF,
> + .parent = TYPE_SYS_BUS_DEVICE,
> + .instance_size = sizeof(STM32F4xxFlashIfState),
> + .instance_init = stm32f4xx_flashif_init,
> + .class_init = stm32f4xx_flashif_class_init
> +};
> +
> +static void stm32f4xx_flashif_register_types(void)
> +{
> + type_register_static(&stm32f4xx_flashif_info);
> +}
> +
> +type_init(stm32f4xx_flashif_register_types)
> diff --git a/hw/misc/trace-events b/hw/misc/trace-events index
> 7f0f5dff3a..bd9a5dd483 100644
> --- a/hw/misc/trace-events
> +++ b/hw/misc/trace-events
> @@ -84,6 +84,10 @@ mos6522_set_sr_int(void) "set sr_int"
> mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 "
> val=0x%"PRIx64 mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 "
> val=0x%x"
>
> +# stm32f4xx_flashif
> +stm32f4xx_flashif_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " "
> +stm32f4xx_flashif_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%"
> PRIx64 " val: 0x%" PRIx64 ""
> +
> # stm32f4xx_syscfg
> stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d,
> Line: %d; Level: %d"
> stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
> diff --git a/include/hw/arm/stm32f405_soc.h
> b/include/hw/arm/stm32f405_soc.h index 1fe97f8c3a..a94c3c51ac 100644
> --- a/include/hw/arm/stm32f405_soc.h
> +++ b/include/hw/arm/stm32f405_soc.h
> @@ -25,6 +25,7 @@
> #ifndef HW_ARM_STM32F405_SOC_H
> #define HW_ARM_STM32F405_SOC_H
>
> +#include "hw/misc/stm32f4xx_flashif.h"
> #include "hw/misc/stm32f4xx_syscfg.h"
> #include "hw/timer/stm32f2xx_timer.h"
> #include "hw/char/stm32f2xx_usart.h"
> @@ -57,6 +58,7 @@ typedef struct STM32F405State {
>
> ARMv7MState armv7m;
>
> + STM32F4xxFlashIfState flashif;
> STM32F4xxSyscfgState syscfg;
> STM32F4xxExtiState exti;
> STM32F2XXUsartState usart[STM_NUM_USARTS]; diff --git
> a/include/hw/misc/stm32f4xx_flashif.h
> b/include/hw/misc/stm32f4xx_flashif.h
> new file mode 100644
> index 0000000000..e364ca39c7
> --- /dev/null
> +++ b/include/hw/misc/stm32f4xx_flashif.h
> @@ -0,0 +1,144 @@
> +/*
> + * STM32F4xx FLASHIF
> + *
> + * Copyright (c) 2020 Stephanos Ioannidis <address@hidden>
> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a copy
> + * of this software and associated documentation files (the
> +"Software"), to deal
> + * in the Software without restriction, including without limitation
> +the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense,
> +and/or sell
> + * copies of the Software, and to permit persons to whom the Software
> +is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> +included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
> +SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
> +OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> +ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> +DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef HW_STM_FLASHIF_H
> +#define HW_STM_FLASHIF_H
> +
> +#include "hw/sysbus.h"
> +#include "hw/hw.h"
> +
> +#define TYPE_STM32F4XX_FLASHIF "stm32f4xx-flashif"
> +#define STM32F4XX_FLASHIF(obj) \
> + OBJECT_CHECK(STM32F4xxFlashIfState, (obj),
> +TYPE_STM32F4XX_FLASHIF)
> +
> +#define FLASH_ACR 0x00
> +#define FLASH_KEYR 0x04
> +#define FLASH_OPTKEYR 0x08
> +#define FLASH_SR 0x0C
> +#define FLASH_CR 0x10
> +#define FLASH_OPTCR 0x14
> +
> +typedef union {
> + struct {
> + uint32_t latency : 3;
> + uint32_t reserved0 : 5;
> + uint32_t prften : 1;
> + uint32_t icen : 1;
> + uint32_t dcen : 1;
> + uint32_t icrst : 1;
> + uint32_t dcrst : 1;
> + uint32_t reserved1 : 19;
> + };
> + uint32_t reg;
> +} FlashAcrType;
> +
> +typedef union {
> + struct {
> + uint32_t key : 32;
> + };
> + uint32_t reg;
> +} FlashKeyrType;
> +
> +typedef union {
> + struct {
> + uint32_t optkey : 32;
> + };
> + uint32_t reg;
> +} FlashOptkeyrType;
> +
> +typedef union {
> + struct {
> + uint32_t eop : 1;
> + uint32_t operr : 1;
> + uint32_t reserved0 : 2;
> + uint32_t wrperr : 1;
> + uint32_t pgaerr : 1;
> + uint32_t pgperr : 1;
> + uint32_t pgserr : 1;
> + uint32_t reserved1 : 8;
> + uint32_t bsy : 1;
> + uint32_t reserved2 : 15;
> + };
> + uint32_t reg;
> +} FlashSrType;
> +
> +typedef union {
> + struct {
> + uint32_t pg : 1;
> + uint32_t ser : 1;
> + uint32_t mer : 1;
> + uint32_t snb : 4;
> + uint32_t reserved0 : 1;
> + uint32_t psize : 2;
> + uint32_t reserved1 : 6;
> + uint32_t strt : 1;
> + uint32_t reserved2 : 7;
> + uint32_t eopie : 1;
> + uint32_t reserved3 : 6;
> + uint32_t lock : 1;
> + };
> + uint32_t reg;
> +} FlashCrType;
> +
> +typedef union {
> + struct {
> + uint32_t optlock : 1;
> + uint32_t optstrt : 1;
> + uint32_t bor_lev : 2;
> + uint32_t reserved0 : 1;
> + uint32_t wdg_sw : 1;
> + uint32_t nrst_stop : 1;
> + uint32_t nrst_stdby : 1;
> + uint32_t rdp : 8;
> + uint32_t nwrp : 12;
> + uint32_t reserved1 : 4;
> + };
> + uint32_t reg;
> +} FlashOptcrType;
> +
> +typedef struct {
> + /* <private> */
> + SysBusDevice parent_obj;
> +
> + /* <public> */
> + MemoryRegion mmio;
> +
> + int32_t cr_key_index;
> + int32_t optcr_key_index;
> +
> + /* Access control register (FLASH_ACR) */
> + FlashAcrType flash_acr;
> + /* Key register (FLASH_KEYR) */
> + FlashKeyrType flash_keyr;
> + /* Option key register (FLASH_OPTKEYR) */
> + FlashOptkeyrType flash_optkeyr;
> + /* Status register (FLASH_SR) */
> + FlashSrType flash_sr;
> + /* Control register (FLASH_CR) */
> + FlashCrType flash_cr;
> + /* Option control register (FLASH_OPTCR) */
> + FlashOptcrType flash_optcr;
> +} STM32F4xxFlashIfState;
> +
> +#endif
> --
> 2.17.1
>
>