mirror of
https://github.com/andreili/katapult.git
synced 2025-08-23 19:34:06 +02:00
stm32: Add stm32g0 support
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
4857a70189
commit
115582ce88
@ -65,7 +65,7 @@ choice
|
||||
select MACH_STM32F0
|
||||
select MACH_STM32F0x2
|
||||
config MACH_STM32G0B1
|
||||
bool "STM32G0B1" if 0
|
||||
bool "STM32G0B1"
|
||||
select MACH_STM32G0
|
||||
config MACH_STM32H743
|
||||
bool "STM32H743" if 0
|
||||
@ -348,9 +348,9 @@ choice
|
||||
config STM32_APP_START_4000
|
||||
bool "16KiB offset" if MACH_STM32F2 || MACH_STM32F4
|
||||
config STM32_APP_START_2000
|
||||
bool "8KiB offset" if MACH_STM32F0 || MACH_STM32F1
|
||||
bool "8KiB offset" if MACH_STM32F0 || MACH_STM32F1 || MACH_STM32G0
|
||||
config STM32_APP_START_1000
|
||||
bool "4KiB offset" if MACH_STM32F0 || MACH_STM32F1
|
||||
bool "4KiB offset" if MACH_STM32F0 || MACH_STM32F1 || MACH_STM32G0
|
||||
endchoice
|
||||
|
||||
config APPLICATION_START
|
||||
|
@ -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
|
||||
|
||||
MCU := $(shell echo $(CONFIG_MCU))
|
||||
MCU_UPPER := $(shell echo $(CONFIG_MCU) | tr a-z A-Z | tr X x)
|
||||
@ -16,6 +17,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 += $(CFLAGS-y) -D$(MCU_UPPER) -mthumb -Ilib/cmsis-core -Ilib/fast-hash
|
||||
|
||||
CFLAGS_canboot.elf += --specs=nano.specs --specs=nosys.specs
|
||||
@ -40,6 +42,9 @@ 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
|
||||
|
||||
src-$(CONFIG_MACH_STM32G0) += stm32/stm32f0_timer.c
|
||||
src-$(CONFIG_MACH_STM32G0) += stm32/stm32g0.c stm32/gpioperiph.c
|
||||
|
||||
usb-src-$(CONFIG_HAVE_STM32_USBFS) := stm32/usbfs.c
|
||||
usb-src-$(CONFIG_HAVE_STM32_USBOTG) := stm32/usbotg.c
|
||||
src-$(CONFIG_USBSERIAL) += $(usb-src-y) stm32/chipid.c generic/usb_cdc.c
|
||||
|
@ -32,6 +32,8 @@ flash_get_page_size(uint32_t addr)
|
||||
return 2 * 1024;
|
||||
uint16_t *flash_size = (void*)FLASHSIZE_BASE;
|
||||
return *flash_size <= 64 ? 1024 : 2 * 1024;
|
||||
} else if (CONFIG_MACH_STM32G0) {
|
||||
return 2 * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,6 +48,10 @@ check_erased(uint32_t addr, uint32_t count)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if CONFIG_MACH_STM32G0 // stm32g0 chip has slightly different bit name
|
||||
#define FLASH_SR_BSY (FLASH_SR_BSY1 | FLASH_SR_BSY2)
|
||||
#endif
|
||||
|
||||
// Wait for flash hardware to report ready
|
||||
static void
|
||||
wait_flash(void)
|
||||
@ -93,10 +99,21 @@ erase_page(uint32_t page_address)
|
||||
sidx = sidx > 0x0f ? 0x0f : sidx;
|
||||
FLASH->CR = (FLASH_CR_PSIZE_1 | FLASH_CR_STRT | FLASH_CR_SER
|
||||
| (sidx << FLASH_CR_SNB_Pos));
|
||||
#else
|
||||
#elif CONFIG_MACH_STM32F0 || CONFIG_MACH_STM32F1
|
||||
FLASH->CR = FLASH_CR_PER;
|
||||
FLASH->AR = page_address;
|
||||
FLASH->CR = FLASH_CR_PER | FLASH_CR_STRT;
|
||||
#elif CONFIG_MACH_STM32G0
|
||||
uint32_t pidx = (page_address - 0x08000000) / (2 * 1024);
|
||||
if (pidx >= 64) {
|
||||
uint16_t *flash_size = (void*)FLASHSIZE_BASE;
|
||||
if (*flash_size <= 256)
|
||||
pidx = pidx + 256 - 64;
|
||||
else
|
||||
pidx = pidx < 128 ? pidx : pidx + 256 - 128;
|
||||
}
|
||||
pidx = pidx > 0x3ff ? 0x3ff : pidx;
|
||||
FLASH->CR = FLASH_CR_PER | FLASH_CR_STRT | (pidx << FLASH_CR_PNB_Pos);
|
||||
#endif
|
||||
wait_flash();
|
||||
}
|
||||
@ -112,13 +129,21 @@ write_block(uint32_t block_address, uint32_t *data)
|
||||
writel(&page[i], data[i]);
|
||||
wait_flash();
|
||||
}
|
||||
#else
|
||||
#elif CONFIG_MACH_STM32F0 || CONFIG_MACH_STM32F1
|
||||
uint16_t *page = (void*)block_address, *data16 = (void*)data;
|
||||
FLASH->CR = FLASH_CR_PG;
|
||||
for (int i = 0; i < CONFIG_BLOCK_SIZE / 2; i++) {
|
||||
writew(&page[i], data16[i]);
|
||||
wait_flash();
|
||||
}
|
||||
#elif CONFIG_MACH_STM32G0
|
||||
uint32_t *page = (void*)block_address;
|
||||
FLASH->CR = FLASH_CR_PG;
|
||||
for (int i = 0; i < CONFIG_BLOCK_SIZE / 8; i++) {
|
||||
writel(&page[i*2], data[i*2]);
|
||||
writel(&page[i*2 + 1], data[i*2 + 1]);
|
||||
wait_flash();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
133
src/stm32/stm32g0.c
Normal file
133
src/stm32/stm32g0.c
Normal file
@ -0,0 +1,133 @@
|
||||
// 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 a peripheral address to its enable bits
|
||||
struct cline
|
||||
lookup_clock_line(uint32_t periph_base)
|
||||
{
|
||||
if (periph_base >= IOPORT_BASE) {
|
||||
uint32_t bit = 1 << ((periph_base - IOPORT_BASE) / 0x400);
|
||||
return (struct cline){.en=&RCC->IOPENR, .rst=&RCC->IOPRSTR, .bit=bit};
|
||||
} else if (periph_base >= AHBPERIPH_BASE) {
|
||||
uint32_t bit = 1 << ((periph_base - AHBPERIPH_BASE) / 0x400);
|
||||
return (struct cline){.en=&RCC->AHBENR, .rst=&RCC->AHBRSTR, .bit=bit};
|
||||
}
|
||||
if (periph_base == USB_BASE)
|
||||
return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<13};
|
||||
if (periph_base == CRS_BASE)
|
||||
return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<16};
|
||||
if (periph_base == SPI1_BASE)
|
||||
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<12};
|
||||
if (periph_base == USART1_BASE)
|
||||
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<14};
|
||||
if (periph_base == ADC1_BASE)
|
||||
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<20};
|
||||
uint32_t bit = 1 << ((periph_base - APBPERIPH_BASE) / 0x400);
|
||||
return (struct cline){.en=&RCC->APBENR1, .rst=&RCC->APBRSTR1, .bit=bit};
|
||||
}
|
||||
|
||||
// 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;
|
||||
pllcfgr |= (pll_freq/FREQ_USB - 1) << RCC_PLLCFGR_PLLQ_Pos;
|
||||
RCC->PLLCFGR = pllcfgr | RCC_PLLCFGR_PLLREN | RCC_PLLCFGR_PLLQEN;
|
||||
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))
|
||||
;
|
||||
|
||||
// Use PLLQCLK for USB (setting USBSEL=2 works in practice)
|
||||
RCC->CCIPR2 = 2 << RCC_CCIPR2_USBSEL_Pos;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Startup
|
||||
****************************************************************/
|
||||
|
||||
// Main entry point - called from armcm_boot.c:ResetHandler()
|
||||
void
|
||||
armcm_main(void)
|
||||
{
|
||||
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();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user