Skip to content

Commit 586213f

Browse files
Merge pull request #42 from jlab-sensing/ents/merge-upstream
Merge Upstream Tock: May 2026
2 parents 9498d5c + 745434d commit 586213f

287 files changed

Lines changed: 5516 additions & 2367 deletions

File tree

Some content is hidden

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

.lcignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@
3333

3434
# Files that are autogenerated and cannot be modified to add the header.
3535
/Cargo.lock
36+
/tools/svd2regs/uv.lock

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"editor.defaultFormatter": "rust-lang.rust-analyzer",
44
"editor.formatOnSave": true,
55
"rust-analyzer.server.extraEnv": {
6-
"RUSTUP_TOOLCHAIN": "nightly-2025-11-03"
6+
"RUSTUP_TOOLCHAIN": "nightly-2026-04-21"
77
},
88
"rust-analyzer.check.allTargets": false,
99
}

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ result_unit_err = "allow"
230230
unusual-byte-groupings = "allow"
231231
# We widely use upper case acronyms for hardware registers and fields.
232232
upper_case_acronyms = "allow"
233-
233+
# Condensing match statements can make code harder to read and inconsistent.
234+
collapsible-match = "allow"
234235

235236
missing_safety_doc = "allow"
236237
doc_lazy_continuation = "allow"
@@ -280,7 +281,6 @@ or_fun_call = "allow"
280281
missing_const_for_fn = "allow"
281282
equatable_if_let = "allow"
282283
derive_partial_eq_without_eq = "allow"
283-
empty_line_after_doc_comments = "allow"
284284
trait_duplication_in_bounds = "allow"
285285
useless_let_if_seq = "allow"
286286

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,15 @@ ci-job-clippy:
407407
@cargo clippy -- -D warnings
408408
# Run `cargo clippy` in select boards so we run clippy with targets that
409409
# actually check the arch-specific functions.
410+
#
411+
# - nrf52840dk: cortex-m4
412+
# - raspberry_pi_pico: cortex-m0
413+
# - hifive1: riscv
414+
# - qemu_i486_q35: x86
410415
@cd boards/nordic/nrf52840dk && cargo clippy -- -D warnings
416+
@cd boards/raspberry_pi_pico && cargo clippy -- -D warnings
411417
@cd boards/hifive1 && cargo clippy -- -D warnings
412-
@cd boards/qemu_i486_q35 && cargo clippy -- -D warnings
418+
@cd boards/qemu_i486_q35 && cargo clippy -Zjson-target-spec -- -D warnings
413419

414420

415421

arch/cortex-m/src/dma_fence.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Licensed under the Apache License, Version 2.0 or the MIT License.
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
// Copyright Tock Contributors 2026.
4+
5+
//! Cortex-M synchronization implementation for Rust when using DMA.
6+
7+
use kernel::platform::dma_fence::DmaFence;
8+
9+
#[derive(Debug, Copy, Clone)]
10+
pub struct CortexMDmaFence {
11+
_private: (),
12+
}
13+
14+
/// An implementation of [DmaFence] for ARM Cortex-M systems.
15+
///
16+
/// The provided `release` and `acquire` methods use opaque assembly
17+
/// blocks and the THUMB `DMB` instructions to make prior writes to
18+
/// shared buffers visible to DMA devices, and DMA writes visible
19+
/// subsequent memory reads, as specified in the ARM Cortex-M
20+
/// Programming Guide to Memory Barrier Instructions [1].
21+
///
22+
/// [1]: https://developer.arm.com/documentation/dai0321/a/
23+
impl CortexMDmaFence {
24+
/// Construct a new [CortexMDmaFence].
25+
///
26+
/// # Safety
27+
///
28+
/// Users of this function guarantee that this fence is an appropriate
29+
/// implementation of [`DmaFence`] for the platform on which this code is
30+
/// running. In practice, this means that users must assert to be running on
31+
/// an ARM Cortex-M (ARM-v6m / ARM-v7m) CPU.
32+
pub unsafe fn new() -> Self {
33+
Self { _private: () }
34+
}
35+
}
36+
37+
#[cfg(all(target_arch = "arm", target_os = "none"))]
38+
unsafe impl DmaFence for CortexMDmaFence {
39+
fn release<T>(self, slice_ptr: *mut [T]) {
40+
let slice_start_ptr: *mut T = slice_ptr.cast();
41+
unsafe {
42+
core::arch::asm!(
43+
"
44+
// This block is opaque to the compiler; the compiler must assume
45+
// that the block could read to the entire buffer from which the
46+
// pointer stored in {dma_buffer_ptr_reg} was derived.
47+
//
48+
// Do not reorder prior memory reads or writes over subsequent
49+
// I/O reads or writes.
50+
dmb
51+
",
52+
dma_buffer_ptr_reg = in(reg) slice_start_ptr,
53+
);
54+
}
55+
}
56+
57+
fn acquire<T>(self, slice_ptr: *mut [T]) {
58+
let slice_start_ptr: *mut T = slice_ptr.cast();
59+
unsafe {
60+
core::arch::asm!(
61+
"
62+
// This block is opaque to the compiler; the compiler must assume
63+
// that the block could write to the entire buffer from which the
64+
// pointer stored in {dma_buffer_ptr_reg} was derived.
65+
//
66+
// Do not reorder prior I/O reads or writes over subsequent
67+
// memory reads or writes.
68+
dmb
69+
",
70+
dma_buffer_ptr_reg = in(reg) slice_start_ptr,
71+
);
72+
}
73+
}
74+
}
75+
76+
#[cfg(not(all(target_arch = "arm", target_os = "none")))]
77+
unsafe impl DmaFence for CortexMDmaFence {
78+
fn release<T>(self, _buf: *mut [T]) {
79+
// When building for another architecture, such as for tests or CI:
80+
unimplemented!("CortexMDmaFence can only be used on cortex-m targets");
81+
}
82+
83+
fn acquire<T>(self, _buf: *mut [T]) {
84+
// When building for another architecture, such as for tests or CI:
85+
unimplemented!("CortexMDmaFence can only be used on cortex-m targets");
86+
}
87+
}

arch/cortex-m/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use core::fmt::Write;
1010

1111
pub mod dcb;
12+
pub mod dma_fence;
1213
pub mod dwt;
1314
pub mod mpu;
1415
pub mod nvic;

arch/cortex-m/src/syscall.rs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const SVC_FRAME_SIZE: usize = 32;
5858
/// Values for encoding the stored state buffer in a binary slice.
5959
const VERSION: usize = 1;
6060
const STORED_STATE_SIZE: usize = size_of::<CortexMStoredState>();
61-
const TAG: [u8; 4] = [b'c', b't', b'x', b'm'];
61+
const TAG: [u8; 4] = *b"ctxm";
6262
const METADATA_LEN: usize = 3;
6363

6464
const VERSION_IDX: usize = 0;
@@ -181,7 +181,7 @@ impl<A: CortexMVariant> kernel::syscall::UserspaceKernelBoundary for SysCall<A>
181181
}
182182

183183
let sp = state.psp as *mut u32;
184-
let (r0, r1, r2, r3) = (sp.offset(0), sp.offset(1), sp.offset(2), sp.offset(3));
184+
let (r0, r1, r2, r3) = (sp.add(0), sp.add(1), sp.add(2), sp.add(3));
185185

186186
// These operations are only safe so long as
187187
// - the pointers are properly aligned. This is guaranteed because the
@@ -245,13 +245,13 @@ impl<A: CortexMVariant> kernel::syscall::UserspaceKernelBoundary for SysCall<A>
245245
// - Instruction addresses require `|1` to indicate thumb code
246246
// - Stack offset 4 is R12, which the syscall interface ignores
247247
let stack_bottom = state.psp as *mut usize;
248-
ptr::write(stack_bottom.offset(7), state.psr); //......... -> APSR
249-
ptr::write(stack_bottom.offset(6), callback.pc.addr() | 1); //... -> PC
250-
ptr::write(stack_bottom.offset(5), state.yield_pc | 1); // -> LR
251-
ptr::write(stack_bottom.offset(3), callback.argument3.as_usize()); // -> R3
252-
ptr::write(stack_bottom.offset(2), callback.argument2); // -> R2
253-
ptr::write(stack_bottom.offset(1), callback.argument1); // -> R1
254-
ptr::write(stack_bottom.offset(0), callback.argument0); // -> R0
248+
ptr::write(stack_bottom.add(7), state.psr); //......... -> APSR
249+
ptr::write(stack_bottom.add(6), callback.pc.addr() | 1); //... -> PC
250+
ptr::write(stack_bottom.add(5), state.yield_pc | 1); // -> LR
251+
ptr::write(stack_bottom.add(3), callback.argument3.as_usize()); // -> R3
252+
ptr::write(stack_bottom.add(2), callback.argument2); // -> R2
253+
ptr::write(stack_bottom.add(1), callback.argument1); // -> R1
254+
ptr::write(stack_bottom.add(0), callback.argument0); // -> R0
255255

256256
Ok(())
257257
}
@@ -296,26 +296,26 @@ impl<A: CortexMVariant> kernel::syscall::UserspaceKernelBoundary for SysCall<A>
296296
// syscall (i.e. we return a value to the app immediately) then this
297297
// will have no effect. If we are doing something like `yield()`,
298298
// however, then we need to have this state.
299-
state.yield_pc = ptr::read(new_stack_pointer.offset(6));
300-
state.psr = ptr::read(new_stack_pointer.offset(7));
299+
state.yield_pc = ptr::read(new_stack_pointer.add(6));
300+
state.psr = ptr::read(new_stack_pointer.add(7));
301301

302302
// Get the syscall arguments and return them along with the syscall.
303303
// It's possible the app did something invalid, in which case we put
304304
// the app in the fault state.
305-
let r0 = ptr::read(new_stack_pointer.offset(0));
306-
let r1 = ptr::read(new_stack_pointer.offset(1));
307-
let r2 = ptr::read(new_stack_pointer.offset(2));
308-
let r3 = ptr::read(new_stack_pointer.offset(3));
305+
let r0 = ptr::read(new_stack_pointer.add(0));
306+
let r1 = ptr::read(new_stack_pointer.add(1));
307+
let r2 = ptr::read(new_stack_pointer.add(2));
308+
let r3 = ptr::read(new_stack_pointer.add(3));
309309

310310
// Get the actual SVC number.
311311
// Read the PC from the stack as a *const u16 (i.e. we're treating instructions as
312312
// u16).
313313
let pcptr_ptr: *const usize = new_stack_pointer;
314314
let pcptr_ptr: *const *const u16 = pcptr_ptr.cast();
315-
let pcptr = ptr::read(pcptr_ptr.offset(6));
315+
let pcptr = ptr::read(pcptr_ptr.add(6));
316316
// The svc instruction is the last instruction before the PC, and should be 16 bits.
317317
// Read it by offsetting the PC.
318-
let svc_instr = ptr::read(pcptr.offset(-1));
318+
let svc_instr = ptr::read(pcptr.sub(1));
319319
let svc_num = (svc_instr & 0xff) as u8;
320320

321321
// Use the helper function to convert these raw values into a Tock
@@ -367,14 +367,14 @@ impl<A: CortexMVariant> kernel::syscall::UserspaceKernelBoundary for SysCall<A>
367367
0xBAD00BAD,
368368
)
369369
} else {
370-
let r0 = ptr::read(stack_pointer.offset(0));
371-
let r1 = ptr::read(stack_pointer.offset(1));
372-
let r2 = ptr::read(stack_pointer.offset(2));
373-
let r3 = ptr::read(stack_pointer.offset(3));
374-
let r12 = ptr::read(stack_pointer.offset(4));
375-
let lr = ptr::read(stack_pointer.offset(5));
376-
let pc = ptr::read(stack_pointer.offset(6));
377-
let xpsr = ptr::read(stack_pointer.offset(7));
370+
let r0 = ptr::read(stack_pointer.add(0));
371+
let r1 = ptr::read(stack_pointer.add(1));
372+
let r2 = ptr::read(stack_pointer.add(2));
373+
let r3 = ptr::read(stack_pointer.add(3));
374+
let r12 = ptr::read(stack_pointer.add(4));
375+
let lr = ptr::read(stack_pointer.add(5));
376+
let pc = ptr::read(stack_pointer.add(6));
377+
let xpsr = ptr::read(stack_pointer.add(7));
378378
(r0, r1, r2, r3, r12, lr, pc, xpsr)
379379
};
380380

arch/cortex-m0/src/lib.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ struct HardFaultStackedRegisters {
3333
/// by the naked hard_fault_handler function.
3434
unsafe extern "C" fn hard_fault_handler_kernel(faulting_stack: *mut u32) -> ! {
3535
let hardfault_stacked_registers = HardFaultStackedRegisters {
36-
r0: *faulting_stack.offset(0),
37-
r1: *faulting_stack.offset(1),
38-
r2: *faulting_stack.offset(2),
39-
r3: *faulting_stack.offset(3),
40-
r12: *faulting_stack.offset(4),
41-
lr: *faulting_stack.offset(5),
42-
pc: *faulting_stack.offset(6),
43-
xpsr: *faulting_stack.offset(7),
36+
r0: *faulting_stack.add(0),
37+
r1: *faulting_stack.add(1),
38+
r2: *faulting_stack.add(2),
39+
r3: *faulting_stack.add(3),
40+
r12: *faulting_stack.add(4),
41+
lr: *faulting_stack.add(5),
42+
pc: *faulting_stack.add(6),
43+
xpsr: *faulting_stack.add(7),
4444
};
4545

4646
panic!(

arch/cortex-m4f/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub mod mpu {
2121
}
2222
}
2323

24+
pub use cortexm::dma_fence;
2425
pub use cortexm::dwt;
2526
pub use cortexm::initialize_ram_jump_to_main;
2627
pub use cortexm::nvic;

arch/cortex-v7m/src/lib.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -288,14 +288,14 @@ unsafe extern "C" fn hard_fault_handler_arm_v7m_kernel(
288288
panic!("kernel stack overflow");
289289
} else {
290290
// Show the normal kernel hardfault message.
291-
let stacked_r0: u32 = *faulting_stack.offset(0);
292-
let stacked_r1: u32 = *faulting_stack.offset(1);
293-
let stacked_r2: u32 = *faulting_stack.offset(2);
294-
let stacked_r3: u32 = *faulting_stack.offset(3);
295-
let stacked_r12: u32 = *faulting_stack.offset(4);
296-
let stacked_lr: u32 = *faulting_stack.offset(5);
297-
let stacked_pc: u32 = *faulting_stack.offset(6);
298-
let stacked_xpsr: u32 = *faulting_stack.offset(7);
291+
let stacked_r0: u32 = *faulting_stack.add(0);
292+
let stacked_r1: u32 = *faulting_stack.add(1);
293+
let stacked_r2: u32 = *faulting_stack.add(2);
294+
let stacked_r3: u32 = *faulting_stack.add(3);
295+
let stacked_r12: u32 = *faulting_stack.add(4);
296+
let stacked_lr: u32 = *faulting_stack.add(5);
297+
let stacked_pc: u32 = *faulting_stack.add(6);
298+
let stacked_xpsr: u32 = *faulting_stack.add(7);
299299

300300
let mode_str = "Kernel";
301301

0 commit comments

Comments
 (0)