Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: start wiring alert pins to thermal task #1739

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

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

15 changes: 13 additions & 2 deletions app/gimlet/base.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@ port = "E"
pin = 3
owner = {name = "sprot", notification = "rot_irq"}

[tasks.sys.config.gpio-irqs.sp3_to_sp_alert_l]
port = "D"
pin = 6
owner = {name = "thermal", notification = "sp3_to_sp_alert_l"}

[tasks.sys.config.gpio-irqs.smbus_nic_temp_to_sp_alert_l]
port = "D"
pin = 15
owner = {name = "thermal", notification = "smbus_nic_temp_to_sp_alert_l"}


[tasks.spi2_driver]
name = "drv-stm32h7-spi-server"
priority = 3
Expand Down Expand Up @@ -131,8 +142,8 @@ priority = 5
max-sizes = {flash = 32768, ram = 8192 }
stacksize = 6000
start = true
task-slots = ["i2c_driver", "sensor", "gimlet_seq", "jefe"]
notifications = ["timer"]
task-slots = ["i2c_driver", "sensor", "gimlet_seq", "jefe", "sys"]
notifications = ["timer", "sp3_to_sp_alert_l", "smbus_nic_temp_to_sp_alert_l"]

[tasks.power]
name = "task-power"
Expand Down
3 changes: 2 additions & 1 deletion task/thermal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ zerocopy.workspace = true

drv-gimlet-seq-api = { path = "../../drv/gimlet-seq-api", optional = true }
drv-sidecar-seq-api = { path = "../../drv/sidecar-seq-api", optional = true }
drv-stm32xx-sys-api = { path = "../../drv/stm32xx-sys-api", optional = true }
drv-transceivers-api = { path = "../../drv/transceivers-api", optional = true }
userlib = { path = "../../sys/userlib", features = ["panic-messages"] }

Expand All @@ -35,7 +36,7 @@ build-i2c = { path = "../../build/i2c" }
build-util = { path = "../../build/util" }

[features]
gimlet = ["drv-gimlet-seq-api", "h753"]
gimlet = ["drv-gimlet-seq-api", "drv-stm32xx-sys-api/h753", "h753"]
sidecar = ["drv-sidecar-seq-api", "drv-transceivers-api", "h753"]
h743 = ["build-i2c/h743"]
h753 = ["build-i2c/h753"]
Expand Down
73 changes: 72 additions & 1 deletion task/thermal/src/bsp/gimlet_bcdef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@ use crate::{
TemperatureSensor,
},
i2c_config::{devices, sensors},
notifications,
};
pub use drv_gimlet_seq_api::SeqError;
use drv_gimlet_seq_api::{PowerState, Sequencer};
use drv_i2c_devices::max31790::Max31790;
use drv_stm32xx_sys_api::{self as sys_api, Sys};
use task_sensor_api::SensorId;
use task_thermal_api::ThermalProperties;
use userlib::{task_slot, units::Celsius, TaskId};
use userlib::{task_slot, units::Celsius, TaskId, UnwrapLite};

task_slot!(SEQ, gimlet_seq);
task_slot!(SYS, sys);

// We monitor the TMP117 air temperature sensors, but don't use them as part of
// the control loop.
Expand Down Expand Up @@ -53,6 +56,10 @@ pub const NUM_FANS: usize = drv_i2c_devices::max31790::MAX_FANS as usize;
/// This controller is tuned and ready to go
pub const USE_CONTROLLER: bool = true;

pub(crate) const ALERT_MASK: u32 =
notifications::SMBUS_NIC_TEMP_TO_SP_ALERT_L_MASK
| notifications::SP3_TO_SP_ALERT_L_MASK;

pub(crate) struct Bsp {
/// Controlled sensors
pub inputs: &'static [InputChannel],
Expand All @@ -67,13 +74,24 @@ pub(crate) struct Bsp {
/// Handle to the sequencer task, to query power state
seq: Sequencer,

/// Handle to the sys task for GPIO alert interrupt control.
sys: Sys,

/// Id of the I2C task, to query MAX5970 status
i2c_task: TaskId,

/// Tuning for the PID controller
pub pid_config: PidConfig,
}

#[derive(Copy, Clone, PartialEq, Eq, counters::Count)]
pub(crate) enum Alert {
/// Alert from the CPU on `SP3_TO_SP_ALERT_L`
SmbusSbTsiAlert,
/// Alert from the T6 on `SMBUS_NIC_TEMP_TO_SP_ALERT_L`
SmbusNicTemp,
}

bitflags::bitflags! {
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct PowerBitmask: u32 {
Expand All @@ -93,6 +111,36 @@ bitflags::bitflags! {
}

impl Bsp {
pub fn is_alerted(&self, notif: u32) -> Option<Alert> {
if notif & notifications::SP3_TO_SP_ALERT_L_MASK != 0
&& self
.sys
.gpio_irq_control(
notifications::SP3_TO_SP_ALERT_L_MASK,
sys_api::IrqControl::Enable,
)
.unwrap_lite()
{
return Some(Alert::SmbusSbTsiAlert);
}

if notif & notifications::SMBUS_NIC_TEMP_TO_SP_ALERT_L_MASK != 0 {
if self.seq.get_state() == PowerState::A0PlusHP
&& self
.sys
.gpio_irq_control(
notifications::SMBUS_NIC_TEMP_TO_SP_ALERT_L_MASK,
sys_api::IrqControl::Enable,
)
.unwrap_lite()
{
return Some(Alert::SmbusNicTemp);
}
}

None
}

pub fn fan_control(&self, fan: crate::Fan) -> FanControl<'_> {
FanControl::Max31790(&self.fctrl, fan.0.try_into().unwrap())
}
Expand Down Expand Up @@ -163,9 +211,32 @@ impl Bsp {

// Handle for the sequencer task, which we check for power state
let seq = Sequencer::from(SEQ.get_task_id());
let sys = Sys::from(SYS.get_task_id());

// Configure GPIO IRQs for thermal alert pins.
// Leave this alone for now; we only want to get an IRQ from it once the
// NIC is up.
// sys.gpio_configure_input(
// sys_api::gpio_irqs::SMBUS_NIC_TEMP_TO_SP_ALERT_L,
// sys_api::Pull::None,
// );
// sys.gpio_irq_configure(
// notifications::SMBUS_NIC_TEMP_TO_SP_ALERT_L,
// sys_api::Edge::Falling,
// );
sys.gpio_configure_input(
sys_api::gpio_irq_pins::SP3_TO_SP_ALERT_L,
// XXX(eliza): IS THIS RIGHT???
sys_api::Pull::None,
);
sys.gpio_irq_configure(
notifications::SP3_TO_SP_ALERT_L_MASK,
sys_api::Edge::Falling,
);

Self {
seq,
sys,
i2c_task,
fctrl,

Expand Down
9 changes: 9 additions & 0 deletions task/thermal/src/bsp/sidecar_bcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ pub const NUM_FANS: usize = sensors::NUM_MAX31790_SPEED_SENSORS;
// Run the PID loop on startup
pub const USE_CONTROLLER: bool = true;

pub(crate) const ALERT_MASK: u32 = 0;

////////////////////////////////////////////////////////////////////////////////

bitflags::bitflags! {
Expand Down Expand Up @@ -73,7 +75,14 @@ pub(crate) struct Bsp {
pub pid_config: PidConfig,
}

#[derive(Copy, Clone, PartialEq, Eq, counters::Count)]
pub(crate) enum Alert {}

impl Bsp {
pub fn is_alerted(&mut self, notif: u32) -> Option<Alert> {
None
}

pub fn fan_control(
&self,
fan: crate::Fan,
Expand Down
27 changes: 22 additions & 5 deletions task/thermal/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl From<usize> for Fan {
task_slot!(I2C, i2c_driver);
task_slot!(SENSOR, sensor);

#[derive(Copy, Clone, Debug, Eq, PartialEq, counters::Count)]
#[derive(Copy, Clone, Eq, PartialEq, counters::Count)]
enum Trace {
#[count(skip)]
None,
Expand All @@ -83,12 +83,18 @@ enum Trace {
PowerDownAt(u64),
AddedDynamicInput(usize),
RemovedDynamicInput(usize),
Alert {
now: u64,
#[count(children)]
alert: bsp::Alert,
},
}
counted_ringbuf!(Trace, 32, Trace::None);

////////////////////////////////////////////////////////////////////////////////

struct ServerImpl<'a> {
bsp: &'a Bsp,
mode: ThermalMode,
control: ThermalControl<'a>,
deadline: u64,
Expand Down Expand Up @@ -291,13 +297,24 @@ impl<'a> idl::InOrderThermalImpl for ServerImpl<'a> {

impl<'a> NotificationHandler for ServerImpl<'a> {
fn current_notification_mask(&self) -> u32 {
notifications::TIMER_MASK
notifications::TIMER_MASK | bsp::ALERT_MASK
}

fn handle_notification(&mut self, _bits: u32) {
fn handle_notification(&mut self, bits: u32) {
let now = sys_get_timer().now;
if now >= self.deadline {
let should_do_work = if let Some(alert) = self.bsp.is_alerted(bits) {
ringbuf_entry!(Trace::Alert { now, alert });
true
} else if now >= self.deadline {
self.deadline = now + TIMER_INTERVAL;
true
} else {
false
};

if should_do_work {
// See if any fans were removed or added since last iteration
// TODO(eliza): should we still do this if woken by an alert?
self.control.update_fan_presence();

// We *always* read sensor data, which does not touch the control
Expand Down Expand Up @@ -327,7 +344,6 @@ impl<'a> NotificationHandler for ServerImpl<'a> {
panic!("Mode must not be 'Off' when server is running")
}
}
self.deadline = now + TIMER_INTERVAL;
}
self.runtime = sys_get_timer().now - now;
sys_set_timer(Some(self.deadline), notifications::TIMER_MASK);
Expand All @@ -351,6 +367,7 @@ fn main() -> ! {
sys_set_timer(Some(deadline), notifications::TIMER_MASK);

let mut server = ServerImpl {
bsp: &bsp,
mode: ThermalMode::Off,
control,
deadline,
Expand Down