Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 12 additions & 2 deletions app/cosmo/base.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ fwid = true

[kernel]
name = "cosmo"
requires = {flash = 32768, ram = 8192}
features = ["dump"]
requires = {flash = 32768, ram = 16384}
features = ["dump", "traptrace"]

[mmio]
peripheral-region = "fmc_nor_psram_bank_1"
Expand Down Expand Up @@ -357,6 +357,16 @@ notifications = ["jefe-state-change", "timer"]
task-slots = ["jefe", "spartan7_loader", "packrat", "sensor"]
uses = ["mmio_dimms"]

[tasks.bork]
name = "task-bork"
priority = 10
max-sizes = {flash = 16384, ram = 16384 }
start = true
notifications = ["timer"]
task-slots = ["sprot", "sys"]
features = ["h753"]
uses = ["rtc"]

[tasks.auxflash]
name = "drv-auxflash-server"
priority = 3
Expand Down
16 changes: 16 additions & 0 deletions app/cosmo/src/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ fn timer_isr_exit() {
}

fn context_switch(addr: usize) {
let rtc = unsafe { &*stm32h7::stm32h753::RTC::ptr() };
rtc.bkpr[0].modify(|_, w| w.bkp().bits(addr as u32));
trace(Event::ContextSwitch(addr));
}

Expand All @@ -86,5 +88,19 @@ static TRACING: kern::profiling::EventsTable = kern::profiling::EventsTable {
};

pub fn table() -> &'static kern::profiling::EventsTable {
let rtc = unsafe { &*stm32h7::stm32h753::RTC::ptr() };

// Unlock
rtc.wpr.write(|w| w.key().bits(0xca));
rtc.wpr.write(|w| w.key().bits(0x53));

// don't erase!
rtc.tampcr.modify(|_, w| w.tamp3noerase().set_bit().tamp2noerase().set_bit().tamp1noerase().set_bit());

// Save our last state
let last = rtc.bkpr[0].read().bkp().bits();
// And rotate
rtc.bkpr[1].modify(|_, w| w.bkp().bits(last));

&TRACING
}
2 changes: 2 additions & 0 deletions app/grapefruit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ readme = "README.md"
version = "0.1.0"

[features]
traptrace = ["ringbuf"]
dump = ["kern/dump"]

[dependencies]
cortex-m = { workspace = true }
cortex-m-rt = { workspace = true }
cfg-if = { workspace = true }
stm32h7 = { workspace = true, features = ["rt", "stm32h753"] }
ringbuf = { path = "../../lib/ringbuf", optional = true }

drv-stm32h7-startup = { path = "../../drv/stm32h7-startup", features = ["h753"] }
kern = { path = "../../sys/kern" }
Expand Down
12 changes: 11 additions & 1 deletion app/grapefruit/base.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ register-map = "../../drv/spartan7-loader/grapefruit/gfruit_top.json"
[kernel]
name = "grapefruit"
requires = {flash = 32768, ram = 8192}
features = ["dump"]
features = ["dump", "traptrace"]

[caboose]
tasks = ["control_plane_agent"]
Expand Down Expand Up @@ -337,6 +337,16 @@ task-slots = ["hash_driver", "spartan7_loader"]
stacksize = 4000
notifications = ["timer"]

[tasks.bork]
name = "task-bork"
priority = 8
max-sizes = {flash = 16384, ram = 16384 }
start = true
notifications = ["timer"]
task-slots = ["sprot", "sys"]
features = ["h753"]
uses = ["rtc"]

[config.net]
# VLAN configuration
[config.net.vlans.sidecar1]
Expand Down
1 change: 1 addition & 0 deletions app/grapefruit/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@

fn main() {
build_util::expose_target_board();
build_util::expose_m_profile().unwrap();
}
6 changes: 6 additions & 0 deletions app/grapefruit/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ use drv_stm32h7_startup::ClockConfig;

use cortex_m_rt::entry;

#[cfg(feature = "traptrace")]
mod tracing;

#[entry]
fn main() -> ! {
system_init();

const CYCLES_PER_MS: u32 = 400_000;

#[cfg(feature = "traptrace")]
kern::profiling::configure_events_table(tracing::table());

unsafe { kern::startup::start_kernel(CYCLES_PER_MS) }
}

Expand Down
106 changes: 106 additions & 0 deletions app/grapefruit/src/tracing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//
// If you are cutting-and-pasting this code into another kernel (and that
// kernel is armv6m), it is hoped that you will cut-and-paste this compile
// error along with it and take heed of its admonition!
//
#[cfg(not(any(armv7m, armv8m)))]
compile_error!("ringbuf is unsound in the kernel on armv6m");

use ringbuf::*;

#[derive(Copy, Clone, PartialEq)]
enum Event {
SyscallEnter(u32),
SyscallExit,
SecondarySyscallEnter,
SecondarySyscallExit,
IsrEnter,
IsrExit,
TimerIsrEnter,
TimerIsrExit,
ContextSwitch(usize),
}

#[derive(Copy, Clone, PartialEq)]
enum Trace {
Event(Event),
None,
}

ringbuf!(Trace, 128, Trace::None);

fn trace(event: Event) {
ringbuf_entry!(Trace::Event(event));
}

fn syscall_enter(nr: u32) {
trace(Event::SyscallEnter(nr));
}

fn syscall_exit() {
trace(Event::SyscallExit);
}

fn secondary_syscall_enter() {
trace(Event::SecondarySyscallEnter);
}

fn secondary_syscall_exit() {
trace(Event::SecondarySyscallExit);
}

fn isr_enter() {
trace(Event::IsrEnter);
}

fn isr_exit() {
trace(Event::IsrExit);
}

fn timer_isr_enter() {
trace(Event::TimerIsrEnter);
}

fn timer_isr_exit() {
trace(Event::TimerIsrExit);
}

fn context_switch(addr: usize) {
let rtc = unsafe { &*stm32h7::stm32h753::RTC::ptr() };
rtc.bkpr[0].modify(|_, w| w.bkp().bits(addr as u32));
trace(Event::ContextSwitch(addr));
}

static TRACING: kern::profiling::EventsTable = kern::profiling::EventsTable {
syscall_enter,
syscall_exit,
secondary_syscall_enter,
secondary_syscall_exit,
isr_enter,
isr_exit,
timer_isr_enter,
timer_isr_exit,
context_switch,
};

pub fn table() -> &'static kern::profiling::EventsTable {
let rtc = unsafe { &*stm32h7::stm32h753::RTC::ptr() };

// Unlock
rtc.wpr.write(|w| w.key().bits(0xca));
rtc.wpr.write(|w| w.key().bits(0x53));

// don't erase!
rtc.tampcr.modify(|_, w| w.tamp3noerase().set_bit().tamp2noerase().set_bit().tamp1noerase().set_bit());

// Save our last state
let last = rtc.bkpr[0].read().bkp().bits();
// And rotate
rtc.bkpr[1].modify(|_, w| w.bkp().bits(last));

&TRACING
}
4 changes: 4 additions & 0 deletions chips/stm32h7/chip.toml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ address = 0x52005000
size = 4096
interrupts = { irq = 92 }

[rtc]
address = 0x58004000
size = 1024

[eth]
address = 0x40028000
size = 0x2000
Expand Down
5 changes: 5 additions & 0 deletions drv/stm32h7-startup/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ unsafe fn system_pre_init() {
// convert it to a reference. We can have a reference to PWR because it's
// hardware, and is thus not uninitialized.
let pwr = &*device::PWR::ptr();
pwr.cr1.modify(|_, w| w.dbp().set_bit());
// Poke CR3 to enable the LDO and prevent further writes.
pwr.cr3.modify(|_, w| w.ldoen().set_bit());

Expand Down Expand Up @@ -324,6 +325,10 @@ pub fn system_init_custom(
// spin
}

p.RCC.cfgr.modify(|_, w| w.rtcpre().bits(0b100));

p.RCC.bdcr.modify(|_, w| w.rtcen().set_bit().rtcsel().lse());

// set RNG clock to PLL1 clock
#[cfg(any(feature = "h743", feature = "h753"))]
p.RCC.d2ccip2r.modify(|_, w| w.rngsel().pll1_q());
Expand Down
23 changes: 23 additions & 0 deletions idl/bork.idol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Cosmo SPD task API
//
// Right now, this doesn't actually do anything, but it lets us use the idol
// runtime for notifications / dispatch.
Interface(
name: "Bork",
ops: {
"ping": (
doc: "blocks until the server is running",
args: {},
reply: Simple("()"),
idempotent: true,
),
"wave_bye_bye": (
doc: "wave bye bye",
args: {},
reply: Simple("()"),
idempotent: true,
),

},
)

2 changes: 1 addition & 1 deletion sys/kern/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ fn generate_statics(gen: &Generated) -> Result<()> {
#[no_mangle]
pub static HUBRIS_IMAGE_ID: u64 = #image_id;

static mut HUBRIS_TASK_TABLE_SPACE:
pub(crate) static mut HUBRIS_TASK_TABLE_SPACE:
core::mem::MaybeUninit<[crate::task::Task; HUBRIS_TASK_COUNT]> =
core::mem::MaybeUninit::uninit();
},
Expand Down
4 changes: 3 additions & 1 deletion sys/kern/src/profiling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ pub(crate) fn event_timer_isr_exit() {
}

pub(crate) fn event_context_switch(tcb: usize) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this change, unless it was broken before?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing profiling just stores the base of the task, which is both fast and may have been fine for cliff's debugging (thanks again cliff for adding this). I was struggling to figure out how to go from task base to useful information so I did the calculation here. If we really hate this, we can get humility to do this work for us.

let base = unsafe { core::ptr::addr_of_mut!(crate::startup::HUBRIS_TASK_TABLE_SPACE) as *mut u32 as u32 as usize};
let size = core::mem::size_of::<crate::task::Task>();
if let Some(t) = table() {
(t.context_switch)(tcb)
(t.context_switch)((tcb - base)/size)
}
}
36 changes: 36 additions & 0 deletions task/bork/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[package]
name = "task-bork"
version = "0.1.0"
edition = "2021"

[dependencies]
# The idle task cannot panic, so we deliberately don't request panic-messages
# to keep the binary tiny.
userlib = { path = "../../sys/userlib" }
cortex-m = { workspace = true }
drv-sprot-api = { path = "../../drv/sprot-api" }
drv-stm32xx-sys-api = { path = "../../drv/stm32xx-sys-api" }
idol-runtime.workspace = true
zerocopy.workspace = true
zerocopy-derive.workspace = true
ringbuf = { path = "../../lib/ringbuf" }
counters = { path = "../../lib/counters" }
num-traits.workspace = true
stm32h7 = { workspace = true, features = ["stm32h753"] }

[features]
h753 = ["drv-stm32xx-sys-api/h753"]

[build-dependencies]
build-util = { path = "../../build/util" }
idol = { workspace = true }

# This section is here to discourage RLS/rust-analyzer from doing test builds,
# since test builds don't work for cross compilation.
[[bin]]
name = "task-bork"
test = false
bench = false

[lints]
workspace = true
16 changes: 16 additions & 0 deletions task/bork/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
build_util::expose_target_board();
build_util::build_notifications()?;

idol::Generator::new().build_server_support(
"../../idl/bork.idol",
"server_stub.rs",
idol::server::ServerStyle::InOrder,
)?;

Ok(())
}
Loading
Loading