mirror of https://github.com/Desuuuu/klipper.git
stm32: Initial support for stm32f070
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
7e090a996a
commit
2c535106ee
|
@ -6,8 +6,8 @@ config STM32_SELECT
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
select HAVE_GPIO
|
select HAVE_GPIO
|
||||||
select HAVE_GPIO_ADC
|
select HAVE_GPIO_ADC if !MACH_STM32F0
|
||||||
select HAVE_GPIO_I2C
|
select HAVE_GPIO_I2C if !MACH_STM32F0
|
||||||
select HAVE_GPIO_SPI
|
select HAVE_GPIO_SPI
|
||||||
select HAVE_GPIO_BITBANGING
|
select HAVE_GPIO_BITBANGING
|
||||||
|
|
||||||
|
@ -29,15 +29,20 @@ choice
|
||||||
config MACH_STM32F446
|
config MACH_STM32F446
|
||||||
bool "STM32F446"
|
bool "STM32F446"
|
||||||
select MACH_STM32F4
|
select MACH_STM32F4
|
||||||
|
config MACH_STM32F070
|
||||||
|
bool "STM32F070"
|
||||||
|
select MACH_STM32F0
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
config MACH_STM32F0
|
||||||
|
bool
|
||||||
config MACH_STM32F1
|
config MACH_STM32F1
|
||||||
bool
|
bool
|
||||||
config MACH_STM32F4
|
config MACH_STM32F4
|
||||||
bool
|
bool
|
||||||
config HAVE_STM32_USBFS
|
config HAVE_STM32_USBFS
|
||||||
bool
|
bool
|
||||||
default y if MACH_STM32F103
|
default y if MACH_STM32F103 || MACH_STM32F0
|
||||||
default n
|
default n
|
||||||
config HAVE_STM32_USBOTG
|
config HAVE_STM32_USBOTG
|
||||||
bool
|
bool
|
||||||
|
@ -46,6 +51,7 @@ config HAVE_STM32_USBOTG
|
||||||
|
|
||||||
config MCU
|
config MCU
|
||||||
string
|
string
|
||||||
|
default "stm32f070xb" if MACH_STM32F070
|
||||||
default "stm32f103xe" if MACH_STM32F103
|
default "stm32f103xe" if MACH_STM32F103
|
||||||
default "stm32f405xx" if MACH_STM32F405
|
default "stm32f405xx" if MACH_STM32F405
|
||||||
default "stm32f407xx" if MACH_STM32F407
|
default "stm32f407xx" if MACH_STM32F407
|
||||||
|
@ -53,12 +59,14 @@ config MCU
|
||||||
|
|
||||||
config CLOCK_FREQ
|
config CLOCK_FREQ
|
||||||
int
|
int
|
||||||
|
default 48000000 if MACH_STM32F0
|
||||||
default 72000000 if MACH_STM32F103
|
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 0x20000 if MACH_STM32F070
|
||||||
default 0x10000 if MACH_STM32F103
|
default 0x10000 if MACH_STM32F103
|
||||||
default 0x80000 if MACH_STM32F4
|
default 0x80000 if MACH_STM32F4
|
||||||
|
|
||||||
|
@ -68,6 +76,7 @@ config RAM_START
|
||||||
|
|
||||||
config RAM_SIZE
|
config RAM_SIZE
|
||||||
hex
|
hex
|
||||||
|
default 0x4000 if MACH_STM32F070
|
||||||
default 0x5000 if MACH_STM32F103
|
default 0x5000 if MACH_STM32F103
|
||||||
default 0x20000 if MACH_STM32F4
|
default 0x20000 if MACH_STM32F4
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,14 @@
|
||||||
CROSS_PREFIX=arm-none-eabi-
|
CROSS_PREFIX=arm-none-eabi-
|
||||||
|
|
||||||
dirs-y += src/stm32 src/generic
|
dirs-y += src/stm32 src/generic
|
||||||
|
dirs-$(CONFIG_MACH_STM32F0) += lib/stm32f0
|
||||||
dirs-$(CONFIG_MACH_STM32F1) += lib/stm32f1
|
dirs-$(CONFIG_MACH_STM32F1) += lib/stm32f1
|
||||||
dirs-$(CONFIG_MACH_STM32F4) += lib/stm32f4
|
dirs-$(CONFIG_MACH_STM32F4) += lib/stm32f4
|
||||||
|
|
||||||
MCU := $(shell echo $(CONFIG_MCU))
|
MCU := $(shell echo $(CONFIG_MCU))
|
||||||
MCU_UPPER := $(shell echo $(CONFIG_MCU) | tr a-z A-Z | tr X x)
|
MCU_UPPER := $(shell echo $(CONFIG_MCU) | tr a-z A-Z | tr X x)
|
||||||
|
|
||||||
|
CFLAGS-$(CONFIG_MACH_STM32F0) += -mcpu=cortex-m0 -Ilib/stm32f0/include
|
||||||
CFLAGS-$(CONFIG_MACH_STM32F1) += -mcpu=cortex-m3 -Ilib/stm32f1/include
|
CFLAGS-$(CONFIG_MACH_STM32F1) += -mcpu=cortex-m3 -Ilib/stm32f1/include
|
||||||
CFLAGS-$(CONFIG_MACH_STM32F4) += -mcpu=cortex-m4 -Ilib/stm32f4/include
|
CFLAGS-$(CONFIG_MACH_STM32F4) += -mcpu=cortex-m4 -Ilib/stm32f4/include
|
||||||
CFLAGS-$(CONFIG_MACH_STM32F4) += -mfpu=fpv4-sp-d16 -mfloat-abi=hard
|
CFLAGS-$(CONFIG_MACH_STM32F4) += -mfpu=fpv4-sp-d16 -mfloat-abi=hard
|
||||||
|
@ -21,19 +23,23 @@ $(OUT)klipper.elf: $(OUT)src/generic/armcm_link.ld
|
||||||
|
|
||||||
# Add source files
|
# Add source files
|
||||||
src-y += stm32/main.c stm32/watchdog.c stm32/gpio.c generic/crc16_ccitt.c
|
src-y += stm32/main.c stm32/watchdog.c stm32/gpio.c generic/crc16_ccitt.c
|
||||||
src-y += generic/armcm_boot.c generic/armcm_irq.c generic/armcm_timer.c
|
src-y += generic/armcm_boot.c generic/armcm_irq.c generic/armcm_reset.c
|
||||||
src-y += generic/armcm_reset.c
|
src-$(CONFIG_MACH_STM32F0) += ../lib/stm32f0/system_stm32f0xx.c
|
||||||
|
src-$(CONFIG_MACH_STM32F0) += generic/timer_irq.c stm32/stm32f0_timer.c
|
||||||
|
src-$(CONFIG_MACH_STM32F0) += stm32/stm32f0.c
|
||||||
src-$(CONFIG_MACH_STM32F1) += ../lib/stm32f1/system_stm32f1xx.c
|
src-$(CONFIG_MACH_STM32F1) += ../lib/stm32f1/system_stm32f1xx.c
|
||||||
src-$(CONFIG_MACH_STM32F1) += stm32/stm32f1.c
|
src-$(CONFIG_MACH_STM32F1) += stm32/stm32f1.c generic/armcm_timer.c
|
||||||
src-$(CONFIG_MACH_STM32F4) += ../lib/stm32f4/system_stm32f4xx.c
|
src-$(CONFIG_MACH_STM32F4) += ../lib/stm32f4/system_stm32f4xx.c
|
||||||
src-$(CONFIG_MACH_STM32F4) += stm32/stm32f4.c
|
src-$(CONFIG_MACH_STM32F4) += stm32/stm32f4.c generic/armcm_timer.c
|
||||||
src-$(CONFIG_HAVE_GPIO_ADC) += stm32/adc.c
|
src-$(CONFIG_HAVE_GPIO_ADC) += stm32/adc.c
|
||||||
src-$(CONFIG_HAVE_GPIO_I2C) += stm32/i2c.c
|
src-$(CONFIG_HAVE_GPIO_I2C) += stm32/i2c.c
|
||||||
src-$(CONFIG_HAVE_GPIO_SPI) += stm32/spi.c
|
src-$(CONFIG_HAVE_GPIO_SPI) += stm32/spi.c
|
||||||
usb-src-$(CONFIG_HAVE_STM32_USBFS) := stm32/usbfs.c
|
usb-src-$(CONFIG_HAVE_STM32_USBFS) := stm32/usbfs.c
|
||||||
usb-src-$(CONFIG_HAVE_STM32_USBOTG) := stm32/usbotg.c
|
usb-src-$(CONFIG_HAVE_STM32_USBOTG) := stm32/usbotg.c
|
||||||
src-$(CONFIG_USBSERIAL) += $(usb-src-y) generic/usb_cdc.c
|
src-$(CONFIG_USBSERIAL) += $(usb-src-y) generic/usb_cdc.c
|
||||||
src-$(CONFIG_SERIAL) += stm32/serial.c generic/serial_irq.c
|
serial-src-y := stm32/serial.c
|
||||||
|
serial-src-$(CONFIG_MACH_STM32F0) := stm32/stm32f0_serial.c
|
||||||
|
src-$(CONFIG_SERIAL) += $(serial-src-y) generic/serial_irq.c
|
||||||
|
|
||||||
# Binary output file rules
|
# Binary output file rules
|
||||||
target-y += $(OUT)klipper.bin
|
target-y += $(OUT)klipper.bin
|
||||||
|
|
|
@ -15,9 +15,13 @@ DECL_ENUMERATION_RANGE("pin", "PA0", GPIO('A', 0), 16);
|
||||||
DECL_ENUMERATION_RANGE("pin", "PB0", GPIO('B', 0), 16);
|
DECL_ENUMERATION_RANGE("pin", "PB0", GPIO('B', 0), 16);
|
||||||
DECL_ENUMERATION_RANGE("pin", "PC0", GPIO('C', 0), 16);
|
DECL_ENUMERATION_RANGE("pin", "PC0", GPIO('C', 0), 16);
|
||||||
DECL_ENUMERATION_RANGE("pin", "PD0", GPIO('D', 0), 16);
|
DECL_ENUMERATION_RANGE("pin", "PD0", GPIO('D', 0), 16);
|
||||||
|
#ifdef GPIOE
|
||||||
DECL_ENUMERATION_RANGE("pin", "PE0", GPIO('E', 0), 16);
|
DECL_ENUMERATION_RANGE("pin", "PE0", GPIO('E', 0), 16);
|
||||||
#ifdef GPIOH
|
#endif
|
||||||
|
#ifdef GPIOF
|
||||||
DECL_ENUMERATION_RANGE("pin", "PF0", GPIO('F', 0), 16);
|
DECL_ENUMERATION_RANGE("pin", "PF0", GPIO('F', 0), 16);
|
||||||
|
#endif
|
||||||
|
#ifdef GPIOH
|
||||||
DECL_ENUMERATION_RANGE("pin", "PG0", GPIO('G', 0), 16);
|
DECL_ENUMERATION_RANGE("pin", "PG0", GPIO('G', 0), 16);
|
||||||
DECL_ENUMERATION_RANGE("pin", "PH0", GPIO('H', 0), 16);
|
DECL_ENUMERATION_RANGE("pin", "PH0", GPIO('H', 0), 16);
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,9 +30,15 @@ DECL_ENUMERATION_RANGE("pin", "PI0", GPIO('I', 0), 16);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GPIO_TypeDef * const digital_regs[] = {
|
GPIO_TypeDef * const digital_regs[] = {
|
||||||
['A' - 'A'] = GPIOA, GPIOB, GPIOC, GPIOD, GPIOE,
|
['A' - 'A'] = GPIOA, GPIOB, GPIOC, GPIOD,
|
||||||
|
#ifdef GPIOE
|
||||||
|
['E' - 'A'] = GPIOE,
|
||||||
|
#endif
|
||||||
|
#ifdef GPIOF
|
||||||
|
['F' - 'A'] = GPIOF,
|
||||||
|
#endif
|
||||||
#ifdef GPIOH
|
#ifdef GPIOH
|
||||||
['F' - 'A'] = GPIOF, GPIOG, GPIOH,
|
['G' - 'A'] = GPIOG, GPIOH,
|
||||||
#endif
|
#endif
|
||||||
#ifdef GPIOI
|
#ifdef GPIOI
|
||||||
['I' - 'A'] = GPIOI,
|
['I' - 'A'] = GPIOI,
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
|
|
||||||
#include "autoconf.h" // CONFIG_MACH_STM32F1
|
#include "autoconf.h" // CONFIG_MACH_STM32F1
|
||||||
|
|
||||||
#if CONFIG_MACH_STM32F1
|
#if CONFIG_MACH_STM32F0
|
||||||
|
#include "stm32f0xx.h"
|
||||||
|
#elif CONFIG_MACH_STM32F1
|
||||||
#include "stm32f1xx.h"
|
#include "stm32f1xx.h"
|
||||||
#else
|
#elif CONFIG_MACH_STM32F4
|
||||||
#include "stm32f4xx.h"
|
#include "stm32f4xx.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,11 @@ DECL_CONSTANT_STR("BUS_PINS_spi3a", "PC11,PC12,PC10");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SPI_FUNCTION GPIO_FUNCTION(CONFIG_MACH_STM32F0 ? 0 : 5)
|
||||||
|
|
||||||
static const struct spi_info spi_bus[] = {
|
static const struct spi_info spi_bus[] = {
|
||||||
{ SPI2, GPIO('B', 14), GPIO('B', 15), GPIO('B', 13), GPIO_FUNCTION(5) },
|
{ SPI2, GPIO('B', 14), GPIO('B', 15), GPIO('B', 13), SPI_FUNCTION },
|
||||||
{ SPI1, GPIO('A', 6), GPIO('A', 7), GPIO('A', 5), GPIO_FUNCTION(5) },
|
{ SPI1, GPIO('A', 6), GPIO('A', 7), GPIO('A', 5), SPI_FUNCTION },
|
||||||
#ifdef SPI3
|
#ifdef SPI3
|
||||||
{ SPI3, GPIO('B', 4), GPIO('B', 5), GPIO('B', 3), GPIO_FUNCTION(6) },
|
{ SPI3, GPIO('B', 4), GPIO('B', 5), GPIO('B', 3), GPIO_FUNCTION(6) },
|
||||||
#if CONFIG_MACH_STM32F4
|
#if CONFIG_MACH_STM32F4
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
// Code to setup clocks and gpio on stm32f0
|
||||||
|
//
|
||||||
|
// 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 "command.h" // DECL_CONSTANT_STR
|
||||||
|
#include "internal.h" // enable_pclock
|
||||||
|
|
||||||
|
#define FREQ_PERIPH 48000000
|
||||||
|
|
||||||
|
// Enable a peripheral clock
|
||||||
|
void
|
||||||
|
enable_pclock(uint32_t periph_base)
|
||||||
|
{
|
||||||
|
if (periph_base < SYSCFG_BASE) {
|
||||||
|
uint32_t pos = (periph_base - APBPERIPH_BASE) / 0x400;
|
||||||
|
RCC->APB1ENR |= 1 << pos;
|
||||||
|
RCC->APB1ENR;
|
||||||
|
} else if (periph_base < AHBPERIPH_BASE) {
|
||||||
|
uint32_t pos = (periph_base - SYSCFG_BASE) / 0x400;
|
||||||
|
RCC->APB2ENR |= 1 << pos;
|
||||||
|
RCC->APB2ENR;
|
||||||
|
} else {
|
||||||
|
uint32_t pos = (periph_base - AHB2PERIPH_BASE) / 0x400;
|
||||||
|
RCC->AHBENR |= 1 << (pos + 17);
|
||||||
|
RCC->AHBENR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a peripheral clock has been enabled
|
||||||
|
int
|
||||||
|
is_enabled_pclock(uint32_t periph_base)
|
||||||
|
{
|
||||||
|
if (periph_base < SYSCFG_BASE) {
|
||||||
|
uint32_t pos = (periph_base - APBPERIPH_BASE) / 0x400;
|
||||||
|
return RCC->APB1ENR & (1 << pos);
|
||||||
|
} else if (periph_base < AHBPERIPH_BASE) {
|
||||||
|
uint32_t pos = (periph_base - SYSCFG_BASE) / 0x400;
|
||||||
|
return RCC->APB2ENR & (1 << pos);
|
||||||
|
} else {
|
||||||
|
uint32_t pos = (periph_base - AHB2PERIPH_BASE) / 0x400;
|
||||||
|
return RCC->AHBENR & (1 << (pos + 17));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 - AHB2PERIPH_BASE) / 0x400;
|
||||||
|
RCC->AHBENR |= 1 << (rcc_pos + 17);
|
||||||
|
RCC->AHBENR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
gpio_clock_enable(regs);
|
||||||
|
|
||||||
|
// Configure GPIO
|
||||||
|
uint32_t mode_bits = mode & 0xf, func = (mode >> 4) & 0xf, od = mode >> 8;
|
||||||
|
uint32_t pup = pullup ? (pullup > 0 ? 1 : 2) : 0;
|
||||||
|
uint32_t pos = gpio % 16, af_reg = pos / 8;
|
||||||
|
uint32_t af_shift = (pos % 8) * 4, af_msk = 0x0f << af_shift;
|
||||||
|
uint32_t m_shift = pos * 2, m_msk = 0x03 << m_shift;
|
||||||
|
|
||||||
|
regs->AFR[af_reg] = (regs->AFR[af_reg] & ~af_msk) | (func << af_shift);
|
||||||
|
regs->MODER = (regs->MODER & ~m_msk) | (mode_bits << m_shift);
|
||||||
|
regs->PUPDR = (regs->PUPDR & ~m_msk) | (pup << m_shift);
|
||||||
|
regs->OTYPER = (regs->OTYPER & ~(1 << pos)) | (od << pos);
|
||||||
|
regs->OSPEEDR = (regs->OSPEEDR & ~m_msk) | (0x02 << m_shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle USB reboot requests
|
||||||
|
void
|
||||||
|
usb_request_bootloader(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_CLOCK_REF_8M
|
||||||
|
DECL_CONSTANT_STR("RESERVE_PINS_crystal", "PF0,PF1");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Configure and enable the PLL as clock source
|
||||||
|
static void
|
||||||
|
pll_setup(void)
|
||||||
|
{
|
||||||
|
uint32_t cfgr;
|
||||||
|
if (CONFIG_CLOCK_REF_8M) {
|
||||||
|
// Configure 48Mhz PLL from external 8Mhz crystal (HSE)
|
||||||
|
RCC->CR |= RCC_CR_HSEON;
|
||||||
|
cfgr = RCC_CFGR_PLLSRC_HSE_PREDIV | ((6 - 2) << RCC_CFGR_PLLMUL_Pos);
|
||||||
|
} else {
|
||||||
|
// Configure 48Mhz PLL from internal 8Mhz oscillator (HSI)
|
||||||
|
cfgr = RCC_CFGR_PLLSRC_HSI_DIV2 | ((12 - 2) << RCC_CFGR_PLLMUL_Pos);
|
||||||
|
}
|
||||||
|
RCC->CFGR = cfgr;
|
||||||
|
RCC->CR |= RCC_CR_PLLON;
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
;
|
||||||
|
|
||||||
|
// Select PLL as source for USB clock
|
||||||
|
if (CONFIG_USBSERIAL)
|
||||||
|
RCC->CFGR3 = RCC_CFGR3_USBSW;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main clock setup called at chip startup
|
||||||
|
void
|
||||||
|
clock_setup(void)
|
||||||
|
{
|
||||||
|
// Set flash latency
|
||||||
|
FLASH->ACR = (1 << FLASH_ACR_LATENCY_Pos) | FLASH_ACR_PRFTBE;
|
||||||
|
|
||||||
|
// Configure main clock
|
||||||
|
pll_setup();
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
// STM32F0 serial
|
||||||
|
//
|
||||||
|
// 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_SERIAL_BAUD
|
||||||
|
#include "board/armcm_boot.h" // armcm_enable_irq
|
||||||
|
#include "board/serial_irq.h" // serial_rx_byte
|
||||||
|
#include "command.h" // DECL_CONSTANT_STR
|
||||||
|
#include "internal.h" // enable_pclock
|
||||||
|
#include "sched.h" // DECL_INIT
|
||||||
|
|
||||||
|
// Select the configured serial port
|
||||||
|
#if CONFIG_SERIAL_PORT == 1
|
||||||
|
DECL_CONSTANT_STR("RESERVE_PINS_serial", "PA10,PA9");
|
||||||
|
#define GPIO_Rx GPIO('A', 10)
|
||||||
|
#define GPIO_Tx GPIO('A', 9)
|
||||||
|
#define USARTx USART1
|
||||||
|
#define USARTx_IRQn USART1_IRQn
|
||||||
|
#elif CONFIG_SERIAL_PORT == 2
|
||||||
|
DECL_CONSTANT_STR("RESERVE_PINS_serial", "PA3,PA2");
|
||||||
|
#define GPIO_Rx GPIO('A', 3)
|
||||||
|
#define GPIO_Tx GPIO('A', 2)
|
||||||
|
#define USARTx USART2
|
||||||
|
#define USARTx_IRQn USART2_IRQn
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CR1_FLAGS (USART_CR1_UE | USART_CR1_RE | USART_CR1_TE \
|
||||||
|
| USART_CR1_RXNEIE)
|
||||||
|
|
||||||
|
void
|
||||||
|
USARTx_IRQHandler(void)
|
||||||
|
{
|
||||||
|
uint32_t sr = USARTx->ISR;
|
||||||
|
if (sr & (USART_ISR_RXNE | USART_ISR_ORE))
|
||||||
|
serial_rx_byte(USARTx->RDR);
|
||||||
|
if (sr & USART_ISR_TXE && USARTx->CR1 & USART_CR1_TXEIE) {
|
||||||
|
uint8_t data;
|
||||||
|
int ret = serial_get_tx_byte(&data);
|
||||||
|
if (ret)
|
||||||
|
USARTx->CR1 = CR1_FLAGS;
|
||||||
|
else
|
||||||
|
USARTx->TDR = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
serial_enable_tx_irq(void)
|
||||||
|
{
|
||||||
|
USARTx->CR1 = CR1_FLAGS | USART_CR1_TXEIE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
serial_init(void)
|
||||||
|
{
|
||||||
|
enable_pclock((uint32_t)USARTx);
|
||||||
|
|
||||||
|
uint32_t pclk = get_pclock_frequency((uint32_t)USARTx);
|
||||||
|
uint32_t div = DIV_ROUND_CLOSEST(pclk, CONFIG_SERIAL_BAUD);
|
||||||
|
USARTx->BRR = (((div / 16) << USART_BRR_DIV_MANTISSA_Pos)
|
||||||
|
| ((div % 16) << USART_BRR_DIV_FRACTION_Pos));
|
||||||
|
USARTx->CR1 = CR1_FLAGS;
|
||||||
|
armcm_enable_irq(USARTx_IRQHandler, USARTx_IRQn, 0);
|
||||||
|
|
||||||
|
gpio_peripheral(GPIO_Rx, GPIO_FUNCTION(1), 1);
|
||||||
|
gpio_peripheral(GPIO_Tx, GPIO_FUNCTION(1), 0);
|
||||||
|
}
|
||||||
|
DECL_INIT(serial_init);
|
|
@ -0,0 +1,124 @@
|
||||||
|
// STM32F0 timer support
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019 Kevin O'Connor <kevin@koconnor.net>
|
||||||
|
//
|
||||||
|
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
|
|
||||||
|
#include "board/armcm_boot.h" // armcm_enable_irq
|
||||||
|
#include "board/armcm_timer.h" // udelay
|
||||||
|
#include "board/internal.h" // TIM3
|
||||||
|
#include "board/io.h" // readl
|
||||||
|
#include "board/irq.h" // irq_disable
|
||||||
|
#include "board/misc.h" // timer_read_time
|
||||||
|
#include "sched.h" // DECL_INIT
|
||||||
|
#include "command.h" // DECL_SHUTDOWN
|
||||||
|
#include "board/timer_irq.h" // timer_dispatch_many
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************
|
||||||
|
* Low level timer code
|
||||||
|
****************************************************************/
|
||||||
|
|
||||||
|
// Use 32bit TIM2 timer if available (otherwise use 16bit TIM3 timer)
|
||||||
|
#ifdef TIM2
|
||||||
|
#define TIMx TIM2
|
||||||
|
#define TIMx_IRQn TIM2_IRQn
|
||||||
|
#define HAVE_TIMER_32BIT 1
|
||||||
|
#else
|
||||||
|
#define TIMx TIM3
|
||||||
|
#define TIMx_IRQn TIM3_IRQn
|
||||||
|
#define HAVE_TIMER_32BIT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline uint32_t
|
||||||
|
timer_get(void)
|
||||||
|
{
|
||||||
|
return TIMx->CNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
timer_set(uint32_t next)
|
||||||
|
{
|
||||||
|
TIMx->CCR1 = next;
|
||||||
|
TIMx->SR = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate timer dispatch as soon as possible
|
||||||
|
void
|
||||||
|
timer_kick(void)
|
||||||
|
{
|
||||||
|
timer_set(timer_get() + 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************
|
||||||
|
* 16bit hardware timer to 32bit conversion
|
||||||
|
****************************************************************/
|
||||||
|
|
||||||
|
// High bits of timer (top 17 bits)
|
||||||
|
static uint32_t timer_high;
|
||||||
|
|
||||||
|
// Return the current time (in absolute clock ticks).
|
||||||
|
uint32_t __always_inline
|
||||||
|
timer_read_time(void)
|
||||||
|
{
|
||||||
|
if (HAVE_TIMER_32BIT)
|
||||||
|
return timer_get();
|
||||||
|
uint32_t th = readl(&timer_high);
|
||||||
|
uint32_t cur = timer_get();
|
||||||
|
// Combine timer_high (high 17 bits) and current time (low 16
|
||||||
|
// bits) using method that handles rollovers correctly.
|
||||||
|
return (th ^ cur) + (th & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update timer_high every 0x8000 clock ticks
|
||||||
|
static uint_fast8_t
|
||||||
|
timer_event(struct timer *t)
|
||||||
|
{
|
||||||
|
timer_high += 0x8000;
|
||||||
|
t->waketime = timer_high + 0x8000;
|
||||||
|
return SF_RESCHEDULE;
|
||||||
|
}
|
||||||
|
static struct timer wrap_timer = {
|
||||||
|
.func = timer_event,
|
||||||
|
.waketime = 0x8000,
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
timer_reset(void)
|
||||||
|
{
|
||||||
|
if (!HAVE_TIMER_32BIT)
|
||||||
|
sched_add_timer(&wrap_timer);
|
||||||
|
}
|
||||||
|
DECL_SHUTDOWN(timer_reset);
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************
|
||||||
|
* Setup and irqs
|
||||||
|
****************************************************************/
|
||||||
|
|
||||||
|
// Hardware timer IRQ handler - dispatch software timers
|
||||||
|
void __aligned(16)
|
||||||
|
TIMx_IRQHandler(void)
|
||||||
|
{
|
||||||
|
irq_disable();
|
||||||
|
uint32_t next = timer_dispatch_many();
|
||||||
|
timer_set(next);
|
||||||
|
irq_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
timer_init(void)
|
||||||
|
{
|
||||||
|
irqstatus_t flag = irq_save();
|
||||||
|
enable_pclock((uint32_t)TIMx);
|
||||||
|
TIMx->CNT = 0;
|
||||||
|
TIMx->DIER = TIM_DIER_CC1IE;
|
||||||
|
TIMx->CCER = TIM_CCER_CC1E;
|
||||||
|
armcm_enable_irq(TIMx_IRQHandler, TIMx_IRQn, 2);
|
||||||
|
timer_kick();
|
||||||
|
timer_reset();
|
||||||
|
TIMx->CR1 = TIM_CR1_CEN;
|
||||||
|
irq_restore(flag);
|
||||||
|
}
|
||||||
|
DECL_INIT(timer_init);
|
|
@ -235,7 +235,7 @@ usb_reset(void)
|
||||||
|
|
||||||
// Main irq handler
|
// Main irq handler
|
||||||
void
|
void
|
||||||
USB_LP_CAN1_RX0_IRQHandler(void)
|
USB_IRQHandler(void)
|
||||||
{
|
{
|
||||||
uint32_t istr = USB->ISTR;
|
uint32_t istr = USB->ISTR;
|
||||||
if (istr & USB_ISTR_CTR) {
|
if (istr & USB_ISTR_CTR) {
|
||||||
|
@ -269,10 +269,12 @@ DECL_CONSTANT_STR("RESERVE_PINS_USB", "PA11,PA12");
|
||||||
void
|
void
|
||||||
usb_init(void)
|
usb_init(void)
|
||||||
{
|
{
|
||||||
|
if (CONFIG_MACH_STM32F1) {
|
||||||
// Pull the D+ pin low briefly to signal a new connection
|
// Pull the D+ pin low briefly to signal a new connection
|
||||||
gpio_out_setup(GPIO('A', 12), 0);
|
gpio_out_setup(GPIO('A', 12), 0);
|
||||||
udelay(5000);
|
udelay(5000);
|
||||||
gpio_in_setup(GPIO('A', 12), 0);
|
gpio_in_setup(GPIO('A', 12), 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Enable USB clock
|
// Enable USB clock
|
||||||
enable_pclock(USB_BASE);
|
enable_pclock(USB_BASE);
|
||||||
|
@ -280,12 +282,21 @@ usb_init(void)
|
||||||
// Setup USB packet memory
|
// Setup USB packet memory
|
||||||
btable_configure();
|
btable_configure();
|
||||||
|
|
||||||
|
// Enable USB pullup
|
||||||
|
#ifdef USB_BCDR_DPPU
|
||||||
|
USB->BCDR = USB_BCDR_DPPU;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Reset usb controller and enable interrupts
|
// Reset usb controller and enable interrupts
|
||||||
USB->CNTR = USB_CNTR_FRES;
|
USB->CNTR = USB_CNTR_FRES;
|
||||||
USB->BTABLE = 0;
|
USB->BTABLE = 0;
|
||||||
USB->DADDR = 0;
|
USB->DADDR = 0;
|
||||||
USB->CNTR = USB_CNTR_RESETM;
|
USB->CNTR = USB_CNTR_RESETM;
|
||||||
USB->ISTR = 0;
|
USB->ISTR = 0;
|
||||||
armcm_enable_irq(USB_LP_CAN1_RX0_IRQHandler, USB_LP_CAN1_RX0_IRQn, 1);
|
#if CONFIG_MACH_STM32F103
|
||||||
|
armcm_enable_irq(USB_IRQHandler, USB_LP_IRQn, 1);
|
||||||
|
#elif CONFIG_MACH_STM32F0
|
||||||
|
armcm_enable_irq(USB_IRQHandler, USB_IRQn, 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
DECL_INIT(usb_init);
|
DECL_INIT(usb_init);
|
||||||
|
|
Loading…
Reference in New Issue