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
|
/*
* Oct 2017 Karl Palsson <karlp@tweak.net.au>
*/
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/flash.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/usart.h>
#include "uart-basic.h"
/* f3 pll setup, based on l1/f4*/
typedef struct {
uint8_t pll_mul;
uint8_t pll_div;
uint8_t pll_source;
uint32_t flash_config;
uint8_t hpre;
uint8_t ppre1;
uint8_t ppre2;
uint32_t apb1_frequency;
uint32_t apb2_frequency;
uint32_t ahb_frequency;
} rcc_clock_scale_t;
static void rcc_clock_setup_pll_f3_special(const rcc_clock_scale_t *clock)
{
/* Turn on the appropriate source for the PLL */
// TODO, some f3's have extra bits here
enum rcc_osc my_osc;
if (clock->pll_source == RCC_CFGR_PLLSRC_HSE_PREDIV) {
my_osc = RCC_HSE;
} else {
my_osc = RCC_HSI;
}
rcc_osc_on(my_osc);
while (!rcc_is_osc_ready(my_osc));
/* Configure flash settings. */
flash_set_ws(clock->flash_config);
/*
* Set prescalers for AHB, ADC, ABP1, ABP2.
* Do this before touching the PLL (TODO: why?).
*/
rcc_set_hpre(clock->hpre);
rcc_set_ppre1(clock->ppre1);
rcc_set_ppre2(clock->ppre2);
rcc_osc_off(RCC_PLL);
while (rcc_is_osc_ready(RCC_PLL));
rcc_set_pll_source(clock->pll_source);
rcc_set_pll_multiplier(clock->pll_mul);
// TODO - iff pll_div != 0, then maybe we're on a target that
// has the dividers?
/* Enable PLL oscillator and wait for it to stabilize. */
rcc_osc_on(RCC_PLL);
while (!rcc_is_osc_ready(RCC_PLL));
/* Select PLL as SYSCLK source. */
rcc_set_sysclk_source(RCC_CFGR_SW_PLL);
rcc_wait_for_sysclk_status(RCC_PLL);
/* Set the peripheral clock frequencies used. */
rcc_ahb_frequency = clock->ahb_frequency;
rcc_apb1_frequency = clock->apb1_frequency;
rcc_apb2_frequency = clock->apb2_frequency;
}
static void setup_clocks(void)
{
rcc_clock_scale_t clock_full_hse8mhz ={
.pll_mul = RCC_CFGR_PLLMUL_PLL_IN_CLK_X9,
.pll_source = RCC_CFGR_PLLSRC_HSE_PREDIV,
.hpre = RCC_CFGR_HPRE_DIV_NONE,
.ppre1 = RCC_CFGR_PPRE1_DIV_2,
.ppre2 = RCC_CFGR_PPRE2_DIV_NONE,
.flash_config = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_2WS,
.apb1_frequency = 36000000,
.apb2_frequency = 72000000,
.ahb_frequency = 72000000,
};
rcc_clock_setup_pll_f3_special(&clock_full_hse8mhz);
}
void usart2_exti26_isr(void)
{
ub_irq_handler();
}
int main(void)
{
int i;
int j = 0;
setup_clocks();
/* Board led */
rcc_periph_clock_enable(RCC_GPIOE);
gpio_mode_setup(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8);
gpio_set(GPIOE, GPIO8);
/* board init for uart2 on pa2/3 */
rcc_periph_clock_enable(RCC_GPIOA);
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2|GPIO3);
/* usart is AF7 */
gpio_set_af(GPIOA, GPIO_AF7, GPIO2|GPIO3);
struct ub_hw ub = {
.uart = USART2,
.uart_nvic = NVIC_USART2_EXTI26_IRQ,
.uart_rcc = RCC_USART2,
};
ub_init(&ub);
printf("hi guys!\n");
while (1) {
gpio_toggle(GPIOE, GPIO8);
for (i = 0; i < 0x100000; i++) { /* Wait a bit. */
__asm__("NOP");
}
ub_task();
gpio_toggle(GPIOE, GPIO8);
for (i = 0; i < 0x100000; i++) { /* Wait a bit. */
__asm__("NOP");
}
}
return 0;
}
|