-
Notifications
You must be signed in to change notification settings - Fork 6.1k
/
temp_nrf5.c
144 lines (110 loc) · 3.39 KB
/
temp_nrf5.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
* Copyright (c) 2016 ARM Ltd.
* Copyright (c) 2019 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT nordic_nrf_temp
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
#include <zephyr/logging/log.h>
#include <hal/nrf_temp.h>
#include <zephyr/irq.h>
LOG_MODULE_REGISTER(temp_nrf5, CONFIG_SENSOR_LOG_LEVEL);
/* The nRF5 temperature device returns measurements in 0.25C
* increments. Scale to mDegrees C.
*/
#define TEMP_NRF5_TEMP_SCALE (1000000 / 4)
struct temp_nrf5_data {
struct k_sem device_sync_sem;
struct k_mutex mutex;
int32_t sample;
struct onoff_manager *clk_mgr;
};
static void hfclk_on_callback(struct onoff_manager *mgr,
struct onoff_client *cli,
uint32_t state,
int res)
{
nrf_temp_task_trigger(NRF_TEMP, NRF_TEMP_TASK_START);
}
static int temp_nrf5_sample_fetch(const struct device *dev,
enum sensor_channel chan)
{
struct temp_nrf5_data *data = dev->data;
struct onoff_client cli;
int r;
/* Error if before sensor initialized */
if (data->clk_mgr == NULL) {
return -EAGAIN;
}
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
return -ENOTSUP;
}
k_mutex_lock(&data->mutex, K_FOREVER);
sys_notify_init_callback(&cli.notify, hfclk_on_callback);
r = onoff_request(data->clk_mgr, &cli);
__ASSERT_NO_MSG(r >= 0);
k_sem_take(&data->device_sync_sem, K_FOREVER);
r = onoff_release(data->clk_mgr);
__ASSERT_NO_MSG(r >= 0);
data->sample = nrf_temp_result_get(NRF_TEMP);
LOG_DBG("sample: %d", data->sample);
nrf_temp_task_trigger(NRF_TEMP, NRF_TEMP_TASK_STOP);
k_mutex_unlock(&data->mutex);
return 0;
}
static int temp_nrf5_channel_get(const struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
struct temp_nrf5_data *data = dev->data;
int32_t uval;
if (chan != SENSOR_CHAN_DIE_TEMP) {
return -ENOTSUP;
}
uval = data->sample * TEMP_NRF5_TEMP_SCALE;
val->val1 = uval / 1000000;
val->val2 = uval % 1000000;
LOG_DBG("Temperature:%d,%d", val->val1, val->val2);
return 0;
}
static void temp_nrf5_isr(const void *arg)
{
const struct device *dev = (const struct device *)arg;
struct temp_nrf5_data *data = dev->data;
nrf_temp_event_clear(NRF_TEMP, NRF_TEMP_EVENT_DATARDY);
k_sem_give(&data->device_sync_sem);
}
static const struct sensor_driver_api temp_nrf5_driver_api = {
.sample_fetch = temp_nrf5_sample_fetch,
.channel_get = temp_nrf5_channel_get,
};
static int temp_nrf5_init(const struct device *dev)
{
struct temp_nrf5_data *data = dev->data;
/* A null clk_mgr indicates sensor has not been initialized */
data->clk_mgr =
z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
__ASSERT_NO_MSG(data->clk_mgr);
k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);
k_mutex_init(&data->mutex);
IRQ_CONNECT(
DT_INST_IRQN(0),
DT_INST_IRQ(0, priority),
temp_nrf5_isr,
DEVICE_DT_INST_GET(0),
0);
irq_enable(DT_INST_IRQN(0));
nrf_temp_int_enable(NRF_TEMP, NRF_TEMP_INT_DATARDY_MASK);
return 0;
}
#define NRF_TEMP_DEFINE(inst) \
static struct temp_nrf5_data temp_nrf5_data_##inst; \
\
SENSOR_DEVICE_DT_INST_DEFINE(inst, temp_nrf5_init, NULL, \
&temp_nrf5_data_##inst, NULL, POST_KERNEL, \
CONFIG_SENSOR_INIT_PRIORITY, &temp_nrf5_driver_api); \
DT_INST_FOREACH_STATUS_OKAY(NRF_TEMP_DEFINE)