diff --git a/README.md b/README.md index 4cc1d1f..54054ce 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## grblHAL ## -Latest build date is 20260314, see the [changelog](changelog.md) for details. +Latest build date is 20260318, see the [changelog](changelog.md) for details. > [!NOTE] > A settings reset will be performed on an update of builds prior to 20241208. Backup and restore of settings is recommended. diff --git a/changelog.md b/changelog.md index 18b4696..f2349a6 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,23 @@ ## grblHAL changelog +Build 20260318 + +Core: + +* Fix for regression. + +* Added MCU clock speed, when available, to DRIVER element in `$I` output. Ref. issue [#923](https://github.com/grblHAL/core/issues/923). + +* Improved diagnostics provided by `$MODBUSSTATS` when communication has been lost. + +Plugins: + +* Networking: moved shared string function to core. + +* SD card: added file systems mount directory, size and remaining space to `$I` output. Ref. core issue [#923](https://github.com/grblHAL/core/issues/923). + +--- + Build 20260314 Core: diff --git a/grbl.h b/grbl.h index db13c3e..15b886d 100644 --- a/grbl.h +++ b/grbl.h @@ -42,7 +42,7 @@ #else #define GRBL_VERSION "1.1f" #endif -#define GRBL_BUILD 20260314 +#define GRBL_BUILD 20260318 #define GRBL_URL "https://github.com/grblHAL" diff --git a/modbus_rtu.c b/modbus_rtu.c index 4dbba94..1d67e6c 100644 --- a/modbus_rtu.c +++ b/modbus_rtu.c @@ -72,7 +72,6 @@ static int8_t stream_instance = -1; static uint32_t rx_timeout = 0, silence_until = 0, silence_timeout; static modbus_exception_t exception_code = ModBus_NoException; static modbus_silence_timeout_t silence; -static uint32_t latency = 0; static queue_entry_t queue[MODBUS_QUEUE_LENGTH]; static rtu_settings_t modbus; static volatile bool spin_lock = false, is_blocking = false, is_up = false; @@ -81,11 +80,14 @@ static volatile modbus_state_t state = ModBus_Idle; static uint8_t dir_port = IOPORT_UNASSIGNED; static struct { + uint32_t rx_count; uint32_t tx_count; uint32_t retries; uint32_t timeouts; uint32_t crc_errors; uint32_t rx_exceptions; + uint32_t latency; + bool no_rx; } stats = {}; static driver_reset_ptr driver_reset; @@ -203,7 +205,8 @@ static void modbus_poll (void *data) char *buf = (char *)((queue_entry_t *)packet)->msg.adu; uint16_t rx_len = packet->msg.rx_length; // store original length for CRC check - latency = max(latency, modbus.rx_timeout - rx_timeout); + stats.rx_count++; + stats.latency = max(stats.latency, modbus.rx_timeout - rx_timeout); do { *buf++ = stream.read(); @@ -240,6 +243,7 @@ static void modbus_poll (void *data) case ModBus_TimeoutException: if(packet->async) state = ModBus_Silent; + stats.no_rx = stream.get_rx_buffer_count() == 0; silence_until = hal.get_elapsed_ticks() + silence_timeout; break; @@ -288,7 +292,8 @@ static bool modbus_send_rtu (modbus_message_t *msg, const modbus_callbacks_t *ca case ModBus_TimeoutException: if(packet->callbacks.on_rx_timeout) packet->callbacks.on_rx_timeout(ModBus_Timeout, packet->msg.context); - is_blocking = packet->callbacks.retries > 0; + if(!(is_blocking = packet->callbacks.retries > 0)) + stats.no_rx = stream.get_rx_buffer_count() == 0; break; case ModBus_Exception: @@ -452,7 +457,7 @@ FLASHMEM static void onReportOptions (bool newopt) on_report_options(newopt); if(!newopt) - report_plugin("MODBUS", "0.22"); + report_plugin("MODBUS", "0.23"); } static bool modbus_rtu_isup (void) @@ -536,13 +541,15 @@ FLASHMEM static status_code_t report_stats (sys_state_t state, char *args) { char buf[110]; - snprintf(buf, sizeof(buf) - 1, "TX: " UINT32FMT ", retries: " UINT32FMT ", timeouts: " UINT32FMT ", RX exceptions: " UINT32FMT ", CRC errors: " UINT32FMT ", latency: " UINT32FMT, - stats.tx_count, stats.retries, stats.timeouts, stats.rx_exceptions, stats.crc_errors, latency); + if(stats.no_rx) + report_message(stats.rx_count ? "Unstable connection to modbus device?" : "No connection to modbus device?", Message_Warning); + snprintf(buf, sizeof(buf) - 1, "TX: " UINT32FMT ", retries: " UINT32FMT ", timeouts: " UINT32FMT ", RX exceptions: " UINT32FMT ", CRC errors: " UINT32FMT ", latency: " UINT32FMT, + stats.tx_count, stats.retries, stats.timeouts, stats.rx_exceptions, stats.crc_errors, stats.latency); report_message(buf, Message_Info); if(args && (*args == 'r' || *args == 'R')) - stats.tx_count = stats.retries = stats.timeouts = stats.rx_exceptions = stats.crc_errors = latency = 0; + memset(&stats, 0, sizeof(stats)); return Status_OK; } diff --git a/report.c b/report.c index 99c257c..57a1a1a 100644 --- a/report.c +++ b/report.c @@ -1095,6 +1095,11 @@ FLASHMEM void report_build_info (char *line, bool extended) if(hal.info) { hal.stream.write("[DRIVER:"); hal.stream.write(hal.info); + if(hal.f_mcu) { + hal.stream.write("@"); + hal.stream.write(uitoa(hal.f_mcu)); + hal.stream.write("MHz"); + } hal.stream.write("]" ASCII_EOL); } @@ -2946,7 +2951,7 @@ ISR_CODE void report_add_realtime (report_tracking_t report) case Report_CycleStart: if(!settings.status_report.pin_state) return; - return; + break; default: break; diff --git a/state_machine.c b/state_machine.c index 29c7579..d72183a 100644 --- a/state_machine.c +++ b/state_machine.c @@ -201,6 +201,7 @@ ISR_CODE sys_state_t ISR_FUNC(state_get)(void) return sys_state; } +// NOTE: keep STATE_HAS_SUBSTATE in sync if this code is expanded to cover new states uint8_t state_get_substate (void) { uint8_t substate = 0; diff --git a/strutils.c b/strutils.c index 8b90e90..7fc24d7 100644 --- a/strutils.c +++ b/strutils.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2019-2024 Terje Io + Copyright (c) 2019-2026 Terje Io grblHAL is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -335,3 +335,25 @@ FLASHMEM char *strtointernetdt (struct tm *dt) #endif } + +FLASHMEM char *btoa (uint64_t bytes) +{ + static char buf[16]; + + uint_fast8_t n = 0; + uint64_t size = bytes; + + while(size > 1024) { + size >>= 10; + n++; + } + + strcpy(buf, ftoa((float)bytes / (float)(1ULL << 10 * n), n ? 2 : 0)); + + if(n == 0) // remove trailing decimal point... + buf[strlen(buf) - 1] = '\0'; + + strcat(buf, n == 0 ? " B" : n == 1 ? " KB" : n == 2 ? " MB" : " GB"); + + return buf; +} diff --git a/strutils.h b/strutils.h index 4c8dfc2..a5cf201 100644 --- a/strutils.h +++ b/strutils.h @@ -1,7 +1,7 @@ /* strutils.h - a collection of useful string utilities -Copyright (c) 2019-2022 Terje Io +Copyright (c) 2019-2026 Terje Io All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -46,5 +46,6 @@ int32_t strlookup (const char *s1, const char *s2, const char delimiter); bool strtotime (char *s, struct tm *time); char *strtoisodt (struct tm *dt); char *strtointernetdt (struct tm *dt); +char *btoa (uint64_t bytes); #endif diff --git a/system.h b/system.h index fbfa3d6..8a4a0bd 100644 --- a/system.h +++ b/system.h @@ -85,6 +85,11 @@ __NOTE:__ flags are mutually exclusive, bit map allows testing for multiple stat #define STATE_TOOL_CHANGE bit(9) //!< Manual tool change, similar to #STATE_HOLD - but stops spindle and allows jogging. ///@} +//! \def STATE_HAS_SUBSTATE +/*! @name Bitmask with system states that may have substate(s). +*/ +#define STATE_HAS_SUBSTATE (STATE_CYCLE|STATE_HOLD|STATE_ESTOP|STATE_ALARM|STATE_SAFETY_DOOR) + //! \def system_state_t /*! @name System state enum values.