Browse Source

🩹 Fix STM32 CPU serial UUID (#26715)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
ellensp 1 year ago
parent
commit
624226c91d

+ 0 - 4
Marlin/src/core/language.h

@@ -89,10 +89,6 @@
   #define MACHINE_NAME DEFAULT_MACHINE_NAME
 #endif
 
-#ifndef MACHINE_UUID
-  #define MACHINE_UUID DEFAULT_MACHINE_UUID
-#endif
-
 #define MARLIN_WEBSITE_URL "marlinfw.org"
 
 //#if !defined(STRING_SPLASH_LINE3) && defined(WEBSITE_URL)

+ 23 - 15
Marlin/src/gcode/host/M115.cpp

@@ -35,7 +35,7 @@
   #include "../../feature/caselight.h"
 #endif
 
-#if ENABLED(HAS_STM32_UID) && !defined(MACHINE_UUID)
+#if !defined(MACHINE_UUID) && HAS_STM32_UID
   #include "../../libs/hex_print.h"
 #endif
 
@@ -62,6 +62,7 @@
  *       at https://reprap.org/wiki/Firmware_Capabilities_Protocol
  */
 void GcodeSuite::M115() {
+
   SERIAL_ECHOPGM("FIRMWARE_NAME:Marlin"
     " " DETAILED_BUILD_VERSION " (" __DATE__ " " __TIME__ ")"
     " SOURCE_CODE_URL:" SOURCE_CODE_URL
@@ -71,24 +72,31 @@ void GcodeSuite::M115() {
     #if NUM_AXES != XYZ
       " AXIS_COUNT:" STRINGIFY(NUM_AXES)
     #endif
+    #if defined(MACHINE_UUID) || HAS_STM32_UID
+      " UUID:"
+    #endif
     #ifdef MACHINE_UUID
-      " UUID:" MACHINE_UUID
+      MACHINE_UUID
     #endif
   );
 
-  // STM32UID:111122223333
-  #if ENABLED(HAS_STM32_UID) && !defined(MACHINE_UUID)
-    // STM32 based devices output the CPU device serial number
-    // Used by LumenPnP / OpenPNP to keep track of unique hardware/configurations
-    // https://github.com/opulo-inc/lumenpnp
-    // Although this code should work on all STM32 based boards
-    SERIAL_ECHOPGM(" UUID:");
-    uint32_t *uid_address = (uint32_t*)UID_BASE;
-    for (uint8_t i = 0; i < 3; ++i) {
-      const uint32_t UID = uint32_t(READ_REG(*(uid_address)));
-      uid_address += 4U;
-      for (int B = 24; B >= 0; B -= 8) print_hex_byte(UID >> B);
-    }
+  #if !defined(MACHINE_UUID) && HAS_STM32_UID
+    /**
+     * STM32-based devices have a 96-bit CPU device serial number.
+     * Used by LumenPnP / OpenPNP to keep track of unique hardware/configurations.
+     * https://github.com/opulo-inc/lumenpnp
+     * This code should work on all STM32-based boards.
+     */
+    #if ENABLED(STM32_UID_SHORT_FORM)
+      uint32_t * const UID = (uint32_t*)UID_BASE;
+      SERIAL_ECHO(hex_long(UID[0]), hex_long(UID[1]), hex_long(UID[2]));
+    #else
+      uint16_t * const UID = (uint16_t*)UID_BASE;
+      SERIAL_ECHO(
+        F("CEDE2A2F-"), hex_word(UID[0]), '-', hex_word(UID[1]), '-', hex_word(UID[2]), '-',
+        hex_word(UID[3]), hex_word(UID[4]), hex_word(UID[5])
+      );
+    #endif
   #endif
 
   SERIAL_EOL();

+ 0 - 5
Marlin/src/inc/Conditionals_adv.h

@@ -1243,11 +1243,6 @@
   #define NO_EEPROM_SELECTED 1
 #endif
 
-// Flag whether hex_print.cpp is used
-#if ANY(AUTO_BED_LEVELING_UBL, M100_FREE_MEMORY_WATCHER, DEBUG_GCODE_PARSER, TMC_DEBUG, MARLIN_DEV_MODE, DEBUG_CARDREADER, M20_TIMESTAMP_SUPPORT)
-  #define NEED_HEX_PRINT 1
-#endif
-
 // Flags for Case Light having a color property or a single pin
 #if ENABLED(CASE_LIGHT_ENABLE)
   #if ANY(CASE_LIGHT_USE_NEOPIXEL, CASE_LIGHT_USE_RGB_LED)

+ 12 - 0
Marlin/src/inc/Conditionals_post.h

@@ -3417,3 +3417,15 @@
     FIL_RUNOUT5_PULLDOWN, FIL_RUNOUT6_PULLDOWN, FIL_RUNOUT7_PULLDOWN, FIL_RUNOUT8_PULLDOWN)
   #define USING_PULLDOWNS 1
 #endif
+
+// Machine UUID can come from STM32 CPU Serial Number
+#ifdef MACHINE_UUID
+  #undef HAS_STM32_UID
+#elif !HAS_STM32_UID && defined(DEFAULT_MACHINE_UUID)
+  #define MACHINE_UUID DEFAULT_MACHINE_UUID
+#endif
+
+// Flag whether hex_print.cpp is needed
+#if ANY(AUTO_BED_LEVELING_UBL, M100_FREE_MEMORY_WATCHER, DEBUG_GCODE_PARSER, TMC_DEBUG, MARLIN_DEV_MODE, DEBUG_CARDREADER, M20_TIMESTAMP_SUPPORT, HAS_STM32_UID)
+  #define NEED_HEX_PRINT 1
+#endif

+ 14 - 16
Marlin/src/libs/hex_print.cpp

@@ -20,7 +20,7 @@
  *
  */
 
-#include "../inc/MarlinConfigPre.h"
+#include "../inc/MarlinConfig.h"
 
 #if NEED_HEX_PRINT
 
@@ -41,28 +41,26 @@ char* hex_byte(const uint8_t b) {
   return &_hex[byte_start + 4];
 }
 
-inline void _hex_word(const uint16_t w) {
+inline void __hex_word(const uint16_t w) {
   _hex[byte_start + 2] = hex_nybble(w >> 12);
   _hex[byte_start + 3] = hex_nybble(w >> 8);
   _hex[byte_start + 4] = hex_nybble(w >> 4);
   _hex[byte_start + 5] = hex_nybble(w);
 }
 
-char* hex_word(const uint16_t w) {
-  _hex_word(w);
+char* _hex_word(const uint16_t w) {
+  __hex_word(w);
   return &_hex[byte_start + 2];
 }
 
-#ifdef CPU_32_BIT
-  char* hex_long(const uintptr_t l) {
-    _hex[2] = hex_nybble(l >> 28);
-    _hex[3] = hex_nybble(l >> 24);
-    _hex[4] = hex_nybble(l >> 20);
-    _hex[5] = hex_nybble(l >> 16);
-    _hex_word((uint16_t)(l & 0xFFFF));
-    return &_hex[2];
-  }
-#endif
+char* _hex_long(const uintptr_t l) {
+  _hex[2] = hex_nybble(l >> 28);
+  _hex[3] = hex_nybble(l >> 24);
+  _hex[4] = hex_nybble(l >> 20);
+  _hex[5] = hex_nybble(l >> 16);
+  __hex_word((uint16_t)(l & 0xFFFF));
+  return &_hex[2];
+}
 
 char* hex_address(const void * const w) {
   #ifdef CPU_32_BIT
@@ -78,11 +76,11 @@ void print_hex_byte(const uint8_t b)         { SERIAL_ECHO(hex_byte(b));    }
 void print_hex_word(const uint16_t w)        { SERIAL_ECHO(hex_word(w));    }
 void print_hex_address(const void * const w) { SERIAL_ECHO(hex_address(w)); }
 
-void print_hex_long(const uint32_t w, const char delimiter) {
+void print_hex_long(const uint32_t w, const char delimiter/*='\0'*/) {
   SERIAL_ECHOPGM("0x");
   for (int B = 24; B >= 8; B -= 8) {
     print_hex_byte(w >> B);
-    SERIAL_CHAR(delimiter);
+    if (delimiter) SERIAL_CHAR(delimiter);
   }
   print_hex_byte(w);
 }

+ 6 - 2
Marlin/src/libs/hex_print.h

@@ -31,11 +31,15 @@ constexpr char hex_nybble(const uint8_t n) {
   return (n & 0xF) + ((n & 0xF) < 10 ? '0' : 'A' - 10);
 }
 char* hex_byte(const uint8_t b);
-char* hex_word(const uint16_t w);
+char* _hex_word(const uint16_t w);
 char* hex_address(const void * const w);
+char* _hex_long(const uintptr_t l);
+
+template<typename T> char* hex_word(T w) { return hex_word((uint16_t)w); }
+template<typename T> char* hex_long(T w) { return hex_long((uint32_t)w); }
 
 void print_hex_nybble(const uint8_t n);
 void print_hex_byte(const uint8_t b);
 void print_hex_word(const uint16_t w);
 void print_hex_address(const void * const w);
-void print_hex_long(const uint32_t w, const char delimiter);
+void print_hex_long(const uint32_t w, const char delimiter='\0');

+ 3 - 1
Marlin/src/pins/stm32f4/pins_OPULO_LUMEN_REV3.h

@@ -44,8 +44,10 @@
 
 // I2C MCP3426 (16-Bit, 240SPS, dual-channel ADC)
 #define HAS_MCP3426_ADC
+
+// Opulo Lumen uses the CPU serial number
 #ifdef STM32F4
-  #define HAS_STM32_UID
+  #define HAS_STM32_UID                        1
 #endif
 
 //

+ 5 - 0
Marlin/src/pins/stm32f4/pins_OPULO_LUMEN_REV4.h

@@ -45,6 +45,11 @@
 // I2C MCP3426 (16-Bit, 240SPS, dual-channel ADC)
 #define HAS_MCP3426_ADC
 
+// Opulo Lumen uses the CPU serial number
+#ifdef STM32F4
+  #define HAS_STM32_UID                        1
+#endif
+
 //
 // Servos
 //

+ 1 - 0
buildroot/tests/Opulo_Lumen_REV3

@@ -7,6 +7,7 @@
 set -e
 
 use_example_configs Opulo/Lumen_REV3
+opt_disable TMC_DEBUG
 exec_test $1 $2 "Opulo Lumen REV3 Pick-and-Place" "$3"
 
 # cleanup