forked from micropython/micropython
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsemihosting_rv32.h
247 lines (206 loc) · 10.8 KB
/
semihosting_rv32.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2024 Alessandro Gatti
*
* 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 MICROPY_INCLUDED_SHARED_RUNTIME_SEMIHOSTING_RV32_H
#define MICROPY_INCLUDED_SHARED_RUNTIME_SEMIHOSTING_RV32_H
/*
* To integrate semihosting, make sure to call mp_semihosting_init() first.
* Then, if the host system's STDOUT should be used instead of a UART, replace
* mp_hal_stdin_rx_chr and similar calls in mphalport.c with the semihosting
* equivalents.
*
* At runtime, make sure that the debugger is attached and semihosting is
* enabled on its end. The terminal must be configured in raw mode with local
* echo disabled, on Linux this can be done with "stty raw -echo" on the
* command line.
*/
/*
* This follows the RISC-V Semihosting specification version 0.3.
*
* That document can be downloaded from
* https://github.com/riscv-non-isa/riscv-semihosting/releases/
*
* Version 0.3 claims that the current RISC-V Semihosting implementation
* should follow Arm's, and more precisely the "Semihosting for AArch32
* and AArch64" document, revision 2023Q3.
*/
#include <stddef.h>
#include <stdint.h>
#include <stdnoreturn.h>
// A container for heap and stack pointers as returned by SYS_HEAPINFO.
typedef struct {
void *heap_base;
void *heap_limit;
void *stack_base;
void *stack_limit;
} mp_semihosting_heap_info_t;
// A 64-bits value indicating how many ticks were counted since the target
// image's execution started.
typedef struct {
uint32_t low;
uint32_t high;
} mp_semihosting_elapsed_ticks_t;
// The host system's STDOUT file handle.
extern int mp_semihosting_stdout;
// The host system's STDERR file handle. If the host system does not support
// explicit STDOUT and STDERR handles, this handle will be aliased to STDOUT
// instead.
extern int mp_semihosting_stderr;
/*
* Even though exit codes from 0x20000 to 0x20007 are part of the original Arm
* specification document, they are omitted due to them being tied to hardware
* events. Whilst some of them may still have a meaning on the RISC-V
* platform, it is not yet clear which ones are available and which ones are
* not. Thus, only "soft" error codes are provided here although the SYS_EXIT
* and SYS_EXIT_EXTENDED semihosting calls accept any 32-bits integer as an
* exit code.
*/
enum {
MP_SEMIHOSTING_EXIT_BREAKPOINT = 0x20020,
MP_SEMIHOSTING_EXIT_WATCHPOINT,
MP_SEMIHOSTING_EXIT_STEP_COMPLETE,
MP_SEMIHOSTING_EXIT_RUNTIME_ERROR_UNKNOWN,
MP_SEMIHOSTING_EXIT_INTERNAL_ERROR,
MP_SEMIHOSTING_EXIT_USER_INTERRUPTION,
MP_SEMIHOSTING_EXIT_APPLICATION_EXIT,
MP_SEMIHOSTING_EXIT_STACK_OVERFLOW,
MP_SEMIHOSTING_EXIT_DIVISION_BY_ZERO,
MP_SEMIHOSTING_EXIT_OS_SPECIFIC
};
// Initialises semihosting support.
void mp_semihosting_init();
// Read a character from the host system's STDIN stream.
int mp_semihosting_rx_char();
// Write the given string to the host system's STDOUT stream.
int mp_semihosting_tx_strn(const char *string, size_t length);
// Write the given string to the host system's STDOUT stream, writing a CR byte
// before each LF byte to be written.
int mp_semihosting_tx_strn_cooked(const char *string, size_t length);
// Terminates execution with the given code and an optional subcode. This
// will choose the appropriate semihosting call (either SYS_EXIT or
// SYS_EXIT_EXTENDED) depending on the host system's reported capabilities.
noreturn void mp_semihosting_terminate(uint32_t code, uint32_t subcode);
// Direct semihosting calls access.
// Open a file on the host system with the given name and file mode.
// The file mode follows fopen(3)'s syntax. The function will return -1 if it
// failed to open the required file, or a file handle number if the operation
// succeeded. To see why the operation failed, call mp_semihosting_errno.
int mp_semihosting_open(const char *file_name, const char *file_mode);
// Close a file previously opened with mp_semihosting_open. If the file cannot
// be closed, the function will return -1, otherwise it will return 0. To see
// why the operation failed, call mp_semihosting_errno.
int mp_semihosting_close(int handle);
// Write the given character to the host system's STDOUT file handle.
void mp_semihosting_writec(char character);
// Write the given NULL-terminated string to the host system's STDOUT file
// handle.
void mp_semihosting_write0(const char *string);
// Write the given buffer to the given host system file handle. The function
// will return how many characters were left to be written (0 if the operation
// wrote the whole buffer), or -1 if the input buffer pointer is NULL.
int mp_semihosting_write(int handle, const void *data, size_t length);
// Read from the given host system file handle into the given buffer. The
// function will return how many characters were left to be read (0 if the
// operation read whole buffer), or -1 if the input buffer pointer is NULL.
int mp_semihosting_read(int handle, void *data, size_t length);
// Read a single character from the host system's STDIN file handle.
int mp_semihosting_readc(void);
// Check whether the given result code represents an error. The function will
// return a non-zero value if the code is indeed an error, or zero otherwise.
int mp_semihosting_iserror(int code);
// Check whether the given host system file handle is mapped to an interactive
// device. The function will return 1 if the handle is mapped to an
// interactive device, 0 if it is mapped to a regular file, and anything else
// if an error occurred.
int mp_semihosting_istty(int handle);
// Move the file pointer on the given host system's file handle to the given
// absolute offset (in bytes). The function will return 0 if the file pointer
// was moved to the requested position, or a negative value if it was not
// possible to do so. To see why the operation failed, call
// mp_semihosting_errno.
int mp_semihosting_seek(int handle, uint32_t offset);
// Get the length (in bytes) of the host system's file mapped to the given
// handle. The function will return a negative value if an error occurred, or
// the requested file's length (in bytes).
int mp_semihosting_flen(int handle);
// Create a temporary file on the host system. The function requires a file
// identifier between 0 and 255 (inclusive) that will be bound to the requested
// temporary file. Subsequent calls to mp_semihosting_tmpnam with the same
// identifier will always return the same host system file name. On success,
// the function will fill the given buffer with the host system's file name,
// and will return 0. If the buffer pointer is NULL, the buffer name area is
// too small, or the operation failed on the host system's end, the function
// will return -1 instead. Make sure that the buffer is big enough to contain
// a host system's full path name.
int mp_semihosting_tmpnam(uint8_t identifier, void *buffer, size_t buffer_length);
// Delete a file on the host system's matching the given file name. The
// function will return 0 if the deletion operation succeeded, or a host system
// dependent error code instead.
int mp_semihosting_remove(const char *file_name);
// Rename a file on the host system's name matching the given file name to the
// new chosen name. The function will return 0 if the rename operation
// succeeded, or a host system dependent error code instead.
int mp_semihosting_rename(const char *old_name, const char *new_name);
// Get how many hundredths of a second passed since execution started. If an
// error occurred whilst retrieving clock value, the function will return -1.
int mp_semihosting_clock(void);
// Get the host system's clock in seconds since midnight of January 1st, 1970
// at UTC.
int mp_semihosting_time(void);
// Execute the given command on the host system. The function will return the
// command's result code retrieved on the host system.
int mp_semihosting_system(const char *command);
// Get the last operation's status code. The function will return the host
// system's errno variable contents, and can be used to see the exact result
// code for failed I/O operations.
int mp_semihosting_errno(void);
// Get the host system's command line that started execution of the target
// image. The function will fill the given buffer with the command line
// arguments passed to the target executable. The function will return 0 on
// success, or -1 if it failed. Make sure that the buffer can contain at
// least 80 bytes, as it is the minimum supported size defined by the
// specifications document.
int mp_semihosting_get_cmdline(void *buffer, size_t buffer_length);
// Fill the given heap info structure with the system's stack and heap
// start/end addresses.
void mp_semihosting_heapinfo(mp_semihosting_heap_info_t *block);
// Terminate the execution with the given reason code and optional subcode.
// This should be preferred over mp_semihosting_exit_extended if the host
// system does not support the SYS_EXIT_EXTENDED semihosting call. In doubt
// use mp_semihosting_terminate instead.
noreturn void mp_semihosting_exit(uint32_t code, uint32_t subcode);
// Terminate the execution with the given reason code and optional subcode.
// This should be preferred over mp_semihosting_exit if the host system
// supports this semihosting call. In doubt use mp_semihosting_terminate
// instead.
noreturn void mp_semihosting_exit_extended(uint32_t code, uint32_t subcode);
// Fill the given structure with how many ticks were counted since execution
// started. On success, the function will return 0, or -1 if it was not
// possible to compute the ticks count.
int mp_semihosting_elapsed(mp_semihosting_elapsed_ticks_t *ticks);
// Get the system's tick frequency. If this value is not known, the function
// will return -1 instead.
int mp_semihosting_tickfreq(void);
#endif // MICROPY_INCLUDED_SHARED_SEMIHOSTING_RUNTIME_RV32_H