feat(MP/kernel): add temperature API
- init and exit fonction for the module - read_temp(), to get the temperature
This commit is contained in:
@@ -11,7 +11,15 @@ SOURCE := main
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
obj-m += $(MODULE).o ## name of the generated module
|
||||
|
||||
$(MODULE)-objs := $(SOURCE).o ## list of objects needed for that module
|
||||
# add folder sources
|
||||
SOURCES_C := $(wildcard $(src)/*.c)
|
||||
# add temperature sources
|
||||
SOURCES_C += $(wildcard $(src)/temperature/*.c)
|
||||
|
||||
|
||||
$(MODULE)-objs := $(patsubst $(src)/%.c, %.o, $(SOURCES_C))
|
||||
|
||||
# $(MODULE)-objs := $(SOURCE).o ## list of objects needed for that module
|
||||
CFLAGS_$(SOURCE).o := -DDEBUG
|
||||
|
||||
# Part executed when called from standard make in module source directory:
|
||||
@@ -28,7 +36,6 @@ clean:
|
||||
|
||||
install:
|
||||
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install
|
||||
install -D -m 0644 $(MODULE).conf $(MODPATH)/etc/modprobe.d/$(MODULE).conf
|
||||
# install -D -m 0644 $(MODULE).conf $(MODPATH)/etc/modprobe.d/$(MODULE).conf
|
||||
|
||||
endif
|
||||
|
||||
|
||||
@@ -2,13 +2,41 @@
|
||||
#include <linux/module.h> // needed by all modules
|
||||
#include <linux/init.h> // needed for macros
|
||||
#include <linux/kernel.h> // needed for debugging
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include "linux/printk.h"
|
||||
|
||||
#include "temperature/temp.h"
|
||||
|
||||
static struct task_struct *temp_thread = NULL;
|
||||
|
||||
/* Thread function that runs in the background */
|
||||
static int temp_thread_fn(void *data) {
|
||||
pr_info("temp_regulator: Background thread started\n");
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
read_temp();
|
||||
/* Wait 1 second (1000 milliseconds) */
|
||||
msleep(1000);
|
||||
}
|
||||
|
||||
pr_info("temp_regulator: Background thread stopping\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init temp_regulator_init(void) {
|
||||
pr_info("Linux module temp_regulator loading...\n");
|
||||
|
||||
|
||||
int ret;
|
||||
|
||||
/* Initialize temperature sensor API */
|
||||
ret = temp_init();
|
||||
if (ret != 0) {
|
||||
pr_err("temp_regulator: Initialization failed with error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pr_info("Linux module temp_regulator loaded\n");
|
||||
return 0;
|
||||
@@ -18,7 +46,9 @@ static void __exit temp_regulator_exit(void) {
|
||||
pr_info("Linux module temp_regulator unloading...\n");
|
||||
|
||||
|
||||
|
||||
/* Release sensor resources */
|
||||
temp_exit();
|
||||
|
||||
pr_info("Linux module temp_regulator unloaded\n");
|
||||
}
|
||||
|
||||
|
||||
83
src/06-mini-project/kernel/temperature/temp.c
Normal file
83
src/06-mini-project/kernel/temperature/temp.c
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "temp.h"
|
||||
|
||||
#define TEMPERATURE_SENSOR_BASE_ADDR 0x01C25000
|
||||
#define TEMPERATURE_SENSOR_REG_SIZE 0x1000
|
||||
#define TEMPERATURE_REG_OFFSET 0x80
|
||||
|
||||
static struct resource *temp_res = NULL;
|
||||
static void __iomem *temp_reg = NULL;
|
||||
|
||||
int temp_init(void) {
|
||||
/* Request physical memory region */
|
||||
temp_res = request_mem_region(TEMPERATURE_SENSOR_BASE_ADDR,
|
||||
TEMPERATURE_SENSOR_REG_SIZE,
|
||||
"nanopi - temperature sensor");
|
||||
if (temp_res == NULL) {
|
||||
pr_warn("temp_regulator: Failed to reserve physical memory region\n");
|
||||
}
|
||||
|
||||
/* Map the physical memory to virtual kernel memory */
|
||||
temp_reg = ioremap(TEMPERATURE_SENSOR_BASE_ADDR, TEMPERATURE_SENSOR_REG_SIZE);
|
||||
if (temp_reg == NULL) {
|
||||
pr_err("temp_regulator: Failed to ioremap registers\n");
|
||||
/* Clean up previously requested region */
|
||||
release_mem_region(TEMPERATURE_SENSOR_BASE_ADDR, TEMPERATURE_SENSOR_REG_SIZE);
|
||||
temp_res = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pr_info("temp_regulator: Temperature sensor memory successfully mapped\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t read_temp(void) {
|
||||
uint32_t temperature = 0;
|
||||
uint32_t raw_val = 0;
|
||||
|
||||
if (temp_reg == NULL) {
|
||||
pr_warn("temp_regulator: Cannot read temperature, sensor not initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the raw register value from THS0_DATA (offset 0x80) */
|
||||
raw_val = ioread32(temp_reg + TEMPERATURE_REG_OFFSET);
|
||||
|
||||
/* Choose the correct formula according to the datasheet */
|
||||
if (raw_val > 0x500) {
|
||||
/* Temperature is lower than 70°C */
|
||||
temperature = -1191 * (int32_t)raw_val / 10 + 223000;
|
||||
} else {
|
||||
/* Temperature is higher than or equal to 70°C */
|
||||
temperature = -1452 * (int32_t)raw_val / 10 + 259000;
|
||||
}
|
||||
|
||||
pr_info("temp_regulator: Temperature=%u.%03u C (register raw value: %u)\n",
|
||||
temperature / 1000,
|
||||
temperature % 1000,
|
||||
raw_val);
|
||||
|
||||
return temperature;
|
||||
}
|
||||
|
||||
void temp_exit(void) {
|
||||
/* Unmap virtual address space */
|
||||
if (temp_reg != NULL) {
|
||||
iounmap(temp_reg);
|
||||
temp_reg = NULL;
|
||||
}
|
||||
|
||||
/* Release physical memory region */
|
||||
if (temp_res != NULL) {
|
||||
release_mem_region(TEMPERATURE_SENSOR_BASE_ADDR, TEMPERATURE_SENSOR_REG_SIZE);
|
||||
temp_res = NULL;
|
||||
}
|
||||
|
||||
pr_info("temp_regulator: Temperature sensor resources released\n");
|
||||
}
|
||||
27
src/06-mini-project/kernel/temperature/temp.h
Normal file
27
src/06-mini-project/kernel/temperature/temp.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef TEMP_H
|
||||
#define TEMP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* temp_init() - Request physical memory and map it into kernel virtual memory.
|
||||
*
|
||||
* Return: 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
int temp_init(void);
|
||||
|
||||
/**
|
||||
* read_temp() - Read the current CPU temperature from the mapped registers.
|
||||
* To convert it in degrees Celsius, divide by 1000.0
|
||||
*
|
||||
* Return: The calculated temperature value.
|
||||
*/
|
||||
uint32_t read_temp(void);
|
||||
|
||||
|
||||
/**
|
||||
* temp_exit() - Unmap the virtual memory and release the requested physical memory region.
|
||||
*/
|
||||
void temp_exit(void);
|
||||
|
||||
#endif /* TEMP_H */
|
||||
Reference in New Issue
Block a user