mirror of
https://github.com/andreili/katapult.git
synced 2025-08-23 19:34:06 +02:00
src: update stm32 source
Bring in the latest changes from Klipper. The STM32F4 variants are still unsupported at this time. Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
73d7ddd5aa
commit
26b12a658b
@ -12,7 +12,7 @@ config CANSERIAL
|
||||
bool
|
||||
default y
|
||||
|
||||
config CANBUS_BAUD
|
||||
config CONFIG_CANBUS_FREQUENCY
|
||||
int "CAN bus speed"
|
||||
default 500000
|
||||
|
||||
|
@ -17,18 +17,27 @@ choice
|
||||
config MACH_STM32F405
|
||||
bool "STM32F405"
|
||||
select MACH_STM32F4
|
||||
select MACH_STM32F4x5
|
||||
config MACH_STM32F407
|
||||
bool "STM32F407"
|
||||
select MACH_STM32F4
|
||||
select MACH_STM32F4x5
|
||||
config MACH_STM32F429
|
||||
bool "STM32F429"
|
||||
select MACH_STM32F4
|
||||
select MACH_STM32F4x5
|
||||
config MACH_STM32F446
|
||||
bool "STM32F446"
|
||||
select MACH_STM32F4
|
||||
config MACH_STM32F042
|
||||
bool "STM32F042"
|
||||
select MACH_STM32F0
|
||||
config MACH_STM32F070
|
||||
bool "STM32F070"
|
||||
select MACH_STM32F0x2
|
||||
config MACH_STM32F072
|
||||
bool "STM32F072"
|
||||
select MACH_STM32F0
|
||||
select MACH_STM32F0x2
|
||||
|
||||
endchoice
|
||||
|
||||
config MACH_STM32F0
|
||||
@ -43,11 +52,12 @@ config MACH_STM32F4
|
||||
config MCU
|
||||
string
|
||||
default "stm32f042x6" if MACH_STM32F042
|
||||
default "stm32f070xb" if MACH_STM32F070
|
||||
default "stm32f072xb" if MACH_STM32F072
|
||||
default "stm32f103xe" if MACH_STM32F103
|
||||
default "stm32f207xx" if MACH_STM32F207
|
||||
default "stm32f405xx" if MACH_STM32F405
|
||||
default "stm32f407xx" if MACH_STM32F407
|
||||
default "stm32f429xx" if MACH_STM32F429
|
||||
default "stm32f446xx" if MACH_STM32F446
|
||||
|
||||
config CLOCK_FREQ
|
||||
@ -56,13 +66,13 @@ config CLOCK_FREQ
|
||||
default 64000000 if MACH_STM32F103 && STM32_CLOCK_REF_INTERNAL
|
||||
default 72000000 if MACH_STM32F103
|
||||
default 120000000 if MACH_STM32F207
|
||||
default 168000000 if MACH_STM32F405 || MACH_STM32F407
|
||||
default 168000000 if MACH_STM32F4x5
|
||||
default 180000000 if MACH_STM32F446
|
||||
|
||||
config FLASH_SIZE
|
||||
hex
|
||||
default 0x8000 if MACH_STM32F042
|
||||
default 0x20000 if MACH_STM32F070
|
||||
default 0x20000 if MACH_STM32F072
|
||||
default 0x10000 if MACH_STM32F103 # Flash size of stm32f103x8 (64KiB)
|
||||
default 0x40000 if MACH_STM32F2
|
||||
default 0x80000 if MACH_STM32F4
|
||||
@ -74,7 +84,7 @@ config RAM_START
|
||||
config RAM_SIZE
|
||||
hex
|
||||
default 0x1800 if MACH_STM32F042
|
||||
default 0x4000 if MACH_STM32F070
|
||||
default 0x4000 if MACH_STM32F072
|
||||
default 0x5000 if MACH_STM32F103 # Ram size of stm32f103x8 (20KiB)
|
||||
default 0x20000 if MACH_STM32F207
|
||||
default 0x20000 if MACH_STM32F4
|
||||
@ -97,6 +107,16 @@ config ARMCM_RAM_VECTORTABLE
|
||||
default y if MACH_STM32F0 && FLASH_START != 0x8000000
|
||||
default n
|
||||
|
||||
config STM32F103GD_DISABLE_SWD
|
||||
bool "Disable SWD at startup (for GigaDevice stm32f103 clones)"
|
||||
depends on MACH_STM32F103
|
||||
default n
|
||||
help
|
||||
The GigaDevice clone of the STM32F103 may not be able to
|
||||
reliably disable SWD at run-time. This can prevent the PA13
|
||||
and PA14 pins from being available. Selecting this option
|
||||
disables SWD at startup and thus makes these pins available.
|
||||
|
||||
choice
|
||||
prompt "Clock Reference"
|
||||
config STM32_CLOCK_REF_8M
|
||||
@ -105,11 +125,14 @@ choice
|
||||
bool "12 MHz crystal"
|
||||
config STM32_CLOCK_REF_16M
|
||||
bool "16 MHz crystal"
|
||||
config STM32_CLOCK_REF_25M
|
||||
bool "25 MHz crystal"
|
||||
config STM32_CLOCK_REF_INTERNAL
|
||||
bool "Internal clock"
|
||||
endchoice
|
||||
config CLOCK_REF_FREQ
|
||||
int
|
||||
default 25000000 if STM32_CLOCK_REF_25M
|
||||
default 16000000 if STM32_CLOCK_REF_16M
|
||||
default 12000000 if STM32_CLOCK_REF_12M
|
||||
default 1 if STM32_CLOCK_REF_INTERNAL
|
||||
@ -117,16 +140,20 @@ config CLOCK_REF_FREQ
|
||||
|
||||
choice
|
||||
prompt "CAN pins"
|
||||
config CAN_PINS_PA11_PA12
|
||||
config STM32_CANBUS_PA11_PA12
|
||||
bool "Pins PA11(rx) and PA12(tx)"
|
||||
config CAN_PINS_PB8_PB9
|
||||
config STM32_CANBUS_PA11_PA12_REMAP
|
||||
bool "Pins on PA9(rx) and PA10(tx)" if MACH_STM32F042
|
||||
config STM32_CANBUS_PB8_PB9
|
||||
bool "Pins PB8(rx) and PB9(tx)"
|
||||
config CAN_PINS_PI8_PH13
|
||||
bool "Pins PI8(rx) and PH13(tx)" if MACH_STM32F4
|
||||
config CAN_PINS_PB5_PB6
|
||||
config STM32_CANBUS_PI9_PH13
|
||||
bool "Pins PI9(rx) and PH13(tx)" if MACH_STM32F4
|
||||
config STM32_CANBUS_PB5_PB6
|
||||
bool "Pins PB5(rx) and PB6(tx)" if MACH_STM32F4
|
||||
config CAN_PINS_PB12_PB13
|
||||
config STM32_CANBUS_PB12_PB13
|
||||
bool "Pins PB12(rx) and PB13(tx)" if MACH_STM32F4
|
||||
config STM32_CANBUS_PD0_PD1
|
||||
bool "Pins PD0(rx) and PD1(tx)"
|
||||
endchoice
|
||||
|
||||
config STM32F0_TRIM
|
||||
@ -138,14 +165,6 @@ config STM32F0_TRIM
|
||||
Default is 16 (use factory default). Each increment increases
|
||||
the clock rate by ~240KHz.
|
||||
|
||||
config STM32F042_PIN_SWAP
|
||||
bool "Use PA9/PA10 for USB or CAN" if MACH_STM32F042
|
||||
depends on MACH_STM32F042
|
||||
default y if MACH_STM32F042
|
||||
default n
|
||||
help
|
||||
Remaps logical pins PA11/PA12 to physical PA9/PA10 on low pincount F042 devices.
|
||||
|
||||
choice
|
||||
depends on MACH_STM32F103
|
||||
prompt "Flash Page Size"
|
||||
|
@ -24,19 +24,22 @@ CFLAGS_canboot.elf += -T $(OUT)src/generic/armcm_link.ld
|
||||
$(OUT)canboot.elf: $(OUT)src/generic/armcm_link.ld
|
||||
|
||||
# Add source files
|
||||
src-y += stm32/gpio.c stm32/flash.c
|
||||
src-y += stm32/gpio.c stm32/flash.c stm32/clockline.c
|
||||
src-y += generic/armcm_boot.c generic/armcm_irq.c
|
||||
src-$(CONFIG_MACH_STM32F0) += ../lib/stm32f0/system_stm32f0xx.c
|
||||
src-$(CONFIG_MACH_STM32F0) += stm32/stm32f0.c stm32/stm32f0_timer.c
|
||||
src-$(CONFIG_MACH_STM32F0) += stm32/gpioperiph.c
|
||||
|
||||
src-$(CONFIG_MACH_STM32F1) += ../lib/stm32f1/system_stm32f1xx.c
|
||||
src-$(CONFIG_MACH_STM32F1) += stm32/stm32f1.c generic/armcm_timer.c
|
||||
|
||||
src-$(CONFIG_MACH_STM32F2) += ../lib/stm32f2/system_stm32f2xx.c
|
||||
src-$(CONFIG_MACH_STM32F2) += stm32/stm32f4.c generic/armcm_timer.c
|
||||
src-$(CONFIG_MACH_STM32F2) += stm32/gpioperiph.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
|
||||
|
||||
can-src-$(CONFIG_CANSERIAL) += stm32/can.c ../lib/fast-hash/fasthash.c
|
||||
src-$(CONFIG_CANSERIAL) += $(can-src-y) generic/canbus.c
|
||||
|
103
src/stm32/can.c
103
src/stm32/can.c
@ -15,31 +15,36 @@
|
||||
#include "internal.h" // enable_pclock
|
||||
#include "ctr.h" // DECL_CONSTANT_STR
|
||||
|
||||
#if CONFIG_CAN_PINS_PA11_PA12
|
||||
#if CONFIG_STM32_CANBUS_PA11_PA12 || CONFIG_STM32_CANBUS_PA11_PA12_REMAP
|
||||
DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PA11,PA12");
|
||||
#define GPIO_Rx GPIO('A', 11)
|
||||
#define GPIO_Tx GPIO('A', 12)
|
||||
#endif
|
||||
#if CONFIG_CAN_PINS_PB8_PB9
|
||||
#if CONFIG_STM32_CANBUS_PB8_PB9
|
||||
DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PB8,PB9");
|
||||
#define GPIO_Rx GPIO('B', 8)
|
||||
#define GPIO_Tx GPIO('B', 9)
|
||||
#endif
|
||||
#if CONFIG_CAN_PINS_PI8_PH13
|
||||
DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PI8,PH13");
|
||||
#define GPIO_Rx GPIO('I', 8)
|
||||
#if CONFIG_STM32_CANBUS_PI9_PH13
|
||||
DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PI9,PH13");
|
||||
#define GPIO_Rx GPIO('I', 9)
|
||||
#define GPIO_Tx GPIO('H', 13)
|
||||
#endif
|
||||
#if CONFIG_CAN_PINS_PB5_PB6
|
||||
#if CONFIG_STM32_CANBUS_PB5_PB6
|
||||
DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PB5,PB6");
|
||||
#define GPIO_Rx GPIO('B', 5)
|
||||
#define GPIO_Tx GPIO('B', 6)
|
||||
#endif
|
||||
#if CONFIG_CAN_PINS_PB12_PB13
|
||||
#if CONFIG_STM32_CANBUS_PB12_PB13
|
||||
DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PB12,PB13");
|
||||
#define GPIO_Rx GPIO('B', 12)
|
||||
#define GPIO_Tx GPIO('B', 13)
|
||||
#endif
|
||||
#if CONFIG_STM32_CANBUS_PD0_PD1
|
||||
DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PD0,PD1");
|
||||
#define GPIO_Rx GPIO('D', 0)
|
||||
#define GPIO_Tx GPIO('D', 1)
|
||||
#endif
|
||||
|
||||
#if CONFIG_MACH_STM32F0
|
||||
#define SOC_CAN CAN
|
||||
@ -61,14 +66,14 @@
|
||||
|
||||
#if CONFIG_MACH_STM32F4
|
||||
#warning CAN on STM32F4 is untested
|
||||
#if (CONFIG_CAN_PINS_PA11_PA12 || CONFIG_CAN_PINS_PB8_PB9 \
|
||||
|| CONFIG_CAN_PINS_PI8_PH13)
|
||||
#if (CONFIG_STM32_CANBUS_PA11_PA12 || CONFIG_STM32_CANBUS_PB8_PB9 \
|
||||
|| CONFIG_STM32_CANBUS_PD0_PD1 || CONFIG_STM32_CANBUS_PI9_PH13)
|
||||
#define SOC_CAN CAN1
|
||||
#define CAN_RX0_IRQn CAN1_RX0_IRQn
|
||||
#define CAN_RX1_IRQn CAN1_RX1_IRQn
|
||||
#define CAN_TX_IRQn CAN1_TX_IRQn
|
||||
#define CAN_SCE_IRQn CAN1_SCE_IRQn
|
||||
#elif CONFIG_CAN_PINS_PB5_PB6 || CONFIG_CAN_PINS_PB12_PB13
|
||||
#elif CONFIG_STM32_CANBUS_PB5_PB6 || CONFIG_STM32_CANBUS_PB12_PB13
|
||||
#define SOC_CAN CAN2
|
||||
#define CAN_RX0_IRQn CAN2_RX0_IRQn
|
||||
#define CAN_RX1_IRQn CAN2_RX1_IRQn
|
||||
@ -152,62 +157,64 @@ canbus_send(uint32_t id, uint32_t len, uint8_t *data)
|
||||
return len;
|
||||
}
|
||||
|
||||
#define CAN_FILTER_NUMBER 0
|
||||
|
||||
// Setup the receive packet filter
|
||||
static void
|
||||
can_set_filter(uint32_t id1, uint32_t id2)
|
||||
void
|
||||
canbus_set_filter(uint32_t id)
|
||||
{
|
||||
uint32_t filternbrbitpos = 1 << CAN_FILTER_NUMBER;
|
||||
|
||||
/* Select the start slave bank */
|
||||
SOC_CAN->FMR |= CAN_FMR_FINIT;
|
||||
/* Initialisation mode for the filter */
|
||||
SOC_CAN->FA1R = 0;
|
||||
|
||||
SOC_CAN->sFilterRegister[CAN_FILTER_NUMBER].FR1 = id1 << (5 + 16);
|
||||
SOC_CAN->sFilterRegister[CAN_FILTER_NUMBER].FR2 = id2 << (5 + 16);
|
||||
uint32_t mask = CAN_RI0R_STID | CAN_TI0R_IDE | CAN_TI0R_RTR;
|
||||
SOC_CAN->sFilterRegister[0].FR1 = CANBUS_ID_ADMIN << CAN_RI0R_STID_Pos;
|
||||
SOC_CAN->sFilterRegister[0].FR2 = mask;
|
||||
SOC_CAN->sFilterRegister[1].FR1 = (id + 1) << CAN_RI0R_STID_Pos;
|
||||
SOC_CAN->sFilterRegister[1].FR2 = mask;
|
||||
SOC_CAN->sFilterRegister[2].FR1 = id << CAN_RI0R_STID_Pos;
|
||||
SOC_CAN->sFilterRegister[2].FR2 = mask;
|
||||
|
||||
/* Identifier list mode for the filter */
|
||||
SOC_CAN->FM1R = filternbrbitpos;
|
||||
/* 32-bit scale for the filter */
|
||||
SOC_CAN->FS1R = filternbrbitpos;
|
||||
SOC_CAN->FS1R = (1<<0) | (1<<1) | (1<<2);
|
||||
|
||||
/* FIFO 0 assigned for the filter */
|
||||
SOC_CAN->FFA1R = 0;
|
||||
/* FIFO 1 assigned to 'id' */
|
||||
SOC_CAN->FFA1R = (1<<2);
|
||||
|
||||
/* Filter activation */
|
||||
SOC_CAN->FA1R = filternbrbitpos;
|
||||
SOC_CAN->FA1R = (1<<0) | (id ? (1<<1) | (1<<2) : 0);
|
||||
/* Leave the initialisation mode for the filter */
|
||||
SOC_CAN->FMR &= ~CAN_FMR_FINIT;
|
||||
}
|
||||
|
||||
void
|
||||
canbus_set_dataport(uint32_t id)
|
||||
{
|
||||
can_set_filter(CANBUS_ID_UUID, id);
|
||||
}
|
||||
|
||||
void
|
||||
canbus_reboot(void)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
// This function handles CAN global interrupts
|
||||
void
|
||||
CAN_IRQHandler(void)
|
||||
{
|
||||
if (SOC_CAN->RF0R & CAN_RF0R_FMP0) {
|
||||
// Rx
|
||||
SOC_CAN->IER &= ~CAN_IER_FMPIE0;
|
||||
canbus_notify_rx();
|
||||
if (SOC_CAN->RF1R & CAN_RF1R_FMP1) {
|
||||
// Read and ack data packet
|
||||
CAN_FIFOMailBox_TypeDef *mb = &SOC_CAN->sFIFOMailBox[1];
|
||||
uint32_t rir_id = (mb->RIR >> CAN_RI0R_STID_Pos) & 0x7FF;
|
||||
uint32_t dlc = mb->RDTR & CAN_RDT0R_DLC;
|
||||
uint32_t rdlr = mb->RDLR, rdhr = mb->RDHR;
|
||||
SOC_CAN->RF1R = CAN_RF1R_RFOM1;
|
||||
|
||||
// Process packet
|
||||
union {
|
||||
struct { uint32_t rdlr, rdhr; };
|
||||
uint8_t data[8];
|
||||
} rdata = { .rdlr = rdlr, .rdhr = rdhr };
|
||||
canbus_process_data(rir_id, dlc, rdata.data);
|
||||
}
|
||||
uint32_t ier = SOC_CAN->IER;
|
||||
if (ier & CAN_IER_FMPIE0 && SOC_CAN->RF0R & CAN_RF0R_FMP0) {
|
||||
// Admin Rx
|
||||
SOC_CAN->IER = ier = ier & ~CAN_IER_FMPIE0;
|
||||
canbus_notify_rx();
|
||||
}
|
||||
if (ier & CAN_IER_TMEIE
|
||||
&& SOC_CAN->TSR & (CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2)) {
|
||||
// Tx
|
||||
SOC_CAN->IER &= ~CAN_IER_TMEIE;
|
||||
SOC_CAN->IER = ier & ~CAN_IER_TMEIE;
|
||||
canbus_notify_tx();
|
||||
}
|
||||
}
|
||||
@ -260,6 +267,12 @@ compute_btr(uint32_t pclock, uint32_t bitrate)
|
||||
return make_btr(sjw, time_seg1, time_seg2, brp);
|
||||
}
|
||||
|
||||
void
|
||||
canbus_reboot(void)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void
|
||||
can_init(void)
|
||||
{
|
||||
@ -270,7 +283,7 @@ can_init(void)
|
||||
|
||||
uint32_t pclock = get_pclock_frequency((uint32_t)SOC_CAN);
|
||||
|
||||
uint32_t btr = compute_btr(pclock, CONFIG_CANBUS_BAUD);
|
||||
uint32_t btr = compute_btr(pclock, CONFIG_CANBUS_FREQUENCY);
|
||||
|
||||
/*##-1- Configure the CAN #######################################*/
|
||||
|
||||
@ -290,17 +303,15 @@ can_init(void)
|
||||
;
|
||||
|
||||
/*##-2- Configure the CAN Filter #######################################*/
|
||||
can_set_filter(CANBUS_ID_UUID, CANBUS_ID_SET);
|
||||
canbus_set_filter(0);
|
||||
|
||||
/*##-3- Configure Interrupts #################################*/
|
||||
|
||||
SOC_CAN->IER = CAN_IER_FMPIE0; // RX mailbox IRQ
|
||||
|
||||
armcm_enable_irq(CAN_IRQHandler, CAN_RX0_IRQn, 0);
|
||||
if (CAN_RX0_IRQn != CAN_RX1_IRQn)
|
||||
armcm_enable_irq(CAN_IRQHandler, CAN_RX1_IRQn, 0);
|
||||
if (CAN_RX0_IRQn != CAN_TX_IRQn)
|
||||
armcm_enable_irq(CAN_IRQHandler, CAN_TX_IRQn, 0);
|
||||
SOC_CAN->IER = CAN_IER_FMPIE1;
|
||||
|
||||
// Convert unique 96-bit chip id into 48 bit representation
|
||||
uint64_t hash = fasthash64((uint8_t*)UID_BASE, 12, 0xA16231A7);
|
||||
|
32
src/stm32/clockline.c
Normal file
32
src/stm32/clockline.c
Normal file
@ -0,0 +1,32 @@
|
||||
// Code to enable clock lines on stm32
|
||||
//
|
||||
// Copyright (C) 2021 Kevin O'Connor <kevin@koconnor.net>
|
||||
//
|
||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
|
||||
#include "board/irq.h" // irq_save
|
||||
#include "internal.h" // struct cline
|
||||
|
||||
// Enable a peripheral clock
|
||||
void
|
||||
enable_pclock(uint32_t periph_base)
|
||||
{
|
||||
struct cline cl = lookup_clock_line(periph_base);
|
||||
irqstatus_t flag = irq_save();
|
||||
*cl.en |= cl.bit;
|
||||
*cl.en; // Pause 2 cycles to ensure peripheral is enabled
|
||||
if (cl.rst) {
|
||||
// Reset peripheral
|
||||
*cl.rst = cl.bit;
|
||||
*cl.rst = 0;
|
||||
}
|
||||
irq_restore(flag);
|
||||
}
|
||||
|
||||
// Check if a peripheral clock has been enabled
|
||||
int
|
||||
is_enabled_pclock(uint32_t periph_base)
|
||||
{
|
||||
struct cline cl = lookup_clock_line(periph_base);
|
||||
return *cl.en & cl.bit;
|
||||
}
|
38
src/stm32/gpioperiph.c
Normal file
38
src/stm32/gpioperiph.c
Normal file
@ -0,0 +1,38 @@
|
||||
// Code to setup gpio on stm32 chip (except for stm32f1)
|
||||
//
|
||||
// Copyright (C) 2019-2021 Kevin O'Connor <kevin@koconnor.net>
|
||||
//
|
||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
|
||||
#include "internal.h" // gpio_peripheral
|
||||
|
||||
// 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);
|
||||
|
||||
// Setup OSPEEDR:
|
||||
// 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);
|
||||
}
|
@ -12,24 +12,34 @@
|
||||
#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
|
||||
|
||||
// gpio.c
|
||||
extern GPIO_TypeDef * const digital_regs[];
|
||||
|
||||
#define GPIO(PORT, NUM) (((PORT)-'A') * 16 + (NUM))
|
||||
#define GPIO2PORT(PIN) ((PIN) / 16)
|
||||
#define GPIO2BIT(PIN) (1<<((PIN) % 16))
|
||||
|
||||
// gpioperiph.c
|
||||
#define GPIO_INPUT 0
|
||||
#define GPIO_OUTPUT 1
|
||||
#define GPIO_OPEN_DRAIN 0x100
|
||||
#define GPIO_FUNCTION(fn) (2 | ((fn) << 4))
|
||||
#define GPIO_ANALOG 3
|
||||
|
||||
void enable_pclock(uint32_t periph_base);
|
||||
int is_enabled_pclock(uint32_t periph_base);
|
||||
uint32_t get_pclock_frequency(uint32_t periph_base);
|
||||
void gpio_clock_enable(GPIO_TypeDef *regs);
|
||||
void gpio_peripheral(uint32_t gpio, uint32_t mode, int pullup);
|
||||
|
||||
// clockline.c
|
||||
void enable_pclock(uint32_t periph_base);
|
||||
int is_enabled_pclock(uint32_t periph_base);
|
||||
|
||||
// stm32??.c
|
||||
struct cline { volatile uint32_t *en, *rst; uint32_t bit; };
|
||||
struct cline lookup_clock_line(uint32_t periph_base);
|
||||
uint32_t get_pclock_frequency(uint32_t periph_base);
|
||||
void gpio_clock_enable(GPIO_TypeDef *regs);
|
||||
|
||||
#endif // internal.h
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code to setup clocks and gpio on stm32f0
|
||||
// Code to setup clocks on stm32f0
|
||||
//
|
||||
// Copyright (C) 2019 Kevin O'Connor <kevin@koconnor.net>
|
||||
// Copyright (C) 2019-2021 Kevin O'Connor <kevin@koconnor.net>
|
||||
//
|
||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
|
||||
@ -13,38 +13,19 @@
|
||||
|
||||
#define FREQ_PERIPH 48000000
|
||||
|
||||
// Enable a peripheral clock
|
||||
void
|
||||
enable_pclock(uint32_t periph_base)
|
||||
// Map a peripheral address to its enable bits
|
||||
struct cline
|
||||
lookup_clock_line(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;
|
||||
if (periph_base >= AHB2PERIPH_BASE) {
|
||||
uint32_t bit = 1 << ((periph_base - AHB2PERIPH_BASE) / 0x400 + 17);
|
||||
return (struct cline){.en=&RCC->AHBENR, .rst=&RCC->AHBRSTR, .bit=bit};
|
||||
} else if (periph_base >= SYSCFG_BASE) {
|
||||
uint32_t bit = 1 << ((periph_base - SYSCFG_BASE) / 0x400);
|
||||
return (struct cline){.en=&RCC->APB2ENR, .rst=&RCC->APB2RSTR, .bit=bit};
|
||||
} 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));
|
||||
uint32_t bit = 1 << ((periph_base - APBPERIPH_BASE) / 0x400);
|
||||
return (struct cline){.en=&RCC->APB1ENR, .rst=&RCC->APB1RSTR, .bit=bit};
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,41 +45,6 @@ gpio_clock_enable(GPIO_TypeDef *regs)
|
||||
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);
|
||||
}
|
||||
|
||||
#define USB_BOOT_FLAG_ADDR (CONFIG_RAM_START + CONFIG_RAM_SIZE - 1024)
|
||||
#define USB_BOOT_FLAG 0x55534220424f4f54 // "USB BOOT"
|
||||
|
||||
// Handle USB reboot requests
|
||||
void
|
||||
usb_request_bootloader(void)
|
||||
{
|
||||
irq_disable();
|
||||
*(uint64_t*)USB_BOOT_FLAG_ADDR = USB_BOOT_FLAG;
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
// Configure and enable the PLL as clock source
|
||||
static void
|
||||
pll_setup(void)
|
||||
@ -160,7 +106,7 @@ armcm_main(void)
|
||||
|
||||
// Support pin remapping USB/CAN pins on low pinout stm32f042
|
||||
#ifdef SYSCFG_CFGR1_PA11_PA12_RMP
|
||||
if (CONFIG_STM32F042_PIN_SWAP) {
|
||||
if (CONFIG_STM32_CANBUS_PA11_PA12_REMAP) {
|
||||
enable_pclock(SYSCFG_BASE);
|
||||
SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code to setup clocks and gpio on stm32f1
|
||||
//
|
||||
// Copyright (C) 2019 Kevin O'Connor <kevin@koconnor.net>
|
||||
// Copyright (C) 2019-2021 Kevin O'Connor <kevin@koconnor.net>
|
||||
//
|
||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
|
||||
@ -13,38 +13,19 @@
|
||||
|
||||
#define FREQ_PERIPH (CONFIG_CLOCK_FREQ / 2)
|
||||
|
||||
// Enable a peripheral clock
|
||||
void
|
||||
enable_pclock(uint32_t periph_base)
|
||||
// Map a peripheral address to its enable bits
|
||||
struct cline
|
||||
lookup_clock_line(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;
|
||||
if (periph_base >= AHBPERIPH_BASE) {
|
||||
uint32_t bit = 1 << ((periph_base - AHBPERIPH_BASE) / 0x400);
|
||||
return (struct cline){.en=&RCC->AHBENR, .bit=bit};
|
||||
} else if (periph_base >= APB2PERIPH_BASE) {
|
||||
uint32_t bit = 1 << ((periph_base - APB2PERIPH_BASE) / 0x400);
|
||||
return (struct cline){.en=&RCC->APB2ENR, .rst=&RCC->APB2RSTR, .bit=bit};
|
||||
} 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);
|
||||
uint32_t bit = 1 << ((periph_base - APB1PERIPH_BASE) / 0x400);
|
||||
return (struct cline){.en=&RCC->APB1ENR, .rst=&RCC->APB1RSTR, .bit=bit};
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,74 +45,6 @@ gpio_clock_enable(GPIO_TypeDef *regs)
|
||||
RCC->APB2ENR;
|
||||
}
|
||||
|
||||
|
||||
static void stm32f1_alternative_remap(uint32_t mapr_mask, uint32_t mapr_value)
|
||||
{
|
||||
// The MAPR register is a mix of write only and r/w bits
|
||||
// We have to save the written values in a global variable
|
||||
static uint32_t mapr = 0;
|
||||
|
||||
mapr &= ~mapr_mask;
|
||||
mapr |= mapr_value;
|
||||
AFIO->MAPR = mapr;
|
||||
}
|
||||
|
||||
// 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 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_OUTPUT | GPIO_OPEN_DRAIN)) {
|
||||
cfg = 0x5;
|
||||
} else if (mode == GPIO_ANALOG) {
|
||||
cfg = 0x0;
|
||||
} else {
|
||||
if (mode & GPIO_OPEN_DRAIN)
|
||||
// Alternate function with open-drain mode
|
||||
cfg = 0xd;
|
||||
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);
|
||||
|
||||
if (gpio == GPIO('A', 13) || gpio == GPIO('A', 14))
|
||||
// Disable SWD to free PA13, PA14
|
||||
stm32f1_alternative_remap(AFIO_MAPR_SWJ_CFG_Msk,
|
||||
AFIO_MAPR_SWJ_CFG_DISABLE);
|
||||
|
||||
// STM32F1 remaps functions to pins in a very different
|
||||
// way from other STM32s.
|
||||
// Code below is emulating a few mappings to work like an STM32F4
|
||||
uint32_t func = (mode >> 4) & 0xf;
|
||||
if(( gpio == GPIO('B', 8) || gpio == GPIO('B', 9)) &&
|
||||
func == 9) { // CAN
|
||||
stm32f1_alternative_remap(AFIO_MAPR_CAN_REMAP_Msk,
|
||||
AFIO_MAPR_CAN_REMAP_REMAP2);
|
||||
}
|
||||
// Add more as needed
|
||||
}
|
||||
|
||||
// Main clock setup called at chip startup
|
||||
static void
|
||||
clock_setup(void)
|
||||
@ -140,9 +53,14 @@ clock_setup(void)
|
||||
uint32_t cfgr;
|
||||
if (!CONFIG_STM32_CLOCK_REF_INTERNAL) {
|
||||
// Configure 72Mhz PLL from external crystal (HSE)
|
||||
uint32_t div = CONFIG_CLOCK_FREQ / CONFIG_CLOCK_REF_FREQ;
|
||||
RCC->CR |= RCC_CR_HSEON;
|
||||
cfgr = (1 << RCC_CFGR_PLLSRC_Pos) | ((div - 2) << RCC_CFGR_PLLMULL_Pos);
|
||||
uint32_t div = CONFIG_CLOCK_FREQ / (CONFIG_CLOCK_REF_FREQ / 2);
|
||||
cfgr = 1 << RCC_CFGR_PLLSRC_Pos;
|
||||
if ((div & 1) && div <= 16)
|
||||
cfgr |= RCC_CFGR_PLLXTPRE_HSE_DIV2;
|
||||
else
|
||||
div /= 2;
|
||||
cfgr |= (div - 2) << RCC_CFGR_PLLMULL_Pos;
|
||||
} else {
|
||||
// Configure 72Mhz PLL from internal 8Mhz oscillator (HSI)
|
||||
uint32_t div2 = (CONFIG_CLOCK_FREQ / 8000000) * 2;
|
||||
@ -166,6 +84,131 @@ clock_setup(void)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* GPIO setup
|
||||
****************************************************************/
|
||||
|
||||
static void
|
||||
stm32f1_alternative_remap(uint32_t mapr_mask, uint32_t mapr_value)
|
||||
{
|
||||
// The MAPR register is a mix of write only and r/w bits
|
||||
// We have to save the written values in a global variable
|
||||
static uint32_t mapr = 0;
|
||||
|
||||
mapr &= ~mapr_mask;
|
||||
mapr |= mapr_value;
|
||||
AFIO->MAPR = mapr;
|
||||
}
|
||||
|
||||
#define STM_OSPEED 0x1 // ~10Mhz at 50pF
|
||||
|
||||
// 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 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 = STM_OSPEED;
|
||||
} else if (mode == (GPIO_OUTPUT | GPIO_OPEN_DRAIN)) {
|
||||
cfg = 0x4 | STM_OSPEED;
|
||||
} else if (mode == GPIO_ANALOG) {
|
||||
cfg = 0x0;
|
||||
} else {
|
||||
if (mode & GPIO_OPEN_DRAIN)
|
||||
// Alternate function with open-drain mode
|
||||
cfg = 0xc | STM_OSPEED;
|
||||
else if (pullup > 0)
|
||||
// Alternate function input pins use GPIO_INPUT mode on the stm32f1
|
||||
cfg = 0x8;
|
||||
else
|
||||
cfg = 0x8 | STM_OSPEED;
|
||||
}
|
||||
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);
|
||||
|
||||
if (gpio == GPIO('A', 13) || gpio == GPIO('A', 14))
|
||||
// Disable SWD to free PA13, PA14
|
||||
stm32f1_alternative_remap(AFIO_MAPR_SWJ_CFG_Msk,
|
||||
AFIO_MAPR_SWJ_CFG_DISABLE);
|
||||
|
||||
// STM32F1 remaps functions to pins in a very different
|
||||
// way from other STM32s.
|
||||
// Code below is emulating a few mappings to work like an STM32F4
|
||||
uint32_t func = (mode >> 4) & 0xf;
|
||||
if (func == 1) {
|
||||
// TIM2
|
||||
if (gpio == GPIO('A', 15) || gpio == GPIO('B', 3))
|
||||
stm32f1_alternative_remap(AFIO_MAPR_TIM2_REMAP_Msk,
|
||||
AFIO_MAPR_TIM2_REMAP_PARTIALREMAP1);
|
||||
else if (gpio == GPIO('B', 10) || gpio == GPIO('B', 11))
|
||||
stm32f1_alternative_remap(AFIO_MAPR_TIM2_REMAP_Msk,
|
||||
AFIO_MAPR_TIM2_REMAP_PARTIALREMAP2);
|
||||
} else if (func == 2) {
|
||||
// TIM3 and TIM4
|
||||
if (gpio == GPIO('B', 4) || gpio == GPIO('B', 5))
|
||||
stm32f1_alternative_remap(AFIO_MAPR_TIM3_REMAP_Msk,
|
||||
AFIO_MAPR_TIM3_REMAP_PARTIALREMAP);
|
||||
else if (gpio == GPIO('C', 6) || gpio == GPIO('C', 7)
|
||||
|| gpio == GPIO('C', 8) || gpio == GPIO('C', 9))
|
||||
stm32f1_alternative_remap(AFIO_MAPR_TIM3_REMAP_Msk,
|
||||
AFIO_MAPR_TIM3_REMAP_FULLREMAP);
|
||||
else if (gpio == GPIO('D', 12) || gpio == GPIO('D', 13)
|
||||
|| gpio == GPIO('D', 14) || gpio == GPIO('D', 15))
|
||||
stm32f1_alternative_remap(AFIO_MAPR_TIM4_REMAP_Msk,
|
||||
AFIO_MAPR_TIM4_REMAP);
|
||||
} else if (func == 4) {
|
||||
// I2C
|
||||
if (gpio == GPIO('B', 8) || gpio == GPIO('B', 9))
|
||||
stm32f1_alternative_remap(AFIO_MAPR_I2C1_REMAP_Msk,
|
||||
AFIO_MAPR_I2C1_REMAP);
|
||||
} else if (func == 5) {
|
||||
// SPI
|
||||
if (gpio == GPIO('B', 3) || gpio == GPIO('B', 4)
|
||||
|| gpio == GPIO('B', 5))
|
||||
stm32f1_alternative_remap(AFIO_MAPR_SPI1_REMAP_Msk,
|
||||
AFIO_MAPR_SPI1_REMAP);
|
||||
} else if (func == 7) {
|
||||
// USART
|
||||
if (gpio == GPIO('B', 6) || gpio == GPIO('B', 7))
|
||||
stm32f1_alternative_remap(AFIO_MAPR_USART1_REMAP_Msk,
|
||||
AFIO_MAPR_USART1_REMAP);
|
||||
else if (gpio == GPIO('D', 5) || gpio == GPIO('D', 6))
|
||||
stm32f1_alternative_remap(AFIO_MAPR_USART2_REMAP_Msk,
|
||||
AFIO_MAPR_USART2_REMAP);
|
||||
else if (gpio == GPIO('D', 8) || gpio == GPIO('D', 9))
|
||||
stm32f1_alternative_remap(AFIO_MAPR_USART3_REMAP_Msk,
|
||||
AFIO_MAPR_USART3_REMAP_FULLREMAP);
|
||||
} else if (func == 9) {
|
||||
// CAN
|
||||
if (gpio == GPIO('B', 8) || gpio == GPIO('B', 9))
|
||||
stm32f1_alternative_remap(AFIO_MAPR_CAN_REMAP_Msk,
|
||||
AFIO_MAPR_CAN_REMAP_REMAP2);
|
||||
if (gpio == GPIO('D', 0) || gpio == GPIO('D', 1))
|
||||
stm32f1_alternative_remap(AFIO_MAPR_CAN_REMAP_Msk,
|
||||
AFIO_MAPR_CAN_REMAP_REMAP3);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Startup
|
||||
****************************************************************/
|
||||
|
||||
// Main entry point - called from armcm_boot.c:ResetHandler()
|
||||
void
|
||||
armcm_main(void)
|
||||
@ -174,7 +217,7 @@ armcm_main(void)
|
||||
SystemInit();
|
||||
SCB->VTOR = (uint32_t)VectorTable;
|
||||
|
||||
// Reset peripheral clocks
|
||||
// Reset peripheral clocks (for some bootloaders that don't)
|
||||
RCC->AHBENR = 0x14;
|
||||
RCC->APB1ENR = 0;
|
||||
RCC->APB2ENR = 0;
|
||||
@ -184,8 +227,13 @@ armcm_main(void)
|
||||
|
||||
// Disable JTAG to free PA15, PB3, PB4
|
||||
enable_pclock(AFIO_BASE);
|
||||
stm32f1_alternative_remap(AFIO_MAPR_SWJ_CFG_Msk,
|
||||
AFIO_MAPR_SWJ_CFG_JTAGDISABLE);
|
||||
if (CONFIG_STM32F103GD_DISABLE_SWD)
|
||||
// GigaDevice clone can't enable PA13/PA14 at runtime - enable here
|
||||
stm32f1_alternative_remap(AFIO_MAPR_SWJ_CFG_Msk,
|
||||
AFIO_MAPR_SWJ_CFG_DISABLE);
|
||||
else
|
||||
stm32f1_alternative_remap(AFIO_MAPR_SWJ_CFG_Msk,
|
||||
AFIO_MAPR_SWJ_CFG_JTAGDISABLE);
|
||||
|
||||
canboot_main();
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code to setup clocks and gpio on stm32f2/stm32f4
|
||||
// Code to setup clocks on stm32f2/stm32f4
|
||||
//
|
||||
// Copyright (C) 2019 Kevin O'Connor <kevin@koconnor.net>
|
||||
// Copyright (C) 2019-2021 Kevin O'Connor <kevin@koconnor.net>
|
||||
//
|
||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
|
||||
@ -11,45 +11,34 @@
|
||||
#include "internal.h" // enable_pclock
|
||||
#include "canboot_main.h" // sched_main
|
||||
|
||||
#define FREQ_PERIPH (CONFIG_CLOCK_FREQ / 4)
|
||||
|
||||
/****************************************************************
|
||||
* Clock setup
|
||||
****************************************************************/
|
||||
|
||||
#define FREQ_PERIPH_DIV (CONFIG_MACH_STM32F401 ? 2 : 4)
|
||||
#define FREQ_PERIPH (CONFIG_CLOCK_FREQ / FREQ_PERIPH_DIV)
|
||||
#define FREQ_USB 48000000
|
||||
|
||||
// Enable a peripheral clock
|
||||
void
|
||||
enable_pclock(uint32_t periph_base)
|
||||
// Map a peripheral address to its enable bits
|
||||
struct cline
|
||||
lookup_clock_line(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 < AHB1PERIPH_BASE) {
|
||||
uint32_t pos = (periph_base - APB2PERIPH_BASE) / 0x400;
|
||||
RCC->APB2ENR |= (1<<pos);
|
||||
RCC->APB2ENR;
|
||||
} else if (periph_base < AHB2PERIPH_BASE) {
|
||||
uint32_t pos = (periph_base - AHB1PERIPH_BASE) / 0x400;
|
||||
RCC->AHB1ENR |= (1<<pos);
|
||||
RCC->AHB1ENR;
|
||||
if (periph_base >= AHB1PERIPH_BASE) {
|
||||
uint32_t bit = 1 << ((periph_base - AHB1PERIPH_BASE) / 0x400);
|
||||
return (struct cline){.en=&RCC->AHB1ENR, .rst=&RCC->AHB1RSTR, .bit=bit};
|
||||
} else if (periph_base >= APB2PERIPH_BASE) {
|
||||
uint32_t bit = 1 << ((periph_base - APB2PERIPH_BASE) / 0x400);
|
||||
if (bit & 0x700)
|
||||
// Skip ADC peripheral reset as they share a bit
|
||||
return (struct cline){.en=&RCC->APB2ENR, .bit=bit};
|
||||
return (struct cline){.en=&RCC->APB2ENR, .rst=&RCC->APB2RSTR, .bit=bit};
|
||||
} else {
|
||||
uint32_t bit = 1 << ((periph_base - APB1PERIPH_BASE) / 0x400);
|
||||
return (struct cline){.en=&RCC->APB1ENR, .rst=&RCC->APB1RSTR, .bit=bit};
|
||||
}
|
||||
}
|
||||
|
||||
// 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 < AHB1PERIPH_BASE) {
|
||||
uint32_t pos = (periph_base - APB2PERIPH_BASE) / 0x400;
|
||||
return RCC->APB2ENR & (1<<pos);
|
||||
} else if (periph_base < AHB2PERIPH_BASE) {
|
||||
uint32_t pos = (periph_base - AHB1PERIPH_BASE) / 0x400;
|
||||
return RCC->AHB1ENR & (1<<pos);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Return the frequency of the given peripheral clock
|
||||
uint32_t
|
||||
get_pclock_frequency(uint32_t periph_base)
|
||||
@ -66,52 +55,6 @@ gpio_clock_enable(GPIO_TypeDef *regs)
|
||||
RCC->AHB1ENR;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
#define USB_BOOT_FLAG_ADDR (CONFIG_RAM_START + CONFIG_RAM_SIZE - 4096)
|
||||
#define USB_BOOT_FLAG 0x55534220424f4f54 // "USB BOOT"
|
||||
|
||||
// Handle USB reboot requests
|
||||
void
|
||||
usb_request_bootloader(void)
|
||||
{
|
||||
irq_disable();
|
||||
if (CONFIG_STM32_FLASH_START_4000) {
|
||||
// HID Bootloader
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
|
||||
RCC->APB1ENR;
|
||||
PWR->CR |= PWR_CR_DBP;
|
||||
// HID Bootloader magic key
|
||||
RTC->BKP4R = 0x424C;
|
||||
PWR->CR &= ~PWR_CR_DBP;
|
||||
} else {
|
||||
// System DFU Bootloader
|
||||
*(uint64_t*)USB_BOOT_FLAG_ADDR = USB_BOOT_FLAG;
|
||||
}
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
// Clock configuration
|
||||
static void
|
||||
enable_clock_stm32f20x(void)
|
||||
@ -138,8 +81,10 @@ enable_clock_stm32f20x(void)
|
||||
static void
|
||||
enable_clock_stm32f40x(void)
|
||||
{
|
||||
#if CONFIG_MACH_STM32F405 || CONFIG_MACH_STM32F407
|
||||
uint32_t pll_base = 2000000, pll_freq = CONFIG_CLOCK_FREQ * 2, pllcfgr;
|
||||
#if CONFIG_MACH_STM32F401 || CONFIG_MACH_STM32F4x5
|
||||
uint32_t pll_base = (CONFIG_STM32_CLOCK_REF_25M) ? 1000000 : 2000000;
|
||||
uint32_t pllp = (CONFIG_MACH_STM32F401) ? 4 : 2;
|
||||
uint32_t pll_freq = CONFIG_CLOCK_FREQ * pllp, pllcfgr;
|
||||
if (!CONFIG_STM32_CLOCK_REF_INTERNAL) {
|
||||
// Configure 168Mhz PLL from external crystal (HSE)
|
||||
uint32_t div = CONFIG_CLOCK_REF_FREQ / pll_base;
|
||||
@ -151,7 +96,7 @@ enable_clock_stm32f40x(void)
|
||||
pllcfgr = RCC_PLLCFGR_PLLSRC_HSI | (div << RCC_PLLCFGR_PLLM_Pos);
|
||||
}
|
||||
RCC->PLLCFGR = (pllcfgr | ((pll_freq/pll_base) << RCC_PLLCFGR_PLLN_Pos)
|
||||
| (0 << RCC_PLLCFGR_PLLP_Pos)
|
||||
| (((pllp >> 1) - 1) << RCC_PLLCFGR_PLLP_Pos)
|
||||
| ((pll_freq/FREQ_USB) << RCC_PLLCFGR_PLLQ_Pos));
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
#endif
|
||||
@ -213,7 +158,7 @@ clock_setup(void)
|
||||
// Configure and enable PLL
|
||||
if (CONFIG_MACH_STM32F207)
|
||||
enable_clock_stm32f20x();
|
||||
else if (CONFIG_MACH_STM32F405 || CONFIG_MACH_STM32F407)
|
||||
else if (CONFIG_MACH_STM32F4x5)
|
||||
enable_clock_stm32f40x();
|
||||
else
|
||||
enable_clock_stm32f446();
|
||||
@ -227,26 +172,32 @@ clock_setup(void)
|
||||
;
|
||||
|
||||
// Switch system clock to PLL
|
||||
RCC->CFGR = RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_PPRE2_DIV4 | RCC_CFGR_SW_PLL;
|
||||
if (FREQ_PERIPH_DIV == 2)
|
||||
RCC->CFGR = RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_SW_PLL;
|
||||
else
|
||||
RCC->CFGR = RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_PPRE2_DIV4 | RCC_CFGR_SW_PLL;
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL)
|
||||
;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Startup
|
||||
****************************************************************/
|
||||
|
||||
// Main entry point - called from armcm_boot.c:ResetHandler()
|
||||
void
|
||||
armcm_main(void)
|
||||
{
|
||||
if (CONFIG_USBSERIAL && *(uint64_t*)USB_BOOT_FLAG_ADDR == USB_BOOT_FLAG) {
|
||||
*(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]));
|
||||
}
|
||||
|
||||
// Run SystemInit() and then restore VTOR
|
||||
SystemInit();
|
||||
SCB->VTOR = (uint32_t)VectorTable;
|
||||
|
||||
// Reset peripheral clocks (for some bootloaders that don't)
|
||||
RCC->AHB1ENR = 0x38000;
|
||||
RCC->AHB2ENR = 0;
|
||||
RCC->APB1ENR = 0;
|
||||
RCC->APB2ENR = 0;
|
||||
|
||||
clock_setup();
|
||||
|
||||
sched_main();
|
||||
|
Loading…
x
Reference in New Issue
Block a user