Skip to content

Commit 5b52b6f

Browse files
committed
drivers: sensors: Add support for RaspberryPi Pico CPU temperature
Support for the measuring the CPU die temperature for the RaspberryPi Pico. Signed-off-by: TOKITA Hiroshi <[email protected]>
1 parent 05d3b57 commit 5b52b6f

File tree

7 files changed

+200
-0
lines changed

7 files changed

+200
-0
lines changed

drivers/sensor/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ add_subdirectory_ifdef(CONFIG_TACH_IT8XXX2 ite_tach_it8xxx2)
114114
add_subdirectory_ifdef(CONFIG_VCMP_IT8XXX2 ite_vcmp_it8xxx2)
115115
add_subdirectory_ifdef(CONFIG_PCNT_ESP32 pcnt_esp32)
116116
add_subdirectory_ifdef(CONFIG_ESP32_TEMP esp32_temp)
117+
add_subdirectory_ifdef(CONFIG_RPI_PICO_TEMP rpi_pico_temp)
117118

118119
if(CONFIG_USERSPACE OR CONFIG_SENSOR_SHELL OR CONFIG_SENSOR_SHELL_BATTERY)
119120
# The above if() is needed or else CMake would complain about

drivers/sensor/Kconfig

+2
Original file line numberDiff line numberDiff line change
@@ -267,4 +267,6 @@ source "drivers/sensor/pcnt_esp32/Kconfig"
267267

268268
source "drivers/sensor/esp32_temp/Kconfig"
269269

270+
source "drivers/sensor/rpi_pico_temp/Kconfig"
271+
270272
endif # SENSOR
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Copyright (c) 2023 TOKITA Hiroshi
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
zephyr_library()
5+
6+
zephyr_library_sources(rpi_pico_temp.c)

drivers/sensor/rpi_pico_temp/Kconfig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Raspberry Pi Pico temperature sensor configuration options
2+
3+
# Copyright (c) 2023 TOKITA Hiroshi
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
config RPI_PICO_TEMP
7+
bool "Raspberry Pi Pico CPU Temperature Sensor"
8+
default y
9+
depends on DT_HAS_RASPBERRYPI_PICO_TEMP_ENABLED
10+
depends on ADC
11+
12+
help
13+
Enable driver for Raspberry Pi Pico CPU temperature sensor.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* Copyright (c) 2023 TOKITA Hiroshi
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/device.h>
8+
#include <zephyr/devicetree.h>
9+
#include <zephyr/drivers/sensor.h>
10+
#include <zephyr/drivers/adc.h>
11+
#include <zephyr/logging/log.h>
12+
13+
#include <hardware/adc.h>
14+
15+
LOG_MODULE_REGISTER(rpi_pico_temp, CONFIG_SENSOR_LOG_LEVEL);
16+
17+
#define DT_DRV_COMPAT raspberrypi_pico_temp
18+
19+
struct rpi_pico_temp_config {
20+
const struct device *adc;
21+
const struct adc_channel_cfg ch_cfg;
22+
const int32_t vbe;
23+
const int32_t vbe_slope;
24+
};
25+
26+
struct rpi_pico_temp_data {
27+
struct adc_sequence adc_seq;
28+
int16_t sample;
29+
};
30+
31+
static int rpi_pico_temp_sample_fetch(const struct device *dev, enum sensor_channel chan)
32+
{
33+
const struct rpi_pico_temp_config *cfg = dev->config;
34+
struct rpi_pico_temp_data *data = dev->data;
35+
int rc;
36+
37+
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
38+
return -ENOTSUP;
39+
}
40+
41+
rc = adc_channel_setup(cfg->adc, &cfg->ch_cfg);
42+
if (rc) {
43+
LOG_DBG("Setup ADC channel %u failed with %d", cfg->ch_cfg.channel_id, rc);
44+
return rc;
45+
}
46+
47+
rc = adc_read(cfg->adc, &data->adc_seq);
48+
49+
return rc;
50+
}
51+
52+
static int rpi_pico_temp_channel_get(const struct device *dev, enum sensor_channel chan,
53+
struct sensor_value *val)
54+
{
55+
const struct rpi_pico_temp_config *cfg = dev->config;
56+
struct rpi_pico_temp_data *data = dev->data;
57+
int32_t mv = 0;
58+
int32_t work;
59+
int rc;
60+
61+
if (chan != SENSOR_CHAN_DIE_TEMP) {
62+
return -ENOTSUP;
63+
}
64+
65+
mv = data->sample;
66+
rc = adc_raw_to_millivolts(adc_ref_internal(cfg->adc), cfg->ch_cfg.gain,
67+
data->adc_seq.resolution, &mv);
68+
if (rc) {
69+
LOG_DBG("adc_raw_to_millivolts() failed %d", rc);
70+
return rc;
71+
}
72+
73+
/*
74+
* Calculate CPU temperature from voltage by the equation:
75+
* T = 27 - (ADC_Voltage - 0.706)/0.001721
76+
*/
77+
work = ((27 * (-cfg->vbe_slope)) - (mv * 1000 - cfg->vbe));
78+
val->val1 = work / (-cfg->vbe_slope);
79+
work -= val->val1 * (-cfg->vbe_slope);
80+
val->val2 = work * 1000000 / (-cfg->vbe_slope);
81+
82+
return 0;
83+
}
84+
85+
static const struct sensor_driver_api rpi_pico_temp_driver_api = {
86+
.sample_fetch = rpi_pico_temp_sample_fetch,
87+
.channel_get = rpi_pico_temp_channel_get,
88+
};
89+
90+
static int rpi_pico_temp_init(const struct device *dev)
91+
{
92+
const struct rpi_pico_temp_config *cfg = dev->config;
93+
94+
if (!device_is_ready(cfg->adc)) {
95+
LOG_ERR("Device %s is not ready", cfg->adc->name);
96+
return -ENODEV;
97+
}
98+
99+
adc_set_temp_sensor_enabled(true);
100+
101+
return 0;
102+
}
103+
104+
#define RPI_PICO_TEMP_DEFINE(inst) \
105+
static const struct rpi_pico_temp_config rpi_pico_temp_config_##inst = { \
106+
.adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst)), \
107+
.vbe = DT_INST_PROP(inst, vbe), \
108+
.vbe_slope = DT_INST_PROP(inst, vbe_slope), \
109+
.ch_cfg = \
110+
{ \
111+
.gain = ADC_GAIN_1, \
112+
.reference = ADC_REF_INTERNAL, \
113+
.acquisition_time = ADC_ACQ_TIME_DEFAULT, \
114+
.channel_id = DT_INST_IO_CHANNELS_INPUT(inst), \
115+
.differential = 0, \
116+
}, \
117+
}; \
118+
static struct rpi_pico_temp_data rpi_pico_temp_dev_data_##inst = { \
119+
.adc_seq = \
120+
{ \
121+
.channels = BIT(DT_INST_IO_CHANNELS_INPUT(inst)), \
122+
.buffer = &rpi_pico_temp_dev_data_##inst.sample, \
123+
.buffer_size = sizeof(rpi_pico_temp_dev_data_##inst.sample), \
124+
.resolution = 12U, \
125+
}, \
126+
}; \
127+
\
128+
SENSOR_DEVICE_DT_INST_DEFINE(inst, rpi_pico_temp_init, NULL, \
129+
&rpi_pico_temp_dev_data_##inst, &rpi_pico_temp_config_##inst, \
130+
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
131+
&rpi_pico_temp_driver_api);
132+
133+
DT_INST_FOREACH_STATUS_OKAY(RPI_PICO_TEMP_DEFINE)

dts/arm/rpi_pico/rp2040.dtsi

+10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
#include "rpi_pico_common.dtsi"
1313

1414
/ {
15+
aliases {
16+
die-temp0 = &die_temp;
17+
};
18+
1519
cpus {
1620
#address-cells = <1>;
1721
#size-cells = <0>;
@@ -185,6 +189,12 @@
185189
pinctrl: pin-controller {
186190
compatible = "raspberrypi,pico-pinctrl";
187191
};
192+
193+
die_temp: dietemp {
194+
compatible = "raspberrypi,pico-temp";
195+
io-channels = <&adc 4>;
196+
status = "disabled";
197+
};
188198
};
189199

190200
&nvic {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright (c) 2023 TOKITA Hiroshi
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: RaspberryPi Pico family temperature sensor node
5+
6+
compatible: "raspberrypi,pico-temp"
7+
8+
include: sensor-device.yaml
9+
10+
properties:
11+
io-channels:
12+
required: true
13+
description: ADC channel for CPU temperature sensor
14+
15+
vbe:
16+
type: int
17+
default: 706000
18+
description: |
19+
Vbe voltage in microvolts at 27 degrees C. Vbe = 0.706V typically.
20+
The temperature sensor measures the Vbe voltage of a biased bipolar diode.
21+
The temperature calculates from the Vbe voltage measured by the sensor
22+
using the following equation typical case.
23+
24+
T = 27 - (ADC_Voltage - 0.706)/0.001721
25+
26+
See also the vbe-slope section.
27+
28+
vbe-slope:
29+
type: int
30+
default: -1721
31+
description: |
32+
The slope of Vbe voltage in microvolts per degree C.
33+
Typically, a slope of -1.721mV per degree.
34+
35+
See also the vbe section.

0 commit comments

Comments
 (0)