From 75386d88dff0d978e1d95e1535c33d80d7ae1aa0 Mon Sep 17 00:00:00 2001 From: JTrantow Date: Sat, 7 Mar 2026 14:03:12 -0600 Subject: [PATCH 1/4] Issue#3849 Fix. --- src/hal/drivers/mesa-hostmot2/hm2_modbus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hal/drivers/mesa-hostmot2/hm2_modbus.c b/src/hal/drivers/mesa-hostmot2/hm2_modbus.c index d186ebeb147..6f4aab3856b 100644 --- a/src/hal/drivers/mesa-hostmot2/hm2_modbus.c +++ b/src/hal/drivers/mesa-hostmot2/hm2_modbus.c @@ -1054,6 +1054,7 @@ static void process(void *arg, long period) HM2_PKTUART_RCR_ICHARBITS_VAL(frsize), inst->maxicharbits); set_error(inst, ENOMSG); force_resend(inst); + queue_reset(inst); break; } inst->rxdata[0] = 0; // This will fail the parse packet if the read did not resolve From c28ccaa997ce3b957d2b572e1fc71fd8d8c925e1 Mon Sep 17 00:00:00 2001 From: JTrantow Date: Sun, 8 Mar 2026 20:25:43 -0500 Subject: [PATCH 2/4] Issue #3849 Fix up ifdelay calculations and ENOMSG handling. --- src/hal/drivers/mesa-hostmot2/hm2_modbus.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/hal/drivers/mesa-hostmot2/hm2_modbus.c b/src/hal/drivers/mesa-hostmot2/hm2_modbus.c index 6f4aab3856b..46728b9de07 100644 --- a/src/hal/drivers/mesa-hostmot2/hm2_modbus.c +++ b/src/hal/drivers/mesa-hostmot2/hm2_modbus.c @@ -374,23 +374,27 @@ static void setup_icdelay(hm2_modbus_inst_t *inst, unsigned baudrate, unsigned p inst->hal->icdelay = inst->maxicharbits; } +#define HARDWARE_MAX_DELAY (1020) //!< Maximum ifdelay in number of bits limited by hardware. +#define HARDWARE_BAUD_LIMIT ((HARDWARE_MAX_DELAY*100000-99999)/175) //!< Baud that limits out the hardware ifdelay. // -// Calculate the inter-frame delay time: +// Calculate the inter-frame delay time in units of numbers of bits. +// Returns: +// - HARDWARE_MAX_DELAY bits if baud > HARDWARE_BAUD_LIMIT // - 3.5 chars if baudrate <= 19200 -// - 1750 microseconds if baudrate > 19200 +// - 1750 microseconds worth of bits when baudrate > 19200 and <= HARDWARE_BAUD_LIMIT // static unsigned calc_ifdelay(hm2_modbus_inst_t *inst, unsigned baudrate, unsigned parity, unsigned stopbits) { - if(baudrate > 582000) { + if(baudrate > HARDWARE_BAUD_LIMIT) { MSG_WARN("%s: warning: Baudrate > 582000 will make inter-frame timer overflow. Setting to maximum.\n", inst->name); - return 1020; + return HARDWARE_MAX_DELAY; } // calculation works for baudrates less than ~24 Mbit/s - if(baudrate <= 19200) + if(baudrate > 19200) return (175u * baudrate + 99999u) / 100000u; unsigned bits = 1 + 8 + (parity ? 1 : 0) + (stopbits > 1 ? 2 : 1); - return (bits * 35 + 9) / 10; // Bit-times * 3.5 rounded up + return (bits * 35 + 9) / 10; // Ceil of bits in 3.5 characters. } // @@ -1049,13 +1053,10 @@ static void process(void *arg, long period) break; } if(inst->maxicharbits && HM2_PKTUART_RCR_ICHARBITS_VAL(frsize) > inst->maxicharbits) { - MSG_WARN("%s: warning: reply to command %u had too long inter-character delay (%u > %u), dropping\n", + MSG_WARN("%s: warning: reply to command %u had too long inter-character delay (%u > %u), trying to interpret\n", inst->name, inst->cmdidx, HM2_PKTUART_RCR_ICHARBITS_VAL(frsize), inst->maxicharbits); set_error(inst, ENOMSG); - force_resend(inst); - queue_reset(inst); - break; } inst->rxdata[0] = 0; // This will fail the parse packet if the read did not resolve r = hm2_pktuart_queue_read_data(inst->uart, inst->rxdata, HM2_PKTUART_RCR_NBYTES_VAL(frsize)); From c025b3fb7b3615d7eb68880ffa6130012f800085 Mon Sep 17 00:00:00 2001 From: JTrantow Date: Tue, 10 Mar 2026 14:54:04 -0500 Subject: [PATCH 3/4] Back to original voodoo caused by conflating modbus timing calculation with pktuart hardware implementation. Note: (175u * baudrate + 99999u) / 100000u; could be implemented as (7u * baudrate + 3999(/4000; which would improve the calculation range but doesn't matter because already screening out large baud rates. --- src/hal/drivers/mesa-hostmot2/hm2_modbus.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/hal/drivers/mesa-hostmot2/hm2_modbus.c b/src/hal/drivers/mesa-hostmot2/hm2_modbus.c index 46728b9de07..48bf69fba7a 100644 --- a/src/hal/drivers/mesa-hostmot2/hm2_modbus.c +++ b/src/hal/drivers/mesa-hostmot2/hm2_modbus.c @@ -374,24 +374,20 @@ static void setup_icdelay(hm2_modbus_inst_t *inst, unsigned baudrate, unsigned p inst->hal->icdelay = inst->maxicharbits; } -#define HARDWARE_MAX_DELAY (1020) //!< Maximum ifdelay in number of bits limited by hardware. -#define HARDWARE_BAUD_LIMIT ((HARDWARE_MAX_DELAY*100000-99999)/175) //!< Baud that limits out the hardware ifdelay. // -// Calculate the inter-frame delay time in units of numbers of bits. -// Returns: -// - HARDWARE_MAX_DELAY bits if baud > HARDWARE_BAUD_LIMIT +// Calculate the inter-frame delay time: // - 3.5 chars if baudrate <= 19200 -// - 1750 microseconds worth of bits when baudrate > 19200 and <= HARDWARE_BAUD_LIMIT +// - 1750 microseconds if baudrate > 19200 // static unsigned calc_ifdelay(hm2_modbus_inst_t *inst, unsigned baudrate, unsigned parity, unsigned stopbits) { - if(baudrate > HARDWARE_BAUD_LIMIT) { + if(baudrate > 582000) { MSG_WARN("%s: warning: Baudrate > 582000 will make inter-frame timer overflow. Setting to maximum.\n", inst->name); - return HARDWARE_MAX_DELAY; + return 1020; } // calculation works for baudrates less than ~24 Mbit/s - if(baudrate > 19200) + if(19200 < baudrate) return (175u * baudrate + 99999u) / 100000u; unsigned bits = 1 + 8 + (parity ? 1 : 0) + (stopbits > 1 ? 2 : 1); return (bits * 35 + 9) / 10; // Ceil of bits in 3.5 characters. From 2252af205417478929cb0ca31155e838addc6130 Mon Sep 17 00:00:00 2001 From: JTrantow Date: Wed, 11 Mar 2026 07:55:05 -0500 Subject: [PATCH 4/4] Reverse (baudrate > 19200). --- src/hal/drivers/mesa-hostmot2/hm2_modbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hal/drivers/mesa-hostmot2/hm2_modbus.c b/src/hal/drivers/mesa-hostmot2/hm2_modbus.c index 48bf69fba7a..a08c2e30693 100644 --- a/src/hal/drivers/mesa-hostmot2/hm2_modbus.c +++ b/src/hal/drivers/mesa-hostmot2/hm2_modbus.c @@ -387,7 +387,7 @@ static unsigned calc_ifdelay(hm2_modbus_inst_t *inst, unsigned baudrate, unsigne } // calculation works for baudrates less than ~24 Mbit/s - if(19200 < baudrate) + if(baudrate > 19200) return (175u * baudrate + 99999u) / 100000u; unsigned bits = 1 + 8 + (parity ? 1 : 0) + (stopbits > 1 ? 2 : 1); return (bits * 35 + 9) / 10; // Ceil of bits in 3.5 characters.