/// This is the main body of the closed loop thermal control logic. The function is called
/// periodically by the timer started in `start_periodic_thermal_loop`. For each iteration, the
/// following steps will be taken:
///     1. Read the current temperature from the temperature driver specified in ThermalConfig
///     2. Filter the raw temperature value using a low-pass filter
///     3. Use the new filtered temperature value as input to the PID control algorithm
///     4. The PID algorithm outputs the available power limit to impose in the system
///     5. Distribute the available power to the power actors (initially this is only the CPU)
This is the main body of the closed loop thermal control logic. The function is called
periodically by the timer started in `start_periodic_thermal_loop`. For each iteration, the
following steps will be taken:
1. Read the current temperature from the temperature driver specified in ThermalConfig
2. Filter the raw temperature value using a low-pass filter
3. Use the new filtered temperature value as input to the PID control algorithm
4. The PID algorithm outputs the available power limit to impose in the system
5. Distribute the available power to the power actors (initially this is only the CPU)
This is the main body of the closed loop thermal control logic . The function is called periodically by the timer started in ` start_periodic_thermal_loop ` . For each iteration the following steps will be taken : 1 . Read the current temperature from the temperature driver specified in ThermalConfig 2 . Filter the raw temperature value using a low - pass filter 3 . Use the new filtered temperature value as input to the PID control algorithm 4 . The PID algorithm outputs the available power limit to impose in the system 5 . Distribute the available power to the power actors ( initially this is only the CPU )
pub async fn iterate_thermal_control(&self) -> Result<(), Error> {
        fuchsia_trace::duration!("power_manager", "ThermalPolicy::iterate_thermal_control");
        let raw_temperature = self.get_temperature().await?;
        self.thermal_metrics.borrow_mut().log_raw_temperature(raw_temperature);
        // Record the timestamp for this iteration now that we have all the data we need to proceed
        let timestamp = Nanoseconds(fasync::Time::now().into_nanos());
        // We should have run the iteration at least once before proceeding
        if !self.state.state_initialized.get() {
            self.state.prev_temperature.set(raw_temperature);
            self.state.prev_timestamp.set(timestamp);
            self.state.state_initialized.set(true);
            self.inspect.state_initialized.set(1);
            return Ok(());
        }
        let time_delta = Seconds::from_nanos(timestamp.0 - self.state.prev_timestamp.get().0);
        if time_delta.0 > self.state.max_time_delta.get().0 {
            self.state.max_time_delta.set(time_delta);
            self.inspect.max_time_delta.set(time_delta.0);
        }
        self.state.prev_timestamp.set(timestamp);
        let filtered_temperature = Celsius(low_pass_filter(
            raw_temperature.0,
            self.state.prev_temperature.get().0,
            time_delta.0,
            self.config.policy_params.controller_params.filter_time_constant.0,
        ));
        self.state.prev_temperature.set(filtered_temperature);
        self.inspect.timestamp.set(timestamp.0);
        self.inspect.time_delta.set(time_delta.0);
        self.inspect.temperature_raw.set(raw_temperature.0);
        self.inspect.temperature_filtered.set(filtered_temperature.0);
        fuchsia_trace::instant!(
            "power_manager",
            "ThermalPolicy::thermal_control_iteration_data",
            fuchsia_trace::Scope::Thread,
            "timestamp" => timestamp.0
        );
        fuchsia_trace::counter!(
            "power_manager",
            "ThermalPolicy raw_temperature",
            0,
            "raw_temperature" => raw_temperature.0
        );
        fuchsia_trace::counter!(
            "power_manager",
            "ThermalPolicy filtered_temperature",
            0,
            "filtered_temperature" => filtered_temperature.0
        );
        // If the new temperature is above the critical threshold then shutdown the system
        let result = self.check_critical_temperature(timestamp, filtered_temperature).await;
        log_if_err!(result, "Error checking critical temperature");
        fuchsia_trace::instant!(
            "power_manager",
            "ThermalPolicy::check_critical_temperature_result",
            fuchsia_trace::Scope::Thread,
            "result" => format!("{:?}", result).as_str()
        );
        // Update the ThermalLimiter node with the latest thermal load
        let result = self.update_thermal_load(timestamp, filtered_temperature).await;
        log_if_err!(result, "Error updating thermal load");
        fuchsia_trace::instant!(
            "power_manager",
            "ThermalPolicy::update_thermal_load_result",
            fuchsia_trace::Scope::Thread,
            "result" => format!("{:?}", result).as_str()
        );
        // Run the thermal feedback controller
        let result = self.iterate_controller(filtered_temperature, time_delta).await;
        log_if_err!(result, "Error running thermal feedback controller");
        fuchsia_trace::instant!(
            "power_manager",
            "ThermalPolicy::iterate_controller_result",
            fuchsia_trace::Scope::Thread,
            "result" => format!("{:?}", result).as_str()
        );
        Ok(())
    }
pub async fn iterate_thermal_control ( & self ) -> Result < ( ) , Error > { fuchsia_trace :: duration ! ( " " " " ) ; let raw_temperature = self . get_temperature ( ) . await ? ; self . thermal_metrics . borrow_mut ( ) . log_raw_temperature ( raw_temperature ) ; // Record the timestamp for this iteration now that we have all the data we need to proceed let timestamp = Nanoseconds ( fasync :: Time :: now ( ) . into_nanos ( ) ) ; // We should have run the iteration at least once before proceeding if ! self . state . state_initialized . get ( ) { self . state . prev_temperature . set ( raw_temperature ) ; self . state . prev_timestamp . set ( timestamp ) ; self . state . state_initialized . set ( true ) ; self . inspect . state_initialized . set ( 1 ) ; return Ok ( ( ) ) ; } let time_delta = Seconds :: from_nanos ( timestamp . 0 - self . state . prev_timestamp . get ( ) . 0 ) ; if time_delta . 0 > self . state . max_time_delta . get ( ) . 0 { self . state . max_time_delta . set ( time_delta ) ; self . inspect . max_time_delta . set ( time_delta . 0 ) ; } self . state . prev_timestamp . set ( timestamp ) ; let filtered_temperature = Celsius ( low_pass_filter ( raw_temperature . 0 , self . state . prev_temperature . get ( ) . 0 , time_delta . 0 , self . config . policy_params . controller_params . filter_time_constant . 0 , ) ) ; self . state . prev_temperature . set ( filtered_temperature ) ; self . inspect . timestamp . set ( timestamp . 0 ) ; self . inspect . time_delta . set ( time_delta . 0 ) ; self . inspect . temperature_raw . set ( raw_temperature . 0 ) ; self . inspect . temperature_filtered . set ( filtered_temperature . 0 ) ; fuchsia_trace :: instant ! ( " " " " fuchsia_trace Scope Thread " " timestamp 0 ) ; fuchsia_trace :: counter ! ( " " " " 0 " " raw_temperature 0 ) ; fuchsia_trace :: counter ! ( " " " " 0 " " filtered_temperature 0 ) ; // If the new temperature is above the critical threshold then shutdown the system let result = self . check_critical_temperature ( timestamp , filtered_temperature ) . await ; log_if_err ! ( result " " ) ; fuchsia_trace :: instant ! ( " " " " fuchsia_trace Scope Thread " " format ( " " result ) as_str ( ) ) ; // Update the ThermalLimiter node with the latest thermal load let result = self . update_thermal_load ( timestamp , filtered_temperature ) . await ; log_if_err ! ( result " " ) ; fuchsia_trace :: instant ! ( " " " " fuchsia_trace Scope Thread " " format ( " " result ) as_str ( ) ) ; // Run the thermal feedback controller let result = self . iterate_controller ( filtered_temperature , time_delta ) . await ; log_if_err ! ( result " " ) ; fuchsia_trace :: instant ! ( " " " " fuchsia_trace Scope Thread " " format ( " " result ) as_str ( ) ) ; Ok ( ( ) ) }
This is the main body of the closed loop thermal control logic.
This is the main body of the closed loop thermal control logic .
&self