ソースを参照

🐛 Fix STM32 set_pwm_duty (#23125)

Mike La Spina 2年前
コミット
5387ceba74
コミッターのメールアドレスに関連付けられたアカウントが存在しません

+ 7
- 4
Marlin/src/HAL/STM32/MarlinSPI.cpp ファイルの表示

@@ -114,16 +114,19 @@ byte MarlinSPI::transfer(uint8_t _data) {
114 114
   return rxData;
115 115
 }
116 116
 
117
+__STATIC_INLINE void LL_SPI_EnableDMAReq_RX(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); }
118
+__STATIC_INLINE void LL_SPI_EnableDMAReq_TX(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); }
119
+
117 120
 uint8_t MarlinSPI::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length) {
118 121
   const uint8_t ff = 0xFF;
119 122
 
120
-  //if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) //only enable if disabled
123
+  //if (!LL_SPI_IsEnabled(_spi.handle)) // only enable if disabled
121 124
   __HAL_SPI_ENABLE(&_spi.handle);
122 125
 
123 126
   if (receiveBuf) {
124 127
     setupDma(_spi.handle, _dmaRx, DMA_PERIPH_TO_MEMORY, true);
125 128
     HAL_DMA_Start(&_dmaRx, (uint32_t)&(_spi.handle.Instance->DR), (uint32_t)receiveBuf, length);
126
-    SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_RXDMAEN); /* Enable Rx DMA Request */
129
+    LL_SPI_EnableDMAReq_RX(_spi.handle.Instance); // Enable Rx DMA Request
127 130
   }
128 131
 
129 132
   // check for 2 lines transfer
@@ -136,7 +139,7 @@ uint8_t MarlinSPI::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16
136 139
   if (transmitBuf) {
137 140
     setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, mincTransmit);
138 141
     HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
139
-    SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_TXDMAEN);   /* Enable Tx DMA Request */
142
+    LL_SPI_EnableDMAReq_TX(_spi.handle.Instance); // Enable Tx DMA Request
140 143
   }
141 144
 
142 145
   if (transmitBuf) {
@@ -160,7 +163,7 @@ uint8_t MarlinSPI::dmaSend(const void * transmitBuf, uint16_t length, bool minc)
160 163
   setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, minc);
161 164
   HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
162 165
   __HAL_SPI_ENABLE(&_spi.handle);
163
-  SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_TXDMAEN);   /* Enable Tx DMA Request */
166
+  LL_SPI_EnableDMAReq_TX(_spi.handle.Instance); // Enable Tx DMA Request
164 167
   HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
165 168
   HAL_DMA_Abort(&_dmaTx);
166 169
   // DeInit objects

+ 51
- 21
Marlin/src/HAL/STM32/fast_pwm.cpp ファイルの表示

@@ -27,37 +27,67 @@
27 27
 #include "../../inc/MarlinConfig.h"
28 28
 #include "timers.h"
29 29
 
30
-void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
31
-  if (!PWM_PIN(pin)) return;            // Don't proceed if no hardware timer
30
+// Array to support sticky frequency sets per timer
31
+static uint16_t timer_freq[TIMER_NUM];
32 32
 
33
+void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
34
+  if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
35
+  bool needs_freq;
33 36
   PinName pin_name = digitalPinToPinName(pin);
34 37
   TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM);
38
+  HardwareTimer *HT;
39
+  TimerModes_t previousMode;
35 40
 
36
-  uint16_t adj_val = Instance->ARR * v / v_size;
37
-  if (invert) adj_val = Instance->ARR - adj_val;
38
-  switch (get_pwm_channel(pin_name)) {
39
-    case TIM_CHANNEL_1: LL_TIM_OC_SetCompareCH1(Instance, adj_val); break;
40
-    case TIM_CHANNEL_2: LL_TIM_OC_SetCompareCH2(Instance, adj_val); break;
41
-    case TIM_CHANNEL_3: LL_TIM_OC_SetCompareCH3(Instance, adj_val); break;
42
-    case TIM_CHANNEL_4: LL_TIM_OC_SetCompareCH4(Instance, adj_val); break;
43
-  }
44
-}
41
+  uint16_t value = v;
42
+  if (invert) value = v_size - value;
45 43
 
46
-#if NEEDS_HARDWARE_PWM
44
+  uint32_t index = get_timer_index(Instance);
47 45
 
48
-  void set_pwm_frequency(const pin_t pin, int f_desired) {
49
-    if (!PWM_PIN(pin)) return;            // Don't proceed if no hardware timer
46
+  if (HardwareTimer_Handle[index] == nullptr) {
47
+    HardwareTimer_Handle[index]->__this = new HardwareTimer((TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM));
48
+    needs_freq = true;                  // The instance must be new set the default frequency of PWM_FREQUENCY
49
+  }
50 50
 
51
-    PinName pin_name = digitalPinToPinName(pin);
52
-    TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); // Get HAL timer instance
51
+  HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this);
52
+  uint32_t channel = STM_PIN_CHANNEL(pinmap_function(pin_name, PinMap_PWM));
53
+  previousMode = HT->getMode(channel);
53 54
 
54
-    LOOP_S_L_N(i, 0, NUM_HARDWARE_TIMERS) // Protect used timers
55
-      if (timer_instance[i] && timer_instance[i]->getHandle()->Instance == Instance)
56
-        return;
55
+  if (previousMode != TIMER_OUTPUT_COMPARE_PWM1)
56
+    HT->setMode(channel, TIMER_OUTPUT_COMPARE_PWM1, pin);
57 57
 
58
-    pwm_start(pin_name, f_desired, 0, RESOLUTION_8B_COMPARE_FORMAT);
58
+  if (needs_freq) {
59
+    if (timer_freq[index] == 0 ) {                    // If the timer is unconfigured and no freq is set then default PWM_FREQUENCY.
60
+      timer_freq[index] = PWM_FREQUENCY;
61
+      set_pwm_frequency(pin_name, timer_freq[index]); // Set the frequency and save the value to the assigned index no.
62
+    }
59 63
   }
64
+  // Note the resolution is sticky here, the input can be upto 16 bits and that would require RESOLUTION_16B_COMPARE_FORMAT (16)
65
+  // If such a need were to manifest then we would need to calc the resolution based on the v_size parameter and add code for it.
66
+  HT->setCaptureCompare(channel, value, RESOLUTION_8B_COMPARE_FORMAT); // Sets the duty, the calc is done in the library :)
67
+  pinmap_pinout(pin_name, PinMap_PWM); // Make sure the pin output state is set.
68
+  if (previousMode != TIMER_OUTPUT_COMPARE_PWM1) HT->resume();
69
+}
60 70
 
61
-#endif
71
+void set_pwm_frequency(const pin_t pin, int f_desired) {
72
+  if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
73
+  HardwareTimer *HT;
74
+  PinName pin_name = digitalPinToPinName(pin);
75
+  TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); // Get HAL timer instance
76
+
77
+  uint32_t index = get_timer_index(Instance);
78
+
79
+  // Protect used timers
80
+  if (index == TEMP_TIMER_NUM || index == STEP_TIMER_NUM
81
+    #if PULSE_TIMER_NUM != STEP_TIMER_NUM
82
+      || index == PULSE_TIMER_NUM
83
+    #endif
84
+  ) return;
85
+
86
+  if (HardwareTimer_Handle[index] == nullptr) // If frequency is set before duty we need to create a handle here. 
87
+    HardwareTimer_Handle[index]->__this = new HardwareTimer((TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM));
88
+  HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this);
89
+  timer_freq[index] = f_desired; // Save the last frequency so duty will not set the default for this timer number.
90
+  HT->setOverflow(f_desired, HERTZ_FORMAT);   
91
+}
62 92
 
63 93
 #endif // HAL_STM32

+ 6
- 6
Marlin/src/HAL/STM32/tft/tft_spi.cpp ファイルの表示

@@ -161,11 +161,11 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) {
161 161
     for (i = 0; i < 4; i++) {
162 162
       #if TFT_MISO_PIN != TFT_MOSI_PIN
163 163
         //if (hspi->Init.Direction == SPI_DIRECTION_2LINES) {
164
-          while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {}
164
+          while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {}
165 165
           SPIx.Instance->DR = 0;
166 166
         //}
167 167
       #endif
168
-      while ((SPIx.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE) {}
168
+      while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_RXNE)) {}
169 169
       Data = (Data << 8) | SPIx.Instance->DR;
170 170
     }
171 171
 
@@ -195,8 +195,8 @@ bool TFT_SPI::isBusy() {
195 195
 
196 196
 void TFT_SPI::Abort() {
197 197
   // Wait for any running spi
198
-  while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {}
199
-  while ((SPIx.Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY) {}
198
+  while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {}
199
+  while ( __HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_BSY)) {}
200 200
   // First, abort any running dma
201 201
   HAL_DMA_Abort(&DMAtx);
202 202
   // DeInit objects
@@ -214,8 +214,8 @@ void TFT_SPI::Transmit(uint16_t Data) {
214 214
 
215 215
   SPIx.Instance->DR = Data;
216 216
 
217
-  while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {}
218
-  while ((SPIx.Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY) {}
217
+  while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {}
218
+  while ( __HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_BSY)) {}
219 219
 
220 220
   if (TFT_MISO_PIN != TFT_MOSI_PIN)
221 221
     __HAL_SPI_CLEAR_OVRFLAG(&SPIx);   // Clear overrun flag in 2 Lines communication mode because received is not read

+ 5
- 1
Marlin/src/HAL/STM32F1/HAL.h ファイルの表示

@@ -264,7 +264,10 @@ void analogWrite(pin_t pin, int pwm_val8); // PWM only! mul by 257 in maple!?
264 264
 #define PLATFORM_M997_SUPPORT
265 265
 void flashFirmware(const int16_t);
266 266
 
267
-#define HAL_CAN_SET_PWM_FREQ   // This HAL supports PWM Frequency adjustment
267
+#ifndef PWM_FREQUENCY
268
+  #define PWM_FREQUENCY      1000 // Default PWM Frequency
269
+#endif  
270
+#define HAL_CAN_SET_PWM_FREQ      // This HAL supports PWM Frequency adjustment
268 271
 
269 272
 /**
270 273
  * set_pwm_frequency
@@ -278,5 +281,6 @@ void set_pwm_frequency(const pin_t pin, int f_desired);
278 281
  *  Set the PWM duty cycle of the provided pin to the provided value
279 282
  *  Optionally allows inverting the duty cycle [default = false]
280 283
  *  Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
284
+ *  The timer must be pre-configured with set_pwm_frequency() if the default frequency is not desired.   
281 285
  */
282 286
 void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);

+ 25
- 25
Marlin/src/HAL/STM32F1/fast_pwm.cpp ファイルの表示

@@ -30,40 +30,40 @@
30 30
 void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
31 31
   if (!PWM_PIN(pin)) return;
32 32
   timer_dev *timer = PIN_MAP[pin].timer_device;
33
+  if (!(timer->regs.bas->SR & TIMER_CR1_CEN))   // Ensure the timer is enabled
34
+    set_pwm_frequency(pin, PWM_FREQUENCY);
33 35
   uint16_t max_val = timer->regs.bas->ARR * v / v_size;
34 36
   if (invert) max_val = v_size - max_val;
35 37
   pwmWrite(pin, max_val);
36
-}
37 38
 
38
-#if NEEDS_HARDWARE_PWM
39
+}
39 40
 
40
-  void set_pwm_frequency(const pin_t pin, int f_desired) {
41
-    if (!PWM_PIN(pin)) return;                    // Don't proceed if no hardware timer
41
+void set_pwm_frequency(const pin_t pin, int f_desired) {
42
+  if (!PWM_PIN(pin)) return;                    // Don't proceed if no hardware timer
42 43
 
43
-    timer_dev *timer = PIN_MAP[pin].timer_device;
44
-    uint8_t channel = PIN_MAP[pin].timer_channel;
44
+  timer_dev *timer = PIN_MAP[pin].timer_device;
45
+  uint8_t channel = PIN_MAP[pin].timer_channel;
45 46
 
46
-    // Protect used timers
47
-    if (timer == get_timer_dev(TEMP_TIMER_NUM)) return;
48
-    if (timer == get_timer_dev(STEP_TIMER_NUM)) return;
49
-    #if PULSE_TIMER_NUM != STEP_TIMER_NUM
50
-      if (timer == get_timer_dev(PULSE_TIMER_NUM)) return;
51
-    #endif
47
+  // Protect used timers
48
+  if (timer == get_timer_dev(TEMP_TIMER_NUM)) return;
49
+  if (timer == get_timer_dev(STEP_TIMER_NUM)) return;
50
+  #if PULSE_TIMER_NUM != STEP_TIMER_NUM
51
+    if (timer == get_timer_dev(PULSE_TIMER_NUM)) return;
52
+  #endif
52 53
 
53
-    if (!(timer->regs.bas->SR & TIMER_CR1_CEN))   // Ensure the timer is enabled
54
-      timer_init(timer);
54
+  if (!(timer->regs.bas->SR & TIMER_CR1_CEN))   // Ensure the timer is enabled
55
+    timer_init(timer);
55 56
 
56
-    timer_set_mode(timer, channel, TIMER_PWM);
57
-    uint16_t preload = 255;                       // Lock 255 PWM resolution for high frequencies
58
-    int32_t prescaler = (HAL_TIMER_RATE) / (preload + 1) / f_desired - 1;
59
-    if (prescaler > 65535) {                      // For low frequencies increase prescaler
60
-      prescaler = 65535;
61
-      preload = (HAL_TIMER_RATE) / (prescaler + 1) / f_desired - 1;
62
-    }
63
-    if (prescaler < 0) return;                    // Too high frequency
64
-    timer_set_reload(timer, preload);
65
-    timer_set_prescaler(timer, prescaler);
57
+  timer_set_mode(timer, channel, TIMER_PWM);
58
+  uint16_t preload = 255;                       // Lock 255 PWM resolution for high frequencies
59
+  int32_t prescaler = (HAL_TIMER_RATE) / (preload + 1) / f_desired - 1;
60
+  if (prescaler > 65535) {                      // For low frequencies increase prescaler
61
+    prescaler = 65535;
62
+    preload = (HAL_TIMER_RATE) / (prescaler + 1) / f_desired - 1;
66 63
   }
64
+  if (prescaler < 0) return;                    // Too high frequency
65
+  timer_set_reload(timer, preload);
66
+  timer_set_prescaler(timer, prescaler);
67
+}
67 68
 
68
-#endif // NEEDS_HARDWARE_PWM
69 69
 #endif // __STM32F1__

+ 1
- 1
Marlin/src/lcd/extui/mks_ui/wifi_module.cpp ファイルの表示

@@ -345,7 +345,7 @@ static bool longName2DosName(const char *longName, char *dosName) {
345 345
           hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
346 346
 
347 347
           SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE);       // Update error code
348
-          hdma->State= HAL_DMA_STATE_READY;                 // Change the DMA state
348
+          hdma->State = HAL_DMA_STATE_READY;                // Change the DMA state
349 349
           __HAL_UNLOCK(hdma);                               // Process Unlocked
350 350
           return HAL_ERROR;
351 351
         }

+ 0
- 1
Marlin/src/pins/stm32f1/pins_LONGER3D_LK.h ファイルの表示

@@ -96,7 +96,6 @@
96 96
 #else
97 97
   #define FAST_PWM_FAN                            // STM32 Variant allow TIMER2 Hardware PWM
98 98
   #define FAST_PWM_FAN_FREQUENCY           31400  // This frequency allow a good range, fan starts at 3%, half noise at 50%
99
-  #define NEEDS_HARDWARE_PWM                   1
100 99
   #define FAN_MIN_PWM                          5
101 100
   #define FAN_MAX_PWM                        255
102 101
 #endif

読み込み中…
キャンセル
保存