stm32: Initial support for stm32g0

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2021-12-18 19:11:17 -05:00
parent 4576b3918c
commit 6e8f28117b
6 changed files with 253 additions and 8 deletions

View File

@ -6,9 +6,9 @@ config STM32_SELECT
bool
default y
select HAVE_GPIO
select HAVE_GPIO_ADC
select HAVE_GPIO_I2C if !(MACH_STM32F031 || MACH_STM32H7)
select HAVE_GPIO_SPI if !MACH_STM32F031
select HAVE_GPIO_ADC if !MACH_STM32G0
select HAVE_GPIO_I2C if !(MACH_STM32F031 || MACH_STM32G0 || MACH_STM32H7)
select HAVE_GPIO_SPI if !(MACH_STM32F031 || MACH_STM32G0)
select HAVE_GPIO_HARD_PWM if MACH_STM32F1 || MACH_STM32F4 || MACH_STM32H7
select HAVE_GPIO_BITBANGING if !MACH_STM32F031
select HAVE_STRICT_TIMING
@ -64,6 +64,9 @@ choice
bool "STM32F072"
select MACH_STM32F0
select MACH_STM32F0x2
config MACH_STM32G0B1
bool "STM32G0B1"
select MACH_STM32G0
config MACH_STM32H743
bool "STM32H743"
select MACH_STM32H7
@ -80,6 +83,8 @@ config MACH_STM32F2
bool
config MACH_STM32F4
bool
config MACH_STM32G0
bool
config MACH_STM32H7
bool
config MACH_STM32F0x2 # F042, F072 series
@ -109,6 +114,7 @@ config MCU
default "stm32f407xx" if MACH_STM32F407
default "stm32f429xx" if MACH_STM32F429
default "stm32f446xx" if MACH_STM32F446
default "stm32g0b1xx" if MACH_STM32G0B1
default "stm32h743xx" if MACH_STM32H743
default "stm32h750xx" if MACH_STM32H750
@ -121,6 +127,7 @@ config CLOCK_FREQ
default 84000000 if MACH_STM32F401
default 168000000 if MACH_STM32F4x5
default 180000000 if MACH_STM32F446
default 64000000 if MACH_STM32G0
default 400000000 if MACH_STM32H7 # 400Mhz is max Klipper currently supports
config FLASH_SIZE
@ -131,6 +138,7 @@ config FLASH_SIZE
default 0x10000 if MACH_STM32F103 # Flash size of stm32f103x8 (64KiB)
default 0x40000 if MACH_STM32F2 || MACH_STM32F401
default 0x80000 if MACH_STM32F4x5 || MACH_STM32F446
default 0x20000 if MACH_STM32G0B1
default 0x20000 if MACH_STM32H750
default 0x200000 if MACH_STM32H743
@ -148,6 +156,7 @@ config RAM_SIZE
default 0x20000 if MACH_STM32F207
default 0x10000 if MACH_STM32F401
default 0x20000 if MACH_STM32F4x5 || MACH_STM32F446
default 0x24000 if MACH_STM32G0B1
default 0x20000 if MACH_STM32H750
default 0x80000 if MACH_STM32H743
@ -171,9 +180,9 @@ config STM32F103GD_DISABLE_SWD
######################################################################
choice
prompt "Bootloader offset" if MACH_STM32F1 || MACH_STM32F2 || MACH_STM32F4 || MACH_STM32F070 || MACH_STM32H743
prompt "Bootloader offset"
config STM32_FLASH_START_2000
bool "8KiB bootloader (stm32duino)" if MACH_STM32F103 || MACH_STM32F070
bool "8KiB bootloader" if MACH_STM32F103 || MACH_STM32F070 || MACH_STM32G0
config STM32_FLASH_START_5000
bool "20KiB bootloader" if MACH_STM32F103
config STM32_FLASH_START_7000

View File

@ -8,6 +8,7 @@ dirs-$(CONFIG_MACH_STM32F0) += lib/stm32f0
dirs-$(CONFIG_MACH_STM32F1) += lib/stm32f1
dirs-$(CONFIG_MACH_STM32F2) += lib/stm32f2
dirs-$(CONFIG_MACH_STM32F4) += lib/stm32f4
dirs-$(CONFIG_MACH_STM32G0) += lib/stm32g0
dirs-$(CONFIG_MACH_STM32H7) += lib/stm32h7
MCU := $(shell echo $(CONFIG_MCU))
@ -17,6 +18,7 @@ CFLAGS-$(CONFIG_MACH_STM32F0) += -mcpu=cortex-m0 -Ilib/stm32f0/include
CFLAGS-$(CONFIG_MACH_STM32F1) += -mcpu=cortex-m3 -Ilib/stm32f1/include
CFLAGS-$(CONFIG_MACH_STM32F2) += -mcpu=cortex-m3 -Ilib/stm32f2/include
CFLAGS-$(CONFIG_MACH_STM32F4) += -mcpu=cortex-m4 -Ilib/stm32f4/include
CFLAGS-$(CONFIG_MACH_STM32G0) += -mcpu=cortex-m0plus -Ilib/stm32g0/include
CFLAGS-$(CONFIG_MACH_STM32H7) += -mcpu=cortex-m7 -Ilib/stm32h7/include
CFLAGS += $(CFLAGS-y) -D$(MCU_UPPER) -mthumb -Ilib/cmsis-core -Ilib/fast-hash
@ -40,6 +42,8 @@ src-$(CONFIG_MACH_STM32F2) += stm32/gpioperiph.c stm32/adc.c stm32/i2c.c
src-$(CONFIG_MACH_STM32F4) += ../lib/stm32f4/system_stm32f4xx.c
src-$(CONFIG_MACH_STM32F4) += stm32/stm32f4.c generic/armcm_timer.c
src-$(CONFIG_MACH_STM32F4) += stm32/gpioperiph.c stm32/adc.c stm32/i2c.c
src-$(CONFIG_MACH_STM32G0) += generic/timer_irq.c stm32/stm32f0_timer.c
src-$(CONFIG_MACH_STM32G0) += stm32/stm32g0.c stm32/gpioperiph.c
src-$(CONFIG_MACH_STM32H7) += ../lib/stm32h7/system_stm32h7xx.c
src-$(CONFIG_MACH_STM32H7) += stm32/stm32h7.c generic/armcm_timer.c
src-$(CONFIG_MACH_STM32H7) += stm32/gpioperiph.c stm32/stm32h7_adc.c
@ -51,6 +55,7 @@ usb-src-$(CONFIG_HAVE_STM32_USBOTG) := stm32/usbotg.c
src-$(CONFIG_USBSERIAL) += $(usb-src-y) stm32/chipid.c generic/usb_cdc.c
serial-src-y := stm32/serial.c
serial-src-$(CONFIG_MACH_STM32F0) := stm32/stm32f0_serial.c
serial-src-$(CONFIG_MACH_STM32G0) := stm32/stm32f0_serial.c
serial-src-$(CONFIG_MACH_STM32H7) := stm32/stm32h7_serial.c
src-$(CONFIG_SERIAL) += $(serial-src-y) generic/serial_irq.c
src-$(CONFIG_CANSERIAL) += stm32/can.c ../lib/fast-hash/fasthash.c

View File

@ -31,6 +31,7 @@ gpio_peripheral(uint32_t gpio, uint32_t mode, int pullup)
// stm32f0 is ~10Mhz at 50pF
// stm32f2 is ~25Mhz at 40pF
// stm32f4 is ~50Mhz at 40pF
// stm32g0 is ~30Mhz at 50pF
// stm32h7 is ~85Mhz at 50pF
uint32_t ospeed = CONFIG_MACH_STM32F0 ? 0x01 : 0x02;
regs->OSPEEDR = (regs->OSPEEDR & ~m_msk) | (ospeed << m_shift);

View File

@ -12,6 +12,8 @@
#include "stm32f2xx.h"
#elif CONFIG_MACH_STM32F4
#include "stm32f4xx.h"
#elif CONFIG_MACH_STM32G0
#include "stm32g0xx.h"
#elif CONFIG_MACH_STM32H7
#include "stm32h7xx.h"
#endif

View File

@ -48,6 +48,17 @@
#define USART2_IRQn USART1_IRQn
#endif
#if CONFIG_MACH_STM32G0
// The stm32g0 has slightly different register names
#define USART2_IRQn USART2_LPUART2_IRQn
#define USART_CR1_RXNEIE USART_CR1_RXNEIE_RXFNEIE
#define USART_CR1_TXEIE USART_CR1_TXEIE_TXFNFIE
#define USART_ISR_RXNE USART_ISR_RXNE_RXFNE
#define USART_ISR_TXE USART_ISR_TXE_TXFNF
#define USART_BRR_DIV_MANTISSA_Pos 4
#define USART_BRR_DIV_FRACTION_Pos 0
#endif
#define CR1_FLAGS (USART_CR1_UE | USART_CR1_RE | USART_CR1_TE \
| USART_CR1_RXNEIE)

217
src/stm32/stm32g0.c Normal file
View File

@ -0,0 +1,217 @@
// Code to setup clocks on stm32g0
//
// Copyright (C) 2019-2021 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
#include "autoconf.h" // CONFIG_CLOCK_REF_FREQ
#include "board/armcm_boot.h" // armcm_main
#include "board/irq.h" // irq_disable
#include "command.h" // DECL_CONSTANT_STR
#include "internal.h" // enable_pclock
#include "sched.h" // sched_main
/****************************************************************
* Clock setup
****************************************************************/
#define FREQ_PERIPH 64000000
#define FREQ_USB 48000000
// Map an APB peripheral address to an enable bit
static int
lookup_apb_bit(uint32_t periph_base)
{
if (periph_base == USB_BASE)
return 13;
if (periph_base == CRS_BASE)
return 16;
if (periph_base == SPI1_BASE)
return 32 + 12;
if (periph_base == USART1_BASE)
return 32 + 14;
if (periph_base == ADC1_BASE)
return 32 + 20;
return (periph_base - APBPERIPH_BASE) / 0x400;
}
// Enable a peripheral clock
void
enable_pclock(uint32_t periph_base)
{
if (periph_base >= IOPORT_BASE) {
uint32_t pos = (periph_base - IOPORT_BASE) / 0x400;
RCC->IOPENR |= 1 << pos;
RCC->IOPENR;
RCC->IOPRSTR |= (1<<pos);
RCC->IOPRSTR &= ~(1<<pos);
} else if (periph_base >= AHBPERIPH_BASE) {
uint32_t pos = (periph_base - AHBPERIPH_BASE) / 0x400;
RCC->AHBENR |= 1 << pos;
RCC->AHBENR;
RCC->AHBRSTR |= (1<<pos);
RCC->AHBRSTR &= ~(1<<pos);
} else {
uint32_t pos = lookup_apb_bit(periph_base);
if (pos < 32) {
RCC->APBENR1 |= 1 << pos;
RCC->APBENR1;
RCC->APBRSTR1 |= (1 << pos);
RCC->APBRSTR1 &= ~(1 << pos);
} else {
RCC->APBENR2 |= 1 << (pos - 32);
RCC->APBENR2;
RCC->APBRSTR2 |= (1 << (pos - 32));
RCC->APBRSTR2 &= ~(1 << (pos - 32));
}
}
}
// Check if a peripheral clock has been enabled
int
is_enabled_pclock(uint32_t periph_base)
{
if (periph_base >= IOPORT_BASE) {
uint32_t pos = (periph_base - IOPORT_BASE) / 0x400;
return RCC->IOPENR & (1 << pos);
} else if (periph_base >= AHBPERIPH_BASE) {
uint32_t pos = (periph_base - AHBPERIPH_BASE) / 0x400;
return RCC->AHBENR & (1 << pos);
} else {
uint32_t pos = lookup_apb_bit(periph_base);
if (pos < 32)
return RCC->APBENR1 & (1 << pos);
return RCC->APBENR2 & (1 << (pos - 32));
}
}
// Return the frequency of the given peripheral clock
uint32_t
get_pclock_frequency(uint32_t periph_base)
{
return FREQ_PERIPH;
}
// Enable a GPIO peripheral clock
void
gpio_clock_enable(GPIO_TypeDef *regs)
{
uint32_t rcc_pos = ((uint32_t)regs - IOPORT_BASE) / 0x400;
RCC->IOPENR |= 1 << rcc_pos;
RCC->IOPENR;
}
#if !CONFIG_STM32_CLOCK_REF_INTERNAL
DECL_CONSTANT_STR("RESERVE_PINS_crystal", "PF0,PF1");
#endif
// Configure and enable the PLL as clock source
static void
clock_setup(void)
{
uint32_t pll_base = 4000000, pll_freq = 192000000, pllcfgr;
if (!CONFIG_STM32_CLOCK_REF_INTERNAL) {
// Configure PLL from external crystal (HSE)
uint32_t div = CONFIG_CLOCK_REF_FREQ / pll_base;
RCC->CR |= RCC_CR_HSEON;
pllcfgr = RCC_PLLCFGR_PLLSRC_HSE | ((div - 1) << RCC_PLLCFGR_PLLM_Pos);
} else {
// Configure PLL from internal 16Mhz oscillator (HSI)
uint32_t div = 16000000 / pll_base;
pllcfgr = RCC_PLLCFGR_PLLSRC_HSI | ((div - 1) << RCC_PLLCFGR_PLLM_Pos);
}
pllcfgr |= (pll_freq/pll_base) << RCC_PLLCFGR_PLLN_Pos;
pllcfgr |= (pll_freq/CONFIG_CLOCK_FREQ - 1) << RCC_PLLCFGR_PLLR_Pos;
RCC->PLLCFGR = pllcfgr | RCC_PLLCFGR_PLLREN;
RCC->CR |= RCC_CR_PLLON;
// Wait for PLL lock
while (!(RCC->CR & RCC_CR_PLLRDY))
;
// Switch system clock to PLL
RCC->CFGR = (2 << RCC_CFGR_SW_Pos);
while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != (2 << RCC_CFGR_SWS_Pos))
;
// Enable USB clock
if (CONFIG_USBSERIAL) {
RCC->CR |= RCC_CR_HSI48ON;
while (!(RCC->CR & RCC_CR_HSI48RDY))
;
enable_pclock(CRS_BASE);
CRS->CR |= CRS_CR_AUTOTRIMEN | CRS_CR_CEN;
}
}
/****************************************************************
* USB bootloader
****************************************************************/
#define USB_BOOT_FLAG_ADDR (CONFIG_RAM_START + CONFIG_RAM_SIZE - 1024)
#define USB_BOOT_FLAG 0x55534220424f4f54 // "USB BOOT"
// Flag that bootloader is desired and reboot
static void
usb_reboot_for_dfu_bootloader(void)
{
irq_disable();
*(uint64_t*)USB_BOOT_FLAG_ADDR = USB_BOOT_FLAG;
NVIC_SystemReset();
}
// Check if rebooting into system DFU Bootloader
static void
check_usb_dfu_bootloader(void)
{
if (!CONFIG_USBSERIAL || *(uint64_t*)USB_BOOT_FLAG_ADDR != USB_BOOT_FLAG)
return;
*(uint64_t*)USB_BOOT_FLAG_ADDR = 0;
uint32_t *sysbase = (uint32_t*)0x1fff0000;
asm volatile("mov sp, %0\n bx %1"
: : "r"(sysbase[0]), "r"(sysbase[1]));
}
// Handle USB reboot requests
void
usb_request_bootloader(void)
{
usb_reboot_for_dfu_bootloader();
}
/****************************************************************
* Startup
****************************************************************/
// Main entry point - called from armcm_boot.c:ResetHandler()
void
armcm_main(void)
{
check_usb_dfu_bootloader();
SCB->VTOR = (uint32_t)VectorTable;
// Reset clock registers (in case bootloader has changed them)
RCC->CR |= RCC_CR_HSION;
while (!(RCC->CR & RCC_CR_HSIRDY))
;
RCC->CFGR = 0x00000000;
RCC->CR = RCC_CR_HSION;
while (RCC->CR & RCC_CR_PLLRDY)
;
RCC->PLLCFGR = 0x00001000;
RCC->IOPENR = 0x00000000;
RCC->AHBENR = 0x00000100;
RCC->APBENR1 = 0x00000000;
RCC->APBENR2 = 0x00000000;
// Set flash latency
FLASH->ACR = (2<<FLASH_ACR_LATENCY_Pos) | FLASH_ACR_ICEN | FLASH_ACR_PRFTEN;
// Configure main clock
clock_setup();
sched_main();
}