|
@@ -137,3 +137,44 @@ void HAL_adc_start_conversion(uint8_t adc_pin);
|
137
|
137
|
void HAL_idletask();
|
138
|
138
|
void HAL_init();
|
139
|
139
|
void HAL_init_board();
|
|
140
|
+
|
|
141
|
+//
|
|
142
|
+// Delay in cycles (used by DELAY_NS / DELAY_US)
|
|
143
|
+//
|
|
144
|
+FORCE_INLINE static void DELAY_CYCLES(uint32_t x) {
|
|
145
|
+ unsigned long start, ccount, stop;
|
|
146
|
+
|
|
147
|
+ /**
|
|
148
|
+ * It's important to care for race conditions (and overflows) here.
|
|
149
|
+ * Race condition example: If `stop` calculates to being close to the upper boundary of
|
|
150
|
+ * `uint32_t` and if at the same time a longer loop interruption kicks in (e.g. due to other
|
|
151
|
+ * FreeRTOS tasks or interrupts), `ccount` might overflow (and therefore be below `stop` again)
|
|
152
|
+ * without the loop ever being able to notice that `ccount` had already been above `stop` once
|
|
153
|
+ * (and that therefore the number of cycles to delay has already passed).
|
|
154
|
+ * As DELAY_CYCLES (through DELAY_NS / DELAY_US) is used by software SPI bit banging to drive
|
|
155
|
+ * LCDs and therefore might be called very, very often, this seemingly improbable situation did
|
|
156
|
+ * actually happen in reality. It resulted in apparently random print pauses of ~17.9 seconds
|
|
157
|
+ * (0x100000000 / 240 MHz) or multiples thereof, essentially ruining the current print by causing
|
|
158
|
+ * large blobs of filament.
|
|
159
|
+ */
|
|
160
|
+
|
|
161
|
+ __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (start) );
|
|
162
|
+ stop = start + x;
|
|
163
|
+ ccount = start;
|
|
164
|
+
|
|
165
|
+ if (stop >= start) {
|
|
166
|
+ // no overflow, so only loop while in between start and stop:
|
|
167
|
+ // 0x00000000 -----------------start****stop-- 0xffffffff
|
|
168
|
+ while (ccount >= start && ccount < stop) {
|
|
169
|
+ __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (ccount) );
|
|
170
|
+ }
|
|
171
|
+ }
|
|
172
|
+ else {
|
|
173
|
+ // stop did overflow, so only loop while outside of stop and start:
|
|
174
|
+ // 0x00000000 **stop-------------------start** 0xffffffff
|
|
175
|
+ while (ccount >= start || ccount < stop) {
|
|
176
|
+ __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (ccount) );
|
|
177
|
+ }
|
|
178
|
+ }
|
|
179
|
+
|
|
180
|
+}
|