Paparazzi UAS  v5.12_stable-4-g9b43e9b
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
mcu_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010-2012 The Paparazzi team
3  *
4  * This file is part of Paparazzi.
5  *
6  * Paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * Paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  */
22 
29 #include "mcu.h"
30 
31 #include BOARD_CONFIG
32 
33 #include <inttypes.h>
34 #include <libopencm3/stm32/gpio.h>
35 #include <libopencm3/stm32/rcc.h>
36 #include <libopencm3/stm32/timer.h>
37 #include <libopencm3/stm32/flash.h>
38 #include <libopencm3/cm3/scb.h>
39 
40 #include "std.h"
41 
42 #if defined(STM32F4)
43 /* untested, should go into libopencm3 */
44 const struct rcc_clock_scale rcc_hse_24mhz_3v3[RCC_CLOCK_3V3_END] = {
45  { /* 48MHz */
46  .pllm = 24,
47  .plln = 96,
48  .pllp = 2,
49  .pllq = 2,
50  .hpre = RCC_CFGR_HPRE_DIV_NONE,
51  .ppre1 = RCC_CFGR_PPRE_DIV_4,
52  .ppre2 = RCC_CFGR_PPRE_DIV_2,
53  .power_save = 1,
54  .flash_config = FLASH_ACR_ICE | FLASH_ACR_DCE | FLASH_ACR_LATENCY_3WS,
55  .ahb_frequency = 48000000,
56  .apb1_frequency = 12000000,
57  .apb2_frequency = 24000000,
58  },
59  { /* 84MHz */
60  .pllm = 24,
61  .plln = 336,
62  .pllp = 4,
63  .pllq = 7,
64  .hpre = RCC_CFGR_HPRE_DIV_NONE,
65  .ppre1 = RCC_CFGR_PPRE_DIV_2,
66  .ppre2 = RCC_CFGR_PPRE_DIV_NONE,
67  .power_save = 1,
68  .flash_config = FLASH_ACR_ICE | FLASH_ACR_DCE | FLASH_ACR_LATENCY_2WS,
69  .ahb_frequency = 84000000,
70  .apb1_frequency = 42000000,
71  .apb2_frequency = 84000000,
72  },
73  { /* 120MHz */
74  .pllm = 24,
75  .plln = 240,
76  .pllp = 2,
77  .pllq = 5,
78  .hpre = RCC_CFGR_HPRE_DIV_NONE,
79  .ppre1 = RCC_CFGR_PPRE_DIV_4,
80  .ppre2 = RCC_CFGR_PPRE_DIV_2,
81  .power_save = 1,
82  .flash_config = FLASH_ACR_ICE | FLASH_ACR_DCE | FLASH_ACR_LATENCY_3WS,
83  .ahb_frequency = 120000000,
84  .apb1_frequency = 30000000,
85  .apb2_frequency = 60000000,
86  },
87  { /* 168MHz */
88  .pllm = 24,
89  .plln = 336,
90  .pllp = 2,
91  .pllq = 7,
92  .hpre = RCC_CFGR_HPRE_DIV_NONE,
93  .ppre1 = RCC_CFGR_PPRE_DIV_4,
94  .ppre2 = RCC_CFGR_PPRE_DIV_2,
95  .flash_config = FLASH_ACR_ICE | FLASH_ACR_DCE | FLASH_ACR_LATENCY_5WS,
96  .ahb_frequency = 168000000,
97  .apb1_frequency = 42000000,
98  .apb2_frequency = 84000000,
99  },
100 };
101 #endif
102 
103 #if defined(STM32F1)
104 /*---------------------------------------------------------------------------*/
108 void rcc_clock_setup_in_hse_24mhz_out_24mhz_pprz(void);
109 void rcc_clock_setup_in_hse_24mhz_out_24mhz_pprz(void)
110 {
111  /* Enable internal high-speed oscillator. */
112  rcc_osc_on(RCC_HSI);
113  rcc_wait_for_osc_ready(RCC_HSI);
114 
115  /* Select HSI as SYSCLK source. */
116  rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
117 
118  /* Enable external high-speed oscillator 24MHz. */
119  rcc_osc_on(RCC_HSE);
120  rcc_wait_for_osc_ready(RCC_HSE);
121  rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK);
122 
123  /*
124  * Set prescalers for AHB, ADC, ABP1, ABP2.
125  * Do this before touching the PLL (TODO: why?).
126  */
127  rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 24MHz Max. 72MHz */
128  rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV2); /* Set. 12MHz Max. 14MHz */
129  rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_NODIV); /* Set. 24MHz Max. 36MHz */
130  rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 24MHz Max. 72MHz */
131 
132  /*
133  * Sysclk runs with 24MHz -> 0 waitstates.
134  * 0WS from 0-24MHz
135  * 1WS from 24-48MHz
136  * 2WS from 48-72MHz
137  */
138  flash_set_ws(FLASH_ACR_LATENCY_0WS);
139 
140  /*
141  * Set the PLL multiplication factor to 2.
142  * 24MHz (external) * 2 (multiplier) / 2 (RCC_CFGR_PLLXTPRE_HSE_CLK_DIV2) = 24MHz
143  */
144  rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL2);
145 
146  /* Select HSE as PLL source. */
147  rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_CLK);
148 
149  /*
150  * External frequency divide by 2 before entering PLL
151  * (only valid/needed for HSE).
152  */
153  rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK_DIV2);
154 
155  rcc_osc_on(RCC_PLL);
156  rcc_wait_for_osc_ready(RCC_PLL);
157 
158  /* Select PLL as SYSCLK source. */
159  rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
160 
161  /* Set the peripheral clock frequencies used */
162  rcc_ahb_frequency = 24000000;
163  rcc_apb1_frequency = 24000000;
164  rcc_apb2_frequency = 24000000;
165 }
166 #endif
167 
168 void mcu_arch_init(void)
169 {
170 #if LUFTBOOT
171  PRINT_CONFIG_MSG("We are running luftboot, the interrupt vector is being relocated.")
172 #if defined STM32F4
173  SCB_VTOR = 0x00004000;
174 #else
175  SCB_VTOR = 0x00002000;
176 #endif
177 #endif
178 #if EXT_CLK == 8000000
179 #if defined(STM32F1)
180  PRINT_CONFIG_MSG("Using 8MHz external clock to PLL it to 72MHz.")
181  rcc_clock_setup_in_hse_8mhz_out_72mhz();
182 #elif defined(STM32F4)
183 #if AHB_CLK == 84000000
184  PRINT_CONFIG_MSG("Using 8MHz external clock to PLL it to 84MHz.")
185  rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_84MHZ]);
186 #else
187  PRINT_CONFIG_MSG("Using 8MHz external clock to PLL it to 168MHz.")
188  rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
189 #endif
190 #endif
191 #elif EXT_CLK == 12000000
192 #if defined(STM32F1)
193  PRINT_CONFIG_MSG("Using 12MHz external clock to PLL it to 72MHz.")
194  rcc_clock_setup_in_hse_12mhz_out_72mhz();
195 #elif defined(STM32F4)
196  PRINT_CONFIG_MSG("Using 12MHz external clock to PLL it to 168MHz.")
197  rcc_clock_setup_hse_3v3(&rcc_hse_12mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
198 #endif
199 #elif EXT_CLK == 16000000
200 #if defined(STM32F4)
201  PRINT_CONFIG_MSG("Using 16MHz external clock to PLL it to 168MHz.")
202  rcc_clock_setup_hse_3v3(&rcc_hse_16mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
203 #endif
204 #elif EXT_CLK == 24000000
205 #if defined(STM32F4)
206  PRINT_CONFIG_MSG("Using 24MHz external clock to PLL it to 168MHz.")
207  rcc_clock_setup_hse_3v3(&rcc_hse_24mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
208 #elif defined(STM32F1)
209  rcc_clock_setup_in_hse_24mhz_out_24mhz_pprz();
210 #endif
211 #elif EXT_CLK == 25000000
212 #if defined(STM32F4)
213  PRINT_CONFIG_MSG("Using 25MHz external clock to PLL it to 168MHz.")
214  rcc_clock_setup_hse_3v3(&rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
215 #endif
216 #else
217 #error EXT_CLK is either set to an unsupported frequency or not defined at all. Please check!
218 #endif
219 
220  /* Configure priority grouping 0 bits for pre-emption priority and 4 bits for sub-priority.
221  * this was previously in i2c driver
222  * FIXME is it really needed ?
223  */
224  scb_set_priority_grouping(SCB_AIRCR_PRIGROUP_NOGROUP_SUB16);
225 
226 }
227 
228 #if defined(STM32F1)
229 #define RCC_CFGR_PPRE2_SHIFT 11
230 #define RCC_CFGR_PPRE2 (7 << RCC_CFGR_PPRE2_SHIFT)
231 
232 #define RCC_CFGR_PPRE1_SHIFT 8
233 #define RCC_CFGR_PPRE1 (7 << RCC_CFGR_PPRE1_SHIFT)
234 
235 static inline uint32_t rcc_get_ppre1(void)
236 {
237  return RCC_CFGR & RCC_CFGR_PPRE1;
238 }
239 
240 static inline uint32_t rcc_get_ppre2(void)
241 {
242  return RCC_CFGR & RCC_CFGR_PPRE2;
243 }
244 #elif defined(STM32F4)
245 static inline uint32_t rcc_get_ppre1(void)
246 {
247  return RCC_CFGR & ((1 << 10) | (1 << 11) | (1 << 12));
248 }
249 
250 static inline uint32_t rcc_get_ppre2(void)
251 {
252  return RCC_CFGR & ((1 << 13) | (1 << 14) | (1 << 15));
253 }
254 #endif
255 
264 {
265  switch (timer_peripheral) {
266  // Timers on high speed APB2
267  case TIM1:
268  case TIM8:
269 #ifdef TIM9
270  case TIM9:
271 #endif
272 #ifdef TIM10
273  case TIM10:
274 #endif
275 #ifdef TIM11
276  case TIM11:
277 #endif
278  if (!rcc_get_ppre2()) {
279  /* without APB2 prescaler, runs at APB2 freq */
280  return rcc_apb2_frequency;
281  } else {
282  /* with any ABP2 prescaler, runs at 2 * APB2 freq */
283  return rcc_apb2_frequency * 2;
284  }
285 
286  // timers on low speed APB1
287  case TIM2:
288  case TIM3:
289  case TIM4:
290  case TIM5:
291  case TIM6:
292  case TIM7:
293 #ifdef TIM12
294  case TIM12:
295 #endif
296 #ifdef TIM13
297  case TIM13:
298 #endif
299 #ifdef TIM14
300  case TIM14:
301 #endif
302  if (!rcc_get_ppre1()) {
303  /* without APB1 prescaler, runs at APB1 freq */
304  return rcc_apb1_frequency;
305  } else {
306  /* with any ABP1 prescaler, runs at 2 * APB1 freq */
307  return rcc_apb1_frequency * 2;
308  }
309  default:
310  // other timers currently not supported
311  break;
312  }
313  return 0;
314 }
void mcu_arch_init(void)
Definition: mcu_arch.c:109
uint32_t timer_get_frequency(uint32_t timer_peripheral)
Get Timer clock frequency (before prescaling) Only valid if using the internal clock for the timer...
Definition: mcu_arch.c:263
unsigned long uint32_t
Definition: types.h:18
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
Arch independent mcu ( Micro Controller Unit ) utilities.