1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 05:12:57 +01:00

cpu/efm32: add coretemp driver

This commit is contained in:
Bas Stottelaar 2020-01-08 00:44:48 +01:00
parent a11514a198
commit 431e6efdf6
8 changed files with 211 additions and 0 deletions

View File

@ -29,4 +29,9 @@ ifneq (,$(filter cpu_ezr32wg,$(USEMODULE)))
DIRS += families/ezr32wg
endif
# add EFM32 specific drivers, if enabled
ifneq (,$(filter efm32_coretemp,$(USEMODULE)))
DIRS += drivers/coretemp
endif
include $(RIOTBASE)/Makefile.base

View File

@ -16,6 +16,10 @@ USEPKG += gecko_sdk
# include layered power management
USEMODULE += pm_layered
ifneq (,$(filter efm32_coretemp,$(USEMODULE)))
FEATURES_REQUIRED += periph_adc
endif
# CMSIS-DSP is needed for arm_math.h on Cortex-M0+ architectures
ifeq ($(CPU_CORE),cortex-m0plus)
USEPKG += cmsis-dsp

View File

@ -16,6 +16,9 @@ RIOTBOOT_LEN ?= 0x2000
# the em_device.h header requires a global define with the cpu model
CFLAGS += -D$(call uppercase_and_underscore,$(CPU_MODEL))
# include EFM32 specific driver headers
INCLUDES += -I$(RIOTCPU)/efm32/include/drivers
# include cortexm_common
LINKER_SCRIPT = cortexm.ld

View File

@ -0,0 +1,3 @@
MODULE = efm32_coretemp
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2018-2020 Bas Stottelaar <basstottelaar@gmail.com>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_efm32_drivers_coretemp
* @{
*
* @file
* @brief Implementation of EFM32 internal temperature sensor
*
* @author Bas Stottelaar <basstottelaar@gmail.com>
*
* @}
*/
#include <errno.h>
#include "board.h"
#include "coretemp.h"
#include "periph/adc.h"
#include "em_device.h"
int16_t coretemp_read(void)
{
/* initialize factory calibration values */
int32_t cal_temp = ((DEVINFO->CAL & _DEVINFO_CAL_TEMP_MASK) >>
_DEVINFO_CAL_TEMP_SHIFT);
#if defined(_SILICON_LABS_32B_SERIES_0)
int32_t cal_value = ((DEVINFO->ADC0CAL2 & _DEVINFO_ADC0CAL2_TEMP1V25_MASK) >>
_DEVINFO_ADC0CAL2_TEMP1V25_SHIFT);
#else
int32_t cal_value = ((DEVINFO->ADC0CAL3 & _DEVINFO_ADC0CAL3_TEMPREAD1V25_MASK) >>
_DEVINFO_ADC0CAL3_TEMPREAD1V25_SHIFT);
#endif
/* no factory calibration values */
if ((cal_temp == 0xFF) || (cal_value == 0x0FFF)) {
return -10000;
}
/* convert temperature channel */
int32_t value = adc_sample(CORETEMP_ADC, ADC_RES_12BIT);
/* t_grad is the inverse of 1.25 Vref / (4096 * mV/C) times 1000, so that
we can divide by an integer below with sufficient resolution (values
are from the datasheets) */
#if defined(_SILICON_LABS_32B_SERIES_0)
int32_t t_grad = -6291; /* -1.92 mV/C */
#else
int32_t t_grad = -6029; /* -1.84 mv/C */
#endif
/* convert to degrees centi-degrees Celsius (times 100) */
return (int16_t) ((cal_temp * 100) - ((cal_value - value) * 100000 / t_grad));
}
int coretemp_init(void)
{
/* sanity check to ensure the internal temperature sensor is selected */
#if defined(_SILICON_LABS_32B_SERIES_0)
assert(adc_channel_config[CORETEMP_ADC].input == adcSingleInputTemp);
#else
assert(adc_channel_config[CORETEMP_ADC].input == adcPosSelTEMP);
#endif
/* initialize ADC */
if (adc_init(CORETEMP_ADC) != 0) {
return -EIO;
}
return 0;
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2020 Bas Stottelaar <basstottelaar@gmail.com>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_efm32_drivers_coretemp
* @{
*
* @file
* @brief SAUL adoption for EFM32 internal temperature sensor
*
* @author Bas Stottelaar <basstottelaar@gmail.com>
*
* @}
*/
#include "coretemp.h"
#include "saul_reg.h"
static int _read(const void *dev, phydat_t *res)
{
(void)dev;
res->val[0] = coretemp_read();
res->unit = UNIT_TEMP_C;
res->scale = -2;
return 1;
}
const saul_driver_t efm32_coretemp_saul_driver = {
.read = _read,
.write = saul_notsup,
.type = SAUL_SENSE_TEMP
};
const saul_reg_info_t efm32_coretemp_saul_info = {
.name = "coretemp"
};

View File

@ -0,0 +1,5 @@
/**
* @defgroup cpu_efm32_drivers EFM32 specific drivers
* @ingroup cpu_efm32
* @brief Specific drivers for the EFM32 family of CPUs.
*/

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2020 Bas Stottelaar <basstottelaar@gmail.com>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup cpu_efm32_drivers_coretemp EFM32 internal temperature sensor
* @ingroup cpu_efm32_drivers
* @ingroup drivers_saul
* @brief Driver for the EFM32 internal temperature sensor
*
* All EFM32 chips have an internal ADC input channel that reads the internal
* temperature sensor. This EFM32-specific driver provides an interface for
* reading this value, compensated using factory-calibrated values.
*
* The board must define `CORETEMP_ADC` to point to the ADC line that connects
* to the right ADC input channel.
*
* This driver provides @ref drivers_saul capabilities.
*
* @{
*
* @file
* @brief Interface definition of the EFM32 internal temperature sensor
* driver.
*
* @author Bas Stottelaar <basstottelaar@gmail.com>
*/
#ifndef DRIVERS_CORETEMP_H
#define DRIVERS_CORETEMP_H
#include "kernel_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize the sensor.
*
* @return 0 on successful initialization
* @return -EIO on ADC initialization error
*
* This driver assumes that the `CORETEMP_ADC` is defined and points to the ADC
* input channel that is connected to the internal temperature sensor.
*/
int coretemp_init(void);
/**
* @brief Read the current temperature from the sensor.
*
* @return current temperature in centi-degrees Celsius
* (times 100)
*
* Temperature readings are compensated using the factory-calibration values.
*/
int16_t coretemp_read(void);
#ifdef __cplusplus
}
#endif
#endif /* DRIVERS_CORETEMP_H */
/** @} */