diff --git a/module/thermal_mgmt/include/mod_thermal_mgmt.h b/module/thermal_mgmt/include/mod_thermal_mgmt.h index 4cfd134023f99eea358487fa87047cd49dc8f99f..2ab9c747413ac34bc0fc888b1daf810498d0ceb2 100644 --- a/module/thermal_mgmt/include/mod_thermal_mgmt.h +++ b/module/thermal_mgmt/include/mod_thermal_mgmt.h @@ -177,7 +177,13 @@ struct mod_thermal_mgmt_dev_config { /*! Integral term (PI loop) */ int32_t k_integral; - } pi_controller; +#ifdef PID + /*! Derivative term (PID loop) */ + int32_t k_derivative; + } pid_controller; +#else + }pi_controller; +#endif /*! Temperature sensor identifier */ fwk_id_t sensor_id; diff --git a/module/thermal_mgmt/src/mod_thermal_mgmt.c b/module/thermal_mgmt/src/mod_thermal_mgmt.c index bdfcea68d669fbd16f9da1db7d85c929ec05675f..2b452ad897fd060375eb15b0875d5a6f0fd0b15e 100644 --- a/module/thermal_mgmt/src/mod_thermal_mgmt.c +++ b/module/thermal_mgmt/src/mod_thermal_mgmt.c @@ -34,6 +34,68 @@ struct mod_thermal_mgmt_actor_ctx *get_actor_ctx( return &dev_ctx->actor_ctx_table[actor]; } + +#ifdef PID +static void pid_control(fwk_id_t id) +{ + struct mod_thermal_mgmt_dev_ctx *dev_ctx; + int32_t err, terr, pid_power; + int32_t k_p, k_i,k_d; + + dev_ctx = get_dev_ctx(id); + + if (dev_ctx->cur_temp < + dev_ctx->config->pid_controller.switch_on_temperature) { + /* The PID loop is not activated */ + dev_ctx->integral_error = 0; + dev_ctx->last_error = 0; + dev_ctx->thermal_allocatable_power = (uint32_t)dev_ctx->config->tdp; + + return; + } + + k_i = dev_ctx->config->pid_controller.k_integral; + + err = (int32_t)dev_ctx->config->pid_controller.control_temperature - + (int32_t)dev_ctx->cur_temp; + + k_p = (err < 0) ? dev_ctx->config->pid_controller.k_p_overshoot : + dev_ctx->config->pid_controller.k_p_undershoot; + + /* Evaluate the integral term */ + if (((err > 0) && (dev_ctx->integral_error < (INT32_MAX - err))) || + ((err < 0) && (dev_ctx->integral_error > (INT32_MIN - err)))) { + terr = dev_ctx->integral_error + err; + + if ((err < dev_ctx->config->pid_controller.integral_cutoff) && + (terr < dev_ctx->config->pid_controller.integral_max)) { + /* + * The error is below the cutoff value and, + * the accumulated error is still within the maximum permissible + * value, thus continue integration. + */ + dev_ctx->integral_error = terr; + } + } + + /* Calculate the derivative term */ + k_d = dev_ctx->config->pid_controller.k_derivative; + + dev_ctx->derivative_error = err - dev_ctx->last_error; + dev_ctx->last_error = err; + + /* Calculate the PID power */ + + pid_power = (k_p * err) + (k_i * dev_ctx->integral_error)+ (k_d * dev_ctx->derivative_error); + + if (pid_power + (int32_t)dev_ctx->config->tdp > 0) { + dev_ctx->thermal_allocatable_power = + pid_power + (uint32_t)dev_ctx->config->tdp; + } else { + dev_ctx->thermal_allocatable_power = 0; + } +} +#else static void pi_control(fwk_id_t id) { struct mod_thermal_mgmt_dev_ctx *dev_ctx; @@ -84,6 +146,7 @@ static void pi_control(fwk_id_t id) dev_ctx->thermal_allocatable_power = 0; } } +#endif static void thermal_protection(struct mod_thermal_mgmt_dev_ctx *dev_ctx) { @@ -176,7 +239,11 @@ static int control_update(fwk_id_t id) if (dev_ctx->control_needs_update) { dev_ctx->control_needs_update = false; if (dev_ctx->config->thermal_actors_count > 0) { - pi_control(id); +#ifdef PID + pid_control(id); +#else + pi_control(id); +#endif } dev_ctx->tot_spare_power = 0; diff --git a/module/thermal_mgmt/src/thermal_mgmt.h b/module/thermal_mgmt/src/thermal_mgmt.h index a6d3f4b4f2a85af1ebc7288ccc6a3691124024c5..7b7ed6ba8090380eb2ec2f4a455758c3d5987b7f 100644 --- a/module/thermal_mgmt/src/thermal_mgmt.h +++ b/module/thermal_mgmt/src/thermal_mgmt.h @@ -97,6 +97,14 @@ struct mod_thermal_mgmt_dev_ctx { /* Integral (accumulated) error */ int32_t integral_error; +#ifdef PID + /* Derivative error */ + int32_t derivative_error; + + /* Last error for the derivative */ + int32_t last_error; +#endif + /* Table of thermal actors */ struct mod_thermal_mgmt_actor_ctx *actor_ctx_table;