1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "pico/stdio/driver.h"
8 #include "pico/stdio_semihosting.h"
9 #include "pico/binary_info.h"
10 
stdio_semihosting_out_chars(const char * buf,int length)11 static void stdio_semihosting_out_chars(const char *buf, int length) {
12     // must be volatile or the buffer gets put in registers & optimized away
13     volatile struct {
14         // https://developer.arm.com/documentation/dui0375/g/What-is-Semihosting-/SYS-WRITE--0x05-
15         // arguments, in order:
16         // word 0 = file handle (1 = stdout)
17         // word 1 = pointer to buffer
18         // word 2 = length of buffer
19         size_t fd;
20         const char *buf;
21         size_t len;
22     } args;
23 
24     args.fd = 1;  // 1 = stdout
25     args.buf = buf;
26     args.len = length;
27 
28     __asm (
29     // r1 must contain a pointer to the arguments
30     "mov r1, %[args]\n"
31     // semihosting call number 0x05 = SYS_WRITE
32     "mov r0, #5\n"
33     // make the semihosting call: https://developer.arm.com/documentation/dui0375/g/What-is-Semihosting-/The-semihosting-interface
34     "bkpt 0xab\n"
35     :
36     : [args] "r" (&args)
37     : "r0", "r1");
38 }
39 
40 stdio_driver_t stdio_semihosting = {
41         .out_chars = stdio_semihosting_out_chars,
42 #if PICO_STDIO_ENABLE_CRLF_SUPPORT
43         .crlf_enabled = PICO_STDIO_SEMIHOSTING_DEFAULT_CRLF
44 #endif
45 };
46 
stdio_semihosting_init()47 void stdio_semihosting_init() {
48 #if !PICO_NO_BI_STDIO_SEMIHOSTING
49     bi_decl_if_func_used(bi_program_feature("semihosting stdout"));
50 #endif
51     stdio_set_driver_enabled(&stdio_semihosting, true);
52 }
53 
54