-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13 from sifive/elf
Move to the ELF toolchain
- Loading branch information
Showing
26 changed files
with
287 additions
and
165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,3 +25,4 @@ | |
*.mk | ||
/return_pass | ||
/return_fail | ||
*.specs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,20 +8,39 @@ | |
%.c: mee/machine/@[email protected] | ||
%.S: mee/machine/@[email protected] | ||
%.o: mee/machine/@[email protected] | ||
%.c: riscv__menv__mee.specs | ||
%.S: riscv__menv__mee.specs | ||
%.o: riscv__menv__mee.specs | ||
%.c: riscv__mmachine__@[email protected] | ||
%.S: riscv__mmachine__@[email protected] | ||
%.o: riscv__mmachine__@[email protected] | ||
|
||
# Every test depends on the generated linker script. | ||
$(check_PROGRAMS): mee-@[email protected] | ||
$(check_PROGRAMS): riscv__mmachine__@[email protected] | ||
|
||
# Every test depends on the freshly-compiled library. | ||
$(check_PROGRAMS): libmee-@[email protected] | ||
$(check_PROGRAMS): libriscv__mmachine__@[email protected] | ||
|
||
# Generates a linker script that's more reasonable that whatever GCC's default | ||
# is. | ||
ldsdir = $(libdir) | ||
lds_DATA = mee-@[email protected] | ||
mee-@[email protected]: @LDSCRIPT_GENERATOR@ @[email protected] | ||
lds_DATA = riscv__mmachine__@[email protected] | ||
riscv__mmachine__@[email protected]: @LDSCRIPT_GENERATOR@ @[email protected] | ||
$< --dtb $(filter %.dtb,$^) --linker $@ | ||
|
||
# Generates a SPEC file that sets a reasonable set of default options for this | ||
# build. | ||
specdir = $(libdir) | ||
spec_DATA = | ||
|
||
spec_DATA += riscv__mmachine__@[email protected] | ||
riscv__mmachine__@[email protected]: @SPECS_GENERATOR@ @[email protected] | ||
$< --dtb $(filter %.dtb,$^) --specs $@ --prefix @prefix@ --machine @MACHINE_NAME@ | ||
|
||
spec_DATA += riscv__menv__mee.specs | ||
riscv__menv__mee.specs: riscv__menv__mee.specs.in | ||
cat $^ > $@ | ||
|
||
# In order to generate code that's actually compatible with a machine we must | ||
# pass the march and mabi arguments to GCC that coorespond to the hardware. | ||
# This is handled by generating a makefile fragment, including it, and then | ||
|
@@ -45,6 +64,7 @@ nobase_include_HEADERS = \ | |
mee/compiler.h \ | ||
mee/clock.h \ | ||
mee/io.h \ | ||
mee/machine.h \ | ||
mee/shutdown.h \ | ||
mee/tty.h \ | ||
mee/uart.h | ||
|
@@ -64,14 +84,12 @@ mee/machine/@[email protected]: @MEE_HEADER_GENERATOR@ @[email protected] | |
# Everything in here is compiled into a single library, which contains all the | ||
# source files in the project. It's named for one specific machine, which GCC | ||
# uses to select the target machine that this MEE implementation points at. | ||
lib_LIBRARIES = libmee-@[email protected] | ||
lib_LIBRARIES = libriscv__mmachine__@[email protected] | ||
|
||
libmee_@MACHINE_NAME@_a_CFLAGS = -mmee-machine=@MACHINE_NAME@ | ||
libmee_@MACHINE_NAME@_a_CFLAGS += -ffunction-sections -fdata-sections | ||
libmee_@MACHINE_NAME@_a_CFLAGS += -march=$(FRAMEWORK_BOARD_DTS_MARCH) -mabi=$(FRAMEWORK_BOARD_DTS_MABI) | ||
libmee_@MACHINE_NAME@_a_CCASFLAGS = $(libmee_@MACHINE_NAME@_a_CFLAGS) -DASSEMBLY | ||
libriscv__mmachine__@MACHINE_NAME@_a_CFLAGS = -menv=mee -mmachine=@MACHINE_NAME@ | ||
libriscv__mmachine__@MACHINE_NAME@_a_CCASFLAGS = -menv=mee -mmachine=@MACHINE_NAME@ | ||
|
||
libmee_@MACHINE_NAME@_a_SOURCES = \ | ||
libriscv__mmachine__@MACHINE_NAME@_a_SOURCES = \ | ||
src/drivers/fixed-clock.c \ | ||
src/drivers/sifive,fe310-g000,hfrosc.c \ | ||
src/drivers/sifive,fe310-g000,hfxosc.c \ | ||
|
@@ -92,37 +110,28 @@ check_PROGRAMS = | |
# The simplest possible pair of tests: one that passes and one that fails | ||
check_PROGRAMS += return_pass | ||
return_pass_SOURCES = test/return_pass.c | ||
return_pass_CFLAGS = -mmee-machine=@MACHINE_NAME@ | ||
return_pass_CFLAGS += -ffunction-sections -fdata-sections | ||
return_pass_CFLAGS += -march=$(FRAMEWORK_BOARD_DTS_MARCH) -mabi=$(FRAMEWORK_BOARD_DTS_MABI) | ||
return_pass_CFLAGS = -menv=mee -mmachine=@MACHINE_NAME@ | ||
return_pass_LDFLAGS = -L. -Wl,--gc-sections -Wl,-Map=return_pass.map | ||
|
||
check_PROGRAMS += return_fail | ||
return_fail_SOURCES = test/return_fail.c | ||
return_fail_CFLAGS = -mmee-machine=@MACHINE_NAME@ | ||
return_fail_CFLAGS += -ffunction-sections -fdata-sections | ||
return_fail_CFLAGS += -march=$(FRAMEWORK_BOARD_DTS_MARCH) -mabi=$(FRAMEWORK_BOARD_DTS_MABI) | ||
return_fail_CFLAGS = -menv=mee -mmachine=@MACHINE_NAME@ | ||
return_fail_LDFLAGS = -L. -Wl,--gc-sections -Wl,-Map=return_fail.map | ||
|
||
# A simple "Hello, World!" program that directly uses the MEE interface to | ||
# print to the serial terminal. | ||
check_PROGRAMS += hello | ||
hello_SOURCES = test/hello.c | ||
hello_CFLAGS = -mmee-machine=@MACHINE_NAME@ | ||
hello_CFLAGS += -ffunction-sections -fdata-sections | ||
hello_CFLAGS += -march=$(FRAMEWORK_BOARD_DTS_MARCH) -mabi=$(FRAMEWORK_BOARD_DTS_MABI) | ||
hello_CFLAGS = -menv=mee -mmachine=@MACHINE_NAME@ | ||
hello_LDFLAGS = -L. -Wl,--gc-sections -Wl,-Map=hello.map | ||
|
||
check_PROGRAMS += pll_set_hz | ||
pll_set_hz_SOURCES = test/pll_set_hz.c | ||
pll_set_hz_CFLAGS = -mmee-machine=@MACHINE_NAME@ | ||
pll_set_hz_CFLAGS += -ffunction-sections -fdata-sections | ||
pll_set_hz_CFLAGS += -march=$(FRAMEWORK_BOARD_DTS_MARCH) -mabi=$(FRAMEWORK_BOARD_DTS_MABI) | ||
pll_set_hz_CFLAGS = -menv=mee -mmachine=@MACHINE_NAME@ | ||
pll_set_hz_LDFLAGS = -L. -Wl,--gc-sections -Wl,-Map=pll_set_hz.map | ||
|
||
# Extra clean targets | ||
clean-local: | ||
-rm -rf @[email protected] | ||
-rm -rf mee/machine/@[email protected] @[email protected] mee-@[email protected] | ||
-rm -rf return_pass.map return_fail.map | ||
-rm -rf hello.map | ||
-rm -rf *.map *.specs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
# MEE Specification | ||
|
||
The MEE is designed to provide a source-level compatibility for | ||
bare-metal code between platforms. This specification defines the | ||
publicly available API. The intent is that this API is stable so users | ||
can rely on it not changing, but we're not going to make any guarantees | ||
about it until our 1.0.0 release. | ||
|
||
Note that the MEE does not define an ABI -- specifically that means that | ||
binaries will not be compatible between different versions of the MBI, | ||
or between different platforms. | ||
|
||
## User API | ||
|
||
The core of the MEE is a C API that is designed to allow programmers to | ||
write portable bare-metal embedded code. | ||
|
||
Any symbol beginning with `__mee_` is internal to the MEE and must not | ||
be called or defined by user code. Symbols beginning with `mee_` are | ||
public interfaces and can be considered to be a stable API. The best | ||
documentation for most of these symbols are found in the code, but some | ||
is listed below. | ||
|
||
### Clock Interface | ||
|
||
The clock interface allows for controlling the rate of various clocks in | ||
the system. Clocks are defined by a pointer to a `struct mee_clock`, the | ||
contents of which is implementation defined. Users of the clock | ||
interface must call the functions defined below in order to interact | ||
with a `struct mee_clock *`. | ||
|
||
Note that no mechanism for obtaining a pointer to a `struct mee_clock` | ||
has been defined, making it impossible to call any of these functions | ||
without invoking implementation-defined behavior. | ||
|
||
#### `long mee_clock_get_rate_hz(const struct mee_clock *clock)` | ||
|
||
Returns the clock rate of the given clock, in Hz. | ||
|
||
#### `long mee_clock_set_rate_hz(const struct mee_clock *clock, long hz)` | ||
|
||
Attempts to set the rate of the given clock to the given value, in Hz. | ||
Returns the rate the given clock was actually set to, which may be | ||
different than the requested rate. There are no hard requirements on | ||
what clock rates can be set, but it's expected that a best effort | ||
approach is taken to match the caller's desired clock rate. | ||
|
||
#### `void mee_clock_register_rate_change_callback(struct mee_clock *clk, int (*cb)(struct mee_clock *, void *), void *priv)` | ||
|
||
Registers a function (and an associated opaque data block) that will be | ||
called whenever the giver clock's rate has been changed. This function | ||
will be called after the driver-specific clock frequency changing code | ||
has returned, but before the caller of `mee_clock_set_rate_hz()` has | ||
been returned to. | ||
|
||
It's not guaranteed that the given clock's rate will have actually | ||
changed every time the given function is called, but it's guaranteed | ||
that the given function will be called every time the given clock's rate | ||
has been changed. | ||
|
||
### Power Control Interface | ||
|
||
The MEE defines a mechanism to control the power state of a given | ||
machine. The interface is currently quite simple: it's just the | ||
`mee_shutdown()` function. | ||
|
||
#### `void mee_shutdown(int code) __attribute__((noreturn))` | ||
|
||
Terminates execution of this program, attempting to pass the given code | ||
to whomever may be looking. The code `0` indicates success, while all | ||
other codes indicate failure. The exact mechanism by which execution | ||
terminates is implementation defined, but some examples include: | ||
|
||
* Spinning in an infinite loop. | ||
* Printing the return code to standard out and spinning in an infinite | ||
loop. | ||
* Toggling an external I/O to disable the power to the core. | ||
* Poking through a hole to the host that's providing this environment | ||
and indicating success or failure. | ||
|
||
### TTY Interface | ||
|
||
The MEE provides an terminal interface. This interface is designed to | ||
provide a simple mechanism for getting text-based data outside of the | ||
MEE -- in other words, it's designed to be used to implement C library | ||
functions like `printf()`. | ||
|
||
#### `int mee_tty_putc(unsigned char c);` | ||
|
||
Writes the given character to the default terminal, returning 0 on | ||
success or -1 on failure. | ||
|
||
### UART Interface | ||
|
||
The UART interface allows users of the MEE to control | ||
|
||
Note that there is no mechanism for obtaining a pointer to a `struct | ||
mee_uart` without invoking implementation-defined behavior, thus making | ||
calling any of these functions impossible. | ||
|
||
#### `int mee_uart_init(struct mee_uart *uart)` | ||
|
||
Initializes the given UART. This must be called exactly once before any | ||
other function on this UART can be called. It is invalid to initialize | ||
a UART more than once. | ||
|
||
#### `int mee_uart_putc(struct mee_uart *uart, unsigned char c)` | ||
|
||
Writes the given character to the given UART, returning 0 on success and | ||
-1 on failure. | ||
|
||
#### `int mee_uart_getc(struct mee_uart *uart, unsigned char *c)` | ||
|
||
Reads a character from the given UART, storing it at the given character | ||
pointer. This returns 0 on success and -1 on failure. | ||
|
||
#### `int mee_uart_get_baud_rate(struct mee_uart *uart)` | ||
|
||
Obtains the baud rate of the given UART, or `-1` to signify an error. | ||
|
||
#### `int mee_uart_set_baud_rate(struct mee_uart *uart, int baud_rate)` | ||
|
||
Sets the baud rate of the given UART. Returns 0 on success, or -1 on | ||
failure. Failure to set the baud rate can render the UART unusable | ||
until a subsequent coll to `mee_uart_set_baud_rate()` returns success. | ||
|
||
### C Startup Interface | ||
|
||
The MEE handles entering the C library's start routine, which is defined | ||
by the symbol `_start`. This symbol must be defined by the C library in | ||
order to allow the MEE to do anything meaningful. | ||
|
||
The MEE follows the standard RISC-V bootloader ABI when calling | ||
`_start`: | ||
|
||
* `a0` contains the hart ID. | ||
* `a1` contains a pointer to the machine description. The MEE always | ||
sets this to NULL, as machines are described statically. | ||
* `a2` contains a callback that should be called from within the child | ||
environment after it has initialized itself. | ||
|
||
This can be described as a the C function `void _start(long hartid, | ||
unsigned char *dtb, void (*after_init)(void))'. Note that the MEE does | ||
not initialize a C environment and therefor this cannot actually be a C | ||
function -- for example, there may not be a stack. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.