Skip to content

Commit d25782b

Browse files
committed
bsp:k230:add support for temperature sensor driver
Added a temperature sensor driver and a test file test_ts.c. The test uses temperature sensor to measure the chip temperature, to check if the driver works correctly. Signed-off-by: XU HU [email protected]
1 parent 235bbef commit d25782b

File tree

8 files changed

+492
-2
lines changed

8 files changed

+492
-2
lines changed

bsp/k230/.config

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4
118118
# CONFIG_RT_UTEST_TC_USING_KLIBC is not set
119119
# end of klibc options
120120

121-
CONFIG_RT_NAME_MAX=8
121+
CONFIG_RT_NAME_MAX=64
122122
# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
123123
# CONFIG_RT_USING_NANO is not set
124124
CONFIG_RT_USING_SMART=y
@@ -228,6 +228,7 @@ CONFIG_FINSH_THREAD_PRIORITY=20
228228
CONFIG_FINSH_THREAD_STACK_SIZE=8192
229229
CONFIG_FINSH_USING_HISTORY=y
230230
CONFIG_FINSH_HISTORY_LINES=5
231+
# CONFIG_FINSH_USING_WORD_OPERATION is not set
231232
CONFIG_FINSH_USING_SYMTAB=y
232233
CONFIG_FINSH_CMD_SIZE=80
233234
CONFIG_MSH_USING_BUILT_IN_COMMANDS=y
@@ -1591,6 +1592,7 @@ CONFIG_PKG_ZLIB_VER="latest"
15911592
# Drivers Configuration
15921593
#
15931594
# CONFIG_BSP_USING_ADC is not set
1595+
# CONFIG_BSP_USING_TS is not set
15941596
# CONFIG_BSP_USING_PWM is not set
15951597
CONFIG_BSP_USING_HARDLOCK=y
15961598
CONFIG_BSP_USING_SDIO=y

bsp/k230/board/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ menu "Drivers Configuration"
44
bool "Enable ADC"
55
select RT_USING_ADC
66
default n
7+
8+
config BSP_USING_TS
9+
bool "Enable TS"
10+
select RT_USING_TS
11+
default n
712

813
menuconfig BSP_USING_PWM
914
bool "Enable PWM"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# RT-Thread building script for component
2+
3+
from building import *
4+
5+
cwd = GetCurrentDir()
6+
src = Glob('*.c')
7+
CPPPATH = [cwd]
8+
9+
group = DefineGroup('TS', src, depend = ['BSP_USING_TS'], CPPPATH = CPPPATH)
10+
11+
Return('group')
Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
2+
*
3+
* Redistribution and use in source and binary forms, with or without
4+
* modification, are permitted provided that the following conditions are met:
5+
* 1. Redistributions of source code must retain the above copyright
6+
* notice, this list of conditions and the following disclaimer.
7+
* 2. Redistributions in binary form must reproduce the above copyright
8+
* notice, this list of conditions and the following disclaimer in the
9+
* documentation and/or other materials provided with the distribution.
10+
*
11+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
12+
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
13+
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14+
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
16+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
17+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21+
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
/*
27+
* Copyright (c) 2006-2025 RT-Thread Development Team
28+
*
29+
* SPDX-License-Identifier: Apache-2.0
30+
*/
31+
32+
#include "drv_ts.h"
33+
#include <rtthread.h>
34+
#include <rthw.h>
35+
#include <rtdevice.h>
36+
37+
#ifdef RT_USING_POSIX
38+
#include <dfs_posix.h>
39+
#include <dfs_poll.h>
40+
#include <posix_termios.h>
41+
#endif
42+
43+
#include "math.h"
44+
#include "rtdbg.h"
45+
#include "board.h"
46+
#include <riscv_io.h>
47+
#include "ioremap.h"
48+
49+
// Register offsets
50+
#define REG_TSENW_OFFSET 0x000
51+
#define REG_TSENR_OFFSET 0x004
52+
53+
// Bit positions for REG_TSENW
54+
#define TSENW_TS_TEST_EN_POS 6
55+
#define TSENW_TS_TRIM_POS 2
56+
#define TSENW_TS_CONV_MODE_POS 1
57+
#define TSENW_TS_EN_POS 0
58+
59+
// Bit positions for REG_TSENR
60+
#define TSENR_TS_DOUT_VALID_POS 12
61+
#define TSENR_TS_DOUT_MASK 0xFFF
62+
63+
static struct rt_mutex ts_mutex;
64+
static uint8_t ts_trim = 8;
65+
static uint8_t ts_mode = RT_DEVICE_TS_CTRL_MODE_CONTINUUOS;
66+
static void *ts_base_addr = RT_NULL;
67+
68+
static void tsensor_start(void) {
69+
if (ts_base_addr == RT_NULL) return; // Ensure base address is set
70+
71+
// Ensure single output mode is selected and enable the TSensor
72+
uint32_t reg_val = readl(ts_base_addr + REG_TSENW_OFFSET);
73+
if(RT_DEVICE_TS_CTRL_MODE_CONTINUUOS == ts_mode) {
74+
reg_val |= (1 << TSENW_TS_CONV_MODE_POS); // Set continuous mode bit
75+
} else {
76+
reg_val &= ~(1 << TSENW_TS_CONV_MODE_POS); // Clear continuous mode bit
77+
}
78+
reg_val |= (1 << TSENW_TS_EN_POS); // Set enable bit
79+
writel(reg_val, ts_base_addr + REG_TSENW_OFFSET);
80+
}
81+
82+
static void tsensor_stop(void) {
83+
if (ts_base_addr == RT_NULL) return; // Ensure base address is set
84+
85+
// Disable the TSensor
86+
uint32_t reg_val = readl(ts_base_addr + REG_TSENW_OFFSET);
87+
reg_val &= ~((1 << TSENW_TS_EN_POS));
88+
writel(reg_val, ts_base_addr + REG_TSENW_OFFSET);
89+
}
90+
91+
static int tsensor_read_data(uint16_t *data, uint32_t timeout_ms) {
92+
if (ts_base_addr == RT_NULL || data == RT_NULL) return -1; // Ensure base address is set
93+
94+
uint32_t max_attempts = timeout_ms; // Max attempts for the given timeout in ms
95+
96+
for (uint32_t attempt = 0; attempt < max_attempts; attempt++) {
97+
// Check if the data is valid
98+
if ((readl(ts_base_addr + REG_TSENR_OFFSET) >> TSENR_TS_DOUT_VALID_POS) & 0x1) {
99+
// Read the 12-bit temperature data
100+
*data = readl(ts_base_addr + REG_TSENR_OFFSET) & TSENR_TS_DOUT_MASK;
101+
return 0; // Success
102+
}
103+
104+
// Delay before next polling attempt
105+
rt_thread_mdelay(1); // Delay in microseconds
106+
}
107+
108+
return -2; // Timeout error
109+
}
110+
111+
static double tsensor_calculate_temperature(uint16_t data) {
112+
return (1e-10 * pow(data, 4) * 1.01472
113+
- 1e-6 * pow(data, 3) * 1.10063
114+
+ 4.36150 * 1e-3 * pow(data, 2)
115+
- 7.10128 * data
116+
+ 3565.87);
117+
}
118+
119+
void tsensor_init(void) {
120+
if (ts_base_addr == RT_NULL) return; // Ensure base address is set
121+
122+
if(RT_EOK != rt_mutex_take(&ts_mutex, rt_tick_from_millisecond(500))) {
123+
LOG_E("%s mutex take timeout.\n");
124+
125+
return;
126+
}
127+
128+
// Configure the TSensor with the default settings
129+
uint32_t reg_val = readl(ts_base_addr + REG_TSENW_OFFSET);
130+
reg_val &= ~(0xF << TSENW_TS_TRIM_POS); // Clear previous trim value
131+
reg_val |= (ts_trim << TSENW_TS_TRIM_POS); // Set new trim value
132+
writel(reg_val, ts_base_addr + REG_TSENW_OFFSET);
133+
134+
rt_mutex_release(&ts_mutex);
135+
}
136+
137+
void tsensor_set_trim(uint8_t trim) {
138+
if(RT_EOK != rt_mutex_take(&ts_mutex, rt_tick_from_millisecond(500))) {
139+
LOG_E("%s mutex take timeout.\n");
140+
return;
141+
}
142+
143+
// Ensure the trim_value is within range (4 bits)
144+
ts_trim = trim & 0xF;
145+
rt_mutex_release(&ts_mutex);
146+
tsensor_init();
147+
}
148+
149+
uint8_t tsensor_get_trim(void) {
150+
uint8_t temp;
151+
152+
if(RT_EOK != rt_mutex_take(&ts_mutex, rt_tick_from_millisecond(500))) {
153+
LOG_E("%s mutex take timeout.\n");
154+
return -1;
155+
}
156+
157+
temp = ts_trim;
158+
159+
rt_mutex_release(&ts_mutex);
160+
161+
return temp;
162+
}
163+
164+
void tsensor_set_mode(uint8_t mode) {
165+
if(RT_EOK != rt_mutex_take(&ts_mutex, rt_tick_from_millisecond(500))) {
166+
LOG_E("%s mutex take timeout.\n");
167+
168+
return;
169+
}
170+
171+
ts_mode = mode;
172+
173+
rt_mutex_release(&ts_mutex);
174+
}
175+
176+
uint8_t tsensor_get_mode(void) {
177+
uint8_t temp;
178+
179+
if(RT_EOK != rt_mutex_take(&ts_mutex, rt_tick_from_millisecond(500))) {
180+
LOG_E("%s mutex take timeout.\n");
181+
return -1;
182+
}
183+
184+
temp = ts_mode;
185+
rt_mutex_release(&ts_mutex);
186+
return temp;
187+
}
188+
189+
int tsensor_read_temp(double *temp) {
190+
uint16_t data;
191+
192+
if (RT_EOK != rt_mutex_take(&ts_mutex, rt_tick_from_millisecond(500))) {
193+
LOG_E("%s mutex take timeout.\n");
194+
return -1;
195+
}
196+
197+
tsensor_start();
198+
rt_thread_mdelay(10);
199+
200+
if (0x00 == tsensor_read_data(&data, 100)) {
201+
*((double *)temp) = tsensor_calculate_temperature(data);
202+
tsensor_stop();
203+
rt_mutex_release(&ts_mutex);
204+
return 0;
205+
} else {
206+
tsensor_stop();
207+
rt_mutex_release(&ts_mutex);
208+
return -1;
209+
}
210+
}
211+
212+
static rt_err_t ts_deivce_open(rt_device_t dev, rt_uint16_t oflag)
213+
{
214+
tsensor_init();
215+
216+
return RT_EOK;
217+
}
218+
219+
static rt_err_t ts_device_close(rt_device_t dev)
220+
{
221+
tsensor_stop();
222+
223+
return RT_EOK;
224+
}
225+
226+
static rt_ssize_t ts_device_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
227+
{
228+
if(sizeof(double) != size) {
229+
LOG_E("%s invalid buffer size %u\n", __func__, size);
230+
return 0;
231+
}
232+
233+
if(0x00 != tsensor_read_temp(buffer)) {
234+
return 0; // read failed
235+
}
236+
237+
return sizeof(double);
238+
}
239+
240+
static rt_err_t ts_device_control(rt_device_t dev, int cmd, void *args)
241+
{
242+
uint8_t trim_val = tsensor_get_trim();
243+
uint8_t work_mode = tsensor_get_mode();
244+
245+
switch(cmd) {
246+
case RT_DEVICE_TS_CTRL_SET_MODE:
247+
work_mode = (rt_uint8_t)(*(rt_uint8_t *)args);
248+
tsensor_set_mode(work_mode);
249+
break;
250+
case RT_DEVICE_TS_CTRL_GET_MODE:
251+
*((rt_uint8_t *)args) = (rt_uint8_t)work_mode;
252+
break;
253+
case RT_DEVICE_TS_CTRL_SET_TRIM:
254+
trim_val = (rt_uint8_t)(*(rt_uint8_t *)args);
255+
tsensor_set_trim(trim_val);
256+
break;
257+
case RT_DEVICE_TS_CTRL_GET_TRIM:
258+
*((rt_uint8_t *)args) = (rt_uint8_t)trim_val;
259+
break;
260+
default:
261+
LOG_E("%s unsupport cmd 0x%x\n", __func__, cmd);
262+
break;
263+
}
264+
265+
return RT_EOK;
266+
}
267+
268+
static struct rt_device ts_device;
269+
270+
static const struct rt_device_ops ts_ops =
271+
{
272+
RT_NULL,
273+
ts_deivce_open,
274+
ts_device_close,
275+
ts_device_read,
276+
RT_NULL,
277+
ts_device_control
278+
};
279+
280+
static int register_ts_device(void)
281+
{
282+
rt_device_t device;
283+
rt_err_t ret = RT_EOK;
284+
285+
device = &ts_device;
286+
287+
#ifdef RT_USING_DEVICE_OPS
288+
device->ops = &ts_ops;
289+
#else
290+
device->init = RT_NULL;
291+
device->open = ts_deivce_open;
292+
device->close = ts_device_close;
293+
device->read = ts_device_read;
294+
device->write = RT_NULL;
295+
device->control = ts_device_control;
296+
#endif
297+
298+
if(RT_EOK != (ret = rt_device_register(device, "ts", RT_DEVICE_FLAG_RDWR))) {
299+
LOG_E("ts device register fail\n");
300+
return -1;
301+
}
302+
303+
return 0;
304+
}
305+
306+
static int rt_hw_ts_init(void)
307+
{
308+
if(RT_NULL == (ts_base_addr = rt_ioremap((void*)TS_BASE_ADDR, TS_IO_SIZE))) {
309+
LOG_E("ts ioremap error\n");
310+
return -1;
311+
}
312+
if(0x00 != register_ts_device()) {
313+
return -2;
314+
}
315+
if(RT_EOK != rt_mutex_init(&ts_mutex, "dev_ts", RT_IPC_FLAG_PRIO)) {
316+
LOG_E("ts init mutex error\n");
317+
return -3;
318+
}
319+
320+
return RT_EOK;
321+
}
322+
INIT_DEVICE_EXPORT(rt_hw_ts_init);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
#ifndef __DRV_TS__
3+
#define __DRV_TS__
4+
5+
#include <rtdef.h>
6+
7+
#define RT_DEVICE_TS_CTRL_SET_MODE 1
8+
#define RT_DEVICE_TS_CTRL_GET_MODE 2
9+
#define RT_DEVICE_TS_CTRL_SET_TRIM 3
10+
#define RT_DEVICE_TS_CTRL_GET_TRIM 4
11+
12+
#define RT_DEVICE_TS_CTRL_MODE_SINGLE 0x01
13+
#define RT_DEVICE_TS_CTRL_MODE_CONTINUUOS 0x02
14+
15+
void tsensor_init(void);
16+
17+
void tsensor_set_trim(uint8_t trim);
18+
uint8_t tsensor_get_trim(void);
19+
20+
void tsensor_set_mode(uint8_t mode);
21+
uint8_t tsensor_get_mode(void);
22+
23+
int tsensor_read_temp(double *temp);
24+
25+
#endif /*__DRV_TS__*/

0 commit comments

Comments
 (0)