QEMU Trace

Trace

semihosting    itm    segger-rtt

https://github.com/pokitoz/qemu-lm3s6965evb

https://github.com/pokitoz/qemu-lm3s6965evb/blob/master/start.c

https://github.com/iNvEr7/qemu-learn

Cortex-M3

链接参数中需要加入 -specs=nano.specs -specs=rdimon.specs

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

/*
Static functions and constant data */ const int SYS_WRITE0 = 0x04; void semihost(int sys_id, const void *arg) { register int r0 __asm__ ("r0") = sys_id; register const void *r1 __asm__ ("r1") = arg; __asm__ volatile ("bkpt 0xab"); (void) r0; (void) r1; } void logPrint(const char* format, ...) { char buffer[256] = {''}; int bufferPos = 0; unsigned int hex; va_list arg; va_start(arg, format); for(const char* nextChar = format; *nextChar != ''; nextChar++) { while ((*nextChar != '%') && (*nextChar != '')) { sprintf(buffer + bufferPos, "%c", *nextChar); bufferPos++; nextChar++; } if (*nextChar == '') { break; } nextChar++; switch (*nextChar) { case 'x': hex = va_arg(arg, unsigned int); int written = 0; written = sprintf(buffer + bufferPos, "%x", hex); bufferPos = bufferPos + written; break; } } buffer[bufferPos] = ''; va_end(arg); semihost(SYS_WRITE0, buffer); } int main(void) { uint8_t i; uint8_t str[] = "hello world! "; semihost(SYS_WRITE0, str); for(i = 0; i < 8; i++) { logPrint("hello world! 0x%x ", i); } return 0; }
/*
 * This file is part of the µOS++ distribution.
 *   (https://github.com/micro-os-plus)
 * Copyright (c) 2015 Liviu Ionescu.
 *
 * 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 CMSIS_PLUS_ARM_SEMIHOSTING_H_
#define CMSIS_PLUS_ARM_SEMIHOSTING_H_

// ----------------------------------------------------------------------------

// Semihosting operations.
enum OperationNumber
{
  // Regular operations
  SEMIHOSTING_EnterSVC = 0x17,
  SEMIHOSTING_ReportException = 0x18,
  SEMIHOSTING_SYS_CLOSE = 0x02,
  SEMIHOSTING_SYS_CLOCK = 0x10,
  SEMIHOSTING_SYS_ELAPSED = 0x30,
  SEMIHOSTING_SYS_ERRNO = 0x13,
  SEMIHOSTING_SYS_FLEN = 0x0C,
  SEMIHOSTING_SYS_GET_CMDLINE = 0x15,
  SEMIHOSTING_SYS_HEAPINFO = 0x16,
  SEMIHOSTING_SYS_ISERROR = 0x08,
  SEMIHOSTING_SYS_ISTTY = 0x09,
  SEMIHOSTING_SYS_OPEN = 0x01,
  SEMIHOSTING_SYS_READ = 0x06,
  SEMIHOSTING_SYS_READC = 0x07,
  SEMIHOSTING_SYS_REMOVE = 0x0E,
  SEMIHOSTING_SYS_RENAME = 0x0F,
  SEMIHOSTING_SYS_SEEK = 0x0A,
  SEMIHOSTING_SYS_SYSTEM = 0x12,
  SEMIHOSTING_SYS_TICKFREQ = 0x31,
  SEMIHOSTING_SYS_TIME = 0x11,
  SEMIHOSTING_SYS_TMPNAM = 0x0D,
  SEMIHOSTING_SYS_WRITE = 0x05,
  SEMIHOSTING_SYS_WRITEC = 0x03,
  SEMIHOSTING_SYS_WRITE0 = 0x04,

  // Codes returned by SEMIHOSTING_ReportException
  ADP_Stopped_ApplicationExit = ((2 << 16) + 38),
  ADP_Stopped_RunTimeError = ((2 << 16) + 35),

};

// ----------------------------------------------------------------------------

// SWI numbers and reason codes for RDI (Angel) monitors.
#define AngelSWI_ARM                    0x123456
#ifdef __thumb__
#define AngelSWI                        0xAB
#else
#define AngelSWI                        AngelSWI_ARM
#endif
// For thumb only architectures use the BKPT instruction instead of SWI.
#if defined(__ARM_ARCH_7M__)     
    || defined(__ARM_ARCH_7EM__) 
    || defined(__ARM_ARCH_6M__)
#define AngelSWIInsn                    "bkpt"
#define AngelSWIAsm                     bkpt
#else
#define AngelSWIInsn                    "swi"
#define AngelSWIAsm                     swi
#endif

#if defined(OS_DEBUG_SEMIHOSTING_FAULTS)
// Testing the local semihosting handler cannot use another BKPT, since this
// configuration cannot trigger HaedFault exceptions while the debugger is
// connected, so we use an illegal op code, that will trigger an
// UsageFault exception.
#define AngelSWITestFault       "setend be"
#define AngelSWITestFaultOpCode (0xB658)
#endif

static inline int
__attribute__ ((always_inline))
call_host (int reason, void* arg)
{
  int value;
  asm volatile (

      " mov r0, %[rsn]  
"
      " mov r1, %[arg]  
"
#if defined(OS_DEBUG_SEMIHOSTING_FAULTS)
      " " AngelSWITestFault " 
"
#else
      " " AngelSWIInsn " %[swi] 
"
#endif
      " mov %[val], r0"

      : [val] "=r" (value) /* Outputs */
      : [rsn] "r" (reason), [arg] "r" (arg), [swi] "i" (AngelSWI) /* Inputs */
      : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc"
      // Clobbers r0 and r1, and lr if in supervisor mode
  );

  // Accordingly to page 13-77 of ARM DUI 0040D other registers
  // can also be clobbered. Some memory positions may also be
  // changed by a system call, so they should not be kept in
  // registers. Note: we are assuming the manual is right and
  // Angel is respecting the APCS.
  return value;
}

// ----------------------------------------------------------------------------

// Function used in _exit() to return the status code as Angel exception.
static inline void
__attribute__ ((always_inline,noreturn))
report_exception (int reason)
{
  call_host (SEMIHOSTING_ReportException, (void*) reason);

  for (;;)
    ;
}

// ----------------------------------------------------------------------------

#endif /* CMSIS_PLUS_ARM_SEMIHOSTING_H_ */
View Code

https://github.com/micro-os-plus/semihosting-xpack

https://github.com/micro-os-plus/micro-os-plus-iii/blob/1ea30f65acfc9b25e8bf6558035e5dd1bc3b9127/include/cmsis-plus/arm/semihosting.h

ITM

 /*
  * This file is part of the µOS++ distribution.
  *   (https://github.com/micro-os-plus)
  * Copyright (c) 2015 Liviu Ionescu.
  *
  * 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.
  */
 
 #if defined(__ARM_EABI__)
 
 // ----------------------------------------------------------------------------
 
 #if defined(TRACE)
 
 #include <cmsis-plus/os-app-config.h>
 
 #if defined(OS_USE_TRACE_ITM)
 
 #include <cmsis-plus/diag/trace.h>
 
 // TODO: Find a better way to include the ITM definitions (including
 // the entire vendor header is averkill).
 #include <cmsis_device.h>
 
 // ----------------------------------------------------------------------------
 
 namespace os
 {
     namespace trace
     {
       // ------------------------------------------------------------------------
 
       void
       initialize (void)
       {
         // For ITM no inits required.
         // The debug registers are set the JTAG software.
       }
 
       // ----------------------------------------------------------------------
 
 #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
 
       // ITM is the ARM standard mechanism, running over SWD/SWO on Cortex-M3/M4
       // devices, and is the recommended setting, if available.
       //
       // The JLink probe and the GDB server fully support SWD/SWO
       // and the JLink Debugging plug-in enables it by default.
       // The current OpenOCD does not include support to parse the SWO stream,
       // so this configuration will not work on OpenOCD (will not crash, but
       // nothing will be displayed in the output console).
 
 #if !defined(OS_INTEGER_TRACE_ITM_STIMULUS_PORT)
 #define OS_INTEGER_TRACE_ITM_STIMULUS_PORT     (0)
 #endif
 
       ssize_t
       write (const void* buf, std::size_t nbyte)
       {
         if (buf == nullptr || nbyte == 0)
           {
             return 0;
           }
 
         const char* cbuf = (const char*) buf;
 
         for (size_t i = 0; i < nbyte; i++)
           {
             // Check if ITM or the stimulus port are not enabled.
             if (((ITM->TCR & ITM_TCR_ITMENA_Msk) == 0)
                 || ((ITM->TER & (1UL << OS_INTEGER_TRACE_ITM_STIMULUS_PORT))
                     == 0))
               {
                 // Return the number of sent characters (may be 0).
                 return (ssize_t) i;
               }
 
             // Wait until STIMx is ready...
             while (ITM->PORT[OS_INTEGER_TRACE_ITM_STIMULUS_PORT].u32 == 0)
               ;
             // then send data, one byte at a time
             ITM->PORT[OS_INTEGER_TRACE_ITM_STIMULUS_PORT].u8 =
                 (uint8_t) (*cbuf++);
           }
 
         // All characters successfully sent.
         return (ssize_t) nbyte;
       }
 
 #else
 
 #error "ITM available only on ARCH 7M"
 
 #endif /* defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) */
 
     } /* namespace trace */
 } /* namespace os */
 
 #endif /* defined(OS_USE_TRACE_ITM) */
 #endif /* defined(TRACE) */
 
 // ----------------------------------------------------------------------------
 
 #endif /* defined(__ARM_EABI__) */
 
View Code

http://micro-os-plus.github.io/reference/cmsis-plus/trace-itm_8cpp_source.html

http://micro-os-plus.github.io/reference/cmsis-plus/trace-semihosting_8cpp_source.html

https://wiki.segger.com/Semihosting

https://www.keil.com/support/man/docs/armcc/armcc_pge1358787045051.htm

https://bbs.pediy.com/thread-266324.htm

https://github.com/iNvEr7/qemu-learn/tree/master/semihosting-newlib

https://github.com/OP-TEE/build/blob/637c7863d7e428d673b18bae21ac1db52b2a9b8d/qemu.mk#L179

QEMU Bug

https://bugs.launchpad.net/qemu/+bug/1915925

https://bugs.launchpad.net/qemu/+bug/1918302

不是newlib的bug

https://sourceware.org/pipermail/newlib/2021/018261.html

patch

https://github.com/qemu/qemu/tree/c95bd5ff1660883d15ad6e0005e4c8571604f51a

diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
index 94950b6c56..d8181c972c 100644
--- a/semihosting/arm-compat-semi.c
+++ b/semihosting/arm-compat-semi.c
@@ -1232,7 +1232,11 @@ target_ulong do_common_semihosting(CPUState *cs)
             for (i = 0; i < ARRAY_SIZE(retvals); i++) {
                 bool fail;
 
-                fail = SET_ARG(i, retvals[i]);
+                if (is_a64(env)) {
+                    fail = put_user_u64(retvals[i], arg0 + i * 8);
+                } else {
+                    fail = put_user_u32(retvals[i], arg0 + i * 4);
+                }
 
                 if (fail) {
                     /* Couldn't write back to argument block */

 或者使用下面这个

diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
index 94950b6c56..1028e19133 100644
--- a/semihosting/arm-compat-semi.c
+++ b/semihosting/arm-compat-semi.c
@@ -789,6 +789,11 @@ static const GuestFDFunctions guestfd_fns[] = {
     (is_a64(env) ?                                      
      put_user_u64(val, args + (n) * 8) :                
      put_user_u32(val, args + (n) * 4))
+
+#define SET_ARG0(n, val)                                 
+    (is_a64(env) ?                                      
+     put_user_u64(val, arg0 + (n) * 8) :                
+     put_user_u32(val, arg0 + (n) * 4))
 #endif
 
 #ifdef TARGET_RISCV
@@ -1232,7 +1237,7 @@ target_ulong do_common_semihosting(CPUState *cs)
             for (i = 0; i < ARRAY_SIZE(retvals); i++) {
                 bool fail;
 
-                fail = SET_ARG(i, retvals[i]);
+                fail = SET_ARG0(i, retvals[i]);
 
                 if (fail) {
                     /* Couldn't write back to argument block */

github上最新commit的代码已经修复该问题

https://github.com/qemu/qemu/commit/35e3f029a966845e090dc8b295312751524df967

xPack QEMU ARM (qemu-system-gnuarmeclipse)已经修复该问题

https://github.com/xpack-dev-tools/qemu

https://github.com/xpack-dev-tools/qemu/blob/xpack/target-arm/arm-semi.c

https://github.com/xpack-dev-tools/qemu/commit/f5666418c449b49917ea24cdb0bed76a602a3c74

            for (i = 0; i < ARRAY_SIZE(retvals); i++) {
                bool fail;

                if (is_a64(env)) {
                    fail = put_user_u64(retvals[i], arg0 + i * 8);
                } else {
                    fail = put_user_u32(retvals[i], arg0 + i * 4);
                }

                if (fail) {
                    /* Couldn't write back to argument block */
                    return -1;
                }
            }
            return 0;
        }

https://www.bahutou.cn/2018/04/11/RTOS-dev-env/

https://github.com/beckus/stm32_p103_demos

https://logiase.github.io/The-Embedded-Rust-Book-CN/start/qemu.html

https://rustcc.com/article?id=88c8ac37-c31c-495c-8b17-7e12b51a618a

https://github.com/rust-embedded/cortex-m-quickstart

https://docs.rust-embedded.org/book/start/qemu.html

https://github.com/cbhust/STM32F429_Discovery_FreeRTOS_9

https://www.cnblogs.com/wall-f/p/7615943.html

https://github.com/SuYouge/stm32f4-vscode/tree/ucos/cube/UCOSIII

原文地址:https://www.cnblogs.com/sinferwu/p/14565703.html