mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210709' into staging
target-arm queue: * New machine type: stm32vldiscovery * hw/intc/arm_gicv3_cpuif: Fix virtual irq number check in icv_[dir|eoir]_write * hw/gpio/pl061: Honour Luminary PL061 PUR and PDR registers * virt: Fix implementation of GPIO-based powerdown/shutdown mechanism * Correct the encoding of MDCCSR_EL0 and DBGDSCRint * hw/intc: Improve formatting of MEMTX_ERROR guest error message # gpg: Signature made Fri 09 Jul 2021 17:09:10 BST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20210709: hw/intc: Improve formatting of MEMTX_ERROR guest error message target/arm: Correct the encoding of MDCCSR_EL0 and DBGDSCRint hw/arm/stellaris: Expand comment about handling of OLED chipselect hw/gpio/pl061: Document a shortcoming in our implementation hw/gpio/pl061: Convert to 3-phase reset and assert GPIO lines correctly on reset hw/arm/virt: Make PL061 GPIO lines pulled low, not high hw/gpio/pl061: Make pullup/pulldown of outputs configurable hw/gpio/pl061: Honour Luminary PL061 PUR and PDR registers hw/gpio/pl061: Document the interface of this device hw/gpio/pl061: Add tracepoints for register read and write hw/gpio/pl061: Clean up read/write offset handling logic hw/gpio/pl061: Convert DPRINTF to tracepoints hw/intc/arm_gicv3_cpuif: Fix virtual irq number check in icv_[dir|eoir]_write tests/boot-serial-test: Add STM32VLDISCOVERY board testcase docs/system: arm: Add stm32 boards description stm32vldiscovery: Add the STM32VLDISCOVERY Machine stm32f100: Add the stm32f100 SoC Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+13
@@ -893,6 +893,13 @@ F: hw/*/stellaris*
|
||||
F: include/hw/input/gamepad.h
|
||||
F: docs/system/arm/stellaris.rst
|
||||
|
||||
STM32VLDISCOVERY
|
||||
M: Alexandre Iooss <erdnaxe@crans.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/stm32vldiscovery.c
|
||||
F: docs/system/arm/stm32.rst
|
||||
|
||||
Versatile Express
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
@@ -948,6 +955,12 @@ L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/virt-acpi-build.c
|
||||
|
||||
STM32F100
|
||||
M: Alexandre Iooss <erdnaxe@crans.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/stm32f100_soc.c
|
||||
|
||||
STM32F205
|
||||
M: Alistair Francis <alistair@alistair23.me>
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
|
||||
@@ -18,6 +18,7 @@ CONFIG_CHEETAH=y
|
||||
CONFIG_SX1=y
|
||||
CONFIG_NSERIES=y
|
||||
CONFIG_STELLARIS=y
|
||||
CONFIG_STM32VLDISCOVERY=y
|
||||
CONFIG_REALVIEW=y
|
||||
CONFIG_VERSATILE=y
|
||||
CONFIG_VEXPRESS=y
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
STMicroelectronics STM32 boards (``netduino2``, ``netduinoplus2``, ``stm32vldiscovery``)
|
||||
========================================================================================
|
||||
|
||||
The `STM32`_ chips are a family of 32-bit ARM-based microcontroller by
|
||||
STMicroelectronics.
|
||||
|
||||
.. _STM32: https://www.st.com/en/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus.html
|
||||
|
||||
The STM32F1 series is based on ARM Cortex-M3 core. The following machines are
|
||||
based on this chip :
|
||||
|
||||
- ``stm32vldiscovery`` STM32VLDISCOVERY board with STM32F100RBT6 microcontroller
|
||||
|
||||
The STM32F2 series is based on ARM Cortex-M3 core. The following machines are
|
||||
based on this chip :
|
||||
|
||||
- ``netduino2`` Netduino 2 board with STM32F205RFT6 microcontroller
|
||||
|
||||
The STM32F4 series is based on ARM Cortex-M4F core. This series is pin-to-pin
|
||||
compatible with STM32F2 series. The following machines are based on this chip :
|
||||
|
||||
- ``netduinoplus2`` Netduino Plus 2 board with STM32F405RGT6 microcontroller
|
||||
|
||||
There are many other STM32 series that are currently not supported by QEMU.
|
||||
|
||||
Supported devices
|
||||
-----------------
|
||||
|
||||
* ARM Cortex-M3, Cortex M4F
|
||||
* Analog to Digital Converter (ADC)
|
||||
* EXTI interrupt
|
||||
* Serial ports (USART)
|
||||
* SPI controller
|
||||
* System configuration (SYSCFG)
|
||||
* Timer controller (TIMER)
|
||||
|
||||
Missing devices
|
||||
---------------
|
||||
|
||||
* Camera interface (DCMI)
|
||||
* Controller Area Network (CAN)
|
||||
* Cycle Redundancy Check (CRC) calculation unit
|
||||
* Digital to Analog Converter (DAC)
|
||||
* DMA controller
|
||||
* Ethernet controller
|
||||
* Flash Interface Unit
|
||||
* GPIO controller
|
||||
* I2C controller
|
||||
* Inter-Integrated Sound (I2S) controller
|
||||
* 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)
|
||||
|
||||
Boot options
|
||||
------------
|
||||
|
||||
The STM32 machines can be started using the ``-kernel`` option to load a
|
||||
firmware. Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ qemu-system-arm -M stm32vldiscovery -kernel firmware.bin
|
||||
@@ -97,6 +97,7 @@ undocumented; you can get a complete list by running
|
||||
arm/collie
|
||||
arm/sx1
|
||||
arm/stellaris
|
||||
arm/stm32
|
||||
arm/virt
|
||||
arm/xlnx-versal-virt
|
||||
|
||||
|
||||
@@ -239,6 +239,10 @@ config STELLARIS
|
||||
select STELLARIS_ENET # ethernet
|
||||
select UNIMP
|
||||
|
||||
config STM32VLDISCOVERY
|
||||
bool
|
||||
select STM32F100_SOC
|
||||
|
||||
config STRONGARM
|
||||
bool
|
||||
select PXA2XX
|
||||
@@ -326,6 +330,12 @@ config RASPI
|
||||
select SDHCI
|
||||
select USB_DWC2
|
||||
|
||||
config STM32F100_SOC
|
||||
bool
|
||||
select ARM_V7M
|
||||
select STM32F2XX_USART
|
||||
select STM32F2XX_SPI
|
||||
|
||||
config STM32F205_SOC
|
||||
bool
|
||||
select ARM_V7M
|
||||
|
||||
@@ -24,6 +24,7 @@ arm_ss.add(when: 'CONFIG_Z2', if_true: files('z2.c'))
|
||||
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_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'))
|
||||
@@ -39,6 +40,7 @@ arm_ss.add(when: 'CONFIG_STRONGARM', if_true: files('strongarm.c'))
|
||||
arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('allwinner-a10.c', 'cubieboard.c'))
|
||||
arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 'orangepi.c'))
|
||||
arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c', 'bcm2836.c', 'raspi.c'))
|
||||
arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
|
||||
arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
|
||||
arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c'))
|
||||
arm_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp.c', 'xlnx-zcu102.c'))
|
||||
|
||||
+55
-1
@@ -1453,13 +1453,67 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
|
||||
DeviceState *sddev;
|
||||
DeviceState *ssddev;
|
||||
|
||||
/* Some boards have both an OLED controller and SD card connected to
|
||||
/*
|
||||
* Some boards have both an OLED controller and SD card connected to
|
||||
* the same SSI port, with the SD card chip select connected to a
|
||||
* GPIO pin. Technically the OLED chip select is connected to the
|
||||
* SSI Fss pin. We do not bother emulating that as both devices
|
||||
* should never be selected simultaneously, and our OLED controller
|
||||
* ignores stray 0xff commands that occur when deselecting the SD
|
||||
* card.
|
||||
*
|
||||
* The h/w wiring is:
|
||||
* - GPIO pin D0 is wired to the active-low SD card chip select
|
||||
* - GPIO pin A3 is wired to the active-low OLED chip select
|
||||
* - The SoC wiring of the PL061 "auxiliary function" for A3 is
|
||||
* SSI0Fss ("frame signal"), which is an output from the SoC's
|
||||
* SSI controller. The SSI controller takes SSI0Fss low when it
|
||||
* transmits a frame, so it can work as a chip-select signal.
|
||||
* - GPIO A4 is aux-function SSI0Rx, and wired to the SD card Tx
|
||||
* (the OLED never sends data to the CPU, so no wiring needed)
|
||||
* - GPIO A5 is aux-function SSI0Tx, and wired to the SD card Rx
|
||||
* and the OLED display-data-in
|
||||
* - GPIO A2 is aux-function SSI0Clk, wired to SD card and OLED
|
||||
* serial-clock input
|
||||
* So a guest that wants to use the OLED can configure the PL061
|
||||
* to make pins A2, A3, A5 aux-function, so they are connected
|
||||
* directly to the SSI controller. When the SSI controller sends
|
||||
* data it asserts SSI0Fss which selects the OLED.
|
||||
* A guest that wants to use the SD card configures A2, A4 and A5
|
||||
* as aux-function, but leaves A3 as a software-controlled GPIO
|
||||
* line. It asserts the SD card chip-select by using the PL061
|
||||
* to control pin D0, and lets the SSI controller handle Clk, Tx
|
||||
* and Rx. (The SSI controller asserts Fss during tx cycles as
|
||||
* usual, but because A3 is not set to aux-function this is not
|
||||
* forwarded to the OLED, and so the OLED stays unselected.)
|
||||
*
|
||||
* The QEMU implementation instead is:
|
||||
* - GPIO pin D0 is wired to the active-low SD card chip select,
|
||||
* and also to the OLED chip-select which is implemented
|
||||
* as *active-high*
|
||||
* - SSI controller signals go to the devices regardless of
|
||||
* whether the guest programs A2, A4, A5 as aux-function or not
|
||||
*
|
||||
* The problem with this implementation is if the guest doesn't
|
||||
* care about the SD card and only uses the OLED. In that case it
|
||||
* may choose never to do anything with D0 (leaving it in its
|
||||
* default floating state, which reliably leaves the card disabled
|
||||
* because an SD card has a pullup on CS within the card itself),
|
||||
* and only set up A2, A3, A5. This for us would mean the OLED
|
||||
* never gets the chip-select assert it needs. We work around
|
||||
* this with a manual raise of D0 here (despite board creation
|
||||
* code being the wrong place to raise IRQ lines) to put the OLED
|
||||
* into an initially selected state.
|
||||
*
|
||||
* In theory the right way to model this would be:
|
||||
* - Implement aux-function support in the PL061, with an
|
||||
* extra set of AFIN and AFOUT GPIO lines (set up so that
|
||||
* if a GPIO line is in auxfn mode the main GPIO in and out
|
||||
* track the AFIN and AFOUT lines)
|
||||
* - Wire the AFOUT for D0 up to either a line from the
|
||||
* SSI controller that's pulled low around every transmit,
|
||||
* or at least to an always-0 line here on the board
|
||||
* - Make the ssd0323 OLED controller chipselect active-low
|
||||
*/
|
||||
bus = qdev_get_child_bus(dev, "ssi");
|
||||
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* STM32F100 SoC
|
||||
*
|
||||
* Copyright (c) 2021 Alexandre Iooss <erdnaxe@crans.org>
|
||||
* Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
|
||||
*
|
||||
* 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 "qapi/error.h"
|
||||
#include "qemu/module.h"
|
||||
#include "hw/arm/boot.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/arm/stm32f100_soc.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/misc/unimp.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
/* stm32f100_soc implementation is derived from stm32f205_soc */
|
||||
|
||||
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 int usart_irq[STM_NUM_USARTS] = {37, 38, 39};
|
||||
static const int spi_irq[STM_NUM_SPIS] = {35, 36};
|
||||
|
||||
static void stm32f100_soc_initfn(Object *obj)
|
||||
{
|
||||
STM32F100State *s = STM32F100_SOC(obj);
|
||||
int i;
|
||||
|
||||
object_initialize_child(obj, "armv7m", &s->armv7m, TYPE_ARMV7M);
|
||||
|
||||
for (i = 0; i < STM_NUM_USARTS; i++) {
|
||||
object_initialize_child(obj, "usart[*]", &s->usart[i],
|
||||
TYPE_STM32F2XX_USART);
|
||||
}
|
||||
|
||||
for (i = 0; i < STM_NUM_SPIS; i++) {
|
||||
object_initialize_child(obj, "spi[*]", &s->spi[i], TYPE_STM32F2XX_SPI);
|
||||
}
|
||||
}
|
||||
|
||||
static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
{
|
||||
STM32F100State *s = STM32F100_SOC(dev_soc);
|
||||
DeviceState *dev, *armv7m;
|
||||
SysBusDevice *busdev;
|
||||
int i;
|
||||
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
MemoryRegion *sram = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *flash = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
|
||||
|
||||
/*
|
||||
* Init flash region
|
||||
* Flash starts at 0x08000000 and then is aliased to boot memory at 0x0
|
||||
*/
|
||||
memory_region_init_rom(flash, OBJECT(dev_soc), "STM32F100.flash",
|
||||
FLASH_SIZE, &error_fatal);
|
||||
memory_region_init_alias(flash_alias, OBJECT(dev_soc),
|
||||
"STM32F100.flash.alias", flash, 0, FLASH_SIZE);
|
||||
memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
|
||||
memory_region_add_subregion(system_memory, 0, flash_alias);
|
||||
|
||||
/* Init SRAM region */
|
||||
memory_region_init_ram(sram, NULL, "STM32F100.sram", SRAM_SIZE,
|
||||
&error_fatal);
|
||||
memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
|
||||
|
||||
/* Init ARMv7m */
|
||||
armv7m = DEVICE(&s->armv7m);
|
||||
qdev_prop_set_uint32(armv7m, "num-irq", 61);
|
||||
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
|
||||
qdev_prop_set_bit(armv7m, "enable-bitband", true);
|
||||
object_property_set_link(OBJECT(&s->armv7m), "memory",
|
||||
OBJECT(get_system_memory()), &error_abort);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Attach UART (uses USART registers) and USART controllers */
|
||||
for (i = 0; i < STM_NUM_USARTS; i++) {
|
||||
dev = DEVICE(&(s->usart[i]));
|
||||
qdev_prop_set_chr(dev, "chardev", serial_hd(i));
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->usart[i]), errp)) {
|
||||
return;
|
||||
}
|
||||
busdev = SYS_BUS_DEVICE(dev);
|
||||
sysbus_mmio_map(busdev, 0, usart_addr[i]);
|
||||
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
|
||||
}
|
||||
|
||||
/* SPI 1 and 2 */
|
||||
for (i = 0; i < STM_NUM_SPIS; i++) {
|
||||
dev = DEVICE(&(s->spi[i]));
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
|
||||
return;
|
||||
}
|
||||
busdev = SYS_BUS_DEVICE(dev);
|
||||
sysbus_mmio_map(busdev, 0, spi_addr[i]);
|
||||
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
|
||||
}
|
||||
|
||||
create_unimplemented_device("timer[2]", 0x40000000, 0x400);
|
||||
create_unimplemented_device("timer[3]", 0x40000400, 0x400);
|
||||
create_unimplemented_device("timer[4]", 0x40000800, 0x400);
|
||||
create_unimplemented_device("timer[6]", 0x40001000, 0x400);
|
||||
create_unimplemented_device("timer[7]", 0x40001400, 0x400);
|
||||
create_unimplemented_device("RTC", 0x40002800, 0x400);
|
||||
create_unimplemented_device("WWDG", 0x40002C00, 0x400);
|
||||
create_unimplemented_device("IWDG", 0x40003000, 0x400);
|
||||
create_unimplemented_device("I2C1", 0x40005400, 0x400);
|
||||
create_unimplemented_device("I2C2", 0x40005800, 0x400);
|
||||
create_unimplemented_device("BKP", 0x40006C00, 0x400);
|
||||
create_unimplemented_device("PWR", 0x40007000, 0x400);
|
||||
create_unimplemented_device("DAC", 0x40007400, 0x400);
|
||||
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);
|
||||
create_unimplemented_device("timer[16]", 0x40014400, 0x400);
|
||||
create_unimplemented_device("timer[17]", 0x40014800, 0x400);
|
||||
create_unimplemented_device("DMA", 0x40020000, 0x400);
|
||||
create_unimplemented_device("RCC", 0x40021000, 0x400);
|
||||
create_unimplemented_device("Flash Int", 0x40022000, 0x400);
|
||||
create_unimplemented_device("CRC", 0x40023000, 0x400);
|
||||
}
|
||||
|
||||
static Property stm32f100_soc_properties[] = {
|
||||
DEFINE_PROP_STRING("cpu-type", STM32F100State, cpu_type),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void stm32f100_soc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = stm32f100_soc_realize;
|
||||
device_class_set_props(dc, stm32f100_soc_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo stm32f100_soc_info = {
|
||||
.name = TYPE_STM32F100_SOC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(STM32F100State),
|
||||
.instance_init = stm32f100_soc_initfn,
|
||||
.class_init = stm32f100_soc_class_init,
|
||||
};
|
||||
|
||||
static void stm32f100_soc_types(void)
|
||||
{
|
||||
type_register_static(&stm32f100_soc_info);
|
||||
}
|
||||
|
||||
type_init(stm32f100_soc_types)
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* ST STM32VLDISCOVERY machine
|
||||
*
|
||||
* Copyright (c) 2021 Alexandre Iooss <erdnaxe@crans.org>
|
||||
* Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
|
||||
*
|
||||
* 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 "qapi/error.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/arm/stm32f100_soc.h"
|
||||
#include "hw/arm/boot.h"
|
||||
|
||||
/* stm32vldiscovery implementation is derived from netduinoplus2 */
|
||||
|
||||
/* Main SYSCLK frequency in Hz (24MHz) */
|
||||
#define SYSCLK_FRQ 24000000ULL
|
||||
|
||||
static void stm32vldiscovery_init(MachineState *machine)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
/*
|
||||
* TODO: ideally we would model the SoC RCC and let it handle
|
||||
* system_clock_scale, including its ability to define different
|
||||
* possible SYSCLK sources.
|
||||
*/
|
||||
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
|
||||
|
||||
dev = qdev_new(TYPE_STM32F100_SOC);
|
||||
qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
|
||||
armv7m_load_kernel(ARM_CPU(first_cpu),
|
||||
machine->kernel_filename,
|
||||
FLASH_SIZE);
|
||||
}
|
||||
|
||||
static void stm32vldiscovery_machine_init(MachineClass *mc)
|
||||
{
|
||||
mc->desc = "ST STM32VLDISCOVERY (Cortex-M3)";
|
||||
mc->init = stm32vldiscovery_init;
|
||||
}
|
||||
|
||||
DEFINE_MACHINE("stm32vldiscovery", stm32vldiscovery_machine_init)
|
||||
|
||||
@@ -895,6 +895,9 @@ static void create_gpio_devices(const VirtMachineState *vms, int gpio,
|
||||
MachineState *ms = MACHINE(vms);
|
||||
|
||||
pl061_dev = qdev_new("pl061");
|
||||
/* Pull lines down to 0 if not driven by the PL061 */
|
||||
qdev_prop_set_uint32(pl061_dev, "pullups", 0);
|
||||
qdev_prop_set_uint32(pl061_dev, "pulldowns", 0xff);
|
||||
s = SYS_BUS_DEVICE(pl061_dev);
|
||||
sysbus_realize_and_unref(s, &error_fatal);
|
||||
memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
|
||||
|
||||
+271
-70
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,15 @@ nrf51_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x
|
||||
nrf51_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
|
||||
nrf51_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
|
||||
|
||||
# pl061.c
|
||||
pl061_update(const char *id, uint32_t dir, uint32_t data, uint32_t pullups, uint32_t floating) "%s GPIODIR 0x%x GPIODATA 0x%x pullups 0x%x floating 0x%x"
|
||||
pl061_set_output(const char *id, int gpio, int level) "%s setting output %d to %d"
|
||||
pl061_input_change(const char *id, int gpio, int level) "%s input %d changed to %d"
|
||||
pl061_update_istate(const char *id, uint32_t istate, uint32_t im, int level) "%s GPIORIS 0x%x GPIOIE 0x%x interrupt level %d"
|
||||
pl061_read(const char *id, uint64_t offset, uint64_t r) "%s offset 0x%" PRIx64 " value 0x%" PRIx64
|
||||
pl061_write(const char *id, uint64_t offset, uint64_t value) "%s offset 0x%" PRIx64 " value 0x%" PRIx64
|
||||
pl061_reset(const char *id) "%s reset"
|
||||
|
||||
# sifive_gpio.c
|
||||
sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
|
||||
sifive_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64
|
||||
|
||||
@@ -1227,7 +1227,7 @@ static void icv_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
|
||||
trace_gicv3_icv_dir_write(gicv3_redist_affid(cs), value);
|
||||
|
||||
if (irq >= cs->gic->num_irq) {
|
||||
if (irq >= GICV3_MAXIRQ) {
|
||||
/* Also catches special interrupt numbers and LPIs */
|
||||
return;
|
||||
}
|
||||
@@ -1262,7 +1262,7 @@ static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
trace_gicv3_icv_eoir_write(ri->crm == 8 ? 0 : 1,
|
||||
gicv3_redist_affid(cs), value);
|
||||
|
||||
if (irq >= cs->gic->num_irq) {
|
||||
if (irq >= GICV3_MAXIRQ) {
|
||||
/* Also catches special interrupt numbers and LPIs */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -453,7 +453,7 @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
|
||||
if (r == MEMTX_ERROR) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: invalid guest read at offset " TARGET_FMT_plx
|
||||
"size %u\n", __func__, offset, size);
|
||||
" size %u\n", __func__, offset, size);
|
||||
trace_gicv3_redist_badread(gicv3_redist_affid(cs), offset,
|
||||
size, attrs.secure);
|
||||
/* The spec requires that reserved registers are RAZ/WI;
|
||||
@@ -510,7 +510,7 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
|
||||
if (r == MEMTX_ERROR) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: invalid guest write at offset " TARGET_FMT_plx
|
||||
"size %u\n", __func__, offset, size);
|
||||
" size %u\n", __func__, offset, size);
|
||||
trace_gicv3_redist_badwrite(gicv3_redist_affid(cs), offset, data,
|
||||
size, attrs.secure);
|
||||
/* The spec requires that reserved registers are RAZ/WI;
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* STM32F100 SoC
|
||||
*
|
||||
* Copyright (c) 2021 Alexandre Iooss <erdnaxe@crans.org>
|
||||
*
|
||||
* 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_ARM_STM32F100_SOC_H
|
||||
#define HW_ARM_STM32F100_SOC_H
|
||||
|
||||
#include "hw/char/stm32f2xx_usart.h"
|
||||
#include "hw/ssi/stm32f2xx_spi.h"
|
||||
#include "hw/arm/armv7m.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_STM32F100_SOC "stm32f100-soc"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(STM32F100State, STM32F100_SOC)
|
||||
|
||||
#define STM_NUM_USARTS 3
|
||||
#define STM_NUM_SPIS 2
|
||||
|
||||
#define FLASH_BASE_ADDRESS 0x08000000
|
||||
#define FLASH_SIZE (128 * 1024)
|
||||
#define SRAM_BASE_ADDRESS 0x20000000
|
||||
#define SRAM_SIZE (8 * 1024)
|
||||
|
||||
struct STM32F100State {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
char *cpu_type;
|
||||
|
||||
ARMv7MState armv7m;
|
||||
|
||||
STM32F2XXUsartState usart[STM_NUM_USARTS];
|
||||
STM32F2XXSPIState spi[STM_NUM_SPIS];
|
||||
};
|
||||
|
||||
#endif
|
||||
+13
-3
@@ -6326,11 +6326,21 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
|
||||
.access = PL1_RW, .accessfn = access_tda,
|
||||
.fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1),
|
||||
.resetvalue = 0 },
|
||||
/* MDCCSR_EL0, aka DBGDSCRint. This is a read-only mirror of MDSCR_EL1.
|
||||
/*
|
||||
* MDCCSR_EL0[30:29] map to EDSCR[30:29]. Simply RAZ as the external
|
||||
* Debug Communication Channel is not implemented.
|
||||
*/
|
||||
{ .name = "MDCCSR_EL0", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 2, .opc1 = 3, .crn = 0, .crm = 1, .opc2 = 0,
|
||||
.access = PL0_R, .accessfn = access_tda,
|
||||
.type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
/*
|
||||
* DBGDSCRint[15,12,5:2] map to MDSCR_EL1[15,12,5:2]. Map all bits as
|
||||
* it is unlikely a guest will care.
|
||||
* We don't implement the configurable EL0 access.
|
||||
*/
|
||||
{ .name = "MDCCSR_EL0", .state = ARM_CP_STATE_BOTH,
|
||||
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
|
||||
{ .name = "DBGDSCRint", .state = ARM_CP_STATE_AA32,
|
||||
.cp = 14, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
|
||||
.type = ARM_CP_ALIAS,
|
||||
.access = PL1_R, .accessfn = access_tda,
|
||||
.fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), },
|
||||
|
||||
@@ -94,6 +94,41 @@ static const uint8_t kernel_nrf51[] = {
|
||||
0x1c, 0x25, 0x00, 0x40 /* 0x4000251c = UART TXD */
|
||||
};
|
||||
|
||||
static const uint8_t kernel_stm32vldiscovery[] = {
|
||||
0x00, 0x00, 0x00, 0x00, /* Stack top address */
|
||||
0x1d, 0x00, 0x00, 0x00, /* Reset handler address */
|
||||
0x00, 0x00, 0x00, 0x00, /* NMI */
|
||||
0x00, 0x00, 0x00, 0x00, /* Hard fault */
|
||||
0x00, 0x00, 0x00, 0x00, /* Memory management fault */
|
||||
0x00, 0x00, 0x00, 0x00, /* Bus fault */
|
||||
0x00, 0x00, 0x00, 0x00, /* Usage fault */
|
||||
0x0b, 0x4b, /* ldr r3, [pc, #44] Get RCC */
|
||||
0x44, 0xf2, 0x04, 0x02, /* movw r2, #16388 */
|
||||
0x1a, 0x60, /* str r2, [r3] */
|
||||
0x0a, 0x4b, /* ldr r3, [pc, #40] Get GPIOA */
|
||||
0x1a, 0x68, /* ldr r2, [r3] */
|
||||
0x22, 0xf0, 0xf0, 0x02, /* bic r2, r2, #240 */
|
||||
0x1a, 0x60, /* str r2, [r3] */
|
||||
0x1a, 0x68, /* ldr r2, [r3] */
|
||||
0x42, 0xf0, 0xb0, 0x02, /* orr r2, r2, #176 */
|
||||
0x1a, 0x60, /* str r2, [r3] */
|
||||
0x07, 0x4b, /* ldr r3, [pc, #26] Get BAUD */
|
||||
0x45, 0x22, /* movs r2, #69 */
|
||||
0x1a, 0x60, /* str r2, [r3] */
|
||||
0x06, 0x4b, /* ldr r3, [pc, #24] Get ENABLE */
|
||||
0x42, 0xf2, 0x08, 0x02, /* movw r2, #8200 */
|
||||
0x1a, 0x60, /* str r2, [r3] */
|
||||
0x05, 0x4b, /* ldr r3, [pc, #20] Get TXD */
|
||||
0x54, 0x22, /* movs r2, 'T' */
|
||||
0x1a, 0x60, /* str r2, [r3] */
|
||||
0xfe, 0xe7, /* b . */
|
||||
0x18, 0x10, 0x02, 0x40, /* 0x40021018 = RCC */
|
||||
0x04, 0x08, 0x01, 0x40, /* 0x40010804 = GPIOA */
|
||||
0x08, 0x38, 0x01, 0x40, /* 0x40013808 = USART1 BAUD */
|
||||
0x0c, 0x38, 0x01, 0x40, /* 0x4001380c = USART1 ENABLE */
|
||||
0x04, 0x38, 0x01, 0x40 /* 0x40013804 = USART1 TXD */
|
||||
};
|
||||
|
||||
typedef struct testdef {
|
||||
const char *arch; /* Target architecture */
|
||||
const char *machine; /* Name of the machine */
|
||||
@@ -144,6 +179,8 @@ static testdef_t tests[] = {
|
||||
{ "aarch64", "virt", "-cpu max", "TT", sizeof(kernel_aarch64),
|
||||
kernel_aarch64 },
|
||||
{ "arm", "microbit", "", "T", sizeof(kernel_nrf51), kernel_nrf51 },
|
||||
{ "arm", "stm32vldiscovery", "", "T",
|
||||
sizeof(kernel_stm32vldiscovery), kernel_stm32vldiscovery },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user