... | ... | @@ -4,9 +4,9 @@ |
|
|
|
|
|
One classical problem that pops up when developing a device driver is having to set the **baudrate** of a communication peripheral (e.g. SPI) or the **period** of a Timer. In these cases, in fact, the peripheral typically provides just a `DIV` or `PRESCALER` register. The baudrate for that specific peripheral is then defined as:
|
|
|
|
|
|
$$
|
|
|
```math
|
|
|
baudrate = \frac{input\_clock}{Prescaler}
|
|
|
$$
|
|
|
```
|
|
|
|
|
|
But wait, what exactly _is_ the input clock? Where does it come from? Were can I read or adjust its value? This page tries to address these questions for a typical `stm32_f4xx` micro using MIOSIX and boardcore.
|
|
|
|
... | ... | @@ -15,7 +15,7 @@ But wait, what exactly _is_ the input clock? Where does it come from? Were can I |
|
|
STM32 microcontrollers are equipped with multiple buses for internal communication.
|
|
|
These buses are part of the **AMBA** (Advanced Microcontroller Bus Architecture) standard provided by ARM. Here is a general diagram of the buses:
|
|
|
|
|
|
<div style="text-align:center"><img src="images/clocks/amba-bus.png" /><br/><i>Typical bus hierarchy for STM32F4xx</i></div>
|
|
|
<div align="center"><img src="images/clocks/amba-bus.png" /><br/><i>Typical bus hierarchy for STM32F4xx</i></div>
|
|
|
<br>
|
|
|
|
|
|
Let's read it from right to left:
|
... | ... | @@ -36,12 +36,10 @@ This is (a portion of) the **clock tree** that you can find in the [Holy Bible]( |
|
|
|
|
|

|
|
|
|
|
|
From the same manual:
|
|
|
|
|
|
> Three different clock sources can be used to drive the system clock (SYSCLK):
|
|
|
> • HSI oscillator clock
|
|
|
> • HSE oscillator clock
|
|
|
> • Main PLL (PLL) clock
|
|
|
From the same manual, we see that three different clock sources can be used to drive the system clock (SYSCLK):
|
|
|
- HSI oscillator clock
|
|
|
- HSE oscillator clock
|
|
|
- Main PLL (PLL) clock
|
|
|
|
|
|
Hence, for each board the clock can be generated either by an **internal RC** or some **external source** that you can connect externally to the corresponding pins. The frequency of this source can then be **upscaled** by the PLLs and finally used as **System Clock**. This is the main clock of the processor, and will be used to derive the AHB speed and consequently the APBs speeds.
|
|
|
|
... | ... | @@ -59,27 +57,27 @@ Luckily enough, this kind of stuff is handled by MIOSIX, which uses the vendor-p |
|
|
|
|
|
- Define the input clock type and speed and the desired `SYSCLCK` in `miosix/config/Makefile.inc`
|
|
|
|
|
|
```Makefile
|
|
|
## Select clock frequency (HSE_VALUE is the xtal on board, fixed)
|
|
|
CLOCK_FREQ := -DHSE_VALUE=8000000 -DSYSCLK_FREQ_168MHz=168000000
|
|
|
```
|
|
|
```make
|
|
|
## Select clock frequency (HSE_VALUE is the xtal on board, fixed)
|
|
|
CLOCK_FREQ := -DHSE_VALUE=8000000 -DSYSCLK_FREQ_168MHz=168000000
|
|
|
```
|
|
|
|
|
|
- For stm32f4xx boards, the bus prescalers are set in `/miosix/arch/common/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c`
|
|
|
|
|
|
```c
|
|
|
/* HCLK = SYSCLK / 1*/
|
|
|
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
|
|
|
```cpp
|
|
|
/* HCLK = SYSCLK / 1*/
|
|
|
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
|
|
|
|
|
|
/* PCLK2 = HCLK / 2*/
|
|
|
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
|
|
|
/* PCLK2 = HCLK / 2*/
|
|
|
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
|
|
|
|
|
|
/* PCLK1 = HCLK / 4*/
|
|
|
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
|
|
|
```
|
|
|
/* PCLK1 = HCLK / 4*/
|
|
|
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
|
|
|
```
|
|
|
|
|
|
And that's pretty much it.
|
|
|
|
|
|
> :warning: **IMPORTANT:** Clocks and startup
|
|
|
> :warning: **IMPORTANT:**
|
|
|
> On reset the 16 MHz internal RC oscillator is selected as the default CPU clock.
|
|
|
> The 16 MHz internal RC oscillator is factory-trimmed to offer 1% accuracy over the full temperature range.
|
|
|
> The application can then select as system clock either the RC oscillator
|
... | ... | |