Skip to content

Commit 613446d

Browse files
committed
Merge branch '✨-arm-hardfp' into 🦆
2 parents 7b6d052 + 8a1fa96 commit 613446d

File tree

6 files changed

+207
-67
lines changed

6 files changed

+207
-67
lines changed

.github/workflows/ci.yml

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,33 @@ jobs:
9595
sudo apt-get install libusb-1.0-0-dev qemu-system-arm
9696
9797
- name: Install Additional Target of the Rust Toolchain
98-
run: rustup target add thumbv6m-none-eabi thumbv7m-none-eabi
98+
run: |
99+
rustup target add thumbv6m-none-eabi thumbv7m-none-eabi thumbv7em-none-eabihf
100+
rustup target add thumbv8m.base-none-eabi thumbv8m.main-none-eabi thumbv8m.main-none-eabihf
101+
102+
- name: Test (MPS2+ AN505, Armv8-M Mainline + FPU)
103+
uses: actions-rs/cargo@v1
104+
with:
105+
command: run
106+
args: -p constance_port_arm_m_test_runner -- -t qemu_mps2_an505 -l debug
107+
108+
- name: Test (MPS2+ AN505, Armv8-M Mainline)
109+
uses: actions-rs/cargo@v1
110+
with:
111+
command: run
112+
args: -p constance_port_arm_m_test_runner -- -t qemu_mps2_an505_v8mml -l debug
113+
114+
- name: Test (MPS2+ AN505, Armv8-M Baseline)
115+
uses: actions-rs/cargo@v1
116+
with:
117+
command: run
118+
args: -p constance_port_arm_m_test_runner -- -t qemu_mps2_an505_v8mbl -l debug
119+
120+
- name: Test (MPS2+ AN505, Armv7-M + FPU + DSP)
121+
uses: actions-rs/cargo@v1
122+
with:
123+
command: run
124+
args: -p constance_port_arm_m_test_runner -- -t qemu_mps2_an505_v7em_hf -l debug
99125

100126
- name: Test (MPS2+ AN385, Armv7-M)
101127
uses: actions-rs/cargo@v1

README.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,20 @@ Constance is a proof-of-concept of a static RTOS that utilizes Rust's compile-ti
1919

2020
## Implementation Status
2121

22-
| Core | Library | Ports |
23-
| :--------------- | :-------------- | :----------------- |
24-
| ☑︎ Tasks |`Mutex` | ☑︎ `std` (Hosted) |
25-
| ☑︎ Hunks |`RwLock` | ☑︎ Armv7-M (no FPU) |
26-
| ☑︎ Wait Objects |`Once` | ☑︎ Armv6-M |
27-
| ☑︎ Timeouts | ☐ Logger | |
28-
| ☐ Semaphores | ☐ C API | |
29-
| ☑︎ Event Groups | | |
30-
| ☐ Mutexes | **Tools** | **Boards** |
31-
| ☑︎ Timers | ☑︎ Test Harness | ☑︎ Hosted |
32-
| ☑︎ Interrupts | ☑︎ Test Suite | ☑︎ F401RE |
33-
| ☑︎ Startup Hooks | ☑︎ Configurator | |
34-
| ☐ CPU Exceptions | | |
35-
| ☐ Panicking | | |
22+
| Core | Library | Ports |
23+
| :--------------- | :-------------- | :------------------ |
24+
| ☑︎ Tasks |`Mutex` | ☑︎ `std` (Hosted) |
25+
| ☑︎ Hunks |`RwLock` | ☑︎ Armv8-M (no CMSE) |
26+
| ☑︎ Wait Objects |`Once` | ☑︎ Armv7-M |
27+
| ☑︎ Timeouts | ☐ Logger | ☑︎ Armv6-M |
28+
| ☐ Semaphores | ☐ C API | |
29+
| ☑︎ Event Groups | | |
30+
| ☐ Mutexes | **Tools** | **Boards** |
31+
| ☑︎ Timers | ☑︎ Test Harness | ☑︎ Hosted |
32+
| ☑︎ Interrupts | ☑︎ Test Suite | ☑︎ F401RE |
33+
| ☑︎ Startup Hooks | ☑︎ Configurator | |
34+
| ☐ CPU Exceptions | | |
35+
| ☐ Panicking | | |
3636

3737
## Example
3838

src/constance_port_arm_m/src/threading.rs

Lines changed: 68 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -229,16 +229,23 @@ impl State {
229229
pp_asm!("
230230
# Save the context of the previous task
231231
#
232-
# [r0 = &running_task, r4-r11 = context, lr = EXC_RETURN]
232+
# [r0 = &running_task, r4-r11 = context,
233+
# s16-s31 = context, lr = EXC_RETURN]
233234
#
234235
# r1 = running_task
235236
# if r1.is_some() {
236-
# r2 = psp as *u32 - 10
237+
# let fpu_active = cfg!(has_fpu) && (lr & FType) == 0;
238+
# r2 = psp as *u32 - if fpu_active { 26 } else { 10 }
239+
# r1.port_task_state.sp = r2
237240
#
241+
# r2[0] = lr (EXC_RETURN)
242+
# r2[1] = control
243+
# r2 += 2;
244+
# if fpu_active {
245+
# r2[0..16] = {s16-s31}
246+
# r2 += 16;
247+
# }
238248
# r2[0..8] = {r4-r11}
239-
# r2[8] = lr (EXC_RETURN)
240-
# r2[9] = control
241-
# r1.port_task_state.sp = r2
242249
# }
243250
#
244251
# [r0 = &running_task]
@@ -252,22 +259,29 @@ impl State {
252259
" } "
253260
mrs r2, psp
254261
mrs r3, control
255-
subs r2, #40
262+
subs r2, #40 "
263+
if cfg!(has_fpu) { "
264+
tst lr, #0x10
265+
it eq
266+
subeq r2, #64
267+
" } "
256268
str r2, [r1] "
257269
if cfg!(any(armv6m, armv8m_base)) { "
258-
stm r2!, {r4-r7}
270+
mov r1, lr
271+
stmia r2!, {r1, r3}
272+
stmia r2!, {r4-r7}
259273
mov r4, r8
260274
mov r5, r9
261275
mov r6, r10
262276
mov r7, r11
263-
stm r2!, {r4-r7}
264-
mov r4, lr
265-
str r4, [r2]
266-
str r3, [r2, 4]
277+
stmia r2!, {r4-r7}
267278
" } else { "
268-
stm r2, {r4-r11}
269-
str lr, [r2, 32]
270-
str r3, [r2, 36]
279+
strd lr, r3, [r2], #8 "
280+
if cfg!(has_fpu) { "
281+
it eq
282+
vstmiaeq r2!, {s16-s31}
283+
" } "
284+
stmia r2, {r4-r11}
271285
" } "
272286
273287
# Choose the next task to run
@@ -284,10 +298,19 @@ impl State {
284298
# if r1.is_some() {
285299
# r2 = r1.port_task_state.sp
286300
#
301+
# lr = r2[0]
302+
# control = r2[1]
303+
# r2 += 2;
304+
#
305+
# let fpu_active = cfg!(has_fpu) && (lr & FType) == 0;
306+
# if fpu_active {
307+
# {s16-s31} = r2[0..16]
308+
# r2 += 16;
309+
# }
310+
#
287311
# {r4-r11} = r2[0..8]
288-
# lr = r2[8]
289-
# control = r2[9]
290-
# psp = &r2[10]
312+
# r2 += 8;
313+
# psp = r2
291314
# } else {
292315
# // The idle task only uses r0-r3, so we can skip most steps
293316
# // in this case
@@ -297,7 +320,7 @@ impl State {
297320
# execution uses the Main Stack.” */
298321
# }
299322
#
300-
# [r4-r11 = context, lr = EXC_RETURN]
323+
# [r4-r11 = context, s16-s31 = context, lr = EXC_RETURN]
301324
302325
ldr r1, [r0] "
303326
if cfg!(armv6m) { "
@@ -308,24 +331,25 @@ impl State {
308331
" } "
309332
ldr r2, [r1] "
310333
if cfg!(any(armv6m, armv8m_base)) { "
311-
adds r2, #16
312-
ldmia r2!, {r4-r7}
313-
mov r8, r4
314-
mov r9, r5
315-
mov r10, r6
316-
mov r11, r7
317-
subs r2, #32
318-
ldmia r2!, {r4-r7}
319-
adds r2, #16
320334
ldmia r2!, {r0, r3}
321335
mov lr, r0
336+
ldmia r2!, {r4-r7}
337+
ldmia r2!, {r0, r1}
338+
mov r8, r0
339+
mov r9, r1
340+
ldmia r2!, {r0, r1}
341+
mov r10, r0
342+
mov r11, r1
322343
" } else { "
323-
ldr lr, [r2, 32]
324-
ldr r3, [r2, 36]
325-
msr control, r3
326-
ldmia r2, {r4-r11}
327-
adds r2, #40
344+
ldrd lr, r3, [r2], #8 "
345+
if cfg!(has_fpu) { "
346+
tst lr, #0x10
347+
it eq
348+
vldmiaeq r2!, {s16-s31}
349+
" } "
350+
ldmia r2!, {r4-r11}
328351
" } "
352+
msr control, r3
329353
msr psp, r2
330354
bx lr
331355
@@ -426,27 +450,27 @@ impl State {
426450
slice::from_raw_parts_mut(sp, 10)
427451
};
428452

429-
// R4-R11: Uninitialized
430-
extra_ctx[0] = MaybeUninit::new(0x04040404);
431-
extra_ctx[1] = MaybeUninit::new(0x05050505);
432-
extra_ctx[2] = MaybeUninit::new(0x06060606);
433-
extra_ctx[3] = MaybeUninit::new(0x07070707);
434-
extra_ctx[4] = MaybeUninit::new(0x08080808);
435-
extra_ctx[5] = MaybeUninit::new(0x09090909);
436-
extra_ctx[6] = MaybeUninit::new(0x10101010);
437-
extra_ctx[7] = MaybeUninit::new(0x11111111);
438453
// EXC_RETURN: 0xfffffffd (“Return to Thread Mode; Exception return gets
439454
// state from the Process stack; On return execution uses
440455
// the Process Stack.”)
441456
// TODO: This differs for Armv8-M
442457
// TODO: Plus, we shouldn't hard-code this here
443-
extra_ctx[8] = MaybeUninit::new(0xfffffffd);
458+
extra_ctx[0] = MaybeUninit::new(0xfffffffd);
444459
// CONTROL: SPSEL = 1 (Use PSP)
445-
extra_ctx[9] = MaybeUninit::new(0x00000002);
460+
extra_ctx[1] = MaybeUninit::new(0x00000002);
446461
// TODO: Secure context (Armv8-M)
447-
// TODO: Floating point registers
448462
// TODO: PSPLIM
449463

464+
// R4-R11: Uninitialized
465+
extra_ctx[2] = MaybeUninit::new(0x04040404);
466+
extra_ctx[3] = MaybeUninit::new(0x05050505);
467+
extra_ctx[4] = MaybeUninit::new(0x06060606);
468+
extra_ctx[5] = MaybeUninit::new(0x07070707);
469+
extra_ctx[6] = MaybeUninit::new(0x08080808);
470+
extra_ctx[7] = MaybeUninit::new(0x09090909);
471+
extra_ctx[8] = MaybeUninit::new(0x10101010);
472+
extra_ctx[9] = MaybeUninit::new(0x11111111);
473+
450474
let task_state = &task.port_task_state;
451475
unsafe { *task_state.sp.get() = sp as _ };
452476
}

src/constance_port_arm_m_test_driver/.cargo/config.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,18 @@ rustflags = [
1717
rustflags = [
1818
"-C", "link-arg=-Tlink.x",
1919
]
20+
21+
[target.thumbv8m.base-none-eabi]
22+
rustflags = [
23+
"-C", "link-arg=-Tlink.x",
24+
]
25+
26+
[target.thumbv8m.main-none-eabi]
27+
rustflags = [
28+
"-C", "link-arg=-Tlink.x",
29+
]
30+
31+
[target.thumbv8m.main-none-eabihf]
32+
rustflags = [
33+
"-C", "link-arg=-Tlink.x",
34+
]

src/constance_port_arm_m_test_runner/src/targets.rs

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,45 @@ pub static TARGETS: &[(&str, &dyn Target)] = &[
4747
"qemu_mps2_an385_v6m",
4848
&OverrideTargetTriple("thumbv6m-none-eabi", QemuMps2An385),
4949
),
50+
(
51+
"qemu_mps2_an505",
52+
&OverrideTargetTriple("thumbv8m.main-none-eabihf", QemuMps2An505),
53+
),
54+
(
55+
"qemu_mps2_an505_v8mml",
56+
&OverrideTargetTriple("thumbv8m.main-none-eabi", QemuMps2An505),
57+
),
58+
(
59+
"qemu_mps2_an505_v8mbl",
60+
&OverrideTargetTriple("thumbv8m.base-none-eabi", QemuMps2An505),
61+
),
62+
(
63+
"qemu_mps2_an505_v7em_hf",
64+
&OverrideTargetTriple("thumbv7em-none-eabihf", QemuMps2An505),
65+
),
66+
(
67+
"qemu_mps2_an505_v7m_hf",
68+
&OverrideTargetTriple("thumbv7m-none-eabihf", QemuMps2An505),
69+
),
70+
(
71+
"qemu_mps2_an505_v7em",
72+
&OverrideTargetTriple("thumbv7em-none-eabi", QemuMps2An505),
73+
),
74+
(
75+
"qemu_mps2_an505_v7m",
76+
&OverrideTargetTriple("thumbv7m-none-eabi", QemuMps2An505),
77+
),
78+
(
79+
"qemu_mps2_an505_v6m",
80+
&OverrideTargetTriple("thumbv6m-none-eabi", QemuMps2An505),
81+
),
5082
];
5183

5284
pub struct NucleoF401re;
5385

5486
impl Target for NucleoF401re {
5587
fn target_triple(&self) -> &str {
56-
// TODO: use `eabihf` when FPU is supported by the Arm-M port
57-
"thumbv7em-none-eabi"
88+
"thumbv7em-none-eabihf"
5889
}
5990

6091
fn cargo_features(&self) -> &[&str] {
@@ -125,7 +156,50 @@ impl Target for QemuMps2An385 {
125156
fn connect(
126157
&self,
127158
) -> Pin<Box<dyn Future<Output = Result<Box<dyn DebugProbe>, Box<dyn Error + Send>>>>> {
128-
Box::pin(async { Ok(Box::new(qemu::QemuDebugProbe::new()) as Box<dyn DebugProbe>) })
159+
Box::pin(async {
160+
Ok(
161+
Box::new(qemu::QemuDebugProbe::new(&["-machine", "mps2-an385"]))
162+
as Box<dyn DebugProbe>,
163+
)
164+
})
165+
}
166+
}
167+
168+
pub struct QemuMps2An505;
169+
170+
impl Target for QemuMps2An505 {
171+
fn target_triple(&self) -> &str {
172+
"thumbv8m-none-eabihf"
173+
}
174+
175+
fn cargo_features(&self) -> &[&str] {
176+
&["output-semihosting"]
177+
}
178+
179+
fn memory_layout_script(&self) -> String {
180+
"
181+
MEMORY
182+
{
183+
/* ZBT SRAM (SSRAM1) Secure alias */
184+
FLASH : ORIGIN = 0x10000000, LENGTH = 4096k
185+
/* ZBT SRAM (SSRAM2 and SSRAM3) Secure alias */
186+
RAM : ORIGIN = 0x38000000, LENGTH = 4096K
187+
}
188+
189+
_stack_start = ORIGIN(RAM) + LENGTH(RAM);
190+
"
191+
.to_owned()
192+
}
193+
194+
fn connect(
195+
&self,
196+
) -> Pin<Box<dyn Future<Output = Result<Box<dyn DebugProbe>, Box<dyn Error + Send>>>>> {
197+
Box::pin(async {
198+
Ok(
199+
Box::new(qemu::QemuDebugProbe::new(&["-machine", "mps2-an505"]))
200+
as Box<dyn DebugProbe>,
201+
)
202+
})
129203
}
130204
}
131205

src/constance_port_arm_m_test_runner/src/targets/qemu.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ use tokio::{io::AsyncRead, process::Child};
1111
use super::{DebugProbe, DynAsyncRead};
1212
use crate::subprocess;
1313

14-
pub(super) struct QemuDebugProbe {}
14+
pub(super) struct QemuDebugProbe {
15+
qemu_args: &'static [&'static str],
16+
}
1517

1618
impl QemuDebugProbe {
17-
pub(super) fn new() -> Self {
18-
Self {}
19+
pub(super) fn new(qemu_args: &'static [&'static str]) -> Self {
20+
Self { qemu_args }
1921
}
2022
}
2123

@@ -27,9 +29,8 @@ impl DebugProbe for QemuDebugProbe {
2729
let result = subprocess::CmdBuilder::new("qemu-system-arm")
2830
.arg("-kernel")
2931
.arg(exe)
32+
.args(self.qemu_args)
3033
.args(&[
31-
"-machine",
32-
"mps2-an385",
3334
"-nographic",
3435
"-d",
3536
"guest_errors",

0 commit comments

Comments
 (0)