From df7985033add697c2e504f60b8662aecb3e12a54 Mon Sep 17 00:00:00 2001 From: fastium Date: Fri, 5 Jun 2026 16:17:49 +0200 Subject: [PATCH] feat(MP/kernel): create regulator - contains the core of the module - manual - auto mode for the temperature regulation - use callback to communicate with temperature and led --- .../kernel/regulator/regulator.c | 137 ++++++++++++++++++ .../kernel/regulator/regulator.h | 20 +++ 2 files changed, 157 insertions(+) create mode 100644 src/06-mini-project/kernel/regulator/regulator.c create mode 100644 src/06-mini-project/kernel/regulator/regulator.h diff --git a/src/06-mini-project/kernel/regulator/regulator.c b/src/06-mini-project/kernel/regulator/regulator.c new file mode 100644 index 0000000..f25693d --- /dev/null +++ b/src/06-mini-project/kernel/regulator/regulator.c @@ -0,0 +1,137 @@ +// workspace/src/06-mini-project/kernel/regulator/regulator.c +#include +#include +#include +#include + +#include "regulator.h" +#include "../sysfs/sysfs.h" + +/* Internal state of the regulator */ +static int current_mode = 1; /* 1 = Auto, 0 = Manual */ +static uint32_t current_period = 2; /* Current blinking period in ms */ + +static struct task_struct *regulator_thread = NULL; + +static struct regulator_callbacks regulator_cbs = {0}; + +/* --- Sysfs Callbacks --- */ + +static uint32_t cb_get_temperature(void) { + return regulator_cbs.get_temperature(); +} + +static int cb_get_mode(void) { + return current_mode; +} + +static void cb_set_mode(int mode) { + /* Accept only 0 or 1 as valid modes */ + if (mode == 0 || mode == 1) { + current_mode = mode; + pr_info("regulator: Mode switched to %s\n", mode ? "Auto" : "Manual"); + } +} + +static uint32_t cb_get_period(void) { + return current_period; +} + +static void cb_set_period(uint32_t freq) { + /* Allow period changes only in Manual mode */ + if (current_mode == 0) { + current_period = freq; + regulator_cbs.adjust_period(current_period); + pr_info("regulator: Manual period set to %u ms\n", current_period); + } else { + pr_warn("regulator: Cannot set period manually in auto mode\n"); + } +} + +/* Pack callbacks into the structure expected by sysfs */ +static struct sysfs_callbacks sysfs_cbs = { + .get_temperature = cb_get_temperature, + .get_mode = cb_get_mode, + .set_mode = cb_set_mode, + .get_period = cb_get_period, + .set_period = cb_set_period, +}; + +/* --- Auto Mode Logic --- */ + +static void process_auto_mode(void) { + uint32_t temp_milli = regulator_cbs.get_temperature(); + uint32_t temp_c = temp_milli / 1000; + uint32_t new_period = 2; + + /* Determine period based on temperature thresholds */ + if (temp_c < 35) { + new_period = 500; + } else if (temp_c < 40) { + new_period = 200; + } else if (temp_c < 45) { + new_period = 100; + } else { + new_period = 50; + } + + /* Apply only if the period has changed to avoid unnecessary hardware updates */ + if (new_period != current_period) { + current_period = new_period; + regulator_cbs.adjust_period(current_period); + pr_info("regulator: Auto mode adjusted period to %u ms (Temp: %u C)\n", + current_period, temp_c); + } +} + +/* Background thread checking the temperature periodically */ +static int regulator_thread_fn(void *data) { + while (!kthread_should_stop()) { + if (current_mode == 1) { + process_auto_mode(); + } + msleep(1000); + } + return 0; +} + +/* --- Public API --- */ + +int regulator_init(struct regulator_callbacks *cbs) { + + if (cbs == NULL) { + pr_err("regulator: Callbacks are NULL\n"); + return -EINVAL; + } + + // register callbacks + regulator_cbs = *cbs; + + /* Initialize sysfs and inject our brain callbacks */ + int ret = temp_regulator_sysfs_init(&sysfs_cbs); + if (ret != 0) { + return ret; + } + + /* Start the background decision loop */ + regulator_thread = kthread_run(regulator_thread_fn, NULL, "regulator_logic"); + if (IS_ERR(regulator_thread)) { + temp_regulator_sysfs_exit(); + return PTR_ERR(regulator_thread); + } + + /* Set initial hardware state */ + regulator_cbs.adjust_period(current_period); + + return 0; +} + +void regulator_exit(void) { + + if (regulator_thread != NULL) { + kthread_stop(regulator_thread); + regulator_thread = NULL; + } + + temp_regulator_sysfs_exit(); +} diff --git a/src/06-mini-project/kernel/regulator/regulator.h b/src/06-mini-project/kernel/regulator/regulator.h new file mode 100644 index 0000000..1660899 --- /dev/null +++ b/src/06-mini-project/kernel/regulator/regulator.h @@ -0,0 +1,20 @@ +// workspace/src/06-mini-project/kernel/regulator/regulator.h +#ifndef REGULATOR_H +#define REGULATOR_H + +#include + +/* Callbacks for adjusting period and getting temperature */ +struct regulator_callbacks { + void (*adjust_period)(int new_period_ms); + uint32_t (*get_temperature)(void); +}; + + +/* Initialize the regulator logic, background thread, and sysfs. Register the callbacks with other parts */ +int regulator_init(struct regulator_callbacks *cbs); + +/* Stop the regulator logic and clean up */ +void regulator_exit(void); + +#endif /* REGULATOR_H */