stm32f4: Add support for STM32F103
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
485164b8b3
commit
7efc53ff59
|
@ -16,32 +16,47 @@ config BOARD_DIRECTORY
|
||||||
|
|
||||||
choice
|
choice
|
||||||
prompt "Processor model"
|
prompt "Processor model"
|
||||||
|
config MACH_STM32F103
|
||||||
|
bool "STM32F103"
|
||||||
|
select MACH_STM32F1xx
|
||||||
config MACH_STM32F405
|
config MACH_STM32F405
|
||||||
bool "STM32F405"
|
bool "STM32F405"
|
||||||
|
select MACH_STM32F4xx
|
||||||
config MACH_STM32F407
|
config MACH_STM32F407
|
||||||
bool "STM32F407"
|
bool "STM32F407"
|
||||||
|
select MACH_STM32F4xx
|
||||||
config MACH_STM32F446
|
config MACH_STM32F446
|
||||||
bool "STM32F446"
|
bool "STM32F446"
|
||||||
|
select MACH_STM32F4xx
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
config MACH_STM32F1xx
|
||||||
|
bool
|
||||||
|
config MACH_STM32F4xx
|
||||||
|
bool
|
||||||
|
|
||||||
config MCU
|
config MCU
|
||||||
string
|
string
|
||||||
default "stm32f405" if MACH_STM32F405
|
default "stm32f103xb" if MACH_STM32F103
|
||||||
default "stm32f407" if MACH_STM32F407
|
default "stm32f405xx" if MACH_STM32F405
|
||||||
default "stm32f446" if MACH_STM32F446
|
default "stm32f407xx" if MACH_STM32F407
|
||||||
|
default "stm32f446xx" if MACH_STM32F446
|
||||||
|
|
||||||
config CLOCK_FREQ
|
config CLOCK_FREQ
|
||||||
int
|
int
|
||||||
|
default 72000000 if MACH_STM32F103
|
||||||
default 168000000 if MACH_STM32F405 || MACH_STM32F407
|
default 168000000 if MACH_STM32F405 || MACH_STM32F407
|
||||||
default 180000000 if MACH_STM32F446
|
default 180000000 if MACH_STM32F446
|
||||||
|
|
||||||
config FLASH_SIZE
|
config FLASH_SIZE
|
||||||
hex
|
hex
|
||||||
|
default 0x10000 if MACH_STM32F103
|
||||||
default 0x80000 if MACH_STM32F405 || MACH_STM32F407
|
default 0x80000 if MACH_STM32F405 || MACH_STM32F407
|
||||||
default 0x80000 if MACH_STM32F446
|
default 0x80000 if MACH_STM32F446
|
||||||
|
|
||||||
config RAM_SIZE
|
config RAM_SIZE
|
||||||
hex
|
hex
|
||||||
|
default 0x5000 if MACH_STM32F103
|
||||||
default 0x30000 if MACH_STM32F405 || MACH_STM32F407
|
default 0x30000 if MACH_STM32F405 || MACH_STM32F407
|
||||||
default 0x20000 if MACH_STM32F446
|
default 0x20000 if MACH_STM32F446
|
||||||
|
|
||||||
|
|
|
@ -4,20 +4,26 @@
|
||||||
CROSS_PREFIX=arm-none-eabi-
|
CROSS_PREFIX=arm-none-eabi-
|
||||||
|
|
||||||
dirs-y += src/stm32f4 src/generic
|
dirs-y += src/stm32f4 src/generic
|
||||||
dirs-y += lib/stm32f4 lib/stm32f4/gcc
|
dirs-$(CONFIG_MACH_STM32F1xx) += lib/stm32f1 lib/stm32f1/gcc
|
||||||
|
dirs-$(CONFIG_MACH_STM32F4xx) += lib/stm32f4 lib/stm32f4/gcc
|
||||||
|
|
||||||
MCU := $(shell echo $(CONFIG_MCU) | tr a-z A-Z)
|
MCU := $(shell echo $(CONFIG_MCU))
|
||||||
CFLAGS += -D$(MCU)xx
|
MCU_UPPER := $(shell echo $(CONFIG_MCU) | tr a-z A-Z | tr X x)
|
||||||
|
|
||||||
CFLAGS += -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard
|
CFLAGS-$(CONFIG_MACH_STM32F1xx) += -mcpu=cortex-m3 -Ilib/stm32f1/include
|
||||||
CFLAGS += -Ilib/cmsis-core -Ilib/stm32f4/include
|
CFLAGS-$(CONFIG_MACH_STM32F4xx) += -mcpu=cortex-m4 -Ilib/stm32f4/include
|
||||||
|
CFLAGS-$(CONFIG_MACH_STM32F4xx) += -mfpu=fpv4-sp-d16 -mfloat-abi=hard
|
||||||
|
|
||||||
|
CFLAGS += $(CFLAGS-y) -D$(MCU_UPPER) -mthumb -Ilib/cmsis-core
|
||||||
CFLAGS_klipper.elf += -T $(OUT)stm32f4.ld --specs=nano.specs --specs=nosys.specs
|
CFLAGS_klipper.elf += -T $(OUT)stm32f4.ld --specs=nano.specs --specs=nosys.specs
|
||||||
|
|
||||||
# Add source files
|
# Add source files
|
||||||
src-y += stm32f4/main.c stm32f4/clock.c stm32f4/watchdog.c stm32f4/gpio.c
|
src-y += stm32f4/main.c stm32f4/watchdog.c stm32f4/gpio.c
|
||||||
src-y += generic/crc16_ccitt.c generic/armcm_irq.c generic/armcm_timer.c
|
src-y += generic/crc16_ccitt.c generic/armcm_irq.c generic/armcm_timer.c
|
||||||
src-y += ../lib/stm32f4/system_stm32f4xx.c
|
src-$(CONFIG_MACH_STM32F1xx) += ../lib/stm32f1/system_stm32f1xx.c
|
||||||
|
src-$(CONFIG_MACH_STM32F1xx) += stm32f4/stm32f1.c
|
||||||
|
src-$(CONFIG_MACH_STM32F4xx) += ../lib/stm32f4/system_stm32f4xx.c
|
||||||
|
src-$(CONFIG_MACH_STM32F4xx) += stm32f4/clock.c
|
||||||
src-$(CONFIG_HAVE_GPIO_ADC) += stm32f4/adc.c
|
src-$(CONFIG_HAVE_GPIO_ADC) += stm32f4/adc.c
|
||||||
src-$(CONFIG_HAVE_GPIO_SPI) += stm32f4/spi.c
|
src-$(CONFIG_HAVE_GPIO_SPI) += stm32f4/spi.c
|
||||||
src-$(CONFIG_SERIAL) += stm32f4/serial.c generic/serial_irq.c
|
src-$(CONFIG_SERIAL) += stm32f4/serial.c generic/serial_irq.c
|
||||||
|
@ -27,7 +33,8 @@ $(OUT)%.o: %.s $(OUT)autoconf.h $(OUT)board-link
|
||||||
@echo " Assembling $@"
|
@echo " Assembling $@"
|
||||||
$(Q)$(AS) $< -o $@
|
$(Q)$(AS) $< -o $@
|
||||||
|
|
||||||
asmsrc-y := ../lib/stm32f4/gcc/startup_$(shell echo $(CONFIG_MCU))xx.s
|
asmsrc-$(CONFIG_MACH_STM32F1xx) := ../lib/stm32f1/gcc/startup_$(MCU).s
|
||||||
|
asmsrc-$(CONFIG_MACH_STM32F4xx) := ../lib/stm32f4/gcc/startup_$(MCU).s
|
||||||
OBJS_klipper.elf += $(patsubst %.s, $(OUT)src/%.o,$(asmsrc-y))
|
OBJS_klipper.elf += $(patsubst %.s, $(OUT)src/%.o,$(asmsrc-y))
|
||||||
|
|
||||||
# Build the linker script
|
# Build the linker script
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "board/misc.h" // timer_from_us
|
#include "board/misc.h" // timer_from_us
|
||||||
#include "command.h" // shutdown
|
#include "command.h" // shutdown
|
||||||
#include "compiler.h" // ARRAY_SIZE
|
#include "compiler.h" // ARRAY_SIZE
|
||||||
|
#include "generic/armcm_timer.h" // udelay
|
||||||
#include "gpio.h" // gpio_adc_setup
|
#include "gpio.h" // gpio_adc_setup
|
||||||
#include "internal.h" // GPIO
|
#include "internal.h" // GPIO
|
||||||
#include "sched.h" // sched_shutdown
|
#include "sched.h" // sched_shutdown
|
||||||
|
@ -21,6 +22,12 @@ static const uint8_t adc_pins[] = {
|
||||||
GPIO('C', 2), GPIO('C', 3), GPIO('C', 4), GPIO('C', 5)
|
GPIO('C', 2), GPIO('C', 3), GPIO('C', 4), GPIO('C', 5)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if CONFIG_MACH_STM32F1xx
|
||||||
|
#define CR2_FLAGS (ADC_CR2_ADON | (7 << ADC_CR2_EXTSEL_Pos) | ADC_CR2_EXTTRIG)
|
||||||
|
#else
|
||||||
|
#define CR2_FLAGS ADC_CR2_ADON
|
||||||
|
#endif
|
||||||
|
|
||||||
struct gpio_adc
|
struct gpio_adc
|
||||||
gpio_adc_setup(uint32_t pin)
|
gpio_adc_setup(uint32_t pin)
|
||||||
{
|
{
|
||||||
|
@ -36,14 +43,22 @@ gpio_adc_setup(uint32_t pin)
|
||||||
// Enable the ADC
|
// Enable the ADC
|
||||||
if (!is_enabled_pclock(ADC1_BASE)) {
|
if (!is_enabled_pclock(ADC1_BASE)) {
|
||||||
enable_pclock(ADC1_BASE);
|
enable_pclock(ADC1_BASE);
|
||||||
uint32_t aticks = 3; // 56 adc cycles
|
uint32_t aticks = 3; // 2.5-3.2us (depending on stm32 chip)
|
||||||
ADC1->SMPR1 = (aticks | (aticks << 3) | (aticks << 6) | (aticks << 9)
|
ADC1->SMPR1 = (aticks | (aticks << 3) | (aticks << 6) | (aticks << 9)
|
||||||
| (aticks << 12) | (aticks << 15) | (aticks << 18)
|
| (aticks << 12) | (aticks << 15) | (aticks << 18)
|
||||||
| (aticks << 21) | (aticks << 24));
|
| (aticks << 21) | (aticks << 24));
|
||||||
ADC1->SMPR2 = (aticks | (aticks << 3) | (aticks << 6) | (aticks << 9)
|
ADC1->SMPR2 = (aticks | (aticks << 3) | (aticks << 6) | (aticks << 9)
|
||||||
| (aticks << 12) | (aticks << 15) | (aticks << 18)
|
| (aticks << 12) | (aticks << 15) | (aticks << 18)
|
||||||
| (aticks << 21) | (aticks << 24) | (aticks << 27));
|
| (aticks << 21) | (aticks << 24) | (aticks << 27));
|
||||||
ADC1->CR2 = ADC_CR2_ADON;
|
ADC1->CR2 = CR2_FLAGS;
|
||||||
|
|
||||||
|
#if CONFIG_MACH_STM32F1xx
|
||||||
|
// Perform calibration
|
||||||
|
udelay(timer_from_us(1));
|
||||||
|
ADC1->CR2 = ADC_CR2_CAL | CR2_FLAGS;
|
||||||
|
while (ADC1->CR2 & ADC_CR2_CAL)
|
||||||
|
;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
gpio_peripheral(pin, GPIO_ANALOG, 0);
|
gpio_peripheral(pin, GPIO_ANALOG, 0);
|
||||||
|
@ -67,9 +82,10 @@ gpio_adc_sample(struct gpio_adc g)
|
||||||
}
|
}
|
||||||
// Start sample
|
// Start sample
|
||||||
ADC1->SQR3 = g.chan;
|
ADC1->SQR3 = g.chan;
|
||||||
ADC1->CR2 = ADC_CR2_SWSTART | ADC_CR2_ADON;
|
ADC1->CR2 = ADC_CR2_SWSTART | CR2_FLAGS;
|
||||||
|
|
||||||
need_delay:
|
need_delay:
|
||||||
return timer_from_us(4);
|
return timer_from_us(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a value; use only after gpio_adc_sample() returns zero
|
// Read a value; use only after gpio_adc_sample() returns zero
|
||||||
|
|
|
@ -16,15 +16,20 @@ DECL_ENUMERATION_RANGE("pin", "PB0", GPIO('B', 0), 32);
|
||||||
DECL_ENUMERATION_RANGE("pin", "PC0", GPIO('C', 0), 32);
|
DECL_ENUMERATION_RANGE("pin", "PC0", GPIO('C', 0), 32);
|
||||||
DECL_ENUMERATION_RANGE("pin", "PD0", GPIO('D', 0), 32);
|
DECL_ENUMERATION_RANGE("pin", "PD0", GPIO('D', 0), 32);
|
||||||
DECL_ENUMERATION_RANGE("pin", "PE0", GPIO('E', 0), 32);
|
DECL_ENUMERATION_RANGE("pin", "PE0", GPIO('E', 0), 32);
|
||||||
|
#ifdef GPIOH
|
||||||
DECL_ENUMERATION_RANGE("pin", "PF0", GPIO('F', 0), 32);
|
DECL_ENUMERATION_RANGE("pin", "PF0", GPIO('F', 0), 32);
|
||||||
DECL_ENUMERATION_RANGE("pin", "PG0", GPIO('G', 0), 32);
|
DECL_ENUMERATION_RANGE("pin", "PG0", GPIO('G', 0), 32);
|
||||||
DECL_ENUMERATION_RANGE("pin", "PH0", GPIO('H', 0), 32);
|
DECL_ENUMERATION_RANGE("pin", "PH0", GPIO('H', 0), 32);
|
||||||
|
#endif
|
||||||
#ifdef GPIOI
|
#ifdef GPIOI
|
||||||
DECL_ENUMERATION_RANGE("pin", "PI0", GPIO('I', 0), 32);
|
DECL_ENUMERATION_RANGE("pin", "PI0", GPIO('I', 0), 32);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GPIO_TypeDef * const digital_regs[] = {
|
GPIO_TypeDef * const digital_regs[] = {
|
||||||
GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH,
|
GPIOA, GPIOB, GPIOC, GPIOD, GPIOE,
|
||||||
|
#ifdef GPIOH
|
||||||
|
GPIOF, GPIOG, GPIOH,
|
||||||
|
#endif
|
||||||
#ifdef GPIOI
|
#ifdef GPIOI
|
||||||
GPIOI,
|
GPIOI,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,7 +2,13 @@
|
||||||
#define __STM32F4_INTERNAL_H
|
#define __STM32F4_INTERNAL_H
|
||||||
// Local definitions for STM32F4 code
|
// Local definitions for STM32F4 code
|
||||||
|
|
||||||
|
#include "autoconf.h" // CONFIG_MACH_STM32F1xx
|
||||||
|
|
||||||
|
#if CONFIG_MACH_STM32F1xx
|
||||||
|
#include "stm32f1xx.h"
|
||||||
|
#else
|
||||||
#include "stm32f4xx.h"
|
#include "stm32f4xx.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
extern GPIO_TypeDef * const digital_regs[];
|
extern GPIO_TypeDef * const digital_regs[];
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
// Code to setup clocks and gpio on stm32f1
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019 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_8M
|
||||||
|
#include "internal.h" // enable_pclock
|
||||||
|
|
||||||
|
#define FREQ_PERIPH (CONFIG_CLOCK_FREQ / 2)
|
||||||
|
|
||||||
|
// Enable a peripheral clock
|
||||||
|
void
|
||||||
|
enable_pclock(uint32_t periph_base)
|
||||||
|
{
|
||||||
|
if (periph_base < APB2PERIPH_BASE) {
|
||||||
|
uint32_t pos = (periph_base - APB1PERIPH_BASE) / 0x400;
|
||||||
|
RCC->APB1ENR |= (1<<pos);
|
||||||
|
RCC->APB1ENR;
|
||||||
|
} else if (periph_base < AHBPERIPH_BASE) {
|
||||||
|
uint32_t pos = (periph_base - APB2PERIPH_BASE) / 0x400;
|
||||||
|
RCC->APB2ENR |= (1<<pos);
|
||||||
|
RCC->APB2ENR;
|
||||||
|
} else {
|
||||||
|
uint32_t pos = (periph_base - AHBPERIPH_BASE) / 0x400;
|
||||||
|
RCC->AHBENR |= (1<<pos);
|
||||||
|
RCC->AHBENR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a peripheral clock has been enabled
|
||||||
|
int
|
||||||
|
is_enabled_pclock(uint32_t periph_base)
|
||||||
|
{
|
||||||
|
if (periph_base < APB2PERIPH_BASE) {
|
||||||
|
uint32_t pos = (periph_base - APB1PERIPH_BASE) / 0x400;
|
||||||
|
return RCC->APB1ENR & (1<<pos);
|
||||||
|
} else if (periph_base < AHBPERIPH_BASE) {
|
||||||
|
uint32_t pos = (periph_base - APB2PERIPH_BASE) / 0x400;
|
||||||
|
return RCC->APB2ENR & (1<<pos);
|
||||||
|
} else {
|
||||||
|
uint32_t pos = (periph_base - AHBPERIPH_BASE) / 0x400;
|
||||||
|
return RCC->AHBENR & (1<<pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the frequency of the given peripheral clock
|
||||||
|
uint32_t
|
||||||
|
get_pclock_frequency(uint32_t periph_base)
|
||||||
|
{
|
||||||
|
return FREQ_PERIPH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the mode and extended function of a pin
|
||||||
|
void
|
||||||
|
gpio_peripheral(uint32_t gpio, uint32_t mode, int pullup)
|
||||||
|
{
|
||||||
|
GPIO_TypeDef *regs = digital_regs[GPIO2PORT(gpio)];
|
||||||
|
|
||||||
|
// Enable GPIO clock
|
||||||
|
uint32_t rcc_pos = ((uint32_t)regs - APB2PERIPH_BASE) / 0x400;
|
||||||
|
RCC->APB2ENR |= 1 << rcc_pos;
|
||||||
|
|
||||||
|
// Configure GPIO
|
||||||
|
uint32_t pos = gpio % 16, shift = (pos % 8) * 4, msk = 0xf << shift, cfg;
|
||||||
|
if (mode == GPIO_INPUT) {
|
||||||
|
cfg = pullup ? 0x8 : 0x4;
|
||||||
|
} else if (mode == GPIO_OUTPUT) {
|
||||||
|
cfg = 0x1;
|
||||||
|
} else if (mode == GPIO_ANALOG) {
|
||||||
|
cfg = 0x0;
|
||||||
|
} else {
|
||||||
|
if (pullup > 0)
|
||||||
|
// Alternate function input pins use GPIO_INPUT mode on the stm32f1
|
||||||
|
cfg = 0x8;
|
||||||
|
else
|
||||||
|
cfg = 0x9;
|
||||||
|
}
|
||||||
|
if (pos & 0x8)
|
||||||
|
regs->CRH = (regs->CRH & ~msk) | (cfg << shift);
|
||||||
|
else
|
||||||
|
regs->CRL = (regs->CRL & ~msk) | (cfg << shift);
|
||||||
|
|
||||||
|
if (pullup > 0)
|
||||||
|
regs->BSRR = 1 << pos;
|
||||||
|
else if (pullup < 0)
|
||||||
|
regs->BSRR = 1 << (pos + 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main clock setup called at chip startup
|
||||||
|
void
|
||||||
|
clock_setup(void)
|
||||||
|
{
|
||||||
|
uint32_t cfgr;
|
||||||
|
if (CONFIG_CLOCK_REF_8M) {
|
||||||
|
// Configure 72Mhz PLL from external 8Mhz crystal (HSE)
|
||||||
|
RCC->CR |= RCC_CR_HSEON;
|
||||||
|
cfgr = ((1 << RCC_CFGR_PLLSRC_Pos) | ((9 - 2) << RCC_CFGR_PLLMULL_Pos)
|
||||||
|
| RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_PPRE2_DIV2
|
||||||
|
| RCC_CFGR_ADCPRE_DIV4);
|
||||||
|
} else {
|
||||||
|
// Configure 72Mhz PLL from internal 8Mhz oscillator (HSI)
|
||||||
|
cfgr = ((0 << RCC_CFGR_PLLSRC_Pos) | ((18 - 2) << RCC_CFGR_PLLMULL_Pos)
|
||||||
|
| RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_PPRE2_DIV2
|
||||||
|
| RCC_CFGR_ADCPRE_DIV4);
|
||||||
|
}
|
||||||
|
RCC->CFGR = cfgr;
|
||||||
|
RCC->CR |= RCC_CR_PLLON;
|
||||||
|
|
||||||
|
// Set flash latency
|
||||||
|
FLASH->ACR = (2 << FLASH_ACR_LATENCY_Pos) | FLASH_ACR_PRFTBE;
|
||||||
|
|
||||||
|
// Wait for PLL lock
|
||||||
|
while (!(RCC->CR & RCC_CR_PLLRDY))
|
||||||
|
;
|
||||||
|
|
||||||
|
// Switch system clock to PLL
|
||||||
|
RCC->CFGR = cfgr | RCC_CFGR_SW_PLL;
|
||||||
|
while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL)
|
||||||
|
;
|
||||||
|
|
||||||
|
// Disable JTAG to free PA15, PB3, PB4
|
||||||
|
enable_pclock(AFIO_BASE);
|
||||||
|
AFIO->MAPR = AFIO_MAPR_SWJ_CFG_JTAGDISABLE;
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ watchdog_init(void)
|
||||||
{
|
{
|
||||||
IWDG->KR = 0x5555;
|
IWDG->KR = 0x5555;
|
||||||
IWDG->PR = 0;
|
IWDG->PR = 0;
|
||||||
IWDG->RLR = 0x0FFF; // 512ms timeout
|
IWDG->RLR = 0x0FFF; // 410-512ms timeout (depending on stm32 chip)
|
||||||
IWDG->KR = 0xCCCC;
|
IWDG->KR = 0xCCCC;
|
||||||
}
|
}
|
||||||
DECL_INIT(watchdog_init);
|
DECL_INIT(watchdog_init);
|
||||||
|
|
Loading…
Reference in New Issue