mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
80 lines
2.2 KiB
C
80 lines
2.2 KiB
C
/*
|
|
* 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;
|
|
}
|