aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2021-04-13 14:41:45 -0700
committerGitHub <noreply@github.com>2021-04-13 14:41:45 -0700
commit1b05661baa79f03830f5ddefa999dc7aaf7b1ce1 (patch)
treec3b934eea5e0522888edc7a4cf742d09afaa7512
parent1ce128fa78c24bb0ed399c647e7139322b5353a7 (diff)
downloadriscv-tests-1b05661baa79f03830f5ddefa999dc7aaf7b1ce1.zip
riscv-tests-1b05661baa79f03830f5ddefa999dc7aaf7b1ce1.tar.gz
riscv-tests-1b05661baa79f03830f5ddefa999dc7aaf7b1ce1.tar.bz2
Add FreeRTOS smoke tests. (#333)
* Add FreeRTOS smoke tests. Make sure that OpenOCD can access all threads in a FreeRTOS binary on single-hart RV32 and RV64. * Also test `-rtos FreeRTOS`.
-rw-r--r--debug/bin/README.md7
-rw-r--r--debug/bin/RTOSDemo32.axfbin0 -> 131616 bytes
-rw-r--r--debug/bin/RTOSDemo64.axfbin0 -> 147328 bytes
-rwxr-xr-xdebug/gdbserver.py54
-rw-r--r--debug/targets.py9
-rw-r--r--debug/targets/RISC-V/spike-1.cfg7
-rw-r--r--debug/targets/RISC-V/spike32.py3
-rw-r--r--debug/targets/RISC-V/spike64.py3
-rw-r--r--debug/testlib.py35
9 files changed, 103 insertions, 15 deletions
diff --git a/debug/bin/README.md b/debug/bin/README.md
new file mode 100644
index 0000000..7e81515
--- /dev/null
+++ b/debug/bin/README.md
@@ -0,0 +1,7 @@
+This directory contains binaries that are not easy to compile.
+
+RTOSDemo32.axf and RTOSDemo64.axf are created by checking out
+https://github.com/FreeRTOS/FreeRTOS, following the instructions in
+`FreeRTOS/Demo/RISC-V-spike-htif_GCC/README.md`, and building:
+* `make XLEN=32 BASE_ADDRESS=0x10000000`
+* `make XLEN=64 BASE_ADDRESS=0x1212340000`
diff --git a/debug/bin/RTOSDemo32.axf b/debug/bin/RTOSDemo32.axf
new file mode 100644
index 0000000..5fa3fe7
--- /dev/null
+++ b/debug/bin/RTOSDemo32.axf
Binary files differ
diff --git a/debug/bin/RTOSDemo64.axf b/debug/bin/RTOSDemo64.axf
new file mode 100644
index 0000000..bfa2a2a
--- /dev/null
+++ b/debug/bin/RTOSDemo64.axf
Binary files differ
diff --git a/debug/gdbserver.py b/debug/gdbserver.py
index 0a174d3..bcac02c 100755
--- a/debug/gdbserver.py
+++ b/debug/gdbserver.py
@@ -1700,6 +1700,60 @@ class VectorTest(GdbSingleHartTest):
assertIn("_exit", output)
assertEqual(self.gdb.p("status"), 0)
+class FreeRtosTest(GdbTest):
+ def early_applicable(self):
+ return self.target.freertos_binary
+
+ def freertos(self):
+ return True
+
+ def test(self):
+ self.gdb.command("file %s" % self.target.freertos_binary)
+ self.gdb.load()
+
+ output = self.gdb.command("monitor riscv_freertos_stacking mainline")
+
+ # Turn off htif, which doesn't work when the file is loaded into spike
+ # through gdb. It only works when spike loads the ELF file itself.
+ bp = self.gdb.b("main")
+ self.gdb.c()
+ self.gdb.command("delete %d" % bp)
+ self.gdb.p("*((int*) &use_htif) = 0")
+ # Need this, otherwise gdb complains that there is no current active
+ # thread.
+ self.gdb.threads()
+
+ bp = self.gdb.b("prvQueueReceiveTask")
+
+ self.gdb.c()
+ self.gdb.command("delete %d" % bp)
+
+ bp = self.gdb.b("prvQueueSendTask")
+ self.gdb.c()
+ self.gdb.command("delete %d" % bp)
+
+ # Now we know for sure at least 2 threads have executed.
+
+ threads = self.gdb.threads()
+ assertGreater(len(threads), 1)
+
+ values = {}
+ for thread in threads:
+ assertNotIn("No Name", thread[1])
+ self.gdb.thread(thread)
+ assertEqual(self.gdb.p("$zero"), 0)
+ output = self.gdb.command("info reg sp")
+ assertIn("ucHeap", output)
+ self.gdb.command("info reg mstatus")
+ values[thread.id] = self.gdb.p("$s11")
+ self.gdb.p("$s11=0x%x" % (values[thread.id] ^ int(thread.id)))
+
+ # Test that writing worked
+ self.gdb.stepi()
+ for thread in self.gdb.threads():
+ self.gdb.thread(thread)
+ assertEqual(self.gdb.p("$s11"), values[thread.id] ^ int(thread.id))
+
parsed = None
def main():
parser = argparse.ArgumentParser(
diff --git a/debug/targets.py b/debug/targets.py
index f8f7b6f..0890465 100644
--- a/debug/targets.py
+++ b/debug/targets.py
@@ -108,6 +108,10 @@ class Target:
# limitation/hardware support.
support_memory_sampling = True
+ # Relative path to a FreeRTOS binary compiled from the spike demo project
+ # in https://github.com/FreeRTOS/FreeRTOS.
+ freertos_binary = None
+
# Internal variables:
directory = None
temporary_files = []
@@ -143,11 +147,12 @@ class Target:
def create(self):
"""Create the target out of thin air, eg. start a simulator."""
- def server(self):
+ def server(self, test):
"""Start the debug server that gdb connects to, eg. OpenOCD."""
return testlib.Openocd(server_cmd=self.server_cmd,
config=self.openocd_config_path,
- timeout=self.server_timeout_sec)
+ timeout=self.server_timeout_sec,
+ freertos=test.freertos())
def do_compile(self, hart, *sources):
binary_name = "%s_%s-%d" % (
diff --git a/debug/targets/RISC-V/spike-1.cfg b/debug/targets/RISC-V/spike-1.cfg
index 3bc32d1..5f11b08 100644
--- a/debug/targets/RISC-V/spike-1.cfg
+++ b/debug/targets/RISC-V/spike-1.cfg
@@ -8,10 +8,13 @@ set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913
set _TARGETNAME $_CHIPNAME.cpu
-target create $_TARGETNAME riscv -chain-position $_TARGETNAME
+if {$::env(USE_FREERTOS)} {
+ target create $_TARGETNAME riscv -chain-position $_TARGETNAME -rtos FreeRTOS
+} else {
+ target create $_TARGETNAME riscv -chain-position $_TARGETNAME
+}
$_TARGETNAME configure -work-area-phys $::env(WORK_AREA) -work-area-size 8096 -work-area-backup 1
-
gdb_report_data_abort enable
gdb_report_register_access_error enable
diff --git a/debug/targets/RISC-V/spike32.py b/debug/targets/RISC-V/spike32.py
index 463e7cf..381aea7 100644
--- a/debug/targets/RISC-V/spike32.py
+++ b/debug/targets/RISC-V/spike32.py
@@ -5,7 +5,7 @@ class spike32_hart(targets.Hart):
xlen = 32
ram = 0x10000000
ram_size = 0x10000000
- bad_address = 0x10000000 - 8
+ bad_address = ram - 8
instruction_hardware_breakpoint_count = 4
reset_vectors = [0x1000]
link_script_path = "spike32.lds"
@@ -19,6 +19,7 @@ class spike32(targets.Target):
timeout_sec = 30
implements_custom_test = True
support_memory_sampling = False # Needs SBA
+ freertos_binary = "bin/RTOSDemo32.axf"
def create(self):
# 64-bit FPRs on 32-bit target
diff --git a/debug/targets/RISC-V/spike64.py b/debug/targets/RISC-V/spike64.py
index cdb67f7..c4c66c8 100644
--- a/debug/targets/RISC-V/spike64.py
+++ b/debug/targets/RISC-V/spike64.py
@@ -5,7 +5,7 @@ class spike64_hart(targets.Hart):
xlen = 64
ram = 0x1212340000
ram_size = 0x10000000
- bad_address = 0x1212340000 - 8
+ bad_address = ram - 8
instruction_hardware_breakpoint_count = 4
reset_vectors = [0x1000]
link_script_path = "spike64.lds"
@@ -18,6 +18,7 @@ class spike64(targets.Target):
openocd_config_path = "spike-1.cfg"
timeout_sec = 30
implements_custom_test = True
+ freertos_binary = "bin/RTOSDemo64.axf"
def create(self):
# 32-bit FPRs only
diff --git a/debug/testlib.py b/debug/testlib.py
index d8fc891..501e0e6 100644
--- a/debug/testlib.py
+++ b/debug/testlib.py
@@ -245,7 +245,8 @@ class Openocd:
logfile = tempfile.NamedTemporaryFile(prefix='openocd', suffix='.log')
logname = logfile.name
- def __init__(self, server_cmd=None, config=None, debug=False, timeout=60):
+ def __init__(self, server_cmd=None, config=None, debug=False, timeout=60,
+ freertos=False):
self.timeout = timeout
if server_cmd:
@@ -280,6 +281,12 @@ class Openocd:
if debug:
cmd.append("-d")
+ extra_env = {}
+ if freertos:
+ extra_env['USE_FREERTOS'] = "1"
+ else:
+ extra_env['USE_FREERTOS'] = "0"
+
raw_logfile = open(Openocd.logname, "wb")
try:
spike_dasm = subprocess.Popen("spike-dasm", stdin=subprocess.PIPE,
@@ -292,17 +299,21 @@ class Openocd:
env_entries = ("REMOTE_BITBANG_HOST", "REMOTE_BITBANG_PORT",
"WORK_AREA")
env_entries = [key for key in env_entries if key in os.environ]
- logfile.write(("+ %s%s\n" % (
- "".join("%s=%s " % (key, os.environ[key]) for key in env_entries),
- " ".join(map(pipes.quote, cmd)))).encode())
+ parts = [
+ " ".join("%s=%s" % (key, os.environ[key]) for key in env_entries),
+ " ".join("%s=%s" % (k, v) for k, v in extra_env.items()),
+ " ".join(map(pipes.quote, cmd))
+ ]
+ logfile.write(("+ %s\n" % " ".join(parts)).encode())
logfile.flush()
self.gdb_ports = []
- self.process = self.start(cmd, logfile)
+ self.process = self.start(cmd, logfile, extra_env)
- def start(self, cmd, logfile):
+ def start(self, cmd, logfile, extra_env):
+ combined_env = {**os.environ, **extra_env}
process = subprocess.Popen(cmd, stdin=subprocess.PIPE,
- stdout=logfile, stderr=logfile)
+ stdout=logfile, stderr=logfile, env=combined_env)
try:
# Wait for OpenOCD to have made it through riscv_examine(). When
@@ -710,7 +721,7 @@ class Gdb:
value = shlex.split(output.split('=')[-1].strip())[1]
return value
- def info_registers(self, group):
+ def info_registers(self, group=""):
output = self.command("info registers %s" % group, ops=5)
result = {}
for line in output.splitlines():
@@ -954,6 +965,12 @@ class BaseTest:
# pylint: disable=no-self-use
return True
+ def freertos(self):
+ """Return a true value if the test is running a FreeRTOS binary where
+ the debugger should expose FreeRTOS threads to gdb."""
+ # pylint: disable=no-self-use
+ return False
+
def setup(self):
pass
@@ -971,7 +988,7 @@ class BaseTest:
if self.target_process:
self.logs.append(self.target_process.logname)
try:
- self.server = self.target.server()
+ self.server = self.target.server(self)
self.logs.append(self.server.logname)
except Exception:
for log in self.logs: