diff --git a/README.md b/README.md index 45cd1be..58a59dc 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## grblHAL ## -Latest build date is 20250530, see the [changelog](changelog.md) for details. +Latest build date is 20250604, 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 e9c1f09..192492b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,24 @@ ## grblHAL changelog +Build 20250604 + +Core: + +* No longer retries Modbus commands if there is a pending reset. + +* Added `$MODBUSSTATS` and `$MODBUSSTATS=R` commands, outputs communication statistics such as number of sent commands, retries etc. +`$MODBUSSTATS=R` clears the statistics after outputting it. Ref. issue [#753](https://github.com/grblHAL/core/issues/753). + +Drivers: + +* STM32Fxxx: bug fix - moved code for assigning IRQs for auxiliary inputs from the core to the drivers. + +Plugins: + +* Spindle: "hardened" code for Huanyang VFD drivers to prevent hardfaults. Updated some VFD drivers to delay reading data from the VFD till after a pending soft reset has been executed. + +--- + Build 20250530 Core: diff --git a/grbl.h b/grbl.h index 9015e15..1c4cb42 100644 --- a/grbl.h +++ b/grbl.h @@ -42,7 +42,7 @@ #else #define GRBL_VERSION "1.1f" #endif -#define GRBL_BUILD 20250530 +#define GRBL_BUILD 20250604 #define GRBL_URL "https://github.com/grblHAL" diff --git a/modbus_rtu.c b/modbus_rtu.c index 433ab2c..25f3df8 100644 --- a/modbus_rtu.c +++ b/modbus_rtu.c @@ -21,9 +21,11 @@ */ +#include #include #include "hal.h" +#include "platform.h" #include "protocol.h" #include "settings.h" #include "crc.h" @@ -89,6 +91,14 @@ static volatile queue_entry_t *tail, *head, *packet = NULL; static volatile modbus_state_t state = ModBus_Idle; static uint8_t dir_port = IOPORT_UNASSIGNED; +static struct { + uint32_t tx_count; + uint32_t retries; + uint32_t timeouts; + uint32_t crc_errors; + uint32_t rx_exceptions; +} stats = {}; + static driver_reset_ptr driver_reset; static on_report_options_ptr on_report_options; static nvs_address_t nvs_address; @@ -107,16 +117,19 @@ static void retry_exception (uint8_t code, void *context) if(packet && packet->callbacks.retries) { state = ModBus_Retry; silence_until = hal.get_elapsed_ticks() + silence_timeout + packet->callbacks.retry_delay; + stats.retries++; } } static inline queue_entry_t *add_message (queue_entry_t *packet, modbus_message_t *msg, bool async, const modbus_callbacks_t *callbacks) { + stats.tx_count++; + memcpy(&packet->msg, msg, sizeof(modbus_message_t)); packet->async = async; - if(callbacks) { + if(callbacks && !sys.reset_pending) { memcpy(&packet->callbacks, callbacks, sizeof(modbus_callbacks_t)); if(!packet->async && packet->callbacks.retries) packet->callbacks.on_rx_exception = retry_exception; @@ -184,6 +197,9 @@ static void modbus_poll (void *data) case ModBus_AwaitReply: if(rx_timeout && --rx_timeout == 0) { + + stats.timeouts++; + if(packet->async) { state = ModBus_Silent; if(packet->callbacks.on_rx_exception) @@ -192,8 +208,10 @@ static void modbus_poll (void *data) } else if(stream.read() == packet->msg.adu[0] && (stream.read() & 0x80)) { exception_code = stream.read(); state = ModBus_Exception; + stats.rx_exceptions++; } else state = ModBus_Timeout; + spin_lock = false; if(state != ModBus_AwaitReply) silence_until = hal.get_elapsed_ticks() + silence_timeout; @@ -210,10 +228,11 @@ static void modbus_poll (void *data) } while(--packet->msg.rx_length); if(packet->msg.crc_check) { - uint_fast16_t crc = modbus_crc16x(((queue_entry_t *)packet)->msg.adu, rx_len - 2); + uint_fast16_t crc = modbus_crc16x(((queue_entry_t *)packet)->msg.adu, rx_len - 2); if(packet->msg.adu[rx_len - 2] != (crc & 0xFF) || packet->msg.adu[rx_len - 1] != (crc >> 8)) { // CRC check error + stats.crc_errors++; if((state = packet->async ? ModBus_Silent : ModBus_Exception) == ModBus_Silent) { if(packet->callbacks.on_rx_exception) packet->callbacks.on_rx_exception(0, packet->msg.context); @@ -499,6 +518,20 @@ static bool claim_stream (io_stream_properties_t const *sstream) return claimed != NULL; } +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, + stats.tx_count, stats.retries, stats.timeouts, stats.rx_exceptions, stats.crc_errors); + + report_message(buf, Message_Info); + + if(args && (*args == 'r' || *args == 'R')) + stats.tx_count = stats.retries = stats.timeouts = stats.rx_exceptions = stats.crc_errors = 0; + + return Status_OK; +} void modbus_rtu_init (int8_t stream, int8_t dir_aux) { @@ -520,6 +553,15 @@ void modbus_rtu_init (int8_t stream, int8_t dir_aux) .restore = modbus_settings_restore }; + static const sys_command_t command_list[] = { + {"MODBUSSTATS", report_stats, { .allow_blocking = On }, { .str = "output Modbus RTU statistics" } }, + }; + + static sys_commands_t commands = { + .n_commands = sizeof(command_list) / sizeof(sys_command_t), + .commands = command_list + }; + if(dir_aux != -2) { int8_t n_out = ioports_available(Port_Digital, Port_Output); @@ -557,6 +599,8 @@ void modbus_rtu_init (int8_t stream, int8_t dir_aux) modbus_register_api(&api); + system_register_commands(&commands); + modbus_set_silence(NULL); } else { diff --git a/pin_bits_masks.h b/pin_bits_masks.h index 815dbb7..b473c98 100644 --- a/pin_bits_masks.h +++ b/pin_bits_masks.h @@ -112,147 +112,153 @@ #endif static aux_ctrl_t aux_ctrl[] = { -// The following pins are bound explicitly to aux input pins +// The following pins are bound explicitly to aux input pins. #if (CONTROL_ENABLE & CONTROL_ESTOP) && defined(RESET_PIN) #ifndef RESET_PORT #define RESET_PORT 0 #endif - { .function = Input_EStop, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .e_stop = On }, .pin = RESET_PIN, .port = (void *)RESET_PORT }, + { .function = Input_EStop, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .e_stop = On }, .pin = RESET_PIN, .port = (void *)RESET_PORT }, #elif (CONTROL_ENABLE & CONTROL_RESET) && defined(RESET_PIN) #ifndef RESET_PORT #define RESET_PORT 0 #endif - { .function = Input_Reset, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .reset = On }, .pin = RESET_PIN, .port = (void *)RESET_PORT }, + { .function = Input_Reset, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .reset = On }, .pin = RESET_PIN, .port = (void *)RESET_PORT }, #endif #if (CONTROL_ENABLE & CONTROL_FEED_HOLD) && defined(FEED_HOLD_PIN) #ifndef FEED_HOLD_PORT #define FEED_HOLD_PORT 0 #endif - { .function = Input_FeedHold, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .feed_hold = On }, .pin = FEED_HOLD_PIN, .port = (void *)FEED_HOLD_PORT }, + { .function = Input_FeedHold, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .feed_hold = On }, .pin = FEED_HOLD_PIN, .port = (void *)FEED_HOLD_PORT }, #endif #if (CONTROL_ENABLE & CONTROL_CYCLE_START) && defined(CYCLE_START_PIN) #ifndef CYCLE_START_PORT #define CYCLE_START_PORT 0 #endif - { .function = Input_CycleStart, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .cycle_start = On }, .pin = CYCLE_START_PIN, .port = (void *)CYCLE_START_PORT }, + { .function = Input_CycleStart, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .cycle_start = On }, .pin = CYCLE_START_PIN, .port = (void *)CYCLE_START_PORT }, #endif #if SAFETY_DOOR_ENABLE && defined(SAFETY_DOOR_PIN) #ifndef SAFETY_DOOR_PORT #define SAFETY_DOOR_PORT 0 #endif - { .function = Input_SafetyDoor, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .safety_door_ajar = On }, .pin = SAFETY_DOOR_PIN, .port = (void *)SAFETY_DOOR_PORT }, + { .function = Input_SafetyDoor, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .safety_door_ajar = On }, .pin = SAFETY_DOOR_PIN, .port = (void *)SAFETY_DOOR_PORT }, #endif #if MOTOR_FAULT_ENABLE && defined(MOTOR_FAULT_PIN) #ifndef MOTOR_FAULT_PORT #define MOTOR_FAULT_PORT 0 #endif - { .function = Input_MotorFault, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .motor_fault = On }, .pin = MOTOR_FAULT_PIN, .port = (void *)MOTOR_FAULT_PORT }, + { .function = Input_MotorFault, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .motor_fault = On }, .pin = MOTOR_FAULT_PIN, .port = (void *)MOTOR_FAULT_PORT }, #endif #if MOTOR_WARNING_ENABLE && defined(MOTOR_WARNING_PIN) #ifndef MOTOR_WARNING_PORT #define MOTOR_WARNING_PORT 0 #endif - { .function = Input_MotorWarning, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .motor_fault = On }, .pin = MOTOR_WARNING_PIN, .port = (void *)MOTOR_WARNING_PORT }, -#endif - -#if PROBE_ENABLE && defined(PROBE_PIN) - #ifndef PROBE_PORT - #define PROBE_PORT 0 - #endif - { .function = Input_Probe, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = PROBE_PIN, .port = (void *)PROBE_PORT }, -#endif -#if PROBE2_ENABLE && defined(PROBE2_PIN) - #ifndef PROBE2_PORT - #define PROBE2_PORT 0 - #endif - { .function = Input_Probe2, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = PROBE2_PIN, .port = (void *)PROBE2_PORT }, -#endif -#if TOOLSETTER_ENABLE && defined(TOOLSETTER_PIN) - #ifndef TOOLSETTER_PORT - #define TOOLSETTER_PORT 0 - #endif - { .function = Input_Toolsetter, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = TOOLSETTER_PIN, .port = (void *)TOOLSETTER_PORT }, + { .function = Input_MotorWarning, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .motor_fault = On }, .pin = MOTOR_WARNING_PIN, .port = (void *)MOTOR_WARNING_PORT }, #endif #if I2C_STROBE_ENABLE && defined(I2C_STROBE_PIN) #ifndef I2C_STROBE_PORT #define I2C_STROBE_PORT 0 #endif - { .function = Input_I2CStrobe, .aux_port = 0xFF, .irq_mode = IRQ_Mode_Change, .cap = { .value = 0 }, .pin = I2C_STROBE_PIN, .port = (void *)I2C_STROBE_PORT }, + { .function = Input_I2CStrobe, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_Change, .cap = { .value = 0 }, .pin = I2C_STROBE_PIN, .port = (void *)I2C_STROBE_PORT }, #endif #if MPG_ENABLE == 1 && defined(MPG_MODE_PIN) #ifndef MPG_MODE_PORT #define MPG_MODE_PORT 0 #endif - { .function = Input_MPGSelect, .aux_port = 0xFF, .irq_mode = IRQ_Mode_Change, .cap = { .value = 0 }, .pin = MPG_MODE_PIN, .port = (void *)MPG_MODE_PORT }, + { .function = Input_MPGSelect, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_Change, .cap = { .value = 0 }, .pin = MPG_MODE_PIN, .port = (void *)MPG_MODE_PORT }, #endif #if QEI_SELECT_ENABLE && defined(QEI_SELECT_PIN) #ifndef QEI_SELECT_PORT #define QEI_SELECT_PORT 0 #endif - { .function = Input_QEI_Select, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = QEI_SELECT_PIN, .port = (void *)QEI_SELECT_PORT }, + { .function = Input_QEI_Select, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = QEI_SELECT_PIN, .port = (void *)QEI_SELECT_PORT }, #endif + +// Probe pins can be bound explicitly and can be "degraded" to not interrupt capable. +#if PROBE_ENABLE && defined(PROBE_PIN) + #ifndef PROBE_PORT + #define PROBE_PORT 0 + #endif + { .function = Input_Probe, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = PROBE_PIN, .port = (void *)PROBE_PORT }, +#endif +#if PROBE2_ENABLE && defined(PROBE2_PIN) + #ifndef PROBE2_PORT + #define PROBE2_PORT 0 + #endif + { .function = Input_Probe2, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = PROBE2_PIN, .port = (void *)PROBE2_PORT }, +#endif +#if TOOLSETTER_ENABLE && defined(TOOLSETTER_PIN) + #ifndef TOOLSETTER_PORT + #define TOOLSETTER_PORT 0 + #endif + { .function = Input_Toolsetter, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = TOOLSETTER_PIN, .port = (void *)TOOLSETTER_PORT }, +#endif + // The following pins are allocated from remaining aux inputs pool #if TOOLSETTER_ENABLE && !defined(TOOLSETTER_PIN) - { .function = Input_Toolsetter, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = 0xFE, .port = NULL }, + { .function = Input_Toolsetter, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = 0xFE, .port = NULL }, #endif #if PROBE2_ENABLE && !defined(PROBE2_PIN) - { .function = Input_Probe2, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = 0xFE, .port = NULL }, + { .function = Input_Probe2, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = 0xFE, .port = NULL }, #endif #if LIMITS_OVERRIDE_ENABLE - { .function = Input_LimitsOverride, .aux_port = 0xFF, .irq_mode = IRQ_Mode_None, .cap = { .limits_override = On }, .pin = 0xFF, .port = NULL }, + { .function = Input_LimitsOverride, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_None, .cap = { .limits_override = On }, .pin = 0xFF, .port = NULL }, #endif #if STOP_DISABLE_ENABLE - { .function = Input_StopDisable, .aux_port = 0xFF, .irq_mode = IRQ_Mode_Change, .cap = { .stop_disable = On }, .pin = 0xFF, .port = NULL }, + { .function = Input_StopDisable, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_Change, .cap = { .stop_disable = On }, .pin = 0xFF, .port = NULL }, #endif #if BLOCK_DELETE_ENABLE - { .function = Input_BlockDelete, .aux_port = 0xFF, .irq_mode = IRQ_Mode_Change, .cap = { .block_delete = On }, .pin = 0xFF, .port = NULL }, + { .function = Input_BlockDelete, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_Change, .cap = { .block_delete = On }, .pin = 0xFF, .port = NULL }, #endif #if SINGLE_BLOCK_ENABLE - { .function = Input_SingleBlock, .aux_port = 0xFF, .irq_mode = IRQ_Mode_Change, .cap = { .single_block = On }, .pin = 0xFF, .port = NULL }, + { .function = Input_SingleBlock, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_Change, .cap = { .single_block = On }, .pin = 0xFF, .port = NULL }, #endif #if PROBE_DISCONNECT_ENABLE - { .function = Input_ProbeDisconnect, .aux_port = 0xFF, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .probe_disconnected = On }, .pin = 0xFF, .port = NULL }, + { .function = Input_ProbeDisconnect, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .probe_disconnected = On }, .pin = 0xFF, .port = NULL }, #endif }; +static inline bool aux_ctrl_is_probe (pin_function_t function) +{ + return function == Input_Probe || function == Input_Probe2 || function == Input_Toolsetter; +} + +#ifdef STM32_PLATFORM + +static inline aux_ctrl_t *aux_ctrl_get_fn (void *port, uint8_t pin) +{ + aux_ctrl_t *ctrl_pin = NULL; + + if(sizeof(aux_ctrl) / sizeof(aux_ctrl_t)) { + uint_fast8_t idx; + for(idx = 0; ctrl_pin == NULL && aux_ctrl[idx].pin != 0xFF && idx < sizeof(aux_ctrl) / sizeof(aux_ctrl_t); idx++) { + if(aux_ctrl[idx].pin == pin && aux_ctrl[idx].port == port) + ctrl_pin = &aux_ctrl[idx]; + } + } + + return ctrl_pin; +} + +#endif + static inline aux_ctrl_t *aux_ctrl_remap_explicit (void *port, uint8_t pin, uint8_t aux_port, void *input) { aux_ctrl_t *ctrl_pin = NULL; - uint_fast8_t idx = sizeof(aux_ctrl) / sizeof(aux_ctrl_t); + if(sizeof(aux_ctrl) / sizeof(aux_ctrl_t)) { - if(idx) do { - idx--; - if(aux_ctrl[idx].port == port && aux_ctrl[idx].pin == pin) { - ctrl_pin = &aux_ctrl[idx]; - ctrl_pin->aux_port = aux_port; - ctrl_pin->input = input; - } - } while(idx && ctrl_pin == NULL); + uint_fast8_t idx; -#ifdef STM32_PLATFORM - -// "Hack" to downgrade pin IRQ mode if multiple pins are defined for the same IRQ. - - if(ctrl_pin) { - - idx = sizeof(aux_ctrl) / sizeof(aux_ctrl_t); - const control_signals_t main_signals = { .reset = On, .e_stop = On, .feed_hold = On, .cycle_start = On }; - - do { - if(aux_ctrl[--idx].pin == ctrl_pin->pin) { - if(ctrl_pin != &aux_ctrl[idx]) { - if((aux_ctrl[idx].cap.bits & main_signals.bits) || (aux_ctrl[idx].cap.bits && !ctrl_pin->cap.bits)) - ctrl_pin->irq_mode = IRQ_Mode_None; - } else if(ctrl_pin->cap.bits && !(aux_ctrl[idx].cap.bits & main_signals.bits)) - aux_ctrl[idx].irq_mode = IRQ_Mode_None; + for(idx = 0; ctrl_pin == NULL && aux_ctrl[idx].pin != 0xFF && idx < sizeof(aux_ctrl) / sizeof(aux_ctrl_t); idx++) { + if(aux_ctrl[idx].pin == pin && aux_ctrl[idx].port == port) { + ctrl_pin = &aux_ctrl[idx]; + ctrl_pin->aux_port = aux_port; + ctrl_pin->input = input; } - } while(idx); + } } -#endif // STM32_PLATFORM - return ctrl_pin; } @@ -276,7 +282,7 @@ static inline void aux_ctrl_irq_enable (settings_t *settings, ioport_interrupt_c if(idx) do { if(aux_ctrl[--idx].aux_port != 0xFF && aux_ctrl[idx].irq_mode != IRQ_Mode_None) { - if(!(aux_ctrl[idx].function == Input_Probe || aux_ctrl[idx].function == Input_Probe2 || aux_ctrl[idx].function == Input_Toolsetter)) { + if(!aux_ctrl_is_probe(aux_ctrl[idx].function)) { pin_irq_mode_t irq_mode; if((irq_mode = aux_ctrl[idx].irq_mode) & IRQ_Mode_RisingFalling) irq_mode = (settings->control_invert.mask & aux_ctrl[idx].cap.mask) ? IRQ_Mode_Falling : IRQ_Mode_Rising; @@ -293,7 +299,7 @@ static bool aux_ctrl_claim_port (xbar_t *properties, uint8_t port, void *data) if(ioport_claim(Port_Digital, Port_Input, &port, xbar_fn_to_pinname(((aux_ctrl_t *)data)->function))) ((aux_ctrl_t *)data)->aux_port = port; - return ((aux_ctrl_t *)data)->aux_port != 0xFF; + return ((aux_ctrl_t *)data)->aux_port != IOPORT_UNASSIGNED; } static bool aux_ctrl_find_port (xbar_t *properties, uint8_t port, void *data) @@ -323,7 +329,7 @@ static inline void aux_ctrl_claim_ports (aux_claim_explicit_ptr aux_claim_explic if(aux_ctrl[idx].pin == 0xFF) { if(ioports_enumerate(Port_Digital, Port_Input, cap, aux_claim, (void *)&aux_ctrl[idx])) hal.signals_cap.mask |= aux_ctrl[idx].cap.mask; - } else if(aux_ctrl[idx].aux_port != 0xFF) + } else if(aux_ctrl[idx].aux_port != IOPORT_UNASSIGNED) aux_claim_explicit(&aux_ctrl[idx]); } } @@ -337,7 +343,7 @@ static inline control_signals_t aux_ctrl_scan_status (control_signals_t signals) if(idx) do { if(aux_ctrl[--idx].pin != 0xFF) break; - if(aux_ctrl[idx].aux_port != 0xFF) { + if(aux_ctrl[idx].aux_port != IOPORT_UNASSIGNED) { signals.mask &= ~aux_ctrl[idx].cap.mask; #ifdef GRBL_ESP32 // Snowflake guru workaround if(hal.port.wait_on_input(Port_Digital, aux_ctrl[idx].aux_port, WaitMode_Immediate, FZERO) == 1) @@ -358,99 +364,111 @@ static inline control_signals_t aux_ctrl_scan_status (control_signals_t signals) static aux_ctrl_out_t aux_ctrl_out[] = { #if defined(ESP_PLATFORM) || defined(RP2040) // for now #if defined(STEPPERS_ENABLE_PIN) && STEPPERS_ENABLE_PORT == EXPANDER_PORT - { .function = Output_StepperEnable, .aux_port = 0xFF, .pin = STEPPERS_ENABLE_PIN, .port = (void *)STEPPERS_ENABLE_PORT }, + { .function = Output_StepperEnable, .aux_port = IOPORT_UNASSIGNED, .pin = STEPPERS_ENABLE_PIN, .port = (void *)STEPPERS_ENABLE_PORT }, #endif #if defined(X_ENABLE_PIN) && X_ENABLE_PORT == EXPANDER_PORT - { .function = Output_StepperEnableX, .aux_port = 0xFF, .pin = X_ENABLE_PIN, .port = (void *)X_ENABLE_PORT }, + { .function = Output_StepperEnableX, .aux_port = IOPORT_UNASSIGNED, .pin = X_ENABLE_PIN, .port = (void *)X_ENABLE_PORT }, #endif #if defined(X2_ENABLE_PIN) && X2_ENABLE_PORT == EXPANDER_PORT - { .function = Output_StepperEnableX2, .aux_port = 0xFF, .pin = X2_ENABLE_PIN, .port = (void *)X2_ENABLE_PORT }, + { .function = Output_StepperEnableX2, .aux_port = IOPORT_UNASSIGNED, .pin = X2_ENABLE_PIN, .port = (void *)X2_ENABLE_PORT }, #endif #if defined(Y_ENABLE_PIN) && Y_ENABLE_PORT == EXPANDER_PORT - { .function = Output_StepperEnableY, .aux_port = 0xFF, .pin = Y_ENABLE_PIN, .port = (void *)Y_ENABLE_PORT }, + { .function = Output_StepperEnableY, .aux_port = IOPORT_UNASSIGNED, .pin = Y_ENABLE_PIN, .port = (void *)Y_ENABLE_PORT }, #endif #if defined(Y2_ENABLE_PIN) && Y2_ENABLE_PORT == EXPANDER_PORT - { .function = Output_StepperEnableY2, .aux_port = 0xFF, .pin = Y2_ENABLE_PIN, .port = (void *)Y2_ENABLE_PORT }, + { .function = Output_StepperEnableY2, .aux_port = IOPORT_UNASSIGNED, .pin = Y2_ENABLE_PIN, .port = (void *)Y2_ENABLE_PORT }, #endif #if defined(XY_ENABLE_PIN) && XY_ENABLE_PORT == EXPANDER_PORT - { .function = Output_StepperEnableXY, .aux_port = 0xFF, .pin = XY_ENABLE_PIN, .port = (void *)XY_ENABLE_PORT }, + { .function = Output_StepperEnableXY, .aux_port = IOPORT_UNASSIGNED, .pin = XY_ENABLE_PIN, .port = (void *)XY_ENABLE_PORT }, #endif #if defined(Z_ENABLE_PIN) && Z_ENABLE_PORT == EXPANDER_PORT - { .function = Output_StepperEnableZ, .aux_port = 0xFF, .pin = Z_ENABLE_PIN, .port = (void *)Z_ENABLE_PORT }, + { .function = Output_StepperEnableZ, .aux_port = IOPORT_UNASSIGNED, .pin = Z_ENABLE_PIN, .port = (void *)Z_ENABLE_PORT }, #endif #if defined(Z2_ENABLE_PIN) && Z2_ENABLE_PORT == EXPANDER_PORT - { .function = Output_StepperEnableZ2, .aux_port = 0xFF, .pin = Z2_ENABLE_PIN, .port = (void *)Z2_ENABLE_PORT }, + { .function = Output_StepperEnableZ2, .aux_port = IOPORT_UNASSIGNED, .pin = Z2_ENABLE_PIN, .port = (void *)Z2_ENABLE_PORT }, #endif #if defined(A_ENABLE_PIN) && A_ENABLE_PORT == EXPANDER_PORT - { .function = Output_StepperEnableA, .aux_port = 0xFF, .pin = A_ENABLE_PIN, .port = (void *)A_ENABLE_PORT }, + { .function = Output_StepperEnableA, .aux_port = IOPORT_UNASSIGNED, .pin = A_ENABLE_PIN, .port = (void *)A_ENABLE_PORT }, #endif +#if defined(B_ENABLE_PIN) && B_ENABLE_PORT == EXPANDER_PORT + { .function = Output_StepperEnableB, .aux_port = IOPORT_UNASSIGNED, .pin = B_ENABLE_PIN, .port = (void *)B_ENABLE_PORT }, #endif +#if defined(C_ENABLE_PIN) && C_ENABLE_PORT == EXPANDER_PORT + { .function = Output_StepperEnableC, .aux_port = IOPORT_UNASSIGNED, .pin = C_ENABLE_PIN, .port = (void *)C_ENABLE_PORT }, +#endif +#if defined(U_ENABLE_PIN) && U_ENABLE_PORT == EXPANDER_PORT + { .function = Output_StepperEnableU, .aux_port = IOPORT_UNASSIGNED, .pin = U_ENABLE_PIN, .port = (void *)U_ENABLE_PORT }, +#endif +#if defined(V_ENABLE_PIN) && AV_ENABLE_PORT == EXPANDER_PORT + { .function = Output_StepperEnableV, .aux_port = IOPORT_UNASSIGNED, .pin = V_ENABLE_PIN, .port = (void *)V_ENABLE_PORT }, +#endif +#endif // #ifdef SPINDLE_ENABLE_PIN #ifndef SPINDLE_ENABLE_PORT #define SPINDLE_ENABLE_PORT 0 #endif - { .function = Output_SpindleOn, .aux_port = 0xFF, .pin = SPINDLE_ENABLE_PIN, .port = (void *)SPINDLE_ENABLE_PORT }, + { .function = Output_SpindleOn, .aux_port = IOPORT_UNASSIGNED, .pin = SPINDLE_ENABLE_PIN, .port = (void *)SPINDLE_ENABLE_PORT }, #endif #ifdef SPINDLE_PWM_PIN #ifndef SPINDLE_PWM_PORT #define SPINDLE_PWM_PORT 0 #endif - { .function = Output_SpindlePWM, .aux_port = 0xFF, .pin = SPINDLE_PWM_PIN, .port = (void *)SPINDLE_PWM_PORT }, + { .function = Output_SpindlePWM, .aux_port = IOPORT_UNASSIGNED, .pin = SPINDLE_PWM_PIN, .port = (void *)SPINDLE_PWM_PORT }, #endif #ifdef SPINDLE_DIRECTION_PIN #ifndef SPINDLE_DIRECTION_PORT #define SPINDLE_DIRECTION_PORT 0 #endif - { .function = Output_SpindleDir, .aux_port = 0xFF, .pin = SPINDLE_DIRECTION_PIN, .port = (void *)SPINDLE_DIRECTION_PORT }, + { .function = Output_SpindleDir, .aux_port = IOPORT_UNASSIGNED, .pin = SPINDLE_DIRECTION_PIN, .port = (void *)SPINDLE_DIRECTION_PORT }, #endif #ifdef SPINDLE1_ENABLE_PIN #ifndef SPINDLE1_ENABLE_PORT #define SPINDLE1_ENABLE_PORT 0 #endif - { .function = Output_Spindle1On, .aux_port = 0xFF, .pin = SPINDLE1_ENABLE_PIN, .port = (void *)SPINDLE1_ENABLE_PORT }, + { .function = Output_Spindle1On, .aux_port = IOPORT_UNASSIGNED, .pin = SPINDLE1_ENABLE_PIN, .port = (void *)SPINDLE1_ENABLE_PORT }, #endif #ifdef SPINDLE1_PWM_PIN #ifndef SPINDLE1_PWM_PORT #define SPINDLE1_PWM_PORT 0 #endif - { .function = Output_Spindle1PWM, .aux_port = 0xFF, .pin = SPINDLE1_PWM_PIN, .port = (void *)SPINDLE1_PWM_PORT }, + { .function = Output_Spindle1PWM, .aux_port = IOPORT_UNASSIGNED, .pin = SPINDLE1_PWM_PIN, .port = (void *)SPINDLE1_PWM_PORT }, #endif #ifdef SPINDLE1_DIRECTION_PIN #ifndef SPINDLE1_DIRECTION_PORT #define SPINDLE1_DIRECTION_PORT 0 #endif - { .function = Output_Spindle1Dir, .aux_port = 0xFF, .pin = SPINDLE1_DIRECTION_PIN, .port = (void *)SPINDLE1_DIRECTION_PORT }, + { .function = Output_Spindle1Dir, .aux_port = IOPORT_UNASSIGNED, .pin = SPINDLE1_DIRECTION_PIN, .port = (void *)SPINDLE1_DIRECTION_PORT }, #endif #ifdef COOLANT_FLOOD_PIN #ifndef COOLANT_FLOOD_PORT #define COOLANT_FLOOD_PORT 0 #endif - { .function = Output_CoolantFlood, .aux_port = 0xFF, .pin = COOLANT_FLOOD_PIN, .port = (void *)COOLANT_FLOOD_PORT }, + { .function = Output_CoolantFlood, .aux_port = IOPORT_UNASSIGNED, .pin = COOLANT_FLOOD_PIN, .port = (void *)COOLANT_FLOOD_PORT }, #endif #ifdef COOLANT_MIST_PIN #ifndef COOLANT_MIST_PORT #define COOLANT_MIST_PORT 0 #endif - { .function = Output_CoolantMist, .aux_port = 0xFF, .pin = COOLANT_MIST_PIN, .port = (void *)COOLANT_MIST_PORT }, + { .function = Output_CoolantMist, .aux_port = IOPORT_UNASSIGNED, .pin = COOLANT_MIST_PIN, .port = (void *)COOLANT_MIST_PORT }, #endif #ifdef COPROC_RESET_PIN #ifndef COPROC_RESET_PORT #define COPROC_RESET_PORT 0 #endif - { .function = Output_CoProc_Reset, .aux_port = 0xFF, .pin = COPROC_RESET_PIN, .port = (void *)COPROC_RESET_PORT }, + { .function = Output_CoProc_Reset, .aux_port = IOPORT_UNASSIGNED, .pin = COPROC_RESET_PIN, .port = (void *)COPROC_RESET_PORT }, #endif #ifdef COPROC_BOOT0_PIN #ifndef COPROC_BOOT0_PORT #define COPROC_BOOT0_PORT 0 #endif - { .function = Output_CoProc_Boot0, .aux_port = 0xFF, .pin = COPROC_BOOT0_PIN, .port = (void *)COPROC_BOOT0_PORT }, + { .function = Output_CoProc_Boot0, .aux_port = IOPORT_UNASSIGNED, .pin = COPROC_BOOT0_PIN, .port = (void *)COPROC_BOOT0_PORT }, #endif #if defined(SPI_RST_PIN) && defined(RP2040) #if SPI_RST_PORT == EXPANDER_PORT - { .function = Output_SPIRST, .aux_port = 0xFF, .pin = SPI_RST_PIN, .port = (void *)SPI_RST_PORT }, + { .function = Output_SPIRST, .aux_port = IOPORT_UNASSIGNED, .pin = SPI_RST_PIN, .port = (void *)SPI_RST_PORT }, #endif #endif };