Skip to content

Commit f50acd1

Browse files
Merge branch 'master' into rs/lto-fixes
2 parents aa8cff9 + b970b91 commit f50acd1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+1443
-645
lines changed

.github/workflows/tests.yaml

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,74 @@ on:
44
pull_request:
55
merge_group:
66

7-
name: Run macro tests (tests)
7+
name: Run tests (build and trybuild)
88

99
jobs:
10-
run-tests:
10+
run-trybuild:
1111
strategy:
1212
matrix:
1313
os: [ macos-latest, ubuntu-latest ] # windows shows weird linking errors
1414
runs-on: ${{ matrix.os }}
1515
steps:
1616
- uses: actions/checkout@v4
17-
- uses: dtolnay/rust-toolchain@nightly
17+
- uses: dtolnay/rust-toolchain@stable
1818
- name: Run tests
19-
run: cargo test --package tests
19+
run: cargo test --package tests-trybuild
20+
run-build:
21+
strategy:
22+
matrix:
23+
# All generated code should be running on stable now, MRSV is 1.61.0
24+
toolchain: [ stable, nightly, 1.61.0 ]
25+
target:
26+
- riscv32i-unknown-none-elf
27+
- riscv32im-unknown-none-elf
28+
- riscv32imc-unknown-none-elf
29+
- riscv32imac-unknown-none-elf
30+
- riscv32imafc-unknown-none-elf
31+
- riscv64imac-unknown-none-elf
32+
- riscv64gc-unknown-none-elf
33+
example:
34+
- empty
35+
include:
36+
# Nightly is only for reference and allowed to fail
37+
- toolchain: nightly
38+
experimental: true
39+
exclude:
40+
- toolchain: 1.61.0
41+
target: riscv32im-unknown-none-elf
42+
- toolchain: 1.61.0
43+
target: riscv32imafc-unknown-none-elf
44+
runs-on: ubuntu-latest
45+
continue-on-error: ${{ matrix.experimental || false }}
46+
steps:
47+
- uses: actions/checkout@v4
48+
- uses: dtolnay/rust-toolchain@master
49+
with:
50+
toolchain: ${{ matrix.toolchain }}
51+
targets: ${{ matrix.target }}
52+
- name: Build (no features)
53+
run: RUSTFLAGS="-C link-arg=-Tdevice.x -C link-arg=-Tmemory.x -C link-arg=-Tlink.x" cargo build --package tests-build --target ${{ matrix.target }} --example ${{ matrix.example }}
54+
- name: Build (include device.x)
55+
run: RUSTFLAGS="-C link-arg=-Tmemory.x -C link-arg=-Tlink.x" cargo build --package tests-build --target ${{ matrix.target }} --example ${{ matrix.example }} --features device
56+
- name: Build (include memory.x)
57+
run: RUSTFLAGS="-C link-arg=-Tdevice.x -C link-arg=-Tlink.x" cargo build --package tests-build --target ${{ matrix.target }} --example ${{ matrix.example }} --features memory
58+
- name: Build (include device.x and memory.x)
59+
run: RUSTFLAGS="-C link-arg=-Tlink.x" cargo build --package tests-build --target ${{ matrix.target }} --example ${{ matrix.example }} --features device,memory
60+
61+
- name: Build (custom interrupts and exceptions)
62+
run: RUSTFLAGS="-C link-arg=-Tdevice.x -C link-arg=-Tmemory.x -C link-arg=-Tlink.x" cargo build --package tests-build --target ${{ matrix.target }} --example ${{ matrix.example }} --features no-interrupts,no-exceptions
63+
- name: Build (custom interrupts and exceptions, include device.x)
64+
run: RUSTFLAGS="-C link-arg=-Tmemory.x -C link-arg=-Tlink.x" cargo build --package tests-build --target ${{ matrix.target }} --example ${{ matrix.example }} --features no-interrupts,no-exceptions,device
65+
- name: Build (custom interrupts and exceptions, include memory.x)
66+
run: RUSTFLAGS="-C link-arg=-Tdevice.x -C link-arg=-Tlink.x" cargo build --package tests-build --target ${{ matrix.target }} --example ${{ matrix.example }} --features no-interrupts,no-exceptions,memory
67+
- name: Build (custom interrupts and exceptions, include device.x and memory.x)
68+
run: RUSTFLAGS="-C link-arg=-Tlink.x" cargo build --package tests-build --target ${{ matrix.target }} --example ${{ matrix.example }} --features no-interrupts,no-exceptions,device,memory
2069

2170
# Job to check that all the builds succeeded
2271
tests-check:
2372
needs:
24-
- run-tests
73+
- run-trybuild
74+
- run-build
2575
runs-on: ubuntu-latest
2676
if: always()
2777
steps:

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ members = [
77
"riscv-rt",
88
"riscv-semihosting",
99
"riscv-target-parser",
10-
"tests",
10+
"tests-build",
11+
"tests-trybuild",
1112
]

riscv-peripheral/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
## [v0.2.1] - 2025-02-18
11+
12+
### Changed
13+
14+
- Update `riscv` dependency to 0.13.0
15+
1016
## [v0.2.0] - 2024-10-19
1117

1218
### Added

riscv-peripheral/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "riscv-peripheral"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
edition = "2021"
55
rust-version = "1.75"
66
repository = "https://github.com/rust-embedded/riscv"
@@ -16,7 +16,7 @@ license = "ISC"
1616
[dependencies]
1717
embedded-hal = "1.0.0"
1818
embedded-hal-async = { version = "1.0.0", optional = true }
19-
riscv = { path = "../riscv", version = "0.12.0" }
19+
riscv = { path = "../riscv", version = "0.13.0" }
2020
riscv-pac = { path = "../riscv-pac", version = "0.2.0" }
2121

2222
[dev-dependencies]

riscv-rt/CHANGELOG.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,30 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- New `device` feature to include `device.x` in `link.x`. This feature is based
13+
on the current implementation of `cortex-m-rt`.
14+
- New `memory` feature to include `memory.x` in `link.x`. This feature is based
15+
on the current implementation of `cortex-m-rt`. However, in contrast with
16+
`cortex-m-rt`, including `memory.x` in the linker file is feature gated.
17+
The benefits of leaving this optional are backwards compatibility and
18+
allowing users to define less typical linker scripts that do not rely on a
19+
`device.x` or `memory.x` file.
20+
21+
### Changed
22+
23+
- Linker file now refers to standard exceptions and interrupts only when the
24+
`no-exceptions` and `no-interrupts` features are disabled, respectively.
25+
This is achieved by substituting `${INCLUDE_LINKER_FILES}` with the contents
26+
of `exceptions.x` and/or `interrupts.x`.
27+
28+
## [v0.14.0] - 2025-02-18
29+
1030
### Changed
1131

12-
- Ensure the `.heap` section is 4-byte aligned
32+
- Use `RISCV_MTVEC_ALIGN` to control the alignment constraint of the vector table.
33+
- Ensure the `.heap` section is 4-byte aligned.
1334
- Limit rustc cfg flags to `riscvi`, `riscvm`, `riscvf`, and `riscvd`.
1435
- Temporary use of `RISCV_RT_LLVM_ARCH_PATCH` environment variable to include the
1536
temporary patch required for avoid LLVM spurious errors.

riscv-rt/Cargo.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "riscv-rt"
3-
version = "0.13.0"
3+
version = "0.14.0"
44
rust-version = "1.61"
55
repository = "https://github.com/rust-embedded/riscv"
66
authors = ["The RISC-V Team <risc-v@teams.rust-embedded.org>"]
@@ -23,9 +23,9 @@ targets = [
2323
riscv-target-parser = { path = "../riscv-target-parser", version = "0.1.0" }
2424

2525
[dependencies]
26-
riscv = { path = "../riscv", version = "0.12.0" }
26+
riscv = { path = "../riscv", version = "0.13.0" }
2727
riscv-pac = { path = "../riscv-pac", version = "0.2.0" }
28-
riscv-rt-macros = { path = "macros", version = "0.3.0" }
28+
riscv-rt-macros = { path = "macros", version = "0.4.0" }
2929

3030
[dev-dependencies]
3131
panic-halt = "1.0.0"
@@ -37,3 +37,5 @@ v-trap = ["riscv-rt-macros/v-trap"]
3737
u-boot = ["riscv-rt-macros/u-boot", "single-hart"]
3838
no-interrupts = []
3939
no-exceptions = []
40+
device = []
41+
memory = []

riscv-rt/build.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,34 @@ fn add_linker_script(arch_width: u32) -> io::Result<()> {
1111
let mut content = fs::read_to_string("link.x.in")?;
1212
content = content.replace("${ARCH_WIDTH}", &arch_width.to_string());
1313

14-
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
14+
// Get target-dependent linker configuration and replace ${INCLUDE_LINKER_FILES} with it
15+
let mut include_content = String::new();
16+
17+
// If no-exceptions is disabled, include the exceptions.x files
18+
if env::var_os("CARGO_FEATURE_NO_EXCEPTIONS").is_none() {
19+
let exceptions_content = fs::read_to_string("exceptions.x")?;
20+
include_content.push_str(&(exceptions_content + "\n"));
21+
}
22+
// If no-interrupts is disabled, include the interrupts.x files
23+
if env::var_os("CARGO_FEATURE_NO_INTERRUPTS").is_none() {
24+
let interrupts_content = fs::read_to_string("interrupts.x")?;
25+
include_content.push_str(&(interrupts_content + "\n"));
26+
}
27+
// If device is enabled, include the device.x file (usually, provided by PACs)
28+
if env::var_os("CARGO_FEATURE_DEVICE").is_some() {
29+
include_content.push_str("/* Device-specific exception and interrupt handlers */\n");
30+
include_content.push_str("INCLUDE device.x\n");
31+
}
32+
// If memory is enabled, include the memory.x file (usually, provided by BSPs)
33+
if env::var_os("CARGO_FEATURE_MEMORY").is_some() {
34+
include_content.push_str("/* Device-specific memory layout */\n");
35+
include_content.push_str("INCLUDE memory.x\n");
36+
}
37+
38+
content = content.replace("${INCLUDE_LINKER_FILES}", &include_content);
1539

1640
// Put the linker script somewhere the linker can find it
41+
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
1742
fs::write(out_dir.join("link.x"), content)?;
1843
println!("cargo:rustc-link-search={}", out_dir.display());
1944
println!("cargo:rerun-if-changed=link.x");
@@ -47,6 +72,13 @@ fn main() {
4772
// make sure that these env variables are not changed without notice.
4873
println!("cargo:rerun-if-env-changed=RISCV_RT_BASE_ISA");
4974
println!("cargo:rerun-if-env-changed=RISCV_RT_LLVM_ARCH_PATCH");
75+
if env::var_os("CARGO_FEATURE_V_TRAP").is_some()
76+
&& env::var_os("CARGO_FEATURE_NO_INTERRUPTS").is_none()
77+
{
78+
// This environment variable is used by the `#[riscv::pac_enum()]` call in
79+
// `src/interrupts.rs` (when `v-trap` is enabled and `no-interrupts` disabled).
80+
println!("cargo:rerun-if-env-changed=RISCV_MTVEC_ALIGN");
81+
}
5082

5183
for flag in target.rustc_flags() {
5284
// Required until target_feature risc-v is stable and in-use

riscv-rt/exceptions.x

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* # EXCEPTION HANDLERS DESCRIBED IN THE STANDARD RISC-V ISA
2+
3+
If the `no-exceptions` feature is DISABLED, this file will be included in link.x.in.
4+
If the `no-exceptions` feature is ENABLED, this file will be ignored.
5+
*/
6+
7+
/* It is possible to define a special handler for each exception type.
8+
By default, all exceptions are handled by ExceptionHandler. However,
9+
users can override these alias by defining the symbol themselves */
10+
PROVIDE(InstructionMisaligned = ExceptionHandler);
11+
PROVIDE(InstructionFault = ExceptionHandler);
12+
PROVIDE(IllegalInstruction = ExceptionHandler);
13+
PROVIDE(Breakpoint = ExceptionHandler);
14+
PROVIDE(LoadMisaligned = ExceptionHandler);
15+
PROVIDE(LoadFault = ExceptionHandler);
16+
PROVIDE(StoreMisaligned = ExceptionHandler);
17+
PROVIDE(StoreFault = ExceptionHandler);
18+
PROVIDE(UserEnvCall = ExceptionHandler);
19+
PROVIDE(SupervisorEnvCall = ExceptionHandler);
20+
PROVIDE(MachineEnvCall = ExceptionHandler);
21+
PROVIDE(InstructionPageFault = ExceptionHandler);
22+
PROVIDE(LoadPageFault = ExceptionHandler);
23+
PROVIDE(StorePageFault = ExceptionHandler);

riscv-rt/interrupts.x

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* # CORE INTERRUPT HANDLERS DESCRIBED IN THE STANDARD RISC-V ISA
2+
3+
If the `no-interrupts` feature is DISABLED, this file will be included in link.x.in.
4+
If the `no-interrupts` feature is ENABLED, this file will be ignored.
5+
*/
6+
7+
/* It is possible to define a special handler for each interrupt type.
8+
By default, all interrupts are handled by DefaultHandler. However, users can
9+
override these alias by defining the symbol themselves */
10+
PROVIDE(SupervisorSoft = DefaultHandler);
11+
PROVIDE(MachineSoft = DefaultHandler);
12+
PROVIDE(SupervisorTimer = DefaultHandler);
13+
PROVIDE(MachineTimer = DefaultHandler);
14+
PROVIDE(SupervisorExternal = DefaultHandler);
15+
PROVIDE(MachineExternal = DefaultHandler);
16+
17+
/* When vectored trap mode is enabled, each interrupt source must implement its own
18+
trap entry point. By default, all interrupts start in _DefaultHandler_trap.
19+
However, users can override these alias by defining the symbol themselves */
20+
PROVIDE(_start_SupervisorSoft_trap = _start_DefaultHandler_trap);
21+
PROVIDE(_start_MachineSoft_trap = _start_DefaultHandler_trap);
22+
PROVIDE(_start_SupervisorTimer_trap = _start_DefaultHandler_trap);
23+
PROVIDE(_start_MachineTimer_trap = _start_DefaultHandler_trap);
24+
PROVIDE(_start_SupervisorExternal_trap = _start_DefaultHandler_trap);
25+
PROVIDE(_start_MachineExternal_trap = _start_DefaultHandler_trap);

riscv-rt/link.x.in

Lines changed: 17 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,6 @@
2222
means that you won't see "Address (..) is out of bounds" in the disassembly produced by `objdump`.
2323
*/
2424

25-
PROVIDE(_stext = ORIGIN(REGION_TEXT));
26-
PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
27-
PROVIDE(_max_hart_id = 0);
28-
PROVIDE(_hart_stack_size = 2K);
29-
PROVIDE(_heap_size = 0);
30-
31-
/** TRAP ENTRY POINTS **/
32-
3325
/* Default abort entry point. If no abort symbol is provided, then abort maps to _abort. */
3426
EXTERN(_abort);
3527
PROVIDE(abort = _abort);
@@ -39,57 +31,28 @@ PROVIDE(abort = _abort);
3931
and then returns. Users can override this alias by defining the symbol themselves */
4032
EXTERN(_start_trap);
4133

34+
/* Default exception handler. By default, the exception handler is abort.
35+
Users can override this alias by defining the symbol themselves */
36+
PROVIDE(ExceptionHandler = abort);
37+
38+
/* Default interrupt handler. By default, the interrupt handler is abort.
39+
Users can override this alias by defining the symbol themselves */
40+
PROVIDE(DefaultHandler = abort);
41+
4242
/* Default interrupt trap entry point. When vectored trap mode is enabled,
4343
the riscv-rt crate provides an implementation of this function, which saves caller saved
44-
registers, calls the the DefaultHandler ISR, restores caller saved registers and returns. */
44+
registers, calls the the DefaultHandler ISR, restores caller saved registers and returns.
45+
Note, however, that this provided implementation cannot be overwritten. We use PROVIDE
46+
to avoid compilation errors in direct mode, not to allow users to overwrite the symbol. */
4547
PROVIDE(_start_DefaultHandler_trap = _start_trap);
4648

47-
/* When vectored trap mode is enabled, each interrupt source must implement its own
48-
trap entry point. By default, all interrupts start in _start_trap. However, users can
49-
override these alias by defining the symbol themselves */
50-
PROVIDE(_start_SupervisorSoft_trap = _start_DefaultHandler_trap);
51-
PROVIDE(_start_MachineSoft_trap = _start_DefaultHandler_trap);
52-
PROVIDE(_start_SupervisorTimer_trap = _start_DefaultHandler_trap);
53-
PROVIDE(_start_MachineTimer_trap = _start_DefaultHandler_trap);
54-
PROVIDE(_start_SupervisorExternal_trap = _start_DefaultHandler_trap);
55-
PROVIDE(_start_MachineExternal_trap = _start_DefaultHandler_trap);
56-
57-
/** EXCEPTION HANDLERS **/
49+
${INCLUDE_LINKER_FILES}
5850

59-
/* Default exception handler. The riscv-rt crate provides a weak alias of this function,
60-
which is a busy loop. Users can override this alias by defining the symbol themselves */
61-
PROVIDE(ExceptionHandler = abort);
62-
63-
/* It is possible to define a special handler for each exception type.
64-
By default, all exceptions are handled by ExceptionHandler. However, users can
65-
override these alias by defining the symbol themselves */
66-
PROVIDE(InstructionMisaligned = ExceptionHandler);
67-
PROVIDE(InstructionFault = ExceptionHandler);
68-
PROVIDE(IllegalInstruction = ExceptionHandler);
69-
PROVIDE(Breakpoint = ExceptionHandler);
70-
PROVIDE(LoadMisaligned = ExceptionHandler);
71-
PROVIDE(LoadFault = ExceptionHandler);
72-
PROVIDE(StoreMisaligned = ExceptionHandler);
73-
PROVIDE(StoreFault = ExceptionHandler);
74-
PROVIDE(UserEnvCall = ExceptionHandler);
75-
PROVIDE(SupervisorEnvCall = ExceptionHandler);
76-
PROVIDE(MachineEnvCall = ExceptionHandler);
77-
PROVIDE(InstructionPageFault = ExceptionHandler);
78-
PROVIDE(LoadPageFault = ExceptionHandler);
79-
PROVIDE(StorePageFault = ExceptionHandler);
80-
81-
/** INTERRUPT HANDLERS **/
82-
83-
/* It is possible to define a special handler for each interrupt type.
84-
By default, all interrupts are handled by DefaultHandler. However, users can
85-
override these alias by defining the symbol themselves */
86-
PROVIDE(DefaultHandler = abort);
87-
PROVIDE(SupervisorSoft = DefaultHandler);
88-
PROVIDE(MachineSoft = DefaultHandler);
89-
PROVIDE(SupervisorTimer = DefaultHandler);
90-
PROVIDE(MachineTimer = DefaultHandler);
91-
PROVIDE(SupervisorExternal = DefaultHandler);
92-
PROVIDE(MachineExternal = DefaultHandler);
51+
PROVIDE(_stext = ORIGIN(REGION_TEXT));
52+
PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
53+
PROVIDE(_max_hart_id = 0);
54+
PROVIDE(_hart_stack_size = 2K);
55+
PROVIDE(_heap_size = 0);
9356

9457
SECTIONS
9558
{

0 commit comments

Comments
 (0)