1 /*
2  * Copyright (c) 2020 PHYTEC Messtechnik GmbH
3  * Copyright (c) 2021 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 /*
9  * This file is based on mb.c and mb_util.c from uC/Modbus Stack.
10  *
11  *                                uC/Modbus
12  *                         The Embedded Modbus Stack
13  *
14  *      Copyright 2003-2020 Silicon Laboratories Inc. www.silabs.com
15  *
16  *                   SPDX-License-Identifier: APACHE-2.0
17  *
18  * This software is subject to an open source license and is distributed by
19  *  Silicon Laboratories Inc. pursuant to the terms of the Apache License,
20  *      Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
21  */
22 
23 #include <logging/log.h>
24 LOG_MODULE_REGISTER(modbus_serial, CONFIG_MODBUS_LOG_LEVEL);
25 
26 #include <kernel.h>
27 #include <string.h>
28 #include <sys/byteorder.h>
29 #include <modbus_internal.h>
30 
modbus_serial_tx_on(struct modbus_context * ctx)31 static void modbus_serial_tx_on(struct modbus_context *ctx)
32 {
33 	struct modbus_serial_config *cfg = ctx->cfg;
34 
35 	if (cfg->de != NULL) {
36 		gpio_pin_set(cfg->de->port, cfg->de->pin, 1);
37 	}
38 
39 	uart_irq_tx_enable(cfg->dev);
40 }
41 
modbus_serial_tx_off(struct modbus_context * ctx)42 static void modbus_serial_tx_off(struct modbus_context *ctx)
43 {
44 	struct modbus_serial_config *cfg = ctx->cfg;
45 
46 	uart_irq_tx_disable(cfg->dev);
47 	if (cfg->de != NULL) {
48 		gpio_pin_set(cfg->de->port, cfg->de->pin, 0);
49 	}
50 }
51 
modbus_serial_rx_on(struct modbus_context * ctx)52 static void modbus_serial_rx_on(struct modbus_context *ctx)
53 {
54 	struct modbus_serial_config *cfg = ctx->cfg;
55 
56 	if (cfg->re != NULL) {
57 		gpio_pin_set(cfg->re->port, cfg->re->pin, 1);
58 	}
59 
60 	uart_irq_rx_enable(cfg->dev);
61 }
62 
modbus_serial_rx_off(struct modbus_context * ctx)63 static void modbus_serial_rx_off(struct modbus_context *ctx)
64 {
65 	struct modbus_serial_config *cfg = ctx->cfg;
66 
67 	uart_irq_rx_disable(cfg->dev);
68 	if (cfg->re != NULL) {
69 		gpio_pin_set(cfg->re->port, cfg->re->pin, 0);
70 	}
71 }
72 
73 #ifdef CONFIG_MODBUS_ASCII_MODE
74 /* The function calculates an 8-bit Longitudinal Redundancy Check. */
modbus_ascii_get_lrc(uint8_t * src,size_t length)75 static uint8_t modbus_ascii_get_lrc(uint8_t *src, size_t length)
76 {
77 	uint8_t lrc = 0;
78 	uint8_t tmp;
79 	uint8_t *pblock = src;
80 
81 	while (length-- > 0) {
82 		/* Add the data byte to LRC, increment data pointer. */
83 		if (hex2bin(pblock, 2, &tmp, sizeof(tmp)) != sizeof(tmp)) {
84 			return 0;
85 		}
86 
87 		lrc += tmp;
88 		pblock += 2;
89 	}
90 
91 	/* Two complement the binary sum */
92 	lrc = ~lrc + 1;
93 
94 	return lrc;
95 }
96 
97 /* Parses and converts an ASCII mode frame into a Modbus RTU frame. */
modbus_ascii_rx_adu(struct modbus_context * ctx)98 static int modbus_ascii_rx_adu(struct modbus_context *ctx)
99 {
100 	struct modbus_serial_config *cfg = ctx->cfg;
101 	uint8_t *pmsg;
102 	uint8_t *prx_data;
103 	uint16_t rx_size;
104 	uint8_t frame_lrc;
105 	uint8_t calc_lrc;
106 
107 	rx_size =  cfg->uart_buf_ctr;
108 	prx_data = &ctx->rx_adu.data[0];
109 
110 	if (!(rx_size & 0x01)) {
111 		LOG_WRN("Message should have an odd number of bytes");
112 		return -EMSGSIZE;
113 	}
114 
115 	if (rx_size < MODBUS_ASCII_MIN_MSG_SIZE) {
116 		LOG_WRN("Frame length error");
117 		return -EMSGSIZE;
118 	}
119 
120 	if ((cfg->uart_buf[0] != MODBUS_ASCII_START_FRAME_CHAR) ||
121 	    (cfg->uart_buf[rx_size - 2] != MODBUS_ASCII_END_FRAME_CHAR1) ||
122 	    (cfg->uart_buf[rx_size - 1] != MODBUS_ASCII_END_FRAME_CHAR2)) {
123 		LOG_WRN("Frame character error");
124 		return -EMSGSIZE;
125 	}
126 
127 	/* Take away for the ':', CR, and LF */
128 	rx_size -= 3;
129 	/* Point past the ':' to the address. */
130 	pmsg = &cfg->uart_buf[1];
131 
132 	hex2bin(pmsg, 2, &ctx->rx_adu.unit_id, 1);
133 	pmsg += 2;
134 	rx_size -= 2;
135 	hex2bin(pmsg, 2, &ctx->rx_adu.fc, 1);
136 	pmsg += 2;
137 	rx_size -= 2;
138 
139 	/* Get the data from the message */
140 	ctx->rx_adu.length = 0;
141 	while (rx_size > 2) {
142 		hex2bin(pmsg, 2, prx_data, 1);
143 		prx_data++;
144 		pmsg += 2;
145 		rx_size -= 2;
146 		/* Increment the number of Modbus packets received */
147 		ctx->rx_adu.length++;
148 	}
149 
150 	/* Extract the message's LRC */
151 	hex2bin(pmsg, 2, &frame_lrc, 1);
152 	ctx->rx_adu.crc = frame_lrc;
153 
154 	/*
155 	 * The LRC is calculated on the ADDR, FC and Data fields,
156 	 * not the ':', CR/LF and LRC placed in the message
157 	 * by the sender. We thus need to subtract 5 'ASCII' characters
158 	 * from the received message to exclude these.
159 	 */
160 	calc_lrc = modbus_ascii_get_lrc(&cfg->uart_buf[1],
161 					(cfg->uart_buf_ctr - 5) / 2);
162 
163 	if (calc_lrc != frame_lrc) {
164 		LOG_ERR("Calculated LRC does not match received LRC");
165 		return -EIO;
166 	}
167 
168 	return 0;
169 }
170 
modbus_ascii_bin2hex(uint8_t value,uint8_t * pbuf)171 static uint8_t *modbus_ascii_bin2hex(uint8_t value, uint8_t *pbuf)
172 {
173 	uint8_t u_nibble = (value >> 4) & 0x0F;
174 	uint8_t l_nibble = value & 0x0F;
175 
176 	hex2char(u_nibble, pbuf);
177 	pbuf++;
178 	hex2char(l_nibble, pbuf);
179 	pbuf++;
180 
181 	return pbuf;
182 }
183 
modbus_ascii_tx_adu(struct modbus_context * ctx)184 static void modbus_ascii_tx_adu(struct modbus_context *ctx)
185 {
186 	struct modbus_serial_config *cfg = ctx->cfg;
187 	uint16_t tx_bytes = 0;
188 	uint8_t lrc;
189 	uint8_t *pbuf;
190 
191 	/* Place the start-of-frame character into output buffer */
192 	cfg->uart_buf[0] = MODBUS_ASCII_START_FRAME_CHAR;
193 	tx_bytes = 1;
194 
195 	pbuf = &cfg->uart_buf[1];
196 	pbuf = modbus_ascii_bin2hex(ctx->tx_adu.unit_id, pbuf);
197 	tx_bytes += 2;
198 	pbuf = modbus_ascii_bin2hex(ctx->tx_adu.fc, pbuf);
199 	tx_bytes += 2;
200 
201 	for (int i = 0; i < ctx->tx_adu.length; i++) {
202 		pbuf = modbus_ascii_bin2hex(ctx->tx_adu.data[i], pbuf);
203 		tx_bytes += 2;
204 	}
205 
206 	/*
207 	 * Add the LRC checksum in the packet.
208 	 *
209 	 * The LRC is calculated on the ADDR, FC and Data fields,
210 	 * not the ':' which was inserted in the uart_buf[].
211 	 * Thus we subtract 1 ASCII character from the LRC.
212 	 * The LRC and CR/LF bytes are not YET in the .uart_buf[].
213 	 */
214 	lrc = modbus_ascii_get_lrc(&cfg->uart_buf[1], (tx_bytes - 1) / 2);
215 	pbuf = modbus_ascii_bin2hex(lrc, pbuf);
216 	tx_bytes += 2;
217 
218 	*pbuf++ = MODBUS_ASCII_END_FRAME_CHAR1;
219 	*pbuf++ = MODBUS_ASCII_END_FRAME_CHAR2;
220 	tx_bytes += 2;
221 
222 	/* Update the total number of bytes to send */
223 	cfg->uart_buf_ctr = tx_bytes;
224 	cfg->uart_buf_ptr = &cfg->uart_buf[0];
225 
226 	LOG_DBG("Start frame transmission");
227 	modbus_serial_rx_off(ctx);
228 	modbus_serial_tx_on(ctx);
229 }
230 #else
modbus_ascii_rx_adu(struct modbus_context * ctx)231 static int modbus_ascii_rx_adu(struct modbus_context *ctx)
232 {
233 	return 0;
234 }
235 
modbus_ascii_tx_adu(struct modbus_context * ctx)236 static void modbus_ascii_tx_adu(struct modbus_context *ctx)
237 {
238 }
239 #endif
240 
modbus_rtu_crc16(uint8_t * src,size_t length)241 static uint16_t modbus_rtu_crc16(uint8_t *src, size_t length)
242 {
243 	uint16_t crc = 0xFFFF;
244 	uint8_t shiftctr;
245 	bool flag;
246 	uint8_t *pblock = src;
247 
248 	while (length > 0) {
249 		length--;
250 		crc ^= (uint16_t)*pblock++;
251 		shiftctr = 8;
252 		do {
253 			/* Determine if the shift out of rightmost bit is 1 */
254 			flag = (crc & 0x0001) ? true : false;
255 			/* Shift CRC to the right one bit. */
256 			crc >>= 1;
257 			/*
258 			 * If bit shifted out of rightmost bit was a 1
259 			 * exclusive OR the CRC with the generating polynomial.
260 			 */
261 			if (flag == true) {
262 				crc ^= MODBUS_CRC16_POLY;
263 			}
264 
265 			shiftctr--;
266 		} while (shiftctr > 0);
267 	}
268 
269 	return crc;
270 }
271 
272 /* Copy Modbus RTU frame and check if the CRC is valid. */
modbus_rtu_rx_adu(struct modbus_context * ctx)273 static int modbus_rtu_rx_adu(struct modbus_context *ctx)
274 {
275 	struct modbus_serial_config *cfg = ctx->cfg;
276 	uint16_t calc_crc;
277 	uint16_t crc_idx;
278 	uint8_t *data_ptr;
279 
280 	/* Is the message long enough? */
281 	if ((cfg->uart_buf_ctr < MODBUS_RTU_MIN_MSG_SIZE) ||
282 	    (cfg->uart_buf_ctr > CONFIG_MODBUS_BUFFER_SIZE)) {
283 		LOG_WRN("Frame length error");
284 		return -EMSGSIZE;
285 	}
286 
287 	ctx->rx_adu.unit_id = cfg->uart_buf[0];
288 	ctx->rx_adu.fc = cfg->uart_buf[1];
289 	data_ptr = &cfg->uart_buf[2];
290 	/* Payload length without node address, function code, and CRC */
291 	ctx->rx_adu.length = cfg->uart_buf_ctr - 4;
292 	/* CRC index */
293 	crc_idx = cfg->uart_buf_ctr - sizeof(uint16_t);
294 
295 	memcpy(ctx->rx_adu.data, data_ptr, ctx->rx_adu.length);
296 
297 	ctx->rx_adu.crc = sys_get_le16(&cfg->uart_buf[crc_idx]);
298 	/* Calculate CRC over address, function code, and payload */
299 	calc_crc = modbus_rtu_crc16(&cfg->uart_buf[0],
300 				    cfg->uart_buf_ctr - sizeof(ctx->rx_adu.crc));
301 
302 	if (ctx->rx_adu.crc != calc_crc) {
303 		LOG_WRN("Calculated CRC does not match received CRC");
304 		return -EIO;
305 	}
306 
307 	return 0;
308 }
309 
rtu_tx_adu(struct modbus_context * ctx)310 static void rtu_tx_adu(struct modbus_context *ctx)
311 {
312 	struct modbus_serial_config *cfg = ctx->cfg;
313 	uint16_t tx_bytes = 0;
314 	uint8_t *data_ptr;
315 
316 	cfg->uart_buf[0] = ctx->tx_adu.unit_id;
317 	cfg->uart_buf[1] = ctx->tx_adu.fc;
318 	tx_bytes = 2 + ctx->tx_adu.length;
319 	data_ptr = &cfg->uart_buf[2];
320 
321 	memcpy(data_ptr, ctx->tx_adu.data, ctx->tx_adu.length);
322 
323 	ctx->tx_adu.crc = modbus_rtu_crc16(&cfg->uart_buf[0],
324 					     ctx->tx_adu.length + 2);
325 	sys_put_le16(ctx->tx_adu.crc,
326 		     &cfg->uart_buf[ctx->tx_adu.length + 2]);
327 	tx_bytes += 2;
328 
329 	cfg->uart_buf_ctr = tx_bytes;
330 	cfg->uart_buf_ptr = &cfg->uart_buf[0];
331 
332 	LOG_HEXDUMP_DBG(cfg->uart_buf, cfg->uart_buf_ctr, "uart_buf");
333 	LOG_DBG("Start frame transmission");
334 	modbus_serial_rx_off(ctx);
335 	modbus_serial_tx_on(ctx);
336 }
337 
338 /*
339  * A byte has been received from a serial port. We just store it in the buffer
340  * for processing when a complete packet has been received.
341  */
cb_handler_rx(struct modbus_context * ctx)342 static void cb_handler_rx(struct modbus_context *ctx)
343 {
344 	struct modbus_serial_config *cfg = ctx->cfg;
345 
346 	if ((ctx->mode == MODBUS_MODE_ASCII) &&
347 	    IS_ENABLED(CONFIG_MODBUS_ASCII_MODE)) {
348 		uint8_t c;
349 
350 		if (uart_fifo_read(cfg->dev, &c, 1) != 1) {
351 			LOG_ERR("Failed to read UART");
352 			return;
353 		}
354 
355 		if (c == MODBUS_ASCII_START_FRAME_CHAR) {
356 			/* Restart a new frame */
357 			cfg->uart_buf_ptr = &cfg->uart_buf[0];
358 			cfg->uart_buf_ctr = 0;
359 		}
360 
361 		if (cfg->uart_buf_ctr < CONFIG_MODBUS_BUFFER_SIZE) {
362 			*cfg->uart_buf_ptr++ = c;
363 			cfg->uart_buf_ctr++;
364 		}
365 
366 		if (c == MODBUS_ASCII_END_FRAME_CHAR2) {
367 			k_work_submit(&ctx->server_work);
368 		}
369 
370 	} else {
371 		int n;
372 
373 		/* Restart timer on a new character */
374 		k_timer_start(&cfg->rtu_timer,
375 			      K_USEC(cfg->rtu_timeout), K_NO_WAIT);
376 
377 		n = uart_fifo_read(cfg->dev, cfg->uart_buf_ptr,
378 				   (CONFIG_MODBUS_BUFFER_SIZE -
379 				    cfg->uart_buf_ctr));
380 
381 		cfg->uart_buf_ptr += n;
382 		cfg->uart_buf_ctr += n;
383 	}
384 }
385 
cb_handler_tx(struct modbus_context * ctx)386 static void cb_handler_tx(struct modbus_context *ctx)
387 {
388 	struct modbus_serial_config *cfg = ctx->cfg;
389 	int n;
390 
391 	if (cfg->uart_buf_ctr > 0) {
392 		n = uart_fifo_fill(cfg->dev, cfg->uart_buf_ptr,
393 				   cfg->uart_buf_ctr);
394 		cfg->uart_buf_ctr -= n;
395 		cfg->uart_buf_ptr += n;
396 		return;
397 	}
398 
399 	/* Must wait till the transmission is complete or
400 	 * RS-485 tranceiver could be disabled before all data has
401 	 * been transmitted and message will be corrupted.
402 	 */
403 	if (uart_irq_tx_complete(cfg->dev)) {
404 		/* Disable transmission */
405 		cfg->uart_buf_ptr = &cfg->uart_buf[0];
406 		modbus_serial_tx_off(ctx);
407 		modbus_serial_rx_on(ctx);
408 	}
409 }
410 
uart_cb_handler(const struct device * dev,void * app_data)411 static void uart_cb_handler(const struct device *dev, void *app_data)
412 {
413 	struct modbus_context *ctx = (struct modbus_context *)app_data;
414 	struct modbus_serial_config *cfg;
415 
416 	if (ctx == NULL) {
417 		LOG_ERR("Modbus hardware is not properly initialized");
418 		return;
419 	}
420 
421 	cfg = ctx->cfg;
422 
423 	while (uart_irq_update(cfg->dev) && uart_irq_is_pending(cfg->dev)) {
424 
425 		if (uart_irq_rx_ready(cfg->dev)) {
426 			cb_handler_rx(ctx);
427 		}
428 
429 		if (uart_irq_tx_ready(cfg->dev)) {
430 			cb_handler_tx(ctx);
431 		}
432 	}
433 }
434 
435 /* This function is called when the RTU framing timer expires. */
rtu_tmr_handler(struct k_timer * t_id)436 static void rtu_tmr_handler(struct k_timer *t_id)
437 {
438 	struct modbus_context *ctx;
439 
440 	ctx = (struct modbus_context *)k_timer_user_data_get(t_id);
441 
442 	if (ctx == NULL) {
443 		LOG_ERR("Failed to get Modbus context");
444 		return;
445 	}
446 
447 	k_work_submit(&ctx->server_work);
448 }
449 
configure_gpio(struct modbus_context * ctx)450 static int configure_gpio(struct modbus_context *ctx)
451 {
452 	struct modbus_serial_config *cfg = ctx->cfg;
453 
454 	if (cfg->de != NULL) {
455 		if (!device_is_ready(cfg->de->port)) {
456 			return -ENODEV;
457 		}
458 
459 		if (gpio_pin_configure_dt(cfg->de, GPIO_OUTPUT_INACTIVE)) {
460 			return -EIO;
461 		}
462 	}
463 
464 
465 	if (cfg->re != NULL) {
466 		if (!device_is_ready(cfg->re->port)) {
467 			return -ENODEV;
468 		}
469 
470 		if (gpio_pin_configure_dt(cfg->re, GPIO_OUTPUT_INACTIVE)) {
471 			return -EIO;
472 		}
473 	}
474 
475 	return 0;
476 }
477 
modbus_serial_rx_disable(struct modbus_context * ctx)478 void modbus_serial_rx_disable(struct modbus_context *ctx)
479 {
480 	modbus_serial_rx_off(ctx);
481 }
482 
modbus_serial_rx_enable(struct modbus_context * ctx)483 void modbus_serial_rx_enable(struct modbus_context *ctx)
484 {
485 	modbus_serial_rx_on(ctx);
486 }
487 
modbus_serial_rx_adu(struct modbus_context * ctx)488 int modbus_serial_rx_adu(struct modbus_context *ctx)
489 {
490 	struct modbus_serial_config *cfg = ctx->cfg;
491 	int rc = 0;
492 
493 	switch (ctx->mode) {
494 	case MODBUS_MODE_RTU:
495 		rc = modbus_rtu_rx_adu(ctx);
496 		break;
497 	case MODBUS_MODE_ASCII:
498 		if (!IS_ENABLED(CONFIG_MODBUS_ASCII_MODE)) {
499 			return -ENOTSUP;
500 		}
501 
502 		rc = modbus_ascii_rx_adu(ctx);
503 		break;
504 	default:
505 		LOG_ERR("Unsupported MODBUS mode");
506 		return -ENOTSUP;
507 	}
508 
509 	cfg->uart_buf_ctr = 0;
510 	cfg->uart_buf_ptr = &cfg->uart_buf[0];
511 
512 	return rc;
513 }
514 
modbus_serial_tx_adu(struct modbus_context * ctx)515 int modbus_serial_tx_adu(struct modbus_context *ctx)
516 {
517 	switch (ctx->mode) {
518 	case MODBUS_MODE_RTU:
519 		rtu_tx_adu(ctx);
520 		return 0;
521 	case MODBUS_MODE_ASCII:
522 		if (IS_ENABLED(CONFIG_MODBUS_ASCII_MODE)) {
523 			modbus_ascii_tx_adu(ctx);
524 			return 0;
525 		}
526 	default:
527 		break;
528 	}
529 
530 	return -ENOTSUP;
531 }
532 
modbus_serial_init(struct modbus_context * ctx,struct modbus_iface_param param)533 int modbus_serial_init(struct modbus_context *ctx,
534 		       struct modbus_iface_param param)
535 {
536 	struct modbus_serial_config *cfg = ctx->cfg;
537 	const uint32_t if_delay_max = 3500000;
538 	const uint32_t numof_bits = 11;
539 	struct uart_config uart_cfg;
540 
541 	switch (param.mode) {
542 	case MODBUS_MODE_RTU:
543 	case MODBUS_MODE_ASCII:
544 		ctx->mode = param.mode;
545 		break;
546 	default:
547 		return -ENOTSUP;
548 	}
549 
550 	cfg->dev = device_get_binding(cfg->dev_name);
551 	if (cfg->dev == NULL) {
552 		LOG_ERR("Failed to get UART device %s",
553 			log_strdup(cfg->dev_name));
554 		return -ENODEV;
555 	}
556 
557 	uart_cfg.baudrate = param.serial.baud,
558 	uart_cfg.flow_ctrl = UART_CFG_FLOW_CTRL_NONE;
559 
560 	if (ctx->mode == MODBUS_MODE_ASCII) {
561 		uart_cfg.data_bits = UART_CFG_DATA_BITS_7;
562 	} else {
563 		uart_cfg.data_bits = UART_CFG_DATA_BITS_8;
564 	}
565 
566 	switch (param.serial.parity) {
567 	case UART_CFG_PARITY_ODD:
568 	case UART_CFG_PARITY_EVEN:
569 		uart_cfg.parity = param.serial.parity;
570 		uart_cfg.stop_bits = UART_CFG_STOP_BITS_1;
571 		break;
572 	case UART_CFG_PARITY_NONE:
573 		/* Use of no parity requires 2 stop bits */
574 		uart_cfg.parity = param.serial.parity;
575 		uart_cfg.stop_bits = UART_CFG_STOP_BITS_2;
576 		break;
577 	default:
578 		return -EINVAL;
579 	}
580 
581 	if (uart_configure(cfg->dev, &uart_cfg) != 0) {
582 		LOG_ERR("Failed to configure UART");
583 		return -EINVAL;
584 	}
585 
586 	if (param.serial.baud <= 38400) {
587 		cfg->rtu_timeout = (numof_bits * if_delay_max) /
588 				   param.serial.baud;
589 	} else {
590 		cfg->rtu_timeout = (numof_bits * if_delay_max) / 38400;
591 	}
592 
593 	if (configure_gpio(ctx) != 0) {
594 		return -EIO;
595 	}
596 
597 	cfg->uart_buf_ctr = 0;
598 	cfg->uart_buf_ptr = &cfg->uart_buf[0];
599 
600 	uart_irq_callback_user_data_set(cfg->dev, uart_cb_handler, ctx);
601 	k_timer_init(&cfg->rtu_timer, rtu_tmr_handler, NULL);
602 	k_timer_user_data_set(&cfg->rtu_timer, ctx);
603 
604 	modbus_serial_rx_on(ctx);
605 	LOG_INF("RTU timeout %u us", cfg->rtu_timeout);
606 
607 	return 0;
608 }
609 
modbus_serial_disable(struct modbus_context * ctx)610 void modbus_serial_disable(struct modbus_context *ctx)
611 {
612 	modbus_serial_tx_off(ctx);
613 	modbus_serial_rx_off(ctx);
614 	k_timer_stop(&ctx->cfg->rtu_timer);
615 }
616