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),)
|
ifneq ($(KERNELRELEASE),)
|
||||||
obj-m += $(MODULE).o ## name of the generated module
|
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
|
CFLAGS_$(SOURCE).o := -DDEBUG
|
||||||
|
|
||||||
# Part executed when called from standard make in module source directory:
|
# Part executed when called from standard make in module source directory:
|
||||||
@@ -28,7 +36,6 @@ clean:
|
|||||||
|
|
||||||
install:
|
install:
|
||||||
$(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_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
|
endif
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,41 @@
|
|||||||
#include <linux/module.h> // needed by all modules
|
#include <linux/module.h> // needed by all modules
|
||||||
#include <linux/init.h> // needed for macros
|
#include <linux/init.h> // needed for macros
|
||||||
#include <linux/kernel.h> // needed for debugging
|
#include <linux/kernel.h> // needed for debugging
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
|
||||||
#include "linux/printk.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) {
|
static int __init temp_regulator_init(void) {
|
||||||
pr_info("Linux module temp_regulator loading...\n");
|
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");
|
pr_info("Linux module temp_regulator loaded\n");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -18,7 +46,9 @@ static void __exit temp_regulator_exit(void) {
|
|||||||
pr_info("Linux module temp_regulator unloading...\n");
|
pr_info("Linux module temp_regulator unloading...\n");
|
||||||
|
|
||||||
|
|
||||||
|
/* Release sensor resources */
|
||||||
|
temp_exit();
|
||||||
|
|
||||||
pr_info("Linux module temp_regulator unloaded\n");
|
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