Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
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  PRINT_CONFIG_MSG("Using 8MHz external clock to PLL it to 168MHz.")
184  rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
185 #endif
186 #elif EXT_CLK == 12000000
187 #if defined(STM32F1)
188  PRINT_CONFIG_MSG("Using 12MHz external clock to PLL it to 72MHz.")
189  rcc_clock_setup_in_hse_12mhz_out_72mhz();
190 #elif defined(STM32F4)
191  PRINT_CONFIG_MSG("Using 12MHz external clock to PLL it to 168MHz.")
192  rcc_clock_setup_hse_3v3(&rcc_hse_12mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
193 #endif
194 #elif EXT_CLK == 16000000
195 #if defined(STM32F4)
196  PRINT_CONFIG_MSG("Using 16MHz external clock to PLL it to 168MHz.")
197  rcc_clock_setup_hse_3v3(&rcc_hse_16mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
198 #endif
199 #elif EXT_CLK == 24000000
200 #if defined(STM32F4)
201  PRINT_CONFIG_MSG("Using 24MHz external clock to PLL it to 168MHz.")
202  rcc_clock_setup_hse_3v3(&rcc_hse_24mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
203 #elif defined(STM32F1)
204  rcc_clock_setup_in_hse_24mhz_out_24mhz_pprz();
205 #endif
206 #elif EXT_CLK == 25000000
207 #if defined(STM32F4)
208  PRINT_CONFIG_MSG("Using 25MHz external clock to PLL it to 168MHz.")
209  rcc_clock_setup_hse_3v3(&rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
210 #endif
211 #else
212 #error EXT_CLK is either set to an unsupported frequency or not defined at all. Please check!
213 #endif
214 
215  /* Configure priority grouping 0 bits for pre-emption priority and 4 bits for sub-priority.
216  * this was previously in i2c driver
217  * FIXME is it really needed ?
218  */
219  scb_set_priority_grouping(SCB_AIRCR_PRIGROUP_NOGROUP_SUB16);
220 
221 }
222 
223 #if defined(STM32F1)
224 #define RCC_CFGR_PPRE2_SHIFT 11
225 #define RCC_CFGR_PPRE2 (7 << RCC_CFGR_PPRE2_SHIFT)
226 
227 #define RCC_CFGR_PPRE1_SHIFT 8
228 #define RCC_CFGR_PPRE1 (7 << RCC_CFGR_PPRE1_SHIFT)
229 
230 static inline uint32_t rcc_get_ppre1(void)
231 {
232  return RCC_CFGR & RCC_CFGR_PPRE1;
233 }
234 
235 static inline uint32_t rcc_get_ppre2(void)
236 {
237  return RCC_CFGR & RCC_CFGR_PPRE2;
238 }
239 #elif defined(STM32F4)
240 static inline uint32_t rcc_get_ppre1(void)
241 {
242  return RCC_CFGR & ((1 << 10) | (1 << 11) | (1 << 12));
243 }
244 
245 static inline uint32_t rcc_get_ppre2(void)
246 {
247  return RCC_CFGR & ((1 << 13) | (1 << 14) | (1 << 15));
248 }
249 #endif
250 
259 {
260  switch (timer_peripheral) {
261  // Timers on high speed APB2
262  case TIM1:
263  case TIM8:
264 #ifdef TIM9
265  case TIM9:
266 #endif
267 #ifdef TIM10
268  case TIM10:
269 #endif
270 #ifdef TIM11
271  case TIM11:
272 #endif
273  if (!rcc_get_ppre2()) {
274  /* without APB2 prescaler, runs at APB2 freq */
275  return rcc_apb2_frequency;
276  } else {
277  /* with any ABP2 prescaler, runs at 2 * APB2 freq */
278  return rcc_apb2_frequency * 2;
279  }
280 
281  // timers on low speed APB1
282  case TIM2:
283  case TIM3:
284  case TIM4:
285  case TIM5:
286  case TIM6:
287  case TIM7:
288 #ifdef TIM12
289  case TIM12:
290 #endif
291 #ifdef TIM13
292  case TIM13:
293 #endif
294 #ifdef TIM14
295  case TIM14:
296 #endif
297  if (!rcc_get_ppre1()) {
298  /* without APB1 prescaler, runs at APB1 freq */
299  return rcc_apb1_frequency;
300  } else {
301  /* with any ABP1 prescaler, runs at 2 * APB1 freq */
302  return rcc_apb1_frequency * 2;
303  }
304  default:
305  // other timers currently not supported
306  break;
307  }
308  return 0;
309 }
void mcu_arch_init(void)
Definition: mcu_arch.c:94
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:258
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.