diff --git a/.github/contributing.md b/.github/contributing.md index 24b9dbdf8d..3113c1847c 100644 --- a/.github/contributing.md +++ b/.github/contributing.md @@ -34,8 +34,11 @@ This project and everyone participating in it is governed by the [Marlin Code of We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions. -* [Marlin RepRap forum](https://reprap.org/forum/list.php?415) -* [MarlinFirmware on Facebook](https://www.facebook.com/groups/1049718498464482/) +- [Marlin Documentation](https://marlinfw.org) - Official Marlin documentation +- Facebook Group ["Marlin Firmware"](https://www.facebook.com/groups/1049718498464482/) +- RepRap.org [Marlin Forum](https://forums.reprap.org/list.php?415) +- Facebook Group ["Marlin Firmware for 3D Printers"](https://www.facebook.com/groups/3Dtechtalk/) +- [Marlin Configuration](https://www.youtube.com/results?search_query=marlin+configuration) on YouTube If chat is more your speed, you can join the MarlinFirmware Discord server: diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index ca071a8460..58c3f2b5ce 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -2426,7 +2426,7 @@ /** * Extra G-code to run while executing tool-change commands. Can be used to use an additional - * stepper motor (I axis, see option LINEAR_AXES in Configuration.h) to drive the tool-changer. + * stepper motor (e.g., I axis in Configuration.h) to drive the tool-changer. */ //#define EVENT_GCODE_TOOLCHANGE_T0 "G28 A\nG1 A0" // Extra G-code to run while executing tool-change command T0 //#define EVENT_GCODE_TOOLCHANGE_T1 "G1 A10" // Extra G-code to run while executing tool-change command T1 diff --git a/Marlin/src/gcode/control/M17_M18_M84.cpp b/Marlin/src/gcode/control/M17_M18_M84.cpp index 2ec350148c..6e0a1b4b71 100644 --- a/Marlin/src/gcode/control/M17_M18_M84.cpp +++ b/Marlin/src/gcode/control/M17_M18_M84.cpp @@ -91,7 +91,7 @@ void do_enable(const stepper_flags_t to_enable) { if ((also_enabled &= ~(shall_enable | was_enabled))) { SERIAL_CHAR('('); - LOOP_LINEAR_AXES(a) if (TEST(also_enabled, a)) SERIAL_CHAR(axis_codes[a], ' '); + LOOP_LINEAR_AXES(a) if (TEST(also_enabled, a)) SERIAL_CHAR(AXIS_CHAR(a), ' '); #if HAS_EXTRUDERS #define _EN_ALSO(N) if (TEST(also_enabled, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR('E', '0' + N, ' '); REPEAT(EXTRUDERS, _EN_ALSO) diff --git a/Marlin/src/gcode/feature/trinamic/M569.cpp b/Marlin/src/gcode/feature/trinamic/M569.cpp index ba4e439854..9c5b8afd01 100644 --- a/Marlin/src/gcode/feature/trinamic/M569.cpp +++ b/Marlin/src/gcode/feature/trinamic/M569.cpp @@ -186,7 +186,6 @@ void GcodeSuite::M569_report(const bool forReplay/*=true*/) { if (TERN0(Z3_HAS_STEALTHCHOP, stepperZ3.get_stored_stealthChop())) { say_M569(forReplay, F("I2 Z"), true); } if (TERN0(Z4_HAS_STEALTHCHOP, stepperZ4.get_stored_stealthChop())) { say_M569(forReplay, F("I3 Z"), true); } - #if HAS_I_AXIS if (TERN0(I_HAS_STEALTHCHOP, stepperI.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_I_STR), true); } #endif diff --git a/Marlin/src/gcode/geometry/M206_M428.cpp b/Marlin/src/gcode/geometry/M206_M428.cpp index 726fc53ec1..d3fbaf5dc0 100644 --- a/Marlin/src/gcode/geometry/M206_M428.cpp +++ b/Marlin/src/gcode/geometry/M206_M428.cpp @@ -39,10 +39,8 @@ */ void GcodeSuite::M206() { if (!parser.seen_any()) return M206_report(); - LOOP_LINEAR_AXES(a) if (parser.seenval(AXIS_CHAR(a))) set_home_offset((AxisEnum)a, parser.value_axis_units((AxisEnum)a)); - #if ENABLED(MORGAN_SCARA) if (parser.seenval('T')) set_home_offset(A_AXIS, parser.value_float()); // Theta if (parser.seenval('P')) set_home_offset(B_AXIS, parser.value_float()); // Psi diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h index f97f9005da..5e7675112b 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -824,7 +824,7 @@ * Number of Primary Linear Axes (e.g., XYZ) * X, XY, or XYZ axes. Excluding duplicate axes (X2, Y2. Z2. Z3, Z4) */ -#if HAS_I_AXIS +#if LINEAR_AXES >= 3 #define PRIMARY_LINEAR_AXES 3 #else #define PRIMARY_LINEAR_AXES LINEAR_AXES @@ -961,7 +961,7 @@ #endif /** - * Set a flag for any type of bed probe, including the paper-test + * Set flags for any form of bed probe */ #if ANY(HAS_Z_SERVO_PROBE, FIX_MOUNTED_PROBE, NOZZLE_AS_PROBE, TOUCH_MI_PROBE, Z_PROBE_ALLEN_KEY, Z_PROBE_SLED, SOLENOID_PROBE, SENSORLESS_PROBING, RACK_AND_PINION_PROBE, MAGLEV4) #define HAS_BED_PROBE 1 @@ -1284,29 +1284,6 @@ #define HAS_ETHERNET 1 #endif -// Fallback axis inverting -#ifndef INVERT_X_DIR - #define INVERT_X_DIR false -#endif -#if HAS_Y_AXIS && !defined(INVERT_Y_DIR) - #define INVERT_Y_DIR false -#endif -#if HAS_Z_AXIS && !defined(INVERT_Z_DIR) - #define INVERT_Z_DIR false -#endif -#if HAS_I_AXIS && !defined(INVERT_I_DIR) - #define INVERT_I_DIR false -#endif -#if HAS_J_AXIS && !defined(INVERT_J_DIR) - #define INVERT_J_DIR false -#endif -#if HAS_K_AXIS && !defined(INVERT_K_DIR) - #define INVERT_K_DIR false -#endif -#if HAS_EXTRUDERS && !defined(INVERT_E_DIR) - #define INVERT_E_DIR false -#endif - /** * This setting is also used by M109 when trying to calculate * a ballpark safe margin to prevent wait-forever situation. diff --git a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp index d8306dbf94..b8dc8db817 100644 --- a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp +++ b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp @@ -120,10 +120,11 @@ static void createChar_P(const char c, const byte * const ptr) { #endif #if ENABLED(LCD_USE_I2C_BUZZER) + void MarlinUI::buzz(const long duration, const uint16_t freq) { - if (!sound_on) return; - lcd.buzz(duration, freq); + if (sound_on) lcd.buzz(duration, freq); } + #endif void MarlinUI::set_custom_characters(const HD44780CharSet screen_charset/*=CHARSET_INFO*/) { diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index ec37a77933..945911fe00 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -44,7 +44,7 @@ extern xyze_pos_t current_position, // High-level current tool position // G60/G61 Position Save and Return #if SAVED_POSITIONS - extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for LINEAR_AXES >= 4 + extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for HAS_I_AXIS extern xyze_pos_t stored_position[SAVED_POSITIONS]; #endif diff --git a/Marlin/src/pins/pins.h b/Marlin/src/pins/pins.h index 9c31824b31..38e73ad398 100644 --- a/Marlin/src/pins/pins.h +++ b/Marlin/src/pins/pins.h @@ -877,7 +877,6 @@ #undef BOARD_STM32F103R #undef BOARD_ESP32 #undef BOARD_STEVAL - #undef BOARD_BIGTREE_SKR_MINI_E3 #undef BOARD_BIGTREE_SKR_V1_1 #undef BOARD_BIGTREE_SKR_V1_3 #undef BOARD_BIGTREE_SKR_V1_4 @@ -885,6 +884,7 @@ #undef BOARD_BIGTREE_BTT002_V1_0 #undef BOARD_BIGTREE_SKR_PRO_V1_1 #undef BOARD_BIGTREE_SKR_MINI_V1_1 + #undef BOARD_BIGTREE_SKR_MINI_E3 #undef BOARD_BIGTREE_SKR_E3_DIP #undef BOARD_RUMBA32 #undef BOARD_RUMBA32_AUS3D diff --git a/Marlin/src/pins/ramps/pins_RAMPS.h b/Marlin/src/pins/ramps/pins_RAMPS.h index 6805c76337..353b5f3cc3 100644 --- a/Marlin/src/pins/ramps/pins_RAMPS.h +++ b/Marlin/src/pins/ramps/pins_RAMPS.h @@ -272,7 +272,9 @@ #if HAS_CUTTER && !defined(SPINDLE_LASER_ENA_PIN) #if NUM_SERVOS < 2 // Use servo connector if possible #define SPINDLE_LASER_ENA_PIN 4 // Pullup or pulldown! - #define SPINDLE_LASER_PWM_PIN 6 // Hardware PWM + #ifndef SPINDLE_LASER_PWM_PIN + #define SPINDLE_LASER_PWM_PIN 6 // Hardware PWM + #endif #define SPINDLE_DIR_PIN 5 #elif HAS_FREE_AUX2_PINS #define SPINDLE_LASER_ENA_PIN 40 // Pullup or pulldown! diff --git a/Marlin/src/pins/stm32f4/pins_ANET_ET4.h b/Marlin/src/pins/stm32f4/pins_ANET_ET4.h index 7816e5e505..01ca4560fe 100644 --- a/Marlin/src/pins/stm32f4/pins_ANET_ET4.h +++ b/Marlin/src/pins/stm32f4/pins_ANET_ET4.h @@ -64,7 +64,7 @@ // Z Probe // #if ENABLED(BLTOUCH) - #error "You will need to use 24V to 5V converter and remove one resistor and capacitor from the motherboard. See https://github.com/davidtgbe/Marlin/blob/bugfix-2.0.x/docs/Tutorials/bltouch-en.md for more information. Comment out this line to proceed at your own risk." + #error "You will need to use 24V to 5V converter and remove one resistor and capacitor from the motherboard. See https://bit.ly/3xg9cXO for more information. Comment out this line to proceed at your own risk." #define SERVO0_PIN PC3 #elif !defined(Z_MIN_PROBE_PIN) #define Z_MIN_PROBE_PIN PC3 diff --git a/README.md b/README.md index 6b7d7ab18e..6db420d9d4 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Regular users can open and close their own issues, but only the administrators c - Scott Lahteine [[@thinkyhead](https://github.com/thinkyhead)] - USA - Project Maintainer   [💸 Donate](https://www.thinkyhead.com/donate-to-marlin) - Roxanne Neufeld [[@Roxy-3D](https://github.com/Roxy-3D)] - USA - Keith Bennett [[@thisiskeithb](https://github.com/thisiskeithb)] - USA   [💸 Donate](https://github.com/sponsors/thisiskeithb) - - Peter Ellens [[@ellensp](https://github.com/ellensp)] - New Zealand + - Peter Ellens [[@ellensp](https://github.com/ellensp)] - New Zealand   [💸 Donate](https://ko-fi.com/ellensp) - Victor Oliveira [[@rhapsodyv](https://github.com/rhapsodyv)] - Brazil - Chris Pepper [[@p3p](https://github.com/p3p)] - UK - Jason Smith [[@sjasonsmith](https://github.com/sjasonsmith)] - USA diff --git a/buildroot/bin/use_example_configs b/buildroot/bin/use_example_configs index de2edc2468..ce9ca658ec 100755 --- a/buildroot/bin/use_example_configs +++ b/buildroot/bin/use_example_configs @@ -13,9 +13,7 @@ which curl >/dev/null && TOOL='curl -L -s -S -f -o wgot' which wget >/dev/null && TOOL='wget -q -O wgot' CURR=$(git branch 2>/dev/null | grep ^* | sed 's/\* //g') -[[ $CURR == "bugfix-2.0.x" ]] && BRANCH=bugfix-2.0.x || BRANCH=bugfix-2.1.x - -REPO=$BRANCH +REPO=bugfix-2.0.x if [[ $# > 0 ]]; then IFS=: read -r PART1 PART2 <<< "$@" diff --git a/buildroot/share/PlatformIO/scripts/common-dependencies.py b/buildroot/share/PlatformIO/scripts/common-dependencies.py index 3edbaf043e..4b986274ee 100644 --- a/buildroot/share/PlatformIO/scripts/common-dependencies.py +++ b/buildroot/share/PlatformIO/scripts/common-dependencies.py @@ -70,10 +70,9 @@ if pioutil.is_pio_build(): feat['lib_deps'] = list(filter(lib_re.match, feat['lib_deps'])) + [dep] blab("[%s] lib_deps = %s" % (feature, dep), 3) - def load_config(): + def load_features(): blab("========== Gather [features] entries...") - items = ProjectConfig().items('features') - for key in items: + for key in ProjectConfig().items('features'): feature = key[0].upper() if not feature in FEATURE_CONFIG: FEATURE_CONFIG[feature] = { 'lib_deps': [] } @@ -81,8 +80,7 @@ if pioutil.is_pio_build(): # Add options matching custom_marlin.MY_OPTION to the pile blab("========== Gather custom_marlin entries...") - all_opts = env.GetProjectOptions() - for n in all_opts: + for n in env.GetProjectOptions(): key = n[0] mat = re.match(r'custom_marlin\.(.+)', key) if mat: @@ -127,10 +125,10 @@ if pioutil.is_pio_build(): set_env_field('lib_ignore', lib_ignore) def apply_features_config(): - load_config() + load_features() blab("========== Apply enabled features...") for feature in FEATURE_CONFIG: - if not env.MarlinFeatureIsEnabled(feature): + if not env.MarlinHas(feature): continue feat = FEATURE_CONFIG[feature] @@ -212,7 +210,7 @@ if pioutil.is_pio_build(): # # Return True if a matching feature is enabled # - def MarlinFeatureIsEnabled(env, feature): + def MarlinHas(env, feature): load_marlin_features() r = re.compile('^' + feature + '$') found = list(filter(r.match, env['MARLIN_FEATURES'])) @@ -225,7 +223,7 @@ if pioutil.is_pio_build(): if val in [ '', '1', 'true' ]: some_on = True elif val in env['MARLIN_FEATURES']: - some_on = env.MarlinFeatureIsEnabled(val) + some_on = env.MarlinHas(val) return some_on @@ -239,7 +237,7 @@ if pioutil.is_pio_build(): # # Add a method for other PIO scripts to query enabled features # - env.AddMethod(MarlinFeatureIsEnabled) + env.AddMethod(MarlinHas) # # Add dependencies for enabled Marlin features diff --git a/buildroot/share/PlatformIO/scripts/fix_framework_weakness.py b/buildroot/share/PlatformIO/scripts/fix_framework_weakness.py index 663e7c76d9..83ed17ccca 100644 --- a/buildroot/share/PlatformIO/scripts/fix_framework_weakness.py +++ b/buildroot/share/PlatformIO/scripts/fix_framework_weakness.py @@ -10,7 +10,7 @@ if pioutil.is_pio_build(): Import("env") - if env.MarlinFeatureIsEnabled("POSTMORTEM_DEBUGGING"): + if env.MarlinHas("POSTMORTEM_DEBUGGING"): FRAMEWORK_DIR = env.PioPlatform().get_package_dir("framework-arduinoststm32-maple") patchflag_path = join(FRAMEWORK_DIR, ".exc-patching-done") diff --git a/buildroot/share/PlatformIO/scripts/pioutil.py b/buildroot/share/PlatformIO/scripts/pioutil.py index b8c1e9cfca..32096dab3f 100644 --- a/buildroot/share/PlatformIO/scripts/pioutil.py +++ b/buildroot/share/PlatformIO/scripts/pioutil.py @@ -4,5 +4,10 @@ # Make sure 'vscode init' is not the current command def is_pio_build(): - from SCons.Script import COMMAND_LINE_TARGETS - return "idedata" not in COMMAND_LINE_TARGETS and "_idedata" not in COMMAND_LINE_TARGETS + from SCons.Script import DefaultEnvironment + env = DefaultEnvironment() + return not env.IsIntegrationDump() + +def get_pio_version(): + from platformio import util + return util.pioversion_to_intstr() diff --git a/buildroot/share/PlatformIO/scripts/preprocessor.py b/buildroot/share/PlatformIO/scripts/preprocessor.py index d9c472006c..d0395cd481 100644 --- a/buildroot/share/PlatformIO/scripts/preprocessor.py +++ b/buildroot/share/PlatformIO/scripts/preprocessor.py @@ -40,7 +40,10 @@ def run_preprocessor(env, fn=None): depcmd = cmd + [ filename ] cmd = ' '.join(depcmd) blab(cmd) - define_list = subprocess.check_output(cmd, shell=True).splitlines() + try: + define_list = subprocess.check_output(cmd, shell=True).splitlines() + except: + define_list = {} preprocessor_cache[filename] = define_list return define_list diff --git a/buildroot/share/git/mfconfig b/buildroot/share/git/mfconfig index d3e0b67b3e..d3fe330340 100755 --- a/buildroot/share/git/mfconfig +++ b/buildroot/share/git/mfconfig @@ -110,53 +110,15 @@ if [[ $ACTION == "init" ]]; then ((COMMIT_STEPS)) && git add . >/dev/null && git commit -m "Commit for comparison" >/dev/null # Init Cartesian/SCARA/TPARA configurations to default - echo "- Initializing Cartesian/SCARA/TPARA configs to default state..." + echo "- Initializing configs to default state..." - find "$CEXA" -name $BC ! -path */delta/* -print0 \ + find "$CEXA" -name $BC -print0 \ | while read -d $'\0' F ; do cp "$CDEF/$BC" "$F" ; done - find "$CEXA" -name $AC ! -path */delta/* -print0 \ + find "$CEXA" -name $AC -print0 \ | while read -d $'\0' F ; do cp "$CDEF/$AC" "$F" ; done # DEBUG: Commit the reset for review - ((COMMIT_STEPS)) && git add . >/dev/null && git commit -m "Reset Cartesian/SCARA/TPARA configs..." >/dev/null - - # Create base Delta configurations - cp "$CDEF"/* "$CEXA/delta/generic" - - # DEBUG: Commit the reset for review - ((COMMIT_STEPS)) && git add . >/dev/null && git commit -m "Reset Generic Delta..." >/dev/null - - cp -R "$TEMP/$CEXA/delta/generic"/Conf* "$CEXA/delta/generic" - - # DEBUG: Commit Generic Delta changes for review - ((COMMIT_STEPS)) && git add . >/dev/null && git commit -m "Apply Generic Delta..." >/dev/null - - # Reset all Delta configs to the generic version - find "$CEXA/delta" -name $BC ! -path */generic/* -print0 \ - | while read -d $'\0' F ; do cp "$CEXA/delta/generic/$BC" "$F" ; done - find "$CEXA/delta" -name $AC ! -path */generic/* -print0 \ - | while read -d $'\0' F ; do cp "$CEXA/delta/generic/$AC" "$F" ; done - - # DEBUG: Commit the Delta reset for review - ((COMMIT_STEPS)) && git add . >/dev/null && git commit -m "Reset Delta configs..." >/dev/null - - # Reset all SCARA configs to the default cartesian - find "$CEXA/SCARA" -name $BC \ - | while read -d $'\0' F ; do cp "$CDEF/$BC" "$F" ; done - find "$CEXA/SCARA" -name $AC \ - | while read -d $'\0' F ; do cp "$CDEF/$AC" "$F" ; done - - # DEBUG: Commit the SCARA reset for review - ((COMMIT_STEPS)) && git add . >/dev/null && git commit -m "Reset SCARA..." >/dev/null - - # Reset all TPARA configs to the default cartesian - find "$CEXA/TPARA" -name $BC \ - | while read -d $'\0' F ; do cp "$CDEF/$BC" "$F" ; done - find "$CEXA/TPARA" -name $AC \ - | while read -d $'\0' F ; do cp "$CDEF/$AC" "$F" ; done - - # DEBUG: Commit the TPARA reset for review - ((COMMIT_STEPS)) && git add . >/dev/null && git commit -m "Reset TPARA..." >/dev/null + ((COMMIT_STEPS)) && git add . >/dev/null && git commit -m "Reset configs..." >/dev/null # Update the %VERSION% in the README.md file VERS=$( echo $EXPORT | $SED 's/release-//' ) diff --git a/buildroot/share/scripts/MarlinBinaryProtocol.py b/buildroot/share/scripts/MarlinBinaryProtocol.py index 4887ad9919..ecf9df35e2 100644 --- a/buildroot/share/scripts/MarlinBinaryProtocol.py +++ b/buildroot/share/scripts/MarlinBinaryProtocol.py @@ -376,11 +376,13 @@ class FileTransferProtocol(object): token, data = self.await_response(1000) if token == 'PFT:success': print("File closed") - return + return True elif token == 'PFT:ioerror': print("Client storage device IO error") + return False elif token == 'PFT:invalid': print("No open file") + return False def abort(self): self.protocol.send(FileTransferProtocol.protocol_id, FileTransferProtocol.Packet.ABORT); @@ -417,12 +419,23 @@ class FileTransferProtocol(object): self.write(data[start:end]) kibs = (( (i+1) * block_size) / 1024) / (millis() + 1 - start_time) * 1000 if (i / blocks) >= dump_pctg: - print("\r{0:2.2f}% {1:4.2f}KiB/s {2} Errors: {3}".format((i / blocks) * 100, kibs, "[{0:4.2f}KiB/s]".format(kibs * cratio) if compression_support else "", self.protocol.errors), end='') + print("\r{0:2.0f}% {1:4.2f}KiB/s {2} Errors: {3}".format((i / blocks) * 100, kibs, "[{0:4.2f}KiB/s]".format(kibs * cratio) if compression_support else "", self.protocol.errors), end='') dump_pctg += 0.1 - print("\r{0:2.2f}% {1:4.2f}KiB/s {2} Errors: {3}".format(100, kibs, "[{0:4.2f}KiB/s]".format(kibs * cratio) if compression_support else "", self.protocol.errors)) # no one likes transfers finishing at 99.8% + if self.protocol.errors > 0: + # Dump last status (errors may not be visible) + print("\r{0:2.0f}% {1:4.2f}KiB/s {2} Errors: {3} - Aborting...".format((i / blocks) * 100, kibs, "[{0:4.2f}KiB/s]".format(kibs * cratio) if compression_support else "", self.protocol.errors), end='') + print("") # New line to break the transfer speed line + self.close() + print("Transfer aborted due to protocol errors") + #raise Exception("Transfer aborted due to protocol errors") + return False; + print("\r{0:2.0f}% {1:4.2f}KiB/s {2} Errors: {3}".format(100, kibs, "[{0:4.2f}KiB/s]".format(kibs * cratio) if compression_support else "", self.protocol.errors)) # no one likes transfers finishing at 99.8% - self.close() + if not self.close(): + print("Transfer failed") + return False print("Transfer complete") + return True class EchoProtocol(object): diff --git a/buildroot/share/scripts/upload.py b/buildroot/share/scripts/upload.py index c93092ec19..52fa1abc54 100644 --- a/buildroot/share/scripts/upload.py +++ b/buildroot/share/scripts/upload.py @@ -20,14 +20,18 @@ Import("env") import MarlinBinaryProtocol -# Internal debug flag -Debug = False - #-----------------# # Upload Callback # #-----------------# def Upload(source, target, env): + #-------# + # Debug # + #-------# + Debug = False # Set to True to enable script debug + def debugPrint(data): + if Debug: print(f"[Debug]: {data}") + #------------------# # Marlin functions # #------------------# @@ -39,19 +43,35 @@ def Upload(source, target, env): # Port functions # #----------------# def _GetUploadPort(env): - if Debug: print('Autodetecting upload port...') + debugPrint('Autodetecting upload port...') env.AutodetectUploadPort(env) - port = env.subst('$UPLOAD_PORT') - if not port: + portName = env.subst('$UPLOAD_PORT') + if not portName: raise Exception('Error detecting the upload port.') - if Debug: print('OK') - return port + debugPrint('OK') + return portName #-------------------------# # Simple serial functions # #-------------------------# + def _OpenPort(): + # Open serial port + if port.is_open: return + debugPrint('Opening upload port...') + port.open() + port.reset_input_buffer() + debugPrint('OK') + + def _ClosePort(): + # Open serial port + if port is None: return + if not port.is_open: return + debugPrint('Closing upload port...') + port.close() + debugPrint('OK') + def _Send(data): - if Debug: print(f'>> {data}') + debugPrint(f'>> {data}') strdata = bytearray(data, 'utf8') + b'\n' port.write(strdata) time.sleep(0.010) @@ -60,7 +80,7 @@ def Upload(source, target, env): clean_responses = [] responses = port.readlines() for Resp in responses: - # Test: suppress invaid chars (coming from debug info) + # Suppress invalid chars (coming from debug info) try: clean_response = Resp.decode('utf8').rstrip().lstrip() clean_responses.append(clean_response) @@ -73,24 +93,24 @@ def Upload(source, target, env): # SDCard functions # #------------------# def _CheckSDCard(): - if Debug: print('Checking SD card...') + debugPrint('Checking SD card...') _Send('M21') Responses = _Recv() if len(Responses) < 1 or not any('SD card ok' in r for r in Responses): raise Exception('Error accessing SD card') - if Debug: print('SD Card OK') + debugPrint('SD Card OK') return True #----------------# # File functions # #----------------# def _GetFirmwareFiles(UseLongFilenames): - if Debug: print('Get firmware files...') + debugPrint('Get firmware files...') _Send(f"M20 F{'L' if UseLongFilenames else ''}") Responses = _Recv() if len(Responses) < 3 or not any('file list' in r for r in Responses): raise Exception('Error getting firmware files') - if Debug: print('OK') + debugPrint('OK') return Responses def _FilterFirmwareFiles(FirmwareList, UseLongFilenames): @@ -114,6 +134,17 @@ def Upload(source, target, env): raise Exception(f"Firmware file '{FirmwareFile}' not removed") return Removed + def _RollbackUpload(FirmwareFile): + if not rollback: return + print(f"Rollback: trying to delete firmware '{FirmwareFile}'...") + _OpenPort() + # Wait for SD card release + time.sleep(1) + # Remount SD card + _CheckSDCard() + print(' OK' if _RemoveFirmwareFile(FirmwareFile) else ' Error!') + _ClosePort() + #---------------------# # Callback Entrypoint # @@ -121,6 +152,7 @@ def Upload(source, target, env): port = None protocol = None filetransfer = None + rollback = False # Get Marlin evironment vars MarlinEnv = env['MARLIN_FEATURES'] @@ -204,9 +236,9 @@ def Upload(source, target, env): if not marlin_custom_firmware_upload: raise Exception(f"CUSTOM_FIRMWARE_UPLOAD must be enabled in 'Configuration_adv.h' for '{marlin_motherboard}'") - # Init serial port + # Init & Open serial port port = serial.Serial(upload_port, baudrate = upload_speed, write_timeout = 0, timeout = 0.1) - port.reset_input_buffer() + _OpenPort() # Check SD card status _CheckSDCard() @@ -228,24 +260,26 @@ def Upload(source, target, env): print(' OK' if _RemoveFirmwareFile(OldFirmwareFile) else ' Error!') # Close serial - port.close() + _ClosePort() # Cleanup completed - if Debug: print('Cleanup completed') + debugPrint('Cleanup completed') # WARNING! The serial port must be closed here because the serial transfer that follow needs it! # Upload firmware file - if Debug: print(f"Copy '{upload_firmware_source_name}' --> '{upload_firmware_target_name}'") + debugPrint(f"Copy '{upload_firmware_source_name}' --> '{upload_firmware_target_name}'") protocol = MarlinBinaryProtocol.Protocol(upload_port, upload_speed, upload_blocksize, float(upload_error_ratio), int(upload_timeout)) #echologger = MarlinBinaryProtocol.EchoProtocol(protocol) protocol.connect() + # Mark the rollback (delete broken transfer) from this point on + rollback = True filetransfer = MarlinBinaryProtocol.FileTransferProtocol(protocol) - filetransfer.copy(upload_firmware_source_name, upload_firmware_target_name, upload_compression, upload_test) + transferOK = filetransfer.copy(upload_firmware_source_name, upload_firmware_target_name, upload_compression, upload_test) protocol.disconnect() # Notify upload completed - protocol.send_ascii('M117 Firmware uploaded') + protocol.send_ascii('M117 Firmware uploaded' if transferOK else 'M117 Firmware upload failed') # Remount SD card print('Wait for SD card release...') @@ -253,34 +287,56 @@ def Upload(source, target, env): print('Remount SD card') protocol.send_ascii('M21') - # Trigger firmware update - if upload_reset: - print('Trigger firmware update...') - protocol.send_ascii('M997', True) + # Transfer failed? + if not transferOK: + protocol.shutdown() + _RollbackUpload(upload_firmware_target_name) + else: + # Trigger firmware update + if upload_reset: + print('Trigger firmware update...') + protocol.send_ascii('M997', True) + protocol.shutdown() - protocol.shutdown() - print('Firmware update completed') + print('Firmware update completed' if transferOK else 'Firmware update failed') + return 0 if transferOK else -1 except KeyboardInterrupt: - if port: port.close() + print('Aborted by user') if filetransfer: filetransfer.abort() - if protocol: protocol.shutdown() + if protocol: + protocol.disconnect() + protocol.shutdown() + _RollbackUpload(upload_firmware_target_name) + _ClosePort() raise except serial.SerialException as se: - if port: port.close() - print(f'Serial excepion: {se}') + # This exception is raised only for send_ascii data (not for binary transfer) + print(f'Serial excepion: {se}, transfer aborted') + if protocol: + protocol.disconnect() + protocol.shutdown() + _RollbackUpload(upload_firmware_target_name) + _ClosePort() raise Exception(se) except MarlinBinaryProtocol.FatalError: - if port: port.close() - if protocol: protocol.shutdown() - print('Too many retries, Abort') + print('Too many retries, transfer aborted') + if protocol: + protocol.disconnect() + protocol.shutdown() + _RollbackUpload(upload_firmware_target_name) + _ClosePort() raise - except: - if port: port.close() - if protocol: protocol.shutdown() + except Exception as ex: + print(f"\nException: {ex}, transfer aborted") + if protocol: + protocol.disconnect() + protocol.shutdown() + _RollbackUpload(upload_firmware_target_name) + _ClosePort() print('Firmware not updated') raise diff --git a/docs/ConfigEmbedding.md b/docs/ConfigEmbedding.md index ed4ea39eda..90075bc373 100644 --- a/docs/ConfigEmbedding.md +++ b/docs/ConfigEmbedding.md @@ -1,9 +1,9 @@ # Configuration Embedding -Starting with version 2.0.9.3, Marlin automatically extracts the configuration used to generate the firmware and stores it in the firmware binary. This is enabled by defining `CONFIGURATION_EMBEDDING` in `Configuration_adv.h`. +Starting with version 2.0.9.3, Marlin can automatically extract the configuration used to generate the firmware and store it in the firmware binary. This is enabled by defining `CONFIGURATION_EMBEDDING` in `Configuration_adv.h`. ## How it's done -To create the embedded configuration, we do a compiler pass to process the Configuration files and extract all active options. The active options are parsed into key/value pairs, serialized to JSON format, and stored in a file called `marlin_config.json`, which also includes specific build information (like the git revision, the build date, and some version information. The JSON file is then compressed in a ZIP archive called `.pio/build/mc.zip` which is converted into a C array and stored in a C++ file called `mc.h` which is included in the build. +At the start of the PlatformIO build process, we create an embedded configuration by extracting all active options from the Configuration files and writing them out as JSON to `marlin_config.json`, which also includes specific build information (like the git revision, the build date, and some version information. The JSON file is then compressed in a ZIP archive called `.pio/build/mc.zip` which is converted into a C array and stored in a C++ file called `mc.h` which is included in the build. ## Extracting configurations from a Marlin binary To get the configuration out of a binary firmware, you'll need a non-write-protected SD card inserted into the printer while running the firmware. diff --git a/ini/esp32.ini b/ini/esp32.ini index 05b045f16e..4f5cd27c29 100644 --- a/ini/esp32.ini +++ b/ini/esp32.ini @@ -28,13 +28,13 @@ extends = env:esp32 board_build.partitions = default_16MB.csv [env:PANDA] -extends = env:esp32 -build_flags = ${env:esp32.build_flags} -DUSE_ESP32_EXIO -DUSE_ESP32_TASK_WDT -lib_deps = ${common.lib_deps} - SoftwareSerialEsp32 +extends = env:esp32 +build_flags = ${env:esp32.build_flags} -DUSE_ESP32_EXIO -DUSE_ESP32_TASK_WDT +lib_deps = ${common.lib_deps} + SoftwareSerialEsp32 board_build.partitions = Marlin/src/HAL/ESP32/esp32.csv -upload_speed = 115200 -monitor_speed = 115200 +upload_speed = 115200 +monitor_speed = 115200 [env:mks_tinybee] extends = env:esp32 diff --git a/ini/features.ini b/ini/features.ini index 355544029e..38d01a9ee4 100644 --- a/ini/features.ini +++ b/ini/features.ini @@ -239,5 +239,5 @@ HAS_MICROSTEPS = src_filter=+