drv_ts.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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. * Copyright (c) 2006-2025 RT-Thread Development Team
  27. *
  28. * SPDX-License-Identifier: Apache-2.0
  29. */
  30. #include "drv_ts.h"
  31. #include <rtthread.h>
  32. #include <rthw.h>
  33. #include <rtdevice.h>
  34. #ifdef RT_USING_POSIX
  35. #include <dfs_posix.h>
  36. #include <dfs_poll.h>
  37. #include <posix_termios.h>
  38. #endif
  39. #include "math.h"
  40. #include "rtdbg.h"
  41. #include "board.h"
  42. #include <riscv_io.h>
  43. #include "ioremap.h"
  44. // Register offsets
  45. #define REG_TSENW_OFFSET 0x000
  46. #define REG_TSENR_OFFSET 0x004
  47. // Bit positions for REG_TSENW
  48. #define TSENW_TS_TEST_EN_POS 6
  49. #define TSENW_TS_TRIM_POS 2
  50. #define TSENW_TS_CONV_MODE_POS 1
  51. #define TSENW_TS_EN_POS 0
  52. // Bit positions for REG_TSENR
  53. #define TSENR_TS_DOUT_VALID_POS 12
  54. #define TSENR_TS_DOUT_MASK 0xFFF
  55. static struct rt_mutex ts_mutex;
  56. static uint8_t ts_trim = 8;
  57. static uint8_t ts_mode = RT_DEVICE_TS_CTRL_MODE_CONTINUUOS;
  58. static void *ts_base_addr = RT_NULL;
  59. static rt_err_t tsensor_start(void)
  60. {
  61. uint32_t reg_val;
  62. if (ts_base_addr == RT_NULL)
  63. return -RT_ERROR;
  64. reg_val = readl(ts_base_addr + REG_TSENW_OFFSET);
  65. if (RT_DEVICE_TS_CTRL_MODE_CONTINUUOS == ts_mode)
  66. reg_val |= (1 << TSENW_TS_CONV_MODE_POS);
  67. else
  68. reg_val &= ~(1 << TSENW_TS_CONV_MODE_POS);
  69. reg_val |= (1 << TSENW_TS_EN_POS);
  70. writel(reg_val, ts_base_addr + REG_TSENW_OFFSET);
  71. return RT_EOK;
  72. }
  73. static rt_err_t tsensor_stop(void)
  74. {
  75. if (ts_base_addr == RT_NULL)
  76. return -RT_ERROR;
  77. uint32_t reg_val = readl(ts_base_addr + REG_TSENW_OFFSET);
  78. reg_val &= ~(1 << TSENW_TS_EN_POS);
  79. writel(reg_val, ts_base_addr + REG_TSENW_OFFSET);
  80. return RT_EOK;
  81. }
  82. static int tsensor_read_data(uint16_t *data, uint32_t timeout_ms)
  83. {
  84. if (ts_base_addr == RT_NULL || data == RT_NULL) // Ensure base address is set
  85. return -RT_ERROR;
  86. uint32_t max_attempts = timeout_ms; // Max attempts for the given timeout in ms
  87. for (uint32_t attempt = 0; attempt < max_attempts; attempt++)
  88. {
  89. // Check if the data is valid
  90. if ((readl(ts_base_addr + REG_TSENR_OFFSET) >> TSENR_TS_DOUT_VALID_POS) & 0x1)
  91. {
  92. // Read the 12-bit temperature data
  93. *data = readl(ts_base_addr + REG_TSENR_OFFSET) & TSENR_TS_DOUT_MASK;
  94. return RT_EOK; // Success
  95. }
  96. // Delay before next polling attempt
  97. rt_thread_mdelay(1); // Delay in microseconds
  98. }
  99. return -RT_ETIMEOUT; // Timeout error
  100. }
  101. static double tsensor_calculate_temperature(uint16_t data)
  102. {
  103. return (1e-10 * pow(data, 4) * 1.01472
  104. - 1e-6 * pow(data, 3) * 1.10063
  105. + 4.36150 * 1e-3 * pow(data, 2)
  106. - 7.10128 * data
  107. + 3565.87);
  108. }
  109. static rt_err_t tsensor_init(void)
  110. {
  111. if (ts_base_addr == RT_NULL)
  112. {
  113. return -RT_ERROR;
  114. }
  115. if (RT_EOK != rt_mutex_take(&ts_mutex, rt_tick_from_millisecond(500)))
  116. {
  117. LOG_E("%s mutex take timeout.\n", __func__);
  118. return -RT_ETIMEOUT;
  119. }
  120. uint32_t reg_val = readl(ts_base_addr + REG_TSENW_OFFSET);
  121. reg_val &= ~(0xF << TSENW_TS_TRIM_POS);
  122. reg_val |= (ts_trim << TSENW_TS_TRIM_POS);
  123. writel(reg_val, ts_base_addr + REG_TSENW_OFFSET);
  124. rt_mutex_release(&ts_mutex);
  125. return RT_EOK;
  126. }
  127. static rt_err_t k230_tsensor_set_trim(uint8_t trim)
  128. {
  129. if(RT_EOK != rt_mutex_take(&ts_mutex, rt_tick_from_millisecond(500)))
  130. {
  131. LOG_E("%s mutex take timeout.\n");
  132. return -RT_ETIMEOUT;
  133. }
  134. // Ensure the trim_value is within range (4 bits)
  135. ts_trim = trim & 0xF;
  136. rt_mutex_release(&ts_mutex);
  137. tsensor_init();
  138. return RT_EOK;
  139. }
  140. static uint8_t k230_tsensor_get_trim(void)
  141. {
  142. uint8_t temp;
  143. if(RT_EOK != rt_mutex_take(&ts_mutex, rt_tick_from_millisecond(500)))
  144. {
  145. LOG_E("%s mutex take timeout.\n");
  146. return -RT_ETIMEOUT;
  147. }
  148. temp = ts_trim;
  149. rt_mutex_release(&ts_mutex);
  150. return temp;
  151. }
  152. static rt_err_t k230_tsensor_set_mode(uint8_t mode)
  153. {
  154. if(RT_EOK != rt_mutex_take(&ts_mutex, rt_tick_from_millisecond(500)))
  155. {
  156. LOG_E("%s mutex take timeout.\n");
  157. return -RT_ETIMEOUT;
  158. }
  159. ts_mode = mode;
  160. rt_mutex_release(&ts_mutex);
  161. return RT_EOK;
  162. }
  163. static uint8_t k230_tsensor_get_mode(void)
  164. {
  165. uint8_t temp;
  166. if(RT_EOK != rt_mutex_take(&ts_mutex, rt_tick_from_millisecond(500)))
  167. {
  168. LOG_E("%s mutex take timeout.\n");
  169. return -RT_ETIMEOUT;
  170. }
  171. temp = ts_mode;
  172. rt_mutex_release(&ts_mutex);
  173. return temp;
  174. }
  175. static rt_err_t k230_tsensor_read_temp(double *temp)
  176. {
  177. uint16_t data;
  178. rt_err_t ret = RT_EOK;
  179. if (RT_EOK != rt_mutex_take(&ts_mutex, rt_tick_from_millisecond(500)))
  180. {
  181. LOG_E("%s mutex take timeout.\n");
  182. return -RT_ETIMEOUT;
  183. }
  184. ret = tsensor_start();
  185. if (ret != RT_EOK)
  186. {
  187. return ret;
  188. }
  189. rt_thread_mdelay(10);
  190. if (0x00 == tsensor_read_data(&data, 100))
  191. {
  192. *((double *)temp) = tsensor_calculate_temperature(data);
  193. tsensor_stop();
  194. rt_mutex_release(&ts_mutex);
  195. return RT_EOK;
  196. }
  197. else
  198. {
  199. tsensor_stop();
  200. rt_mutex_release(&ts_mutex);
  201. return -RT_ERROR;
  202. }
  203. }
  204. static rt_err_t ts_device_open(rt_device_t dev, rt_uint16_t oflag)
  205. {
  206. rt_err_t ret;
  207. ret = tsensor_init();
  208. return ret;
  209. }
  210. static rt_err_t ts_device_close(rt_device_t dev)
  211. {
  212. rt_err_t ret;
  213. ret = tsensor_stop();
  214. return ret;
  215. }
  216. static rt_ssize_t ts_device_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  217. {
  218. rt_err_t ret;
  219. if (sizeof(double) != size)
  220. {
  221. LOG_E("%s invalid buffer size %u\n", __func__, size);
  222. return -RT_ERROR;
  223. }
  224. ret = k230_tsensor_read_temp((double *)buffer);
  225. if (ret != 0x00)
  226. {
  227. return -RT_ERROR;
  228. }
  229. return sizeof(double);
  230. }
  231. static rt_err_t ts_device_control(rt_device_t dev, int cmd, void *args)
  232. {
  233. uint8_t trim_val = k230_tsensor_get_trim();
  234. uint8_t work_mode = k230_tsensor_get_mode();
  235. rt_err_t ret = RT_EOK;
  236. switch(cmd)
  237. {
  238. case RT_DEVICE_TS_CTRL_SET_MODE:
  239. work_mode = *(uint8_t *)args;
  240. ret = k230_tsensor_set_mode(work_mode);
  241. break;
  242. case RT_DEVICE_TS_CTRL_GET_MODE:
  243. *(uint8_t *)args = work_mode;
  244. break;
  245. case RT_DEVICE_TS_CTRL_SET_TRIM:
  246. trim_val = *(uint8_t *)args;
  247. ret = k230_tsensor_set_trim(trim_val);
  248. break;
  249. case RT_DEVICE_TS_CTRL_GET_TRIM:
  250. *(uint8_t *)args = trim_val;
  251. break;
  252. default:
  253. LOG_E("%s unsupported cmd 0x%x\n", __func__, cmd);
  254. ret = -RT_ERROR;
  255. break;
  256. }
  257. return ret;
  258. }
  259. static struct rt_device ts_device;
  260. static const struct rt_device_ops ts_ops =
  261. {
  262. .open = ts_device_open,
  263. .close = ts_device_close,
  264. .read = ts_device_read,
  265. .control = ts_device_control
  266. };
  267. static rt_err_t register_ts_device(void)
  268. {
  269. rt_device_t device;
  270. rt_err_t ret = RT_EOK;
  271. device = &ts_device;
  272. #ifdef RT_USING_DEVICE_OPS
  273. device->ops = &ts_ops;
  274. #else
  275. device->init = RT_NULL;
  276. device->open = ts_device_open;
  277. device->close = ts_device_close;
  278. device->read = ts_device_read;
  279. device->write = RT_NULL;
  280. device->control = ts_device_control;
  281. #endif
  282. ret = rt_device_register(device, "ts", RT_DEVICE_FLAG_RDWR);
  283. if(ret != RT_EOK)
  284. {
  285. LOG_E("ts device register fail\n");
  286. return -RT_ERROR;
  287. }
  288. return ret;
  289. }
  290. static int rt_hw_ts_init(void)
  291. {
  292. ts_base_addr = rt_ioremap((void *)TS_BASE_ADDR, TS_IO_SIZE);
  293. if (ts_base_addr == RT_NULL)
  294. {
  295. LOG_E("ts ioremap error\n");
  296. return -RT_ERROR;
  297. }
  298. if (RT_EOK != register_ts_device())
  299. {
  300. LOG_E("ts device register error\n");
  301. return -RT_ERROR;
  302. }
  303. if (RT_EOK != rt_mutex_init(&ts_mutex, "dev_ts", RT_IPC_FLAG_PRIO))
  304. {
  305. LOG_E("ts mutex init error\n");
  306. return -RT_ERROR;
  307. }
  308. return RT_EOK;
  309. }
  310. INIT_DEVICE_EXPORT(rt_hw_ts_init);