stm32: Add Hardware PWM support for STM32G0 processors (#5714)
Uses existing common code for STM32. Adds a table for device- specific PWM mappings. Adds support for enabling all TIM timer devices. Makes it a runtime error to enable devices the code doesn't know how to enable. I have verified performance of the fan pins (PC6, PC7, PB15) on the SKR Mini E3 V3. Signed-off-by: Ben Jackson <ben@ben.com>
This commit is contained in:
parent
83ab6fbae5
commit
b220b8bfaf
|
@ -9,7 +9,7 @@ config STM32_SELECT
|
||||||
select HAVE_GPIO_ADC
|
select HAVE_GPIO_ADC
|
||||||
select HAVE_GPIO_I2C if !(MACH_STM32F031 || MACH_STM32H7)
|
select HAVE_GPIO_I2C if !(MACH_STM32F031 || MACH_STM32H7)
|
||||||
select HAVE_GPIO_SPI if !MACH_STM32F031
|
select HAVE_GPIO_SPI if !MACH_STM32F031
|
||||||
select HAVE_GPIO_HARD_PWM if MACH_STM32F1 || MACH_STM32F4 || MACH_STM32H7
|
select HAVE_GPIO_HARD_PWM if MACH_STM32F1 || MACH_STM32F4 || MACH_STM32G0 || MACH_STM32H7
|
||||||
select HAVE_GPIO_BITBANGING if !MACH_STM32F031
|
select HAVE_GPIO_BITBANGING if !MACH_STM32F031
|
||||||
select HAVE_STRICT_TIMING
|
select HAVE_STRICT_TIMING
|
||||||
select HAVE_CHIPID
|
select HAVE_CHIPID
|
||||||
|
|
|
@ -102,6 +102,53 @@ static const struct gpio_pwm_info pwm_regs[] = {
|
||||||
{TIM9, GPIO('E', 6), 2, GPIO_FUNCTION(3)},
|
{TIM9, GPIO('E', 6), 2, GPIO_FUNCTION(3)},
|
||||||
{TIM10, GPIO('B', 8), 1, GPIO_FUNCTION(3)},
|
{TIM10, GPIO('B', 8), 1, GPIO_FUNCTION(3)},
|
||||||
{TIM11, GPIO('B', 9), 1, GPIO_FUNCTION(3)}
|
{TIM11, GPIO('B', 9), 1, GPIO_FUNCTION(3)}
|
||||||
|
#elif CONFIG_MACH_STM32G0
|
||||||
|
{TIM15, GPIO('A', 2), 1, GPIO_FUNCTION(5)},
|
||||||
|
{TIM15, GPIO('A', 3), 2, GPIO_FUNCTION(5)},
|
||||||
|
{TIM14, GPIO('A', 4), 1, GPIO_FUNCTION(4)},
|
||||||
|
{TIM3, GPIO('A', 6), 1, GPIO_FUNCTION(1)},
|
||||||
|
{TIM3, GPIO('A', 7), 2, GPIO_FUNCTION(1)},
|
||||||
|
{TIM1, GPIO('A', 8), 1, GPIO_FUNCTION(2)},
|
||||||
|
{TIM1, GPIO('A', 9), 2, GPIO_FUNCTION(2)},
|
||||||
|
{TIM1, GPIO('A', 10), 3, GPIO_FUNCTION(2)},
|
||||||
|
{TIM1, GPIO('A', 11), 4, GPIO_FUNCTION(2)},
|
||||||
|
{TIM3, GPIO('B', 0), 3, GPIO_FUNCTION(1)},
|
||||||
|
{TIM3, GPIO('B', 1), 4, GPIO_FUNCTION(1)},
|
||||||
|
{TIM1, GPIO('B', 3), 2, GPIO_FUNCTION(1)},
|
||||||
|
{TIM3, GPIO('B', 4), 1, GPIO_FUNCTION(1)},
|
||||||
|
{TIM3, GPIO('B', 5), 2, GPIO_FUNCTION(1)},
|
||||||
|
{TIM4, GPIO('B', 6), 1, GPIO_FUNCTION(9)},
|
||||||
|
{TIM4, GPIO('B', 7), 2, GPIO_FUNCTION(9)},
|
||||||
|
{TIM4, GPIO('B', 8), 3, GPIO_FUNCTION(9)},
|
||||||
|
{TIM4, GPIO('B', 9), 4, GPIO_FUNCTION(9)},
|
||||||
|
{TIM15, GPIO('B', 14), 1, GPIO_FUNCTION(5)},
|
||||||
|
{TIM15, GPIO('B', 15), 2, GPIO_FUNCTION(5)},
|
||||||
|
{TIM15, GPIO('C', 1), 1, GPIO_FUNCTION(2)},
|
||||||
|
{TIM15, GPIO('C', 2), 2, GPIO_FUNCTION(2)},
|
||||||
|
{TIM3, GPIO('C', 6), 1, GPIO_FUNCTION(1)},
|
||||||
|
{TIM3, GPIO('C', 7), 2, GPIO_FUNCTION(1)},
|
||||||
|
{TIM3, GPIO('C', 8), 3, GPIO_FUNCTION(1)},
|
||||||
|
{TIM3, GPIO('C', 9), 4, GPIO_FUNCTION(1)},
|
||||||
|
{TIM1, GPIO('C', 10), 3, GPIO_FUNCTION(2)},
|
||||||
|
{TIM1, GPIO('C', 11), 4, GPIO_FUNCTION(2)},
|
||||||
|
{TIM14, GPIO('C', 12), 1, GPIO_FUNCTION(2)},
|
||||||
|
{TIM16, GPIO('D', 0), 1, GPIO_FUNCTION(2)},
|
||||||
|
{TIM17, GPIO('D', 1), 1, GPIO_FUNCTION(2)},
|
||||||
|
{TIM4, GPIO('D', 12), 1, GPIO_FUNCTION(2)},
|
||||||
|
{TIM4, GPIO('D', 13), 2, GPIO_FUNCTION(2)},
|
||||||
|
{TIM4, GPIO('D', 14), 3, GPIO_FUNCTION(2)},
|
||||||
|
{TIM4, GPIO('D', 15), 4, GPIO_FUNCTION(2)},
|
||||||
|
{TIM3, GPIO('E', 3), 1, GPIO_FUNCTION(1)},
|
||||||
|
{TIM3, GPIO('E', 4), 2, GPIO_FUNCTION(1)},
|
||||||
|
{TIM3, GPIO('E', 5), 3, GPIO_FUNCTION(1)},
|
||||||
|
{TIM3, GPIO('E', 6), 4, GPIO_FUNCTION(1)},
|
||||||
|
{TIM1, GPIO('E', 9), 1, GPIO_FUNCTION(1)},
|
||||||
|
{TIM1, GPIO('E', 11), 2, GPIO_FUNCTION(1)},
|
||||||
|
{TIM1, GPIO('E', 13), 3, GPIO_FUNCTION(1)},
|
||||||
|
{TIM1, GPIO('E', 14), 4, GPIO_FUNCTION(1)},
|
||||||
|
{TIM14, GPIO('F', 0), 1, GPIO_FUNCTION(2)},
|
||||||
|
{TIM15, GPIO('F', 12), 1, GPIO_FUNCTION(0)},
|
||||||
|
{TIM15, GPIO('F', 13), 2, GPIO_FUNCTION(0)},
|
||||||
#elif CONFIG_MACH_STM32H7
|
#elif CONFIG_MACH_STM32H7
|
||||||
{TIM2, GPIO('A', 0), 1, GPIO_FUNCTION(1)},
|
{TIM2, GPIO('A', 0), 1, GPIO_FUNCTION(1)},
|
||||||
{TIM2, GPIO('A', 5), 1, GPIO_FUNCTION(1)},
|
{TIM2, GPIO('A', 5), 1, GPIO_FUNCTION(1)},
|
||||||
|
@ -234,7 +281,7 @@ gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint8_t val){
|
||||||
}
|
}
|
||||||
// Enable PWM output
|
// Enable PWM output
|
||||||
p->timer->CR1 |= TIM_CR1_CEN;
|
p->timer->CR1 |= TIM_CR1_CEN;
|
||||||
#if CONFIG_MACH_STM32H7
|
#if CONFIG_MACH_STM32H7 || CONFIG_MACH_STM32G0
|
||||||
p->timer->BDTR |= TIM_BDTR_MOE;
|
p->timer->BDTR |= TIM_BDTR_MOE;
|
||||||
#endif
|
#endif
|
||||||
return channel;
|
return channel;
|
||||||
|
|
|
@ -38,14 +38,29 @@ lookup_clock_line(uint32_t periph_base)
|
||||||
return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<13};
|
return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<13};
|
||||||
if (periph_base == CRS_BASE)
|
if (periph_base == CRS_BASE)
|
||||||
return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<16};
|
return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<16};
|
||||||
|
if (periph_base == TIM1_BASE)
|
||||||
|
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<11};
|
||||||
if (periph_base == SPI1_BASE)
|
if (periph_base == SPI1_BASE)
|
||||||
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<12};
|
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<12};
|
||||||
if (periph_base == USART1_BASE)
|
if (periph_base == USART1_BASE)
|
||||||
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<14};
|
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<14};
|
||||||
|
if (periph_base == TIM14_BASE)
|
||||||
|
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<15};
|
||||||
|
if (periph_base == TIM15_BASE)
|
||||||
|
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<16};
|
||||||
|
if (periph_base == TIM16_BASE)
|
||||||
|
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<17};
|
||||||
|
if (periph_base == TIM17_BASE)
|
||||||
|
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<18};
|
||||||
if (periph_base == ADC1_BASE)
|
if (periph_base == ADC1_BASE)
|
||||||
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<20};
|
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<20};
|
||||||
|
if (periph_base >= APBPERIPH_BASE && periph_base <= LPTIM1_BASE)
|
||||||
|
{
|
||||||
uint32_t bit = 1 << ((periph_base - APBPERIPH_BASE) / 0x400);
|
uint32_t bit = 1 << ((periph_base - APBPERIPH_BASE) / 0x400);
|
||||||
return (struct cline){.en=&RCC->APBENR1, .rst=&RCC->APBRSTR1, .bit=bit};
|
return (struct cline){.en=&RCC->APBENR1, .rst=&RCC->APBRSTR1, .bit=bit};
|
||||||
|
}
|
||||||
|
// unknown peripheral. returning .bit=0 makes this a no-op
|
||||||
|
return (struct cline){.en=&RCC->APBENR1, .rst=NULL, .bit=0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the frequency of the given peripheral clock
|
// Return the frequency of the given peripheral clock
|
||||||
|
|
Loading…
Reference in New Issue