1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

stdio_semihosting: Extend with RISC-V support

RISC-V support semihosting in very similar way as the cortex-m
microcontrollers. The code calls a breakpoint instruction and the
attached debugger reads/writes registers and memory for stdio.

The RISC-V architecture doesn't support a call number with the EBREAK
instruction, to allow the debugger to detect a semihosting break point,
the EBREAK instruction is wrapped in a SLLI and SRAI instruction. These
use x0 as output register, making them NOP instructions.

One caveat when using this is that the RISC-V core traps the EBREAK
instruction with trap code 3 when no debugger is attached. Restarting
the application with the debugger attached avoids this.
This commit is contained in:
Koen Zandberg 2020-09-09 11:32:30 +02:00
parent b3ffb690b1
commit 0a6c9c4ec0
No known key found for this signature in database
GPG Key ID: 0895A893E6D2985B
2 changed files with 46 additions and 5 deletions

View File

@ -46,7 +46,7 @@ endif
ifneq (,$(filter stdio_semihosting,$(USEMODULE))) ifneq (,$(filter stdio_semihosting,$(USEMODULE)))
USEMODULE += xtimer USEMODULE += xtimer
FEATURES_REQUIRED += cpu_core_cortexm FEATURES_REQUIRED_ANY += cpu_core_cortexm|arch_riscv
endif endif
# enable stdout buffering for modules that benefit from sending out buffers in larger chunks # enable stdout buffering for modules that benefit from sending out buffers in larger chunks

View File

@ -11,7 +11,10 @@
* @{ * @{
* *
* @file * @file
* @brief STDIO over ARM Semihosting implementation * @brief STDIO over ARM and RISC-V Semihosting implementation
*
* RISC-V semihosting closely mimics ARM semihosting. Only the break sequence is
* different, but all defined values are also used with RISC-V
* *
* @author Koen Zandberg <koen@bergzand.net> * @author Koen Zandberg <koen@bergzand.net>
* *
@ -35,17 +38,19 @@
#define STDIO_SEMIHOSTING_POLL_RATE (10 * US_PER_MS) #define STDIO_SEMIHOSTING_POLL_RATE (10 * US_PER_MS)
/** /**
* @brief ARM Semihosting STDIN file descriptor * @brief ARM Semihosting STDIN file descriptor. Also used with RISC-V
*/ */
#define STDIO_SEMIHOSTING_F_STDIN (1) #define STDIO_SEMIHOSTING_F_STDIN (1)
/** /**
* @brief ARM Semihosting STDOUT file descriptor * @brief ARM Semihosting STDOUT file descriptor. Also used with RISC-V
*/ */
#define STDIO_SEMIHOSTING_F_STDOUT (1) #define STDIO_SEMIHOSTING_F_STDOUT (1)
/** /**
* @name ARM Semihosting commands * @name ARM Semihosting commands.
*
* RISC-V copied over these command names and values
* *
* Extend when required * Extend when required
* @{ * @{
@ -54,6 +59,41 @@
#define STDIO_SEMIHOSTING_SYS_READ (0x06) /**< Read command */ #define STDIO_SEMIHOSTING_SYS_READ (0x06) /**< Read command */
/** @} */ /** @} */
#if defined(CPU_FE310)
static bool _semihosting_connected(void) {
return true;
}
static uint32_t _semihosting_raw(int cmd, uint32_t *args)
{
uint32_t result = 0;
/* Moves cmd and args to r0 and r1. Then triggers a breakpoint.
* Finally moves the results stored in r0 to result
*/
__asm__(
".option norvc \n"
"mv a0, %[cmd] \n"
"mv a1, %[args] \n"
/* Wrapping the ebreak instruction in two NOP SLLI and SRAI instructions
* act as indicator to the GDB session that this is a
* semihosting trap */
"slli x0, x0, 0x1f \n"
"ebreak \n"
"srai x0, x0, 7 \n"
"mv %[result], a0 \n"
: /* Outputs */
[result] "=r" (result)
: /* Inputs */
[cmd] "r" (cmd),
[args] "r" (args)
: /* Clobbered registers */
"a0", "a1", "memory"
);
return result;
}
#elif defined(MODULE_CORTEXM_COMMON)
static bool _semihosting_connected(void) { static bool _semihosting_connected(void) {
#ifdef CoreDebug_DHCSR_C_DEBUGEN_Msk #ifdef CoreDebug_DHCSR_C_DEBUGEN_Msk
/* Best effort attempt to detect if a debug session is active */ /* Best effort attempt to detect if a debug session is active */
@ -84,6 +124,7 @@ static uint32_t _semihosting_raw(int cmd, uint32_t *args)
); );
return result; return result;
} }
#endif
static size_t _semihosting_write(const uint8_t *buffer, size_t len) static size_t _semihosting_write(const uint8_t *buffer, size_t len)
{ {