Преглед на файлове

Improve STM32F4 Flash Behavior (#17946)

Jason Smith преди 5 години
родител
ревизия
25aade1cf1
No account linked to committer's email address
променени са 4 файла, в които са добавени 87 реда и са изтрити 13 реда
  1. 36
    6
      Marlin/src/HAL/STM32/Servo.cpp
  2. 15
    3
      Marlin/src/HAL/STM32/Servo.h
  3. 27
    4
      Marlin/src/HAL/STM32/eeprom_flash.cpp
  4. 9
    0
      Marlin/src/HAL/STM32/inc/SanityCheck.h

+ 36
- 6
Marlin/src/HAL/STM32/Servo.cpp Целия файл

@@ -29,32 +29,62 @@
29 29
 #include "Servo.h"
30 30
 
31 31
 static uint_fast8_t servoCount = 0;
32
+static libServo *servos[NUM_SERVOS] = {0};
32 33
 constexpr millis_t servoDelay[] = SERVO_DELAY;
33 34
 static_assert(COUNT(servoDelay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
34 35
 
35 36
 libServo::libServo()
36
-: delay(servoDelay[servoCount++])
37
-{}
37
+: delay(servoDelay[servoCount]),
38
+  was_attached_before_pause(false),
39
+  value_before_pause(0)
40
+{
41
+  servos[servoCount++] = this;
42
+}
38 43
 
39 44
 int8_t libServo::attach(const int pin) {
40 45
   if (servoCount >= MAX_SERVOS) return -1;
41 46
   if (pin > 0) servo_pin = pin;
42
-  return super::attach(servo_pin);
47
+  return stm32_servo.attach(servo_pin);
43 48
 }
44 49
 
45 50
 int8_t libServo::attach(const int pin, const int min, const int max) {
46 51
   if (servoCount >= MAX_SERVOS) return -1;
47 52
   if (pin > 0) servo_pin = pin;
48
-  return super::attach(servo_pin, min, max);
53
+  return stm32_servo.attach(servo_pin, min, max);
49 54
 }
50 55
 
51 56
 void libServo::move(const int value) {
52 57
   if (attach(0) >= 0) {
53
-    write(value);
58
+    stm32_servo.write(value);
54 59
     safe_delay(delay);
55 60
     TERN_(DEACTIVATE_SERVOS_AFTER_MOVE, detach());
56 61
   }
57 62
 }
58
-#endif // HAS_SERVOS
59 63
 
64
+void libServo::pause() {
65
+  was_attached_before_pause = stm32_servo.attached();
66
+  if (was_attached_before_pause) {
67
+    value_before_pause = stm32_servo.read();
68
+    stm32_servo.detach();
69
+  }
70
+}
71
+
72
+void libServo::resume() {
73
+  if (was_attached_before_pause) {
74
+    attach();
75
+    move(value_before_pause);
76
+  }
77
+}
78
+
79
+void libServo::pause_all_servos() {
80
+  for (auto& servo : servos)
81
+    if (servo) servo->pause();
82
+}
83
+
84
+void libServo::resume_all_servos() {
85
+  for (auto& servo : servos)
86
+    if (servo) servo->resume();
87
+}
88
+
89
+#endif // HAS_SERVOS
60 90
 #endif // ARDUINO_ARCH_STM32 && !STM32GENERIC

+ 15
- 3
Marlin/src/HAL/STM32/Servo.h Целия файл

@@ -27,15 +27,27 @@
27 27
 #include "../../core/millis_t.h"
28 28
 
29 29
 // Inherit and expand on the official library
30
-class libServo : public Servo {
30
+class libServo {
31 31
   public:
32 32
     libServo();
33
-    int8_t attach(const int pin);
33
+    int8_t attach(const int pin = 0); // pin == 0 uses value from previous call
34 34
     int8_t attach(const int pin, const int min, const int max);
35
+    void detach() { stm32_servo.detach(); }
36
+    int read() { return stm32_servo.read(); }
35 37
     void move(const int value);
38
+
39
+    void pause();
40
+    void resume();
41
+
42
+    static void pause_all_servos();
43
+    static void resume_all_servos();
44
+
36 45
   private:
37
-    typedef Servo super;
46
+    Servo stm32_servo;
38 47
 
39 48
     int servo_pin = 0;
40 49
     millis_t delay = 0;
50
+
51
+    bool was_attached_before_pause;
52
+    int value_before_pause;
41 53
 };

+ 27
- 4
Marlin/src/HAL/STM32/eeprom_flash.cpp Целия файл

@@ -28,10 +28,13 @@
28 28
 
29 29
 #include "../shared/eeprom_api.h"
30 30
 
31
-
32
-// Only STM32F4 can support wear leveling at this time
33
-#ifndef STM32F4xx
34
-  #undef FLASH_EEPROM_LEVELING
31
+#if HAS_SERVOS
32
+  #include "Servo.h"
33
+  #define PAUSE_SERVO_OUTPUT() libServo::pause_all_servos()
34
+  #define RESUME_SERVO_OUTPUT() libServo::resume_all_servos()
35
+#else  
36
+  #define PAUSE_SERVO_OUTPUT()
37
+  #define RESUME_SERVO_OUTPUT()
35 38
 #endif
36 39
 
37 40
 /**
@@ -139,6 +142,11 @@ bool PersistentStore::access_start() {
139 142
 bool PersistentStore::access_finish() {
140 143
 
141 144
   if (eeprom_data_written) {
145
+    #ifdef STM32F4xx
146
+      // MCU may come up with flash error bits which prevent some flash operations.
147
+      // Clear flags prior to flash operations to prevent errors.
148
+      __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
149
+    #endif    
142 150
 
143 151
     #if ENABLED(FLASH_EEPROM_LEVELING)
144 152
 
@@ -159,7 +167,11 @@ bool PersistentStore::access_finish() {
159 167
         current_slot = EEPROM_SLOTS - 1;
160 168
         UNLOCK_FLASH();
161 169
 
170
+        PAUSE_SERVO_OUTPUT();
171
+        DISABLE_ISRS();
162 172
         status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
173
+        ENABLE_ISRS();
174
+        RESUME_SERVO_OUTPUT();
163 175
         if (status != HAL_OK) {
164 176
           DEBUG_ECHOLNPAIR("HAL_FLASHEx_Erase=", status);
165 177
           DEBUG_ECHOLNPAIR("GetError=", HAL_FLASH_GetError());
@@ -204,7 +216,18 @@ bool PersistentStore::access_finish() {
204 216
       return success;
205 217
 
206 218
     #else
219
+      // The following was written for the STM32F4 but may work with other MCUs as well.
220
+      // Most STM32F4 flash does not allow reading from flash during erase operations.
221
+      // This takes about a second on a STM32F407 with a 128kB sector used as EEPROM.
222
+      // Interrupts during this time can have unpredictable results, such as killing Servo
223
+      // output. Servo output still glitches with interrupts disabled, but recovers after the
224
+      // erase.
225
+      PAUSE_SERVO_OUTPUT();
226
+      DISABLE_ISRS();
207 227
       eeprom_buffer_flush();
228
+      ENABLE_ISRS();
229
+      RESUME_SERVO_OUTPUT();
230
+
208 231
       eeprom_data_written = false;
209 232
     #endif
210 233
   }

+ 9
- 0
Marlin/src/HAL/STM32/inc/SanityCheck.h Целия файл

@@ -43,3 +43,12 @@
43 43
   #endif
44 44
   #error "SDCARD_EEPROM_EMULATION requires SDSUPPORT. Enable SDSUPPORT or choose another EEPROM emulation."
45 45
 #endif
46
+
47
+#if defined(STM32F4xx) && BOTH(PRINTCOUNTER, FLASH_EEPROM_EMULATION)
48
+  #warning "FLASH_EEPROM_EMULATION may cause long delays when writing and should not be used while printing."
49
+  #error "Disable PRINTCOUNTER or choose another EEPROM emulation."
50
+#endif
51
+
52
+#if !defined(STM32F4xx) && ENABLED(FLASH_EEPROM_LEVELING)
53
+  #error "FLASH_EEPROM_LEVELING is currently only supported on STM32F4 hardware."
54
+#endif

Loading…
Отказ
Запис