libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
rcc_common_all.c
Go to the documentation of this file.
1 /** @addtogroup rcc_file RCC peripheral API
2  * @ingroup peripheral_apis
3  */
4 /*
5  * This file is part of the libopencm3 project.
6  *
7  * Copyright (C) 2013 Frantisek Burian <bufran@seznam.cz>
8  * .. file is merged from many other copyrighted files of stm32 family
9  *
10  * This library is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this library. If not, see <http://www.gnu.org/licenses/>.
22  */
23 /**@{*/
24 
25 #include <libopencm3/stm32/rcc.h>
26 
27 /*---------------------------------------------------------------------------*/
28 /** @brief RCC Enable Peripheral Clocks.
29  *
30  * Enable the clock on particular peripherals. There are three registers
31  * involved, each one controlling the enabling of clocks associated with the
32  * AHB, APB1 and APB2 respectively. Several peripherals could be enabled
33  * simultaneously <em>only if they are controlled by the same register</em>.
34  * @sa rcc_periph_clock_enable for a less error prone version, if you only
35  * need to enable a single peripheral.
36  *
37  * @param[in] *reg Unsigned int32. Pointer to a Clock Enable Register
38  * (either RCC_AHBENR, RCC_APB1ENR or RCC_APB2ENR)
39  *
40  * @param[in] en Unsigned int32. Logical OR of all enables to be set
41  * @li If register is RCC_AHBER, from @ref rcc_ahbenr_en
42  * @li If register is RCC_APB1ENR, from @ref rcc_apb1enr_en
43  * @li If register is RCC_APB2ENR, from @ref rcc_apb2enr_en
44  */
45 
46 void rcc_peripheral_enable_clock(volatile uint32_t *reg, uint32_t en)
47 {
48  *reg |= en;
49 }
50 
51 /*---------------------------------------------------------------------------*/
52 /** @brief RCC Disable Peripheral Clocks.
53  *
54  * Enable the clock on particular peripherals. There are three registers
55  * involved, each one controlling the enabling of clocks associated with
56  * the AHB, APB1 and APB2 respectively. Several peripherals could be disabled
57  * simultaneously <em>only if they are controlled by the same register</em>.
58  * @sa rcc_periph_clock_disable for a less error prone version, if you only
59  * need to disable a single peripheral.
60  *
61  * @param[in] *reg Unsigned int32. Pointer to a Clock Enable Register
62  * (either RCC_AHBENR, RCC_APB1ENR or RCC_APB2ENR)
63  * @param[in] en Unsigned int32. Logical OR of all enables to be used for
64  * disabling.
65  * @li If register is RCC_AHBER, from @ref rcc_ahbenr_en
66  * @li If register is RCC_APB1ENR, from @ref rcc_apb1enr_en
67  * @li If register is RCC_APB2ENR, from @ref rcc_apb2enr_en
68  */
69 void rcc_peripheral_disable_clock(volatile uint32_t *reg, uint32_t en)
70 {
71  *reg &= ~en;
72 }
73 
74 /*---------------------------------------------------------------------------*/
75 /** @brief RCC Reset Peripherals.
76  *
77  * Reset particular peripherals. There are three registers involved, each one
78  * controlling reset of peripherals associated with the AHB, APB1 and APB2
79  * respectively. Several peripherals could be reset simultaneously <em>only if
80  * they are controlled by the same register</em>.
81  * @sa rcc_periph_reset_hold for a less error prone version, if you only
82  * need to reset a single peripheral.
83  * @sa rcc_periph_reset_pulse if you are only going to toggle reset anyway.
84  *
85  * @param[in] *reg Unsigned int32. Pointer to a Reset Register
86  * (either RCC_AHBENR, RCC_APB1ENR or RCC_APB2ENR)
87  * @param[in] reset Unsigned int32. Logical OR of all resets.
88  * @li If register is RCC_AHBRSTR, from @ref rcc_ahbrstr_rst
89  * @li If register is RCC_APB1RSTR, from @ref rcc_apb1rstr_rst
90  * @li If register is RCC_APB2RSTR, from @ref rcc_apb2rstr_rst
91  */
92 void rcc_peripheral_reset(volatile uint32_t *reg, uint32_t reset)
93 {
94  *reg |= reset;
95 }
96 
97 /*---------------------------------------------------------------------------*/
98 /** @brief RCC Remove Reset on Peripherals.
99  *
100  * Remove the reset on particular peripherals. There are three registers
101  * involved, each one controlling reset of peripherals associated with the AHB,
102  * APB1 and APB2 respectively. Several peripherals could have the reset removed
103  * simultaneously <em>only if they are controlled by the same register</em>.
104  * @sa rcc_periph_reset_release for a less error prone version, if you only
105  * need to unreset a single peripheral.
106  * @sa rcc_periph_reset_pulse if you are only going to toggle reset anyway.
107  *
108  * @param[in] *reg Unsigned int32. Pointer to a Reset Register
109  * (either RCC_AHBENR, RCC_APB1ENR or RCC_APB2ENR)
110  * @param[in] clear_reset Unsigned int32. Logical OR of all resets to be
111  * removed:
112  * @li If register is RCC_AHBRSTR, from @ref rcc_ahbrstr_rst
113  * @li If register is RCC_APB1RSTR, from @ref rcc_apb1rstr_rst
114  * @li If register is RCC_APB2RSTR, from @ref rcc_apb2rstr_rst
115  */
116 void rcc_peripheral_clear_reset(volatile uint32_t *reg, uint32_t clear_reset)
117 {
118  *reg &= ~clear_reset;
119 }
120 
121 #define _RCC_REG(i) MMIO32(RCC_BASE + ((i) >> 5))
122 #define _RCC_BIT(i) (1 << ((i) & 0x1f))
123 
124 /*---------------------------------------------------------------------------*/
125 /** @brief Enable Peripheral Clock in running mode.
126  *
127  * Enable the clock on particular peripheral.
128  *
129  * @param[in] clken rcc_periph_clken Peripheral RCC
130  *
131  * For available constants, see #rcc_periph_clken (RCC_UART1 for example)
132  */
133 
135 {
136  _RCC_REG(clken) |= _RCC_BIT(clken);
137 }
138 
139 /*---------------------------------------------------------------------------*/
140 /** @brief Disable Peripheral Clock in running mode.
141  * Disable the clock on particular peripheral.
142  *
143  * @param[in] clken rcc_periph_clken Peripheral RCC
144  *
145  * For available constants, see #rcc_periph_clken (RCC_UART1 for example)
146  */
147 
149 {
150  _RCC_REG(clken) &= ~_RCC_BIT(clken);
151 }
152 
153 /*---------------------------------------------------------------------------*/
154 /** @brief Reset Peripheral, pulsed
155  *
156  * Reset particular peripheral, and restore to working state.
157  *
158  * @param[in] rst rcc_periph_rst Peripheral reset
159  *
160  * For available constants, see #rcc_periph_rst (RST_UART1 for example)
161  */
162 
164 {
165  _RCC_REG(rst) |= _RCC_BIT(rst);
166  _RCC_REG(rst) &= ~_RCC_BIT(rst);
167 }
168 
169 /*---------------------------------------------------------------------------*/
170 /** @brief Reset Peripheral, hold
171  *
172  * Reset particular peripheral, and hold in reset state.
173  *
174  * @param[in] rst rcc_periph_rst Peripheral reset
175  *
176  * For available constants, see #rcc_periph_rst (RST_UART1 for example)
177  */
178 
180 {
181  _RCC_REG(rst) |= _RCC_BIT(rst);
182 }
183 
184 /*---------------------------------------------------------------------------*/
185 /** @brief Reset Peripheral, release
186  *
187  * Restore peripheral from reset state to working state.
188  *
189  * @param[in] rst rcc_periph_rst Peripheral reset
190  *
191  * For available constants, see #rcc_periph_rst (RST_UART1 for example)
192  */
193 
195 {
196  _RCC_REG(rst) &= ~_RCC_BIT(rst);
197 }
198 
199 /** @brief Select the source of Microcontroller Clock Output
200  *
201  * Exact sources available depend on your target. On devices with multiple
202  * MCO pins, this function controls MCO1
203  *
204  * @param[in] mcosrc the unshifted source bits
205  */
206 
207 void rcc_set_mco(uint32_t mcosrc)
208 {
210  (mcosrc << RCC_CFGR_MCO_SHIFT);
211 }
212 
213 /**
214  * RCC Enable Bypass.
215  * Enable an external clock to bypass the internal clock (high speed and low
216  * speed clocks only). The external clock must be enabled (see @ref rcc_osc_on)
217  * and the internal clock must be disabled (see @ref rcc_osc_off) for this to
218  * have effect.
219  * @note The LSE clock is in the backup domain and cannot be bypassed until the
220  * backup domain write protection has been removed (see @ref
221  * pwr_disable_backup_domain_write_protect).
222  * @param[in] osc Oscillator ID. Only HSE and LSE have effect.
223  */
225 {
226  switch (osc) {
227  case RCC_HSE:
229  break;
230  case RCC_LSE:
231 #ifdef RCC_CSR_LSEBYP
232  RCC_CSR |= RCC_CSR_LSEBYP;
233 #else
235 #endif
236  break;
237  default:
238  /* Do nothing, only HSE/LSE allowed here. */
239  break;
240  }
241 }
242 
243 /**
244  * RCC Disable Bypass.
245  * Re-enable the internal clock (high speed and low speed clocks only). The
246  * internal clock must be disabled (see @ref rcc_osc_off) for this to have
247  * effect.
248  * @note The LSE clock is in the backup domain and cannot have bypass removed
249  * until the backup domain write protection has been removed (see @ref
250  * pwr_disable_backup_domain_write_protect) or the backup domain has been reset
251  * (see @ref rcc_backupdomain_reset).
252  * @param[in] osc Oscillator ID. Only HSE and LSE have effect.
253  */
255 {
256  switch (osc) {
257  case RCC_HSE:
258  RCC_CR &= ~RCC_CR_HSEBYP;
259  break;
260  case RCC_LSE:
261 #ifdef RCC_CSR_LSEBYP
262  RCC_CSR &= ~RCC_CSR_LSEBYP;
263 #else
265 #endif
266  break;
267  default:
268  /* Do nothing, only HSE/LSE allowed here. */
269  break;
270  }
271 }
272 
273 /* This is a helper to calculate dividers that go 2/4/8/16/64/128/256/512.
274  * These dividers also use the top bit as an "enable". This is tyipcally
275  * used for AHB and other system clock prescaler. */
276 uint16_t rcc_get_div_from_hpre(uint8_t div_val) {
277  if (div_val < 0x8) {
278  return 1;
279  } else if (div_val <= 0x0b /* DIV16 */) {
280  return (1U << (div_val - 7));
281  } else {
282  return (1U << (div_val - 6));
283  }
284 }
285 /**@}*/
286 
287 #undef _RCC_REG
288 #undef _RCC_BIT
#define RCC_CFGR_MCO_SHIFT
Definition: f0/rcc.h:97
#define RCC_CR
Definition: f0/rcc.h:48
rcc_periph_rst
Definition: f0/rcc.h:506
#define RCC_BDCR_LSEBYP
Definition: f0/rcc.h:330
rcc_periph_clken
Definition: f0/rcc.h:448
rcc_osc
Definition: f0/rcc.h:442
#define RCC_CSR
Definition: f0/rcc.h:57
#define RCC_CFGR
Definition: f0/rcc.h:49
#define RCC_CR_HSEBYP
Definition: f0/rcc.h:72
#define RCC_BDCR
Definition: f0/rcc.h:56
#define RCC_CFGR_MCO_MASK
Definition: f0/rcc.h:98
@ RCC_LSE
Definition: f0/rcc.h:443
@ RCC_HSE
Definition: f0/rcc.h:443
void rcc_periph_reset_release(enum rcc_periph_rst rst)
Reset Peripheral, release.
#define _RCC_REG(i)
void rcc_peripheral_reset(volatile uint32_t *reg, uint32_t reset)
RCC Reset Peripherals.
void rcc_osc_bypass_enable(enum rcc_osc osc)
RCC Enable Bypass.
void rcc_osc_bypass_disable(enum rcc_osc osc)
RCC Disable Bypass.
void rcc_periph_reset_hold(enum rcc_periph_rst rst)
Reset Peripheral, hold.
void rcc_periph_clock_disable(enum rcc_periph_clken clken)
Disable Peripheral Clock in running mode.
void rcc_periph_clock_enable(enum rcc_periph_clken clken)
Enable Peripheral Clock in running mode.
#define _RCC_BIT(i)
void rcc_peripheral_enable_clock(volatile uint32_t *reg, uint32_t en)
RCC Enable Peripheral Clocks.
void rcc_peripheral_clear_reset(volatile uint32_t *reg, uint32_t clear_reset)
RCC Remove Reset on Peripherals.
void rcc_set_mco(uint32_t mcosrc)
Select the source of Microcontroller Clock Output.
void rcc_periph_reset_pulse(enum rcc_periph_rst rst)
Reset Peripheral, pulsed.
void rcc_peripheral_disable_clock(volatile uint32_t *reg, uint32_t en)
RCC Disable Peripheral Clocks.
uint16_t rcc_get_div_from_hpre(uint8_t div_val)
This will return the divisor 1/2/4/8/16/64/128/256/512 which is set as a 4-bit value,...