Browse Source

🐛 Fix STM32 set_pwm_duty (#23125)

vanilla_fb_2.0.x
Mike La Spina 3 years ago
committed by Scott Lahteine
parent
commit
5f08864d1f
  1. 11
      Marlin/src/HAL/STM32/MarlinSPI.cpp
  2. 66
      Marlin/src/HAL/STM32/fast_pwm.cpp
  3. 12
      Marlin/src/HAL/STM32/tft/tft_spi.cpp
  4. 4
      Marlin/src/HAL/STM32F1/HAL.h
  5. 10
      Marlin/src/HAL/STM32F1/fast_pwm.cpp
  6. 2
      Marlin/src/lcd/extui/mks_ui/wifi_module.cpp
  7. 1
      Marlin/src/pins/stm32f1/pins_LONGER3D_LK.h

11
Marlin/src/HAL/STM32/MarlinSPI.cpp

@ -114,16 +114,19 @@ byte MarlinSPI::transfer(uint8_t _data) {
return rxData; return rxData;
} }
__STATIC_INLINE void LL_SPI_EnableDMAReq_RX(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); }
__STATIC_INLINE void LL_SPI_EnableDMAReq_TX(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); }
uint8_t MarlinSPI::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length) { uint8_t MarlinSPI::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length) {
const uint8_t ff = 0xFF; const uint8_t ff = 0xFF;
//if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) //only enable if disabled //if (!LL_SPI_IsEnabled(_spi.handle)) // only enable if disabled
__HAL_SPI_ENABLE(&_spi.handle); __HAL_SPI_ENABLE(&_spi.handle);
if (receiveBuf) { if (receiveBuf) {
setupDma(_spi.handle, _dmaRx, DMA_PERIPH_TO_MEMORY, true); setupDma(_spi.handle, _dmaRx, DMA_PERIPH_TO_MEMORY, true);
HAL_DMA_Start(&_dmaRx, (uint32_t)&(_spi.handle.Instance->DR), (uint32_t)receiveBuf, length); HAL_DMA_Start(&_dmaRx, (uint32_t)&(_spi.handle.Instance->DR), (uint32_t)receiveBuf, length);
SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_RXDMAEN); /* Enable Rx DMA Request */ LL_SPI_EnableDMAReq_RX(_spi.handle.Instance); // Enable Rx DMA Request
} }
// check for 2 lines transfer // check for 2 lines transfer
@ -136,7 +139,7 @@ uint8_t MarlinSPI::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16
if (transmitBuf) { if (transmitBuf) {
setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, mincTransmit); setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, mincTransmit);
HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length); HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */ LL_SPI_EnableDMAReq_TX(_spi.handle.Instance); // Enable Tx DMA Request
} }
if (transmitBuf) { if (transmitBuf) {
@ -160,7 +163,7 @@ uint8_t MarlinSPI::dmaSend(const void * transmitBuf, uint16_t length, bool minc)
setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, minc); setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, minc);
HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length); HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
__HAL_SPI_ENABLE(&_spi.handle); __HAL_SPI_ENABLE(&_spi.handle);
SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */ LL_SPI_EnableDMAReq_TX(_spi.handle.Instance); // Enable Tx DMA Request
HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY); HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
HAL_DMA_Abort(&_dmaTx); HAL_DMA_Abort(&_dmaTx);
// DeInit objects // DeInit objects

66
Marlin/src/HAL/STM32/fast_pwm.cpp

@ -27,37 +27,67 @@
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#include "timers.h" #include "timers.h"
// Array to support sticky frequency sets per timer
static uint16_t timer_freq[TIMER_NUM];
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) { void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
bool needs_freq;
PinName pin_name = digitalPinToPinName(pin); PinName pin_name = digitalPinToPinName(pin);
TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM);
HardwareTimer *HT;
TimerModes_t previousMode;
uint16_t value = v;
if (invert) value = v_size - value;
uint32_t index = get_timer_index(Instance);
uint16_t adj_val = Instance->ARR * v / v_size; if (HardwareTimer_Handle[index] == nullptr) {
if (invert) adj_val = Instance->ARR - adj_val; HardwareTimer_Handle[index]->__this = new HardwareTimer((TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM));
switch (get_pwm_channel(pin_name)) { needs_freq = true; // The instance must be new set the default frequency of PWM_FREQUENCY
case TIM_CHANNEL_1: LL_TIM_OC_SetCompareCH1(Instance, adj_val); break;
case TIM_CHANNEL_2: LL_TIM_OC_SetCompareCH2(Instance, adj_val); break;
case TIM_CHANNEL_3: LL_TIM_OC_SetCompareCH3(Instance, adj_val); break;
case TIM_CHANNEL_4: LL_TIM_OC_SetCompareCH4(Instance, adj_val); break;
} }
}
#if NEEDS_HARDWARE_PWM HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this);
uint32_t channel = STM_PIN_CHANNEL(pinmap_function(pin_name, PinMap_PWM));
previousMode = HT->getMode(channel);
void set_pwm_frequency(const pin_t pin, int f_desired) { if (previousMode != TIMER_OUTPUT_COMPARE_PWM1)
if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer HT->setMode(channel, TIMER_OUTPUT_COMPARE_PWM1, pin);
if (needs_freq) {
if (timer_freq[index] == 0 ) { // If the timer is unconfigured and no freq is set then default PWM_FREQUENCY.
timer_freq[index] = PWM_FREQUENCY;
set_pwm_frequency(pin_name, timer_freq[index]); // Set the frequency and save the value to the assigned index no.
}
}
// Note the resolution is sticky here, the input can be upto 16 bits and that would require RESOLUTION_16B_COMPARE_FORMAT (16)
// 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.
HT->setCaptureCompare(channel, value, RESOLUTION_8B_COMPARE_FORMAT); // Sets the duty, the calc is done in the library :)
pinmap_pinout(pin_name, PinMap_PWM); // Make sure the pin output state is set.
if (previousMode != TIMER_OUTPUT_COMPARE_PWM1) HT->resume();
}
void set_pwm_frequency(const pin_t pin, int f_desired) {
if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
HardwareTimer *HT;
PinName pin_name = digitalPinToPinName(pin); PinName pin_name = digitalPinToPinName(pin);
TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); // Get HAL timer instance TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); // Get HAL timer instance
LOOP_S_L_N(i, 0, NUM_HARDWARE_TIMERS) // Protect used timers uint32_t index = get_timer_index(Instance);
if (timer_instance[i] && timer_instance[i]->getHandle()->Instance == Instance)
return;
pwm_start(pin_name, f_desired, 0, RESOLUTION_8B_COMPARE_FORMAT); // Protect used timers
} if (index == TEMP_TIMER_NUM || index == STEP_TIMER_NUM
#if PULSE_TIMER_NUM != STEP_TIMER_NUM
|| index == PULSE_TIMER_NUM
#endif
) return;
#endif if (HardwareTimer_Handle[index] == nullptr) // If frequency is set before duty we need to create a handle here.
HardwareTimer_Handle[index]->__this = new HardwareTimer((TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM));
HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this);
timer_freq[index] = f_desired; // Save the last frequency so duty will not set the default for this timer number.
HT->setOverflow(f_desired, HERTZ_FORMAT);
}
#endif // HAL_STM32 #endif // HAL_STM32

12
Marlin/src/HAL/STM32/tft/tft_spi.cpp

@ -161,11 +161,11 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) {
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
#if TFT_MISO_PIN != TFT_MOSI_PIN #if TFT_MISO_PIN != TFT_MOSI_PIN
//if (hspi->Init.Direction == SPI_DIRECTION_2LINES) { //if (hspi->Init.Direction == SPI_DIRECTION_2LINES) {
while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {} while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {}
SPIx.Instance->DR = 0; SPIx.Instance->DR = 0;
//} //}
#endif #endif
while ((SPIx.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE) {} while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_RXNE)) {}
Data = (Data << 8) | SPIx.Instance->DR; Data = (Data << 8) | SPIx.Instance->DR;
} }
@ -195,8 +195,8 @@ bool TFT_SPI::isBusy() {
void TFT_SPI::Abort() { void TFT_SPI::Abort() {
// Wait for any running spi // Wait for any running spi
while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {} while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {}
while ((SPIx.Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY) {} while ( __HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_BSY)) {}
// First, abort any running dma // First, abort any running dma
HAL_DMA_Abort(&DMAtx); HAL_DMA_Abort(&DMAtx);
// DeInit objects // DeInit objects
@ -214,8 +214,8 @@ void TFT_SPI::Transmit(uint16_t Data) {
SPIx.Instance->DR = Data; SPIx.Instance->DR = Data;
while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {} while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {}
while ((SPIx.Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY) {} while ( __HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_BSY)) {}
if (TFT_MISO_PIN != TFT_MOSI_PIN) if (TFT_MISO_PIN != TFT_MOSI_PIN)
__HAL_SPI_CLEAR_OVRFLAG(&SPIx); // Clear overrun flag in 2 Lines communication mode because received is not read __HAL_SPI_CLEAR_OVRFLAG(&SPIx); // Clear overrun flag in 2 Lines communication mode because received is not read

4
Marlin/src/HAL/STM32F1/HAL.h

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

10
Marlin/src/HAL/STM32F1/fast_pwm.cpp

@ -30,14 +30,15 @@
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) { void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
if (!PWM_PIN(pin)) return; if (!PWM_PIN(pin)) return;
timer_dev *timer = PIN_MAP[pin].timer_device; timer_dev *timer = PIN_MAP[pin].timer_device;
if (!(timer->regs.bas->SR & TIMER_CR1_CEN)) // Ensure the timer is enabled
set_pwm_frequency(pin, PWM_FREQUENCY);
uint16_t max_val = timer->regs.bas->ARR * v / v_size; uint16_t max_val = timer->regs.bas->ARR * v / v_size;
if (invert) max_val = v_size - max_val; if (invert) max_val = v_size - max_val;
pwmWrite(pin, max_val); pwmWrite(pin, max_val);
}
#if NEEDS_HARDWARE_PWM }
void set_pwm_frequency(const pin_t pin, int f_desired) { void set_pwm_frequency(const pin_t pin, int f_desired) {
if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
timer_dev *timer = PIN_MAP[pin].timer_device; timer_dev *timer = PIN_MAP[pin].timer_device;
@ -63,7 +64,6 @@ void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255
if (prescaler < 0) return; // Too high frequency if (prescaler < 0) return; // Too high frequency
timer_set_reload(timer, preload); timer_set_reload(timer, preload);
timer_set_prescaler(timer, prescaler); timer_set_prescaler(timer, prescaler);
} }
#endif // NEEDS_HARDWARE_PWM
#endif // __STM32F1__ #endif // __STM32F1__

2
Marlin/src/lcd/extui/mks_ui/wifi_module.cpp

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

1
Marlin/src/pins/stm32f1/pins_LONGER3D_LK.h

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

Loading…
Cancel
Save