forked from keirf/flashfloppy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmcu_stm32f105.c
161 lines (140 loc) · 4.64 KB
/
mcu_stm32f105.c
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
* mcu_stm32f105.c
*
* Core and peripheral registers.
*
* Written & released by Keir Fraser <[email protected]>
*
* This is free and unencumbered software released into the public domain.
* See the file COPYING for more details, or visit <http://unlicense.org>.
*/
unsigned int sysclk_mhz = 72;
unsigned int apb1_mhz = 36;
bool_t is_artery_mcu;
unsigned int flash_page_size = FLASH_PAGE_SIZE;
unsigned int ram_kb = 64;
static void identify_mcu(void)
{
/* DBGMCU_IDCODE (E0042000):
* STM32F105RB: 10016418 (device id: 418)
* AT32F415CBT7: 700301c5 (device id: 1c5)
* AT32F415RCT7: 70030240 (device id: 240)
* However the AT32 IDCODE values are undocumented so we cannot rely
* on them (for example, what will be the ID for chips with differing
* amounts of Flash, or numbers of pins?) */
/* We detect an Artery MCU by presence of Cortex-M4 CPUID.
* Cortex-M4: 41xfc24x ; Cortex-M3: 41xfc23x */
is_artery_mcu = ((scb->cpuid >> 4) & 0xf) == 4;
if (is_artery_mcu) {
unsigned int flash_kb = *(uint16_t *)0x1ffff7e0;
ram_kb = 32;
if (flash_kb == 128)
flash_page_size = 1024;
sysclk_mhz = 144;
apb1_mhz = 72;
}
}
static void clock_init(void)
{
/* Flash controller: reads require 2 wait states at 72MHz. */
flash->acr = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY(sysclk_mhz/32);
/* Start up the external oscillator. */
rcc->cr |= RCC_CR_HSEON;
while (!(rcc->cr & RCC_CR_HSERDY))
cpu_relax();
/* PLLs, scalers, muxes. */
if (is_artery_mcu) {
uint32_t rcc_pll = *RCC_PLL;
rcc_pll &= ~(RCC_PLL_PLLCFGEN | RCC_PLL_FREF_MASK);
rcc_pll |= RCC_PLL_FREF_8M;
*RCC_PLL = rcc_pll;
rcc->cfgr = (RCC_CFGR_PLLMUL_18 | /* PLL = 18*8MHz = 144MHz */
RCC_CFGR_USBPSC_3 | /* USB = SYSCLK/3 = 48MHz */
RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_ADCPRE_DIV8 |
RCC_CFGR_APB2PSC_2 | /* APB2 = SYSCLK/2 = 72MHz */
RCC_CFGR_APB1PSC_2); /* APB1 = SYSCLK/2 = 72MHz */
} else {
rcc->cfgr = (RCC_CFGR_PLLMUL(9) | /* PLL = 9*8MHz = 72MHz */
RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_ADCPRE_DIV8 |
RCC_CFGR_APB1PSC_2); /* APB1 = SYSCLK/2 = 36MHz */
}
/* Enable and stabilise the PLL. */
rcc->cr |= RCC_CR_PLLON;
while (!(rcc->cr & RCC_CR_PLLRDY))
cpu_relax();
if (is_artery_mcu)
*RCC_MISC2 |= RCC_MISC2_AUTOSTEP_EN;
/* Switch to the externally-driven PLL for system clock. */
rcc->cfgr |= RCC_CFGR_SW_PLL;
while ((rcc->cfgr & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL)
cpu_relax();
if (is_artery_mcu)
*RCC_MISC2 &= ~RCC_MISC2_AUTOSTEP_EN;
/* Internal oscillator no longer needed. */
rcc->cr &= ~RCC_CR_HSION;
}
static void gpio_init(GPIO gpio)
{
/* Floating Input. Reference Manual states that JTAG pins are in PU/PD
* mode at reset, so ensure all PU/PD are disabled. */
gpio->crl = gpio->crh = 0x44444444u;
}
static void peripheral_init(void)
{
/* Enable basic GPIO and AFIO clocks, all timers, and DMA. */
rcc->apb1enr = (RCC_APB1ENR_TIM2EN |
RCC_APB1ENR_TIM3EN |
RCC_APB1ENR_TIM4EN);
rcc->apb2enr = (RCC_APB2ENR_IOPAEN |
RCC_APB2ENR_IOPBEN |
RCC_APB2ENR_IOPCEN |
RCC_APB2ENR_AFIOEN |
RCC_APB2ENR_TIM1EN);
rcc->ahbenr = RCC_AHBENR_DMA1EN;
/* Turn off serial-wire JTAG and reclaim the GPIOs. */
afio->mapr = AFIO_MAPR_SWJ_CFG_DISABLED;
/* All pins in a stable state. */
gpio_init(gpioa);
gpio_init(gpiob);
gpio_init(gpioc);
}
void stm32_init(void)
{
cortex_init();
identify_mcu();
clock_init();
peripheral_init();
cpu_sync();
}
void gpio_configure_pin(GPIO gpio, unsigned int pin, unsigned int mode)
{
gpio_write_pin(gpio, pin, mode >> 4);
mode &= 0xfu;
if (pin >= 8) {
pin -= 8;
gpio->crh = (gpio->crh & ~(0xfu<<(pin<<2))) | (mode<<(pin<<2));
} else {
gpio->crl = (gpio->crl & ~(0xfu<<(pin<<2))) | (mode<<(pin<<2));
}
}
void _exti_route(unsigned int px, unsigned int pin)
{
unsigned int n = pin >> 2;
unsigned int s = (pin & 3) << 2;
uint32_t exticr = afio->exticr[n];
ASSERT(!in_exception()); /* no races please */
exticr &= ~(0xf << s);
exticr |= px << s;
afio->exticr[n] = exticr;
}
/*
* Local variables:
* mode: C
* c-file-style: "Linux"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/