Browse Source

Improve STM32F4 Flash Behavior (#17946)

Jason Smith 5 years ago
parent
commit
25aade1cf1
No account linked to committer's email address

+ 36
- 6
Marlin/src/HAL/STM32/Servo.cpp View File

29
 #include "Servo.h"
29
 #include "Servo.h"
30
 
30
 
31
 static uint_fast8_t servoCount = 0;
31
 static uint_fast8_t servoCount = 0;
32
+static libServo *servos[NUM_SERVOS] = {0};
32
 constexpr millis_t servoDelay[] = SERVO_DELAY;
33
 constexpr millis_t servoDelay[] = SERVO_DELAY;
33
 static_assert(COUNT(servoDelay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
34
 static_assert(COUNT(servoDelay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
34
 
35
 
35
 libServo::libServo()
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
 int8_t libServo::attach(const int pin) {
44
 int8_t libServo::attach(const int pin) {
40
   if (servoCount >= MAX_SERVOS) return -1;
45
   if (servoCount >= MAX_SERVOS) return -1;
41
   if (pin > 0) servo_pin = pin;
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
 int8_t libServo::attach(const int pin, const int min, const int max) {
50
 int8_t libServo::attach(const int pin, const int min, const int max) {
46
   if (servoCount >= MAX_SERVOS) return -1;
51
   if (servoCount >= MAX_SERVOS) return -1;
47
   if (pin > 0) servo_pin = pin;
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
 void libServo::move(const int value) {
56
 void libServo::move(const int value) {
52
   if (attach(0) >= 0) {
57
   if (attach(0) >= 0) {
53
-    write(value);
58
+    stm32_servo.write(value);
54
     safe_delay(delay);
59
     safe_delay(delay);
55
     TERN_(DEACTIVATE_SERVOS_AFTER_MOVE, detach());
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
 #endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
90
 #endif // ARDUINO_ARCH_STM32 && !STM32GENERIC

+ 15
- 3
Marlin/src/HAL/STM32/Servo.h View File

27
 #include "../../core/millis_t.h"
27
 #include "../../core/millis_t.h"
28
 
28
 
29
 // Inherit and expand on the official library
29
 // Inherit and expand on the official library
30
-class libServo : public Servo {
30
+class libServo {
31
   public:
31
   public:
32
     libServo();
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
     int8_t attach(const int pin, const int min, const int max);
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
     void move(const int value);
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
   private:
45
   private:
37
-    typedef Servo super;
46
+    Servo stm32_servo;
38
 
47
 
39
     int servo_pin = 0;
48
     int servo_pin = 0;
40
     millis_t delay = 0;
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 View File

28
 
28
 
29
 #include "../shared/eeprom_api.h"
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
 #endif
38
 #endif
36
 
39
 
37
 /**
40
 /**
139
 bool PersistentStore::access_finish() {
142
 bool PersistentStore::access_finish() {
140
 
143
 
141
   if (eeprom_data_written) {
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
     #if ENABLED(FLASH_EEPROM_LEVELING)
151
     #if ENABLED(FLASH_EEPROM_LEVELING)
144
 
152
 
159
         current_slot = EEPROM_SLOTS - 1;
167
         current_slot = EEPROM_SLOTS - 1;
160
         UNLOCK_FLASH();
168
         UNLOCK_FLASH();
161
 
169
 
170
+        PAUSE_SERVO_OUTPUT();
171
+        DISABLE_ISRS();
162
         status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
172
         status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
173
+        ENABLE_ISRS();
174
+        RESUME_SERVO_OUTPUT();
163
         if (status != HAL_OK) {
175
         if (status != HAL_OK) {
164
           DEBUG_ECHOLNPAIR("HAL_FLASHEx_Erase=", status);
176
           DEBUG_ECHOLNPAIR("HAL_FLASHEx_Erase=", status);
165
           DEBUG_ECHOLNPAIR("GetError=", HAL_FLASH_GetError());
177
           DEBUG_ECHOLNPAIR("GetError=", HAL_FLASH_GetError());
204
       return success;
216
       return success;
205
 
217
 
206
     #else
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
       eeprom_buffer_flush();
227
       eeprom_buffer_flush();
228
+      ENABLE_ISRS();
229
+      RESUME_SERVO_OUTPUT();
230
+
208
       eeprom_data_written = false;
231
       eeprom_data_written = false;
209
     #endif
232
     #endif
210
   }
233
   }

+ 9
- 0
Marlin/src/HAL/STM32/inc/SanityCheck.h View File

43
   #endif
43
   #endif
44
   #error "SDCARD_EEPROM_EMULATION requires SDSUPPORT. Enable SDSUPPORT or choose another EEPROM emulation."
44
   #error "SDCARD_EEPROM_EMULATION requires SDSUPPORT. Enable SDSUPPORT or choose another EEPROM emulation."
45
 #endif
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…
Cancel
Save