[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v1 5/5] Netduino: Add the Netduino Plus 2 Machine Mo
From: |
Alistair Francis |
Subject: |
[Qemu-devel] [PATCH v1 5/5] Netduino: Add the Netduino Plus 2 Machine Model |
Date: |
Sun, 24 Aug 2014 10:14:15 +1000 |
This patch adds the Netduion Plus 2 machine to QEMU.
Signed-off-by: Alistair Francis <address@hidden>
---
hw/arm/Makefile.objs | 2 +-
hw/arm/netduinoplus2.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 203 insertions(+), 1 deletion(-)
create mode 100644 hw/arm/netduinoplus2.c
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 6088e53..616f1ae 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -2,7 +2,7 @@ obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
obj-$(CONFIG_DIGIC) += digic_boards.o
obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
-obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
+obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
netduinoplus2.o
obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
obj-$(CONFIG_DIGIC) += digic.o
diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c
new file mode 100644
index 0000000..32acac5
--- /dev/null
+++ b/hw/arm/netduinoplus2.c
@@ -0,0 +1,202 @@
+/*
+ * Netduino Plus 2 Machine Model
+ *
+ * Copyright (c) 2014 Alistair Francis <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 "hw/sysbus.h"
+#include "hw/ssi.h"
+#include "hw/arm/arm.h"
+#include "hw/devices.h"
+#include "qemu/timer.h"
+#include "net/net.h"
+#include "elf.h"
+#include "hw/loader.h"
+#include "hw/boards.h"
+#include "exec/address-spaces.h"
+#include "qemu/error-report.h"
+#include "sysemu/qtest.h"
+
+#define FLASH_BASE_ADDRESS 0x08000000
+#define FLASH_SIZE (1024 * 1024)
+#define SRAM_BASE_ADDRESS 0x20000000
+#define SRAM_SIZE (192 * 1024)
+
+typedef struct ARMV7MResetArgs {
+ ARMCPU *cpu;
+ uint32_t reset_sp;
+ uint32_t reset_pc;
+} ARMV7MResetArgs;
+
+static void armv7m_reset(void *opaque)
+{
+ ARMV7MResetArgs *args = opaque;
+
+ cpu_reset(CPU(args->cpu));
+
+ args->cpu->env.regs[13] = args->reset_sp & 0xFFFFFFFC;
+ args->cpu->env.thumb = args->reset_pc & 1;
+ args->cpu->env.regs[15] = args->reset_pc & ~1;
+}
+
+static void netduinoplus2_init(MachineState *machine)
+{
+ static const uint32_t gpio_addr[] = { 0x40020000, 0x40020400, 0x40020800,
+ 0x40020C00, 0x40021000, 0x40021400, 0x40021800, 0x40021C00,
+ 0x40022000, 0x40022400, 0x40022800 };
+ static const uint8_t gpio_letters[] = { 'a', 'b', 'c',
+ 'd', 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k' };
+ static const uint32_t tim2_5_addr[] = { 0x40000000, 0x40000400,
+ 0x40000800, 0x40000C00 };
+ static const uint32_t usart_addr[] = { 0x40011000, 0x40004400,
+ 0x40004800, 0x40004C00, 0x40005000, 0x40011400, 0x40007800,
+ 0x40007C00 };
+ const char *kernel_filename = machine->kernel_filename;
+
+ static const int tim2_5_irq[] = {28, 29, 30, 50};
+ static const int usart_irq[] = {37, 38, 39, 52, 53, 71, 82, 83};
+
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *sram = g_new(MemoryRegion, 1);
+ MemoryRegion *flash = g_new(MemoryRegion, 1);
+ MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
+ MemoryRegion *hack = g_new(MemoryRegion, 1);
+ ARMV7MResetArgs reset_args;
+
+ qemu_irq pic[96];
+ ARMCPU *cpu;
+ CPUARMState *env;
+ DeviceState *nvic;
+ DeviceState *gpio;
+ SysBusDevice *busdev;
+
+ int image_size;
+ uint64_t entry;
+ uint64_t lowaddr;
+ int i;
+ int big_endian = 0;
+
+ /* The Netduinio Plus 2 uses a Cortex-M4, while QEMU currently supports
+ * the Cortex-M3, so that is being used instead
+ */
+ cpu = cpu_arm_init("cortex-m3");
+ env = &cpu->env;
+
+ memory_region_init_ram(flash, NULL, "netduino.flash", FLASH_SIZE);
+ memory_region_init_alias(flash_alias, NULL, "netduino.flash.alias",
+ flash, 0, FLASH_SIZE);
+
+ vmstate_register_ram_global(flash);
+
+ memory_region_set_readonly(flash, true);
+ memory_region_set_readonly(flash_alias, true);
+
+ memory_region_add_subregion(address_space_mem, FLASH_BASE_ADDRESS, flash);
+ memory_region_add_subregion(address_space_mem, 0, flash_alias);
+
+ memory_region_init_ram(sram, NULL, "netduino.sram", SRAM_SIZE);
+ vmstate_register_ram_global(sram);
+ memory_region_add_subregion(address_space_mem, SRAM_BASE_ADDRESS, sram);
+
+ nvic = qdev_create(NULL, "armv7m_nvic");
+ qdev_prop_set_uint32(nvic, "num-irq", 96);
+ env->nvic = nvic;
+ qdev_init_nofail(nvic);
+ sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
+ qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
+ for (i = 0; i < 96; i++) {
+ pic[i] = qdev_get_gpio_in(nvic, i);
+ }
+
+ /* Load the kernel */
+ if (!kernel_filename && !qtest_enabled()) {
+ fprintf(stderr, "Guest image must be specified (using -kernel)\n");
+ exit(1);
+ }
+ if (kernel_filename) {
+ image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
+ NULL, big_endian, ELF_MACHINE, 1);
+ if (image_size < 0) {
+ image_size = load_image_targphys(kernel_filename, 0, FLASH_SIZE);
+ lowaddr = 0;
+ }
+ if (image_size < 0) {
+ error_report("Could not load kernel '%s'", kernel_filename);
+ exit(1);
+ }
+ }
+
+ /* System configuration controller */
+ sysbus_create_simple("netduino_syscfg", 0x40013800,
+ pic[71]);
+
+ /* Attach a UART (uses USART registers) and USART controllers */
+ for (i = 0; i < 7; i++) {
+ sysbus_create_simple("netduino_usart", usart_addr[i],
+ pic[usart_irq[i]]);
+ }
+
+ /* Timer 2 to 5 */
+ for (i = 0; i < 4; i++) {
+ sysbus_create_simple("netduino_timer", tim2_5_addr[i],
+ pic[tim2_5_irq[i]]);
+ }
+
+ /* Attach GPIO devices */
+ for (i = 0; i < 11; i++) {
+ gpio = qdev_create(NULL, "netduino_gpio");
+ qdev_prop_set_uint8(gpio, "gpio-letter", gpio_letters[i]);
+ qdev_init_nofail(gpio);
+ busdev = SYS_BUS_DEVICE(gpio);
+ sysbus_mmio_map(busdev, 0, gpio_addr[i]);
+ }
+
+ /* Hack to map an additional page of ram at the top of the address
+ * space. This stops qemu complaining about executing code outside RAM
+ * when returning from an exception.
+ */
+ memory_region_init_ram(hack, NULL, "netduino.hack", 0x1000);
+ vmstate_register_ram_global(hack);
+ memory_region_set_readonly(hack, true);
+ memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
+
+ reset_args = (ARMV7MResetArgs) {
+ .cpu = cpu,
+ .reset_pc = entry,
+ .reset_sp = (SRAM_BASE_ADDRESS + (SRAM_SIZE * 2)/3),
+ };
+ qemu_register_reset(armv7m_reset,
+ g_memdup(&reset_args, sizeof(reset_args)));
+}
+
+static QEMUMachine netduinoplus2_machine = {
+ .name = "netduinoplus2",
+ .desc = "Netduino Plus 2 Machine (Except with a Cortex-M3)",
+ .init = netduinoplus2_init,
+};
+
+static void netduinoplus2_machine_init(void)
+{
+ qemu_register_machine(&netduinoplus2_machine);
+}
+
+machine_init(netduinoplus2_machine_init);
--
1.9.1