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
26
27/** @brief RCC Enable Peripheral Clocks.
28 *
29 * Enable the clock on particular peripherals. There are three registers
30 * involved, each one controlling the enabling of clocks associated with the
31 * AHB, APB1 and APB2 respectively. Several peripherals could be enabled
32 * simultaneously <em>only if they are controlled by the same register</em>.
33 * @sa rcc_periph_clock_enable for a less error prone version, if you only
34 * need to enable a single peripheral.
35 *
36 * @param[in] *reg Unsigned int32. Pointer to a Clock Enable Register
37 * (either RCC_AHBENR, RCC_APB1ENR or RCC_APB2ENR)
38 *
39 * @param[in] en Unsigned int32. Logical OR of all enables to be set
40 * @li If register is RCC_AHBENR, from @ref rcc_ahbenr_en
41 * @li If register is RCC_APB1ENR, from @ref rcc_apb1enr_en
42 * @li If register is RCC_APB2ENR, from @ref rcc_apb2enr_en
43 */
44void rcc_peripheral_enable_clock(volatile uint32_t *reg, uint32_t en)
45{
46 *reg |= en;
47}
48
49/** @brief RCC Disable Peripheral Clocks.
50 *
51 * Disable the clock on particular peripherals. There are three registers
52 * involved, each one controlling the enabling of clocks associated with
53 * the AHB, APB1 and APB2 respectively. Several peripherals could be disabled
54 * simultaneously <em>only if they are controlled by the same register</em>.
55 * @sa rcc_periph_clock_disable for a less error prone version, if you only
56 * need to disable a single peripheral.
57 *
58 * @param[in] *reg Unsigned int32. Pointer to a Clock Enable Register
59 * (either RCC_AHBENR, RCC_APB1ENR or RCC_APB2ENR)
60 * @param[in] en Unsigned int32. Logical OR of all enables to be used for
61 * disabling.
62 * @li If register is RCC_AHBENR, from @ref rcc_ahbenr_en
63 * @li If register is RCC_APB1ENR, from @ref rcc_apb1enr_en
64 * @li If register is RCC_APB2ENR, from @ref rcc_apb2enr_en
65 */
66void rcc_peripheral_disable_clock(volatile uint32_t *reg, uint32_t en)
67{
68 *reg &= ~en;
69}
70
71/** @brief RCC Reset Peripherals.
72 *
73 * Reset particular peripherals. There are three registers involved, each one
74 * controlling reset of peripherals associated with the AHB, APB1 and APB2
75 * respectively. Several peripherals could be reset simultaneously <em>only if
76 * they are controlled by the same register</em>.
77 * @sa rcc_periph_reset_hold for a less error prone version, if you only
78 * need to reset a single peripheral.
79 * @sa rcc_periph_reset_pulse if you are only going to toggle reset anyway.
80 *
81 * @param[in] *reg Unsigned int32. Pointer to a Reset Register
82 * (either RCC_AHBENR, RCC_APB1ENR or RCC_APB2ENR)
83 * @param[in] reset Unsigned int32. Logical OR of all resets.
84 * @li If register is RCC_AHBRSTR, from @ref rcc_ahbrstr_rst
85 * @li If register is RCC_APB1RSTR, from @ref rcc_apb1rstr_rst
86 * @li If register is RCC_APB2RSTR, from @ref rcc_apb2rstr_rst
87 */
88void rcc_peripheral_reset(volatile uint32_t *reg, uint32_t reset)
89{
90 *reg |= reset;
91}
92
93/** @brief RCC Remove Reset on Peripherals.
94 *
95 * Remove the reset on particular peripherals. There are three registers
96 * involved, each one controlling reset of peripherals associated with the AHB,
97 * APB1 and APB2 respectively. Several peripherals could have the reset removed
98 * simultaneously <em>only if they are controlled by the same register</em>.
99 * @sa rcc_periph_reset_release for a less error prone version, if you only
100 * need to unreset a single peripheral.
101 * @sa rcc_periph_reset_pulse if you are only going to toggle reset anyway.
102 *
103 * @param[in] *reg Unsigned int32. Pointer to a Reset Register
104 * (either RCC_AHBENR, RCC_APB1ENR or RCC_APB2ENR)
105 * @param[in] clear_reset Unsigned int32. Logical OR of all resets to be
106 * removed:
107 * @li If register is RCC_AHBRSTR, from @ref rcc_ahbrstr_rst
108 * @li If register is RCC_APB1RSTR, from @ref rcc_apb1rstr_rst
109 * @li If register is RCC_APB2RSTR, from @ref rcc_apb2rstr_rst
110 */
111void rcc_peripheral_clear_reset(volatile uint32_t *reg, uint32_t clear_reset)
112{
113 *reg &= ~clear_reset;
114}
115
116#define _RCC_REG(i) MMIO32(RCC_BASE + ((i) >> 5))
117#define _RCC_BIT(i) (1 << ((i) & 0x1f))
118
119/** @brief Enable Peripheral Clock in running mode.
120 *
121 * Enable the clock on particular peripheral.
122 *
123 * @param[in] clken rcc_periph_clken Peripheral RCC
124 *
125 * For available constants, see #rcc_periph_clken (RCC_UART1 for example)
126 */
128{
129 _RCC_REG(clken) |= _RCC_BIT(clken);
130}
131
132/** @brief Disable Peripheral Clock in running mode.
133 * Disable the clock on particular peripheral.
134 *
135 * @param[in] clken rcc_periph_clken Peripheral RCC
136 *
137 * For available constants, see #rcc_periph_clken (RCC_UART1 for example)
138 */
140{
141 _RCC_REG(clken) &= ~_RCC_BIT(clken);
142}
143
144/** @brief Reset Peripheral, pulsed
145 *
146 * Reset particular peripheral, and restore to working state.
147 *
148 * @param[in] rst rcc_periph_rst Peripheral reset
149 *
150 * For available constants, see #rcc_periph_rst (RST_UART1 for example)
151 */
153{
154 _RCC_REG(rst) |= _RCC_BIT(rst);
155 _RCC_REG(rst) &= ~_RCC_BIT(rst);
156}
157
158/** @brief Reset Peripheral, hold
159 *
160 * Reset particular peripheral, and hold in reset state.
161 *
162 * @param[in] rst rcc_periph_rst Peripheral reset
163 *
164 * For available constants, see #rcc_periph_rst (RST_UART1 for example)
165 */
167{
168 _RCC_REG(rst) |= _RCC_BIT(rst);
169}
170
171/** @brief Reset Peripheral, release
172 *
173 * Restore peripheral from reset state to working state.
174 *
175 * @param[in] rst rcc_periph_rst Peripheral reset
176 *
177 * For available constants, see #rcc_periph_rst (RST_UART1 for example)
178 */
180{
181 _RCC_REG(rst) &= ~_RCC_BIT(rst);
182}
183
184/** @brief Select the source of Microcontroller Clock Output
185 *
186 * Exact sources available depend on your target. On devices with multiple
187 * MCO pins, this function controls MCO1
188 *
189 * @param[in] mcosrc the unshifted source bits
190 */
191void rcc_set_mco(uint32_t mcosrc)
192{
194 (mcosrc << RCC_CFGR_MCO_SHIFT);
195}
196
197/**
198 * RCC Enable Bypass.
199 * Enable an external clock to bypass the internal clock (high speed and low
200 * speed clocks only). The external clock must be enabled (see @ref rcc_osc_on)
201 * and the internal clock must be disabled (see @ref rcc_osc_off) for this to
202 * have effect.
203 * @note The LSE clock is in the backup domain and cannot be bypassed until the
204 * backup domain write protection has been removed (see @ref
205 * pwr_disable_backup_domain_write_protect).
206 * @param[in] osc Oscillator ID. Only HSE and LSE have effect.
207 */
209{
210 switch (osc) {
211 case RCC_HSE:
213 break;
214 case RCC_LSE:
215#ifdef RCC_CSR_LSEBYP
216 RCC_CSR |= RCC_CSR_LSEBYP;
217#else
219#endif
220 break;
221 default:
222 /* Do nothing, only HSE/LSE allowed here. */
223 break;
224 }
225}
226
227/**
228 * RCC Disable Bypass.
229 * Re-enable the internal clock (high speed and low speed clocks only). The
230 * internal clock must be disabled (see @ref rcc_osc_off) for this to have
231 * effect.
232 * @note The LSE clock is in the backup domain and cannot have bypass removed
233 * until the backup domain write protection has been removed (see @ref
234 * pwr_disable_backup_domain_write_protect) or the backup domain has been reset
235 * (see @ref rcc_backupdomain_reset).
236 * @param[in] osc Oscillator ID. Only HSE and LSE have effect.
237 */
239{
240 switch (osc) {
241 case RCC_HSE:
242 RCC_CR &= ~RCC_CR_HSEBYP;
243 break;
244 case RCC_LSE:
245#ifdef RCC_CSR_LSEBYP
246 RCC_CSR &= ~RCC_CSR_LSEBYP;
247#else
248 RCC_BDCR &= ~RCC_BDCR_LSEBYP;
249#endif
250 break;
251 default:
252 /* Do nothing, only HSE/LSE allowed here. */
253 break;
254 }
255}
256
257/* This is a helper to calculate dividers that go 2/4/8/16/64/128/256/512.
258 * These dividers also use the top bit as an "enable". This is typically
259 * used for AHB and other system clock prescaler. */
260uint16_t rcc_get_div_from_hpre(uint8_t div_val) {
261 if (div_val < 0x8) {
262 return 1;
263 } else if (div_val <= 0x0b /* DIV16 */) {
264 return (1U << (div_val - 7));
265 } else {
266 return (1U << (div_val - 6));
267 }
268}
269/**@}*/
270
271#undef _RCC_REG
272#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:500
#define RCC_BDCR_LSEBYP
Definition: f0/rcc.h:330
rcc_periph_clken
Definition: f0/rcc.h:442
rcc_osc
Definition: f0/rcc.h:436
#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:437
@ RCC_HSE
Definition: f0/rcc.h:437
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,...