diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2019-07-28 23:15:54 -0400 |
---|---|---|
committer | KevinOConnor <kevin@koconnor.net> | 2019-08-05 11:25:40 -0400 |
commit | 8b9cc62359057a686929cc713ffe2931e2203946 (patch) | |
tree | ab2e5469d7919cc6ed652e2928f0eaf9a24420c3 /src/stm32/stm32f1.c | |
parent | ec3d865b517affd77678e5b1a45ef4691619726d (diff) | |
download | kutter-8b9cc62359057a686929cc713ffe2931e2203946.tar.gz kutter-8b9cc62359057a686929cc713ffe2931e2203946.tar.xz kutter-8b9cc62359057a686929cc713ffe2931e2203946.zip |
stm32: Rename stm32f4/ directory to stm32/
Now that the code in stm32f4/ can handle both stm32f1 and stm32f4
chips, rename the directory to just "stm32".
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/stm32/stm32f1.c')
-rw-r--r-- | src/stm32/stm32f1.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/stm32/stm32f1.c b/src/stm32/stm32f1.c new file mode 100644 index 00000000..3064d4c8 --- /dev/null +++ b/src/stm32/stm32f1.c @@ -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; +} |