1 /*
2 * Copyright (c) 2022 Thomas Stranger
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT zephyr_w1_serial
8
9 /**
10 * @brief 1-Wire Bus Master driver using Zephyr serial interface.
11 *
12 * This driver implements the 1-Wire interface using an uart.
13 * The driver uses a uart peripheral with a baudrate of 115.2 kBd to send
14 * and receive data bits and a baurade of 9.6 kBd for slave reset and
15 * presence detection as suggested for normal speed operating mode in:
16 * https://www.maximintegrated.com/en/design/technical-documents/tutorials/2/214.html
17 * For overdrive speed communication baudrates of 1 MBd and 115.2 kBd
18 * are used, respectively.
19 */
20
21 #include <stdint.h>
22 #include <stdbool.h>
23 #include <zephyr/drivers/uart.h>
24 #include <zephyr/drivers/w1.h>
25 #include <zephyr/logging/log.h>
26 #include <zephyr/sys/__assert.h>
27
28 LOG_MODULE_REGISTER(w1_serial, CONFIG_W1_LOG_LEVEL);
29
30 #define W1_SERIAL_READ_REQ_BYTE 0xFF
31 #define W1_SERIAL_BIT_1 0xFF
32 #define W1_SERIAL_BIT_0 0x00
33
34 /* Standard speed signal parameters:
35 * RST: t_RSTL=520us; t_slot=1041us
36 * DATA: t_low1=8.68us; t_low0=78.1us; t_slot=86.8us
37 */
38 #define W1_SERIAL_STD_RESET_BYTE 0xF0
39 #define W1_SERIAL_STD_RESET_BAUD 9600u
40 #define W1_SERIAL_STD_DATA_BAUD 115200u
41
42 /*
43 * Overdrive speed signal parameters:
44 * RST: t_RSTL=52.1us; t_slot=86.8us
45 * DATA: t_low1=1.0us; t_low0=9.0us; t_slot=10.0us
46 */
47 #define W1_SERIAL_OD_RESET_BYTE 0xE0
48 #define W1_SERIAL_OD_RESET_BAUD 115200u
49 #define W1_SERIAL_OD_DATA_BAUD 1000000u
50
51 struct w1_serial_config {
52 /** w1 master config, common to all drivers */
53 struct w1_master_config master_config;
54 /** UART device used for 1-Wire communication */
55 const struct device *uart_dev;
56 };
57
58 struct w1_serial_data {
59 /** w1 master data, common to all drivers */
60 struct w1_master_data master_data;
61 struct uart_config uart_cfg;
62 bool overdrive_active;
63 };
64
65 /*
66 * Concurrently transmits and receives one 1-Wire bit
67 * by sending and receiving one uart byte
68 */
serial_tx_rx(const struct device * dev,const uint8_t * tx_data,uint8_t * rx_data,size_t len,uint32_t timeout)69 static int serial_tx_rx(const struct device *dev, const uint8_t *tx_data,
70 uint8_t *rx_data, size_t len, uint32_t timeout)
71 {
72 const struct w1_serial_config *cfg = dev->config;
73 uint64_t end;
74 uint8_t dummy;
75 int ret = 0;
76
77 __ASSERT_NO_MSG(tx_data != NULL);
78 __ASSERT_NO_MSG(rx_data != NULL);
79
80 for (int i = 0; i < len; ++i) {
81 while (uart_poll_in(cfg->uart_dev, &dummy) == 0) {
82 /* poll in any buffered data */
83 }
84
85 uart_poll_out(cfg->uart_dev, tx_data[i]);
86 end = sys_clock_timeout_end_calc(K_USEC(timeout));
87
88 do {
89 ret = uart_poll_in(cfg->uart_dev, &rx_data[i]);
90 } while (ret != 0 && end > k_uptime_ticks());
91 }
92
93 return ret;
94 }
95
96 /* Concurretly tranmits and receives one 1-Wire byte */
serial_tx_rx_byte(const struct device * dev,uint8_t tx_byte,uint8_t * rx_byte)97 static int serial_tx_rx_byte(const struct device *dev, uint8_t tx_byte,
98 uint8_t *rx_byte)
99 {
100 __ASSERT_NO_MSG(rx_byte != NULL);
101 uint8_t byte_representation[8];
102
103 for (int i = 0; i < 8; ++i) {
104 /*
105 * Transmitting 0xFF the uart start bit pulls the line low to
106 * indicate either write Bit 1, or read low time.
107 * Write Bit 0 is represented as 0x00
108 */
109 byte_representation[i] =
110 ((tx_byte & (1 << i)) != 0) ? W1_SERIAL_BIT_1 : W1_SERIAL_BIT_0;
111 }
112
113 if (serial_tx_rx(dev, &byte_representation[0], &byte_representation[0],
114 8, CONFIG_W1_ZEPHYR_SERIAL_BIT_TIMEOUT) < 0) {
115 return -EIO;
116 }
117
118 *rx_byte = 0;
119 for (int i = 0; i < 8; ++i) {
120 /*
121 * rx-byte different from 0xFF indicates that a slave has
122 * pulled line low to transmit a 0 bit, otherwise a 1 bit.
123 */
124 *rx_byte |= (uint8_t)(byte_representation[i] == 0xFF) << i;
125 }
126
127 return 0;
128 }
129
w1_serial_reset_bus(const struct device * dev)130 static int w1_serial_reset_bus(const struct device *dev)
131 {
132 const struct w1_serial_config *cfg = dev->config;
133 struct w1_serial_data *data = dev->data;
134 uint8_t reset_byte = data->overdrive_active ?
135 W1_SERIAL_OD_RESET_BYTE : W1_SERIAL_STD_RESET_BYTE;
136 /* reset uses 115200/9600=12 slower baudrate,
137 * adjust timeout accordingly, also valid for overdrive speed.
138 */
139 const uint32_t reset_timeout = CONFIG_W1_ZEPHYR_SERIAL_BIT_TIMEOUT * 12;
140
141 data->uart_cfg.baudrate = data->overdrive_active ?
142 W1_SERIAL_OD_RESET_BAUD : W1_SERIAL_STD_RESET_BAUD;
143 if (uart_configure(cfg->uart_dev, &data->uart_cfg) != 0) {
144 LOG_ERR("Failed set baud rate for reset pulse");
145 return -EIO;
146 }
147
148 if (serial_tx_rx(dev, &reset_byte, &reset_byte, 1, reset_timeout) < 0) {
149 LOG_ERR("tx_rx_error reset_present");
150 return -EIO;
151 }
152
153 data->uart_cfg.baudrate = data->overdrive_active ?
154 W1_SERIAL_OD_DATA_BAUD : W1_SERIAL_STD_DATA_BAUD;
155 if (uart_configure(cfg->uart_dev, &data->uart_cfg) != 0) {
156 LOG_ERR("Failed set baud rate for data transfer");
157 return -EIO;
158 }
159
160 /* At least 1 device is present on bus, if reset_byte is different
161 * from 0xF0. But Bus probably shorted if reset_byte is 0x00.
162 */
163 return (reset_byte != W1_SERIAL_STD_RESET_BYTE) && (reset_byte != 0x00);
164 }
165
w1_serial_read_bit(const struct device * dev)166 static int w1_serial_read_bit(const struct device *dev)
167 {
168 uint8_t tx_bit = W1_SERIAL_READ_REQ_BYTE;
169 uint8_t rx_bit;
170
171 if (serial_tx_rx(dev, &tx_bit, &rx_bit, 1,
172 CONFIG_W1_ZEPHYR_SERIAL_BIT_TIMEOUT) != 0) {
173 return -EIO;
174 };
175
176 return rx_bit == W1_SERIAL_READ_REQ_BYTE;
177 }
178
w1_serial_write_bit(const struct device * dev,const bool bit)179 static int w1_serial_write_bit(const struct device *dev, const bool bit)
180 {
181 uint8_t tx_bit;
182 uint8_t rx_bit;
183
184 tx_bit = bit ? W1_SERIAL_BIT_1 : W1_SERIAL_BIT_0;
185 if (serial_tx_rx(dev, &tx_bit, &rx_bit, 1,
186 CONFIG_W1_ZEPHYR_SERIAL_BIT_TIMEOUT) != 0) {
187 return -EIO;
188 }
189 return 0;
190 }
191
w1_serial_read_byte(const struct device * dev)192 static int w1_serial_read_byte(const struct device *dev)
193 {
194 uint8_t tx_byte = 0xFF;
195 uint8_t rx_byte;
196
197 if (serial_tx_rx_byte(dev, tx_byte, &rx_byte) != 0) {
198 return -EIO;
199 }
200
201 return rx_byte;
202 }
203
w1_serial_write_byte(const struct device * dev,const uint8_t byte)204 static int w1_serial_write_byte(const struct device *dev, const uint8_t byte)
205 {
206 uint8_t rx_byte;
207
208 return serial_tx_rx_byte(dev, byte, &rx_byte);
209 }
210
w1_serial_configure(const struct device * dev,enum w1_settings_type type,uint32_t value)211 static int w1_serial_configure(const struct device *dev,
212 enum w1_settings_type type, uint32_t value)
213 {
214 const struct w1_serial_config *cfg = dev->config;
215 struct w1_serial_data *data = dev->data;
216 int ret = 0;
217 bool temp;
218
219 switch (type) {
220 case W1_SETTING_SPEED:
221 temp = (bool)value;
222 if (temp == data->overdrive_active) {
223 break;
224 }
225
226 data->overdrive_active = temp;
227 data->uart_cfg.baudrate = data->overdrive_active ?
228 W1_SERIAL_OD_DATA_BAUD : W1_SERIAL_STD_DATA_BAUD;
229 if (uart_configure(cfg->uart_dev, &data->uart_cfg) != 0) {
230 LOG_ERR("Failed set baud rate for data transfer");
231 ret = -EIO;
232 }
233 break;
234 default:
235 ret = -ENOTSUP;
236 }
237 return ret;
238 }
239
w1_serial_init(const struct device * dev)240 static int w1_serial_init(const struct device *dev)
241 {
242 const struct w1_serial_config *cfg = dev->config;
243 struct w1_serial_data *data = dev->data;
244
245 if (!device_is_ready(cfg->uart_dev)) {
246 LOG_ERR("Serial device not ready");
247 return -ENODEV;
248 }
249
250 data->uart_cfg.baudrate = W1_SERIAL_STD_DATA_BAUD;
251 data->uart_cfg.parity = UART_CFG_PARITY_NONE;
252 data->uart_cfg.data_bits = UART_CFG_DATA_BITS_8;
253 data->uart_cfg.stop_bits = UART_CFG_STOP_BITS_1;
254 data->uart_cfg.flow_ctrl = UART_CFG_FLOW_CTRL_NONE;
255
256 if (uart_configure(cfg->uart_dev, &data->uart_cfg) != 0) {
257 LOG_ERR("Failed to configure UART");
258 return -EINVAL;
259 }
260
261 data->overdrive_active = false;
262
263 LOG_DBG("w1-serial initialized, with %d slave devices",
264 cfg->master_config.slave_count);
265 return 0;
266 }
267
268 static const struct w1_driver_api w1_serial_driver_api = {
269 .reset_bus = w1_serial_reset_bus,
270 .read_bit = w1_serial_read_bit,
271 .write_bit = w1_serial_write_bit,
272 .read_byte = w1_serial_read_byte,
273 .write_byte = w1_serial_write_byte,
274 .configure = w1_serial_configure,
275 };
276
277 #define W1_ZEPHYR_SERIAL_INIT(inst) \
278 static const struct w1_serial_config w1_serial_cfg_##inst = { \
279 .uart_dev = DEVICE_DT_GET(DT_INST_BUS(inst)), \
280 .master_config.slave_count = W1_INST_SLAVE_COUNT(inst) \
281 }; \
282 static struct w1_serial_data w1_serial_data_##inst = {}; \
283 DEVICE_DT_INST_DEFINE(inst, &w1_serial_init, NULL, &w1_serial_data_##inst, \
284 &w1_serial_cfg_##inst, POST_KERNEL, \
285 CONFIG_W1_INIT_PRIORITY, &w1_serial_driver_api); \
286
287 DT_INST_FOREACH_STATUS_OKAY(W1_ZEPHYR_SERIAL_INIT)
288