Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/avr-port-202…
Browse files Browse the repository at this point in the history
…00711' into staging

8bit AVR port from Michael Rolnik.

Michael started to work on the AVR port few years ago [*] and kept
improving the code over various series.

List of people who help him (in chronological order):
- Richard Henderson
- Sarah Harris and Edward Robbins
- Philippe Mathieu-Daudé and Aleksandar Markovic
- Pavel Dovgalyuk
- Thomas Huth

[*] The oldest contribution I could find on the list is from 2016:
https://lists.nongnu.org/archive/html/qemu-devel/2016-06/msg02985.html

Tests included:

$ avocado --show=app run -t arch:avr tests/acceptance/
Fetching asset from tests/acceptance/machine_avr6.py:AVR6Machine.test_freertos
 (1/1) tests/acceptance/machine_avr6.py:AVR6Machine.test_freertos: PASS (2.13 s)
RESULTS    : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
JOB TIME   : 2.35 s

$ make check-qtest-avr
  TEST    check-qtest-avr: tests/qtest/boot-serial-test
  TEST    check-qtest-avr: tests/qtest/cdrom-test
  TEST    check-qtest-avr: tests/qtest/device-introspect-test
  TEST    check-qtest-avr: tests/qtest/machine-none-test
  TEST    check-qtest-avr: tests/qtest/qmp-test
  TEST    check-qtest-avr: tests/qtest/qmp-cmd-test
  TEST    check-qtest-avr: tests/qtest/qom-test
  TEST    check-qtest-avr: tests/qtest/test-hmp
  TEST    check-qtest-avr: tests/qtest/qos-test

CI results:
. https://cirrus-ci.com/build/5697049146425344
. https://gitlab.com/philmd/qemu/-/pipelines/165328058
. https://travis-ci.org/github/philmd/qemu/builds/705817933
. https://app.shippable.com/github/philmd/qemu/runs/822/summary/console

# gpg: Signature made Sat 11 Jul 2020 10:03:11 BST
# gpg:                using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD  6BB2 E3E3 2C2C DEAD C0DE

* remotes/philmd-gitlab/tags/avr-port-20200711: (32 commits)
  target/avr/disas: Fix store instructions display order
  target/avr/cpu: Fix $PC displayed address
  target/avr/cpu: Drop tlb_flush() in avr_cpu_reset()
  target/avr: Add section into QEMU documentation
  tests/acceptance: Test the Arduino MEGA2560 board
  tests/boot-serial: Test some Arduino boards (AVR based)
  hw/avr: Add limited support for some Arduino boards
  hw/avr: Add some ATmega microcontrollers
  hw/avr: Add support for loading ELF/raw binaries
  hw/misc: avr: Add limited support for power reduction device
  hw/timer: avr: Add limited support for 16-bit timer peripheral
  hw/char: avr: Add limited support for USART peripheral
  tests/machine-none: Add AVR support
  target/avr: Register AVR support with the rest of QEMU
  target/avr: Add support for disassembling via option '-d in_asm'
  target/avr: Initialize TCG register variables
  target/avr: Add instruction translation - CPU main translation function
  target/avr: Add instruction translation - MCU Control Instructions
  target/avr: Add instruction translation - Bit and Bit-test Instructions
  target/avr: Add instruction translation - Data Transfer Instructions
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Jul 11, 2020
2 parents 2033cc6 + 19b2934 commit d344983
Show file tree
Hide file tree
Showing 49 changed files with 7,172 additions and 1 deletion.
30 changes: 30 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,14 @@ S: Maintained
F: hw/arm/smmu*
F: include/hw/arm/smmu*

AVR TCG CPUs
M: Michael Rolnik <mrolnik@gmail.com>
R: Sarah Harris <S.E.Harris@kent.ac.uk>
S: Maintained
F: gdb-xml/avr-cpu.xml
F: target/avr/
F: tests/acceptance/machine_avr6.py

CRIS TCG CPUs
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
S: Maintained
Expand Down Expand Up @@ -982,6 +990,28 @@ F: include/hw/*/nrf51*.h
F: include/hw/*/microbit*.h
F: tests/qtest/microbit-test.c

AVR Machines
-------------

AVR MCUs
M: Michael Rolnik <mrolnik@gmail.com>
R: Sarah Harris <S.E.Harris@kent.ac.uk>
S: Maintained
F: default-configs/avr-softmmu.mak
F: hw/avr/
F: include/hw/char/avr_usart.h
F: hw/char/avr_usart.c
F: include/hw/timer/avr_timer16.h
F: hw/timer/avr_timer16.c
F: include/hw/misc/avr_power.h
F: hw/misc/avr_power.c

Arduino
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
R: Sarah Harris <S.E.Harris@kent.ac.uk>
S: Maintained
F: hw/avr/arduino.c

CRIS Machines
-------------
Axis Dev88
Expand Down
7 changes: 7 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -8143,6 +8143,10 @@ case "$target_name" in
mttcg="yes"
gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml"
;;
avr)
gdb_xml_files="avr-cpu.xml"
target_compiler=$cross_cc_avr
;;
cris)
;;
hppa)
Expand Down Expand Up @@ -8387,6 +8391,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
disas_config "ARM_A64"
fi
;;
avr)
disas_config "AVR"
;;
cris)
disas_config "CRIS"
;;
Expand Down
5 changes: 5 additions & 0 deletions default-configs/avr-softmmu.mak
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Default configuration for avr-softmmu

# Boards:
#
CONFIG_ARDUINO=y
37 changes: 37 additions & 0 deletions docs/system/target-avr.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.. _AVR-System-emulator:

AVR System emulator
-------------------

Use the executable ``qemu-system-avr`` to emulate a AVR 8 bit based machine.
These can have one of the following cores: avr1, avr2, avr25, avr3, avr31,
avr35, avr4, avr5, avr51, avr6, avrtiny, xmega2, xmega3, xmega4, xmega5,
xmega6 and xmega7.

As for now it supports few Arduino boards for educational and testing purposes.
These boards use a ATmega controller, which model is limited to USART & 16-bit
timer devices, enought to run FreeRTOS based applications (like
https://github.com/seharris/qemu-avr-tests/blob/master/free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf
).

Following are examples of possible usages, assuming demo.elf is compiled for
AVR cpu

- Continuous non interrupted execution:
``qemu-system-avr -machine mega2560 -bios demo.elf``

- Continuous non interrupted execution with serial output into telnet window:
``qemu-system-avr -machine mega2560 -bios demo.elf -serial
tcp::5678,server,nowait -nographic``
and then in another shell
``telnet localhost 5678``

- Debugging wit GDB debugger:
``qemu-system-avr -machine mega2560 -bios demo.elf -s -S``
and then in another shell
``avr-gdb demo.elf``
and then within GDB shell
``target remote :1234``

- Print out executed instructions:
``qemu-system-avr -machine mega2560 -bios demo.elf -d in_asm``
1 change: 1 addition & 0 deletions docs/system/targets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ Contents:
target-xtensa
target-s390x
target-rx
target-avr
49 changes: 49 additions & 0 deletions gdb-xml/avr-cpu.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2018-2019 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->

<!-- Register numbers are hard-coded in order to maintain backward
compatibility with older versions of tools that didn't use xml
register descriptions. -->

<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.riscv.cpu">
<reg name="r0" bitsize="8" type="int" regnum="0"/>
<reg name="r1" bitsize="8" type="int"/>
<reg name="r2" bitsize="8" type="int"/>
<reg name="r3" bitsize="8" type="int"/>
<reg name="r4" bitsize="8" type="int"/>
<reg name="r5" bitsize="8" type="int"/>
<reg name="r6" bitsize="8" type="int"/>
<reg name="r7" bitsize="8" type="int"/>
<reg name="r8" bitsize="8" type="int"/>
<reg name="r9" bitsize="8" type="int"/>
<reg name="r10" bitsize="8" type="int"/>
<reg name="r11" bitsize="8" type="int"/>
<reg name="r12" bitsize="8" type="int"/>
<reg name="r13" bitsize="8" type="int"/>
<reg name="r14" bitsize="8" type="int"/>
<reg name="r15" bitsize="8" type="int"/>
<reg name="r16" bitsize="8" type="int"/>
<reg name="r17" bitsize="8" type="int"/>
<reg name="r18" bitsize="8" type="int"/>
<reg name="r19" bitsize="8" type="int"/>
<reg name="r20" bitsize="8" type="int"/>
<reg name="r21" bitsize="8" type="int"/>
<reg name="r22" bitsize="8" type="int"/>
<reg name="r23" bitsize="8" type="int"/>
<reg name="r24" bitsize="8" type="int"/>
<reg name="r25" bitsize="8" type="int"/>
<reg name="r26" bitsize="8" type="int"/>
<reg name="r27" bitsize="8" type="int"/>
<reg name="r28" bitsize="8" type="int"/>
<reg name="r29" bitsize="8" type="int"/>
<reg name="r30" bitsize="8" type="int"/>
<reg name="r31" bitsize="8" type="int"/>
<reg name="sreg" bitsize="8" type="int"/>
<reg name="sp" bitsize="8" type="int"/>
<reg name="pc" bitsize="8" type="int"/>
</feature>
1 change: 1 addition & 0 deletions hw/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ source watchdog/Kconfig
# arch Kconfig
source arm/Kconfig
source alpha/Kconfig
source avr/Kconfig
source cris/Kconfig
source hppa/Kconfig
source i386/Kconfig
Expand Down
9 changes: 9 additions & 0 deletions hw/avr/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
config AVR_ATMEGA_MCU
bool
select AVR_TIMER16
select AVR_USART
select AVR_POWER

config ARDUINO
select AVR_ATMEGA_MCU
select UNIMP
3 changes: 3 additions & 0 deletions hw/avr/Makefile.objs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
obj-y += boot.o
obj-$(CONFIG_AVR_ATMEGA_MCU) += atmega.o
obj-$(CONFIG_ARDUINO) += arduino.o
149 changes: 149 additions & 0 deletions hw/avr/arduino.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* QEMU Arduino boards
*
* Copyright (c) 2019-2020 Philippe Mathieu-Daudé
*
* This work is licensed under the terms of the GNU GPLv2 or later.
* See the COPYING file in the top-level directory.
* SPDX-License-Identifier: GPL-2.0-or-later
*/

/* TODO: Implement the use of EXTRAM */

#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/boards.h"
#include "atmega.h"
#include "boot.h"

typedef struct ArduinoMachineState {
/*< private >*/
MachineState parent_obj;
/*< public >*/
AtmegaMcuState mcu;
} ArduinoMachineState;

typedef struct ArduinoMachineClass {
/*< private >*/
MachineClass parent_class;
/*< public >*/
const char *mcu_type;
uint64_t xtal_hz;
} ArduinoMachineClass;

#define TYPE_ARDUINO_MACHINE \
MACHINE_TYPE_NAME("arduino")
#define ARDUINO_MACHINE(obj) \
OBJECT_CHECK(ArduinoMachineState, (obj), TYPE_ARDUINO_MACHINE)
#define ARDUINO_MACHINE_CLASS(klass) \
OBJECT_CLASS_CHECK(ArduinoMachineClass, (klass), TYPE_ARDUINO_MACHINE)
#define ARDUINO_MACHINE_GET_CLASS(obj) \
OBJECT_GET_CLASS(ArduinoMachineClass, (obj), TYPE_ARDUINO_MACHINE)

static void arduino_machine_init(MachineState *machine)
{
ArduinoMachineClass *amc = ARDUINO_MACHINE_GET_CLASS(machine);
ArduinoMachineState *ams = ARDUINO_MACHINE(machine);

object_initialize_child(OBJECT(machine), "mcu", &ams->mcu, amc->mcu_type);
object_property_set_uint(OBJECT(&ams->mcu), "xtal-frequency-hz",
amc->xtal_hz, &error_abort);
sysbus_realize(SYS_BUS_DEVICE(&ams->mcu), &error_abort);

if (machine->firmware) {
if (!avr_load_firmware(&ams->mcu.cpu, machine,
&ams->mcu.flash, machine->firmware)) {
exit(1);
}
}
}

static void arduino_machine_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);

mc->init = arduino_machine_init;
mc->default_cpus = 1;
mc->min_cpus = mc->default_cpus;
mc->max_cpus = mc->default_cpus;
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->no_parallel = 1;
}

static void arduino_duemilanove_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc);

/* https://www.arduino.cc/en/Main/ArduinoBoardDuemilanove */
mc->desc = "Arduino Duemilanove (ATmega168)",
mc->alias = "2009";
amc->mcu_type = TYPE_ATMEGA168_MCU;
amc->xtal_hz = 16 * 1000 * 1000;
};

static void arduino_uno_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc);

/* https://store.arduino.cc/arduino-uno-rev3 */
mc->desc = "Arduino UNO (ATmega328P)";
mc->alias = "uno";
amc->mcu_type = TYPE_ATMEGA328_MCU;
amc->xtal_hz = 16 * 1000 * 1000;
};

static void arduino_mega_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc);

/* https://www.arduino.cc/en/Main/ArduinoBoardMega */
mc->desc = "Arduino Mega (ATmega1280)";
mc->alias = "mega";
amc->mcu_type = TYPE_ATMEGA1280_MCU;
amc->xtal_hz = 16 * 1000 * 1000;
};

static void arduino_mega2560_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc);

/* https://store.arduino.cc/arduino-mega-2560-rev3 */
mc->desc = "Arduino Mega 2560 (ATmega2560)";
mc->alias = "mega2560";
amc->mcu_type = TYPE_ATMEGA2560_MCU;
amc->xtal_hz = 16 * 1000 * 1000; /* CSTCE16M0V53-R0 */
};

static const TypeInfo arduino_machine_types[] = {
{
.name = MACHINE_TYPE_NAME("arduino-duemilanove"),
.parent = TYPE_ARDUINO_MACHINE,
.class_init = arduino_duemilanove_class_init,
}, {
.name = MACHINE_TYPE_NAME("arduino-uno"),
.parent = TYPE_ARDUINO_MACHINE,
.class_init = arduino_uno_class_init,
}, {
.name = MACHINE_TYPE_NAME("arduino-mega"),
.parent = TYPE_ARDUINO_MACHINE,
.class_init = arduino_mega_class_init,
}, {
.name = MACHINE_TYPE_NAME("arduino-mega-2560-v3"),
.parent = TYPE_ARDUINO_MACHINE,
.class_init = arduino_mega2560_class_init,
}, {
.name = TYPE_ARDUINO_MACHINE,
.parent = TYPE_MACHINE,
.instance_size = sizeof(ArduinoMachineState),
.class_size = sizeof(ArduinoMachineClass),
.class_init = arduino_machine_class_init,
.abstract = true,
}
};

DEFINE_TYPES(arduino_machine_types)
Loading

0 comments on commit d344983

Please sign in to comment.