blob: e5defd96219cf95fdd441f10c8782545cf7d5e0d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
// 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;
}
// Enable a GPIO peripheral clock
void
gpio_clock_enable(GPIO_TypeDef *regs)
{
uint32_t rcc_pos = ((uint32_t)regs - APB2PERIPH_BASE) / 0x400;
RCC->APB2ENR |= 1 << rcc_pos;
RCC->APB2ENR;
}
// 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
AFIO->MAPR = AFIO_MAPR_SWJ_CFG_DISABLE;
}
// 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;
}
|