© Warren Gay 2018

Warren Gay, Beginning STM32, https://doi.org/10.1007/978-1-4842-3624-6_15

15. Clock Tree

Warren Gay

(1)St. Catharines, Ontario, Canada

Until this point, there’s been an elephant in the room. We’ve configured and used various clocks without saying too much about them. Now is a good time to reveal some of the clock components that have been lurking in the shadows.

While asynchronous logic circuit designs exist, most microprocessors use one or more clocks. The STM32 series is no exception. This series is highly configurable, adding somewhat to its software complexity. But this added flexibility allows the designer to reduce power requirements by turning off peripherals and clocks that are not required.

This chapter will examine the clocks that the STM32F103C8T6 supports and how to configure them. This information will make it possible for you to calculate the correct prescaler counts needed to produce correct baud rates and SPI clock rates, and to correctly feed timers. It will also give you inside information needed to take advantage of special clock features and avoid pitfalls.

In the Beginning

Many clocks can be derived from others, but there has to be one or more sources at the start of any chain. Within the STM32F103C8T6 there are a total of four independent clock sources, as follows

  1. 8 MHz RC oscillator (HSI)

  2. 4–16 MHz crystal/ceramic oscillator (HSE)

  3. 32.768 kHz crystal oscillator (LSE)

  4. 40 kHz RC oscillator (LSI)

Table 15-1 summarizes the notation used for the preceding oscillators, as well as some of their major characteristics. For example, it is shown that the HSE oscillator is driven by a crystal and enjoys good stability, while the HSI oscillator is driven by RC (resistor and capacitor) and has relatively poor stability.

Table 15-1 STM32 Oscillator Notation

Notation

Low/High Speed

Internal/External

Driven By

Stability

LSI

Low speed

Internal

Resistor and Capacitor

Poor

LSE

Low speed

External

Crystal

Good

HSI

High speed

Internal

Resistor and Capacitor

Poor

HSE

High speed

External

Crystal

Good

RC Oscillators

A good question to ask is why provide RC oscillators if they are not that stable? For some applications, it may be enough that the MCU has a reasonable clock to execute instructions with. This saves the designer from having to supply a crystal and thus reduces the parts count.

Figure 15-1 illustrates the two crystals that are provided with the Blue Pill board. Notice the size of the 8.000 MHz crystal. Right beneath it in the photo is the 32.768 kHz crystal, which is housed in a rectangular blob of plastic. Relative to the MCU chip (above the 8 MHz crystal), these are large components.

The RC oscillator, as electronics folks know, consists of charging and discharging a capacitor through a resistor. The combination of capacitance and resistance determines the overall frequency. Creating capacitors inside of an IC (Integrated Circuit) presents challenges but is worth doing for chip buyers who want to reduce external components.

Note that the only STM32 RC oscillators provided are internal oscillators. Otherwise, resistors and capacitors would need to be supplied externally.

A465982_1_En_15_Fig1_HTML.jpg
Figure 15-1 8 MHz crystal and 32.768 kHz crystal below it

Crystal Oscillators

Crystal oscillators are far more accurate and stable than the RC oscillator. However, they have the disadvantage that an external crystal must be supplied and wired up to the MCU chip. Figure 15-1 illustrates the two crystals found on the Blue Pill PCB, with the 8 MHz crystal used by the HSE oscillator. The 32.768 kHz crystal drives the LSE oscillator.

Oscillator Power

The higher rate at which the oscillator switches between low and high signal levels means additional current consumption. Every time the oscillator switches from low to high electrons have to be pushed into the circuit, thus requiring current flow (charging). When the oscillator switches from high to low, electrons have to be drawn out of the circuit and drained to ground (discharging). All of this requires energy.

It comes as no surprise then, if you do this charging and discharging more frequently in a given second, then more overall current is consumed. This is why so much attention is given to the clock design in the STM32 platform.

For some applications where the system is battery powered and the execution time is less important, it makes sense to use a lower-speed oscillator. If, on the other hand, the application is powered from a desktop over USB and speed is the dominant requirement, then higher oscillator rates are preferred.

Another selection criterion is accuracy. If you implement a serial link between different units, then you need to have an accurate notion of the baud rate. Having choice provides designers with different trade-offs.

Real-time Clock

The HSE, LSE, or LSI clock can be chosen for the source of the RTCCLK (real-time clock). Table 15-2 summarizes the clock configurations available. Note that the divisor is hardwired as 128 when the HSE clock is chosen.

Table 15-2 Real-time Clock Sources When HSE Is 8 MHz

Oscillator Source

Source Frequency

Divisor

Resulting Frequency

HSE

8.000 MHz

128

62.5 kHz

LSE

32.768 kHz

1

32.768 kHz

LSI

40 kHz

1

40 kHz

Watchdog Clock

The independent watchdog (IWDG) is hard wired to the LSI 40-kHz clock.

System Clock (SYSCLK)

The most interesting category of basic clock configuration is the system clock, from which other important clocks are derived. The SYSCLK can only be sourced from two of the four clock sources:

  • HSI (RC), 8 MHz

  • HSE (crystal), 4–16 MHz (8 MHz on Blue Pill)

There is one additional source that is derived from a phase-locked loop (PLL), which multiplies the frequency of the HSI or HSE clock input. When the source for the PLL is the HSI clock, the input is first divided by two. Table 15-3 provides a convenient table of values when HSI is used.

Table 15-3 System Clock Derived from HSI and PLL

Source

Frequency

PLL Multiplier

Resulting Frequency

HSI

8 MHz

No PLL

8 MHz

HSI

8 MHz ÷ 2

2

8 MHz

HSI

8 MHz ÷ 2

3

12 MHz

HSI

8 MHz ÷ 2

4

16 MHz

HSI

8 MHz ÷ 2

5

20 MHz

HSI

8 MHz ÷ 2

6

24 MHz

HSI

8 MHz ÷ 2

7

28 MHz

HSI

8 MHz ÷ 2

8

32 MHz

HSI

8 MHz ÷ 2

9

36 MHz

HSI

8 MHz ÷ 2

10

40 MHz

HSI

8 MHz ÷ 2

11

44 MHz

HSI

8 MHz ÷ 2

12

48 MHz

HSI

8 MHz ÷ 2

13

52 MHz

HSI

8 MHz ÷ 2

14

56 MHz

HSI

8 MHz ÷ 2

15

60 MHz

HSI

8 MHz ÷ 2

16

64 MHz

When the HSE is the chosen clock source, the calculation changes to the values shown in Table 15-4. The input to the PLL can use either the HSE divided by two (HSE ÷ 2) or not divided (HSE ÷ 1). The maximum usable system clock is 72 MHz.

Table 15-4 System Clock Derived from HSE and PLL

Source

Frequency

PLL Multiplier

HSE ÷ 2

HSE ÷ 1

HSE

8.000 MHz

No PLL

8 MHz

8 MHz

HSE

8.000 MHz

2

8 MHz

16 MHz

HSE

8.000 MHz

3

12 MHz

24 MHz

HSE

8.000 MHz

4

16 MHz

32 MHz

HSE

8.000 MHz

5

20 MHz

40 MHz

HSE

8.000 MHz

6

24 MHz

48 MHz

HSE

8.000 MHz

7

28 MHz

56 MHz

HSE

8.000 MHz

8

32 MHz

64 MHz

HSE

8.000 MHz

9

36 MHz

72 MHz

HSE

8.000 MHz

10

40 MHz

over limit

HSE

8.000 MHz

11

44 MHz

over limit

HSE

8.000 MHz

12

48 MHz

over limit

HSE

8.000 MHz

13

52 MHz

over limit

HSE

8.000 MHz

14

56 MHz

over limit

HSE

8.000 MHz

15

60 MHz

over limit

HSE

8.000 MHz

16

64 MHz

over limit

Figure 15-2 provides a slightly simplified diagram of the system clock tree up to the point of the SYSCLK. The asterisks identify what is normally configured for the Blue Pill STM32F103C8T6.

A465982_1_En_15_Fig2_HTML.jpg
Figure 15-2 Simplified summary of clock tree up to the point of SYSCLK

SYSCLK and USB

If you’re not using USB, you can ignore this issue. But when USB support is required, your choices are limited, as outlined in Table 15-5. The USB prescaler must be set so that the USBCLK is 48 MHz.

Table 15-5 Valid Clock Configurations when USB Is Used

SYSCLK Frequency

USB Divisor

Resulting USB Clock

72 MHz

÷ 1.5

48 MHz

48 MHz

÷ 1

48 MHz

AHB Bus

Throughout the ST Microelectronics document RM0008, which describes the STM32 series, references to AHB are made without ever explaining what it is. So, what is the AHB anyway? Wikipedia helps with this: 1

The ARM Advanced Microcontroller Bus Architecture (AMBA) is an open-standard, on-chip interconnect specification for the connection and management of functional blocks in system-on-a-chip (SoC) designs. . . . AMBA was introduced by ARM in 1996. The first AMBA buses were Advanced System Bus (ASB) and Advanced Peripheral Bus (APB). In its second version, AMBA 2 in 1999, ARM added AMBA Hi gh-performance Bus (AHB) that is a single clock-edge protocol.

There we have it—AHB is the AMBA high-performance bus. Within the STM32 family, the AHB has a prescaler that uses the SYSCLK as the input. Assuming that the SYSCLK is 72 MHz, Table 15-6 summarizes the AHB choices.

Table 15-6 STM32F103C8T6 AHB Frequencies with a 72 MHz SYSCLK

Bit Value

Divisor

Resulting Frequency

0xxx

SYSCLK not divided

72 MHz

1000

SYSCLK divided by 2

36 MHz

1001

SYSCLK divided by 4

18 MHz

1010

SYSCLK divided by 8

9 MHz

1011

SYSCLK divided by 16

4.5 MHz

1100

SYSCLK divided by 64

1.125 MHz

1101

SYSCLK divided by 128

562.5 kHz

1110

SYSCLK divided by 256

281.25 kHz

1111

SYSCLK divided by 512

140.625 kHz

Starting from SYSCLK, Figure 15-3 illustrates why this is called a clock tree. From the SYSCLK signal, many other clocks are derived from configured divisors and enables.

A465982_1_En_15_Fig3_HTML.jpg
Figure 15-3 Clock tree starting from SYSCLK

rcc_clock_setup_in_hse_8mhz_out_72mhz( )

In most of the demos presented in this book, the following libopencm3 routine is used at the start of the main program:

rcc_clock_setup_in_hse_8mhz_out_72mhz();

To help us understand specifically what that is doing, Listing 15-1 illustrates the libopencm3 function code for it.

Listing 15-1 The Function rcc_clock_setup_in_hse_8mhz_out_72mhz( )
0911: void rcc_clock_setup_in_hse_8mhz_out_72mhz(void)
0912: {
0913:   /* Enable internal high-speed oscillator. */
0914:   rcc_osc_on(RCC_HSI);
0915:   rcc_wait_for_osc_ready(RCC_HSI);
0916:
0917:   /* Select HSI as SYSCLK source. */
0918:   rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
0919:
0920:   /* Enable external high-speed oscillator 8MHz. */
0921:   rcc_osc_on(RCC_HSE);
0922:   rcc_wait_for_osc_ready(RCC_HSE);
0923:   rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK);
0924:
0925:   /*
0926:    * Set prescalers for AHB, ADC, ABP1, ABP2.
0927:    * Do this before touching the PLL (TODO: why?).
0928:    */
0929:   rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV);/* Set. 72MHz Max. 72MHz */
0930:   rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV8);/*Set. 9MHz Max. 14MHz */
0931:   rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 36MHz Max. 36MHz */
0932:   rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV);/* Set. 72MHz Max. 72MHz */
0933:
0934:   /*
0935:    * Sysclk runs with 72MHz -> 2 waitstates.
0936:    * 0WS from 0-24MHz
0937:    * 1WS from 24-48MHz
0938:    * 2WS from 48-72MHz
0939:    */
0940:   flash_set_ws(FLASH_ACR_LATENCY_2WS);
0941:
0942:   /*
0943:    * Set the PLL multiplication factor to 9.
0944:    * 8MHz (external) * 9 (multiplier) = 72MHz
0945:    */
0946:   rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL9);
0947:
0948:   /* Select HSE as PLL source. */
0949:   rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_CLK);
0950:
0951:   /*
0952:    * External frequency undivided before entering PLL
0953:    * (only valid/needed for HSE).
0954:    */
0955:   rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK);
0956:
0957:   /* Enable PLL oscillator and wait for it to stabilize. */
0958:   rcc_osc_on(RCC_PLL);
0959:   rcc_wait_for_osc_ready(RCC_PLL);
0960:
0961:   /* Select PLL as SYSCLK source. */
0962:   rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
0963:
0964:   /* Set the peripheral clock frequencies used */
0965:   rcc_ahb_frequency = 72000000;
0966:   rcc_apb1_frequency = 36000000;
0967:   rcc_apb2_frequency = 72000000;
0968: }

The basic steps used are the following:

  1. The HSI oscillator is turned on and waits for it to become ready (lines 914 to 915).

  2. Selects the HSI oscillator as the SYSCLK source (line 918).

  3. The HSE (8 MHz crystal oscillator) is enabled in line 921, and the code waits until it is ready (line 922).

  4. The SYSCLK is then switched to use the HSE clock (line 923). Note that this is not the PLL yet, so at this point the SYSCLK is 8.000 MHz as determined by the crystal.

  5. The AHB is set to use no divisor in its prescaler (line 929), resulting in an input AHB clock of 72 MHz after the PLL is selected (later) as the clock source.

  6. The ADC prescaler is configured with a divisor of 8 (line 930), which results in a frequency of 9 MHz (after switch to the PLL). As the comment indicates, it must not exceed 14 MHz.

  7. The prescaler for APB1 (Advanced Peripheral Bus 1) is set to divide by 2, resulting in an APB1 clock of 36 MHz after switch to the PLL (line 931). This is the maximum frequency for this bus.

  8. The prescaler for APB2 is set to use no divisor, resulting in an APB2 frequency of 72 MHz when switched later to use the PLL (line 932). This is also the maximum frequency for APB2.

  9. Since the SYSCLK runs at 72 MHz, there must be two wait cycles inserted for each flash memory access (line 940).

  10. The PLL is now set with a multiplier of 9 to set its output clock to 72 MHz (line 946).

  11. Line 955 removes any ÷ 2 setting for HSE entering the PLL that might be set.

  12. Finally, line 962 selects the PLL as the SYSCLK source. This increases the SYSCLK from 8 to 72 MHz, with the AHB bus now operating at 72 MHz, APB1 running at 36 MHz, and APB2 running at 72 MHz.

  13. Lines 965 to 967 set global values rcc_ahb_frequency, rcc_apb1_frequency and rcc_apb2_frequency for application use.

The globals are defined in rcc.h and are defined as follows:

#include <libopencm3/stm32/rcc.h>

extern uint32_t rcc_ahb_frequency;
extern uint32_t rcc_apb1_frequency;
extern uint32_t rcc_apb2_frequency;

From this, you can see that there is quite a bit that must be done at startup to make sure that no clocks falter or fail.

APB1 Peripherals

Each peripheral connected to the APB1 bus in the Blue Pill device receives a 36 MHz clock (unless otherwise configured). Each peripheral, however, has a private AND-gate to enable/disable this clock in order to save power. To enable the receipt of the clock, the peripheral must enable it. For example, the CAN peripheral must enable the clock for the peripheral itself. The same applies to APB1 timer peripherals.

APB2 Peripherals

Like the APB1 peripherals, each peripheral attached to the APB2 bus must enable/disable the receipt of their own 72 MHz clock. This also applies to APB2 timer peripherals.

Timers

Special mention is made of timers here because there is a not-so-obvious wrinkle in their configuration. APB1 and APB2 timers have a prescaler, allowing their bus clocks to be divided down for a lower frequency. The exception, however, is that when the APB1/APB2 prescaler is set to one, the bus frequency is multiplied by two!

Note

When a timer prescaler is set to 1, the output of the prescaler is a bus frequency times 2!

rcc_set_mco( )

The libopencm3 library provides a function named rcc_set_mco() to configure a clock output on GPIO PA8. The valid macro values passed as an argument are described in Table 15-7.

rcc_set_mco(macro);
Table 15-7 Valid Arguments to rcc_set_mco( )

Macro Name

Value

Description

RCC_CFGR_MCO_NOCLK

0 x 0

No clock to MCO (disconnected)

RCC_CFGR_MCO_SYSCLK

0 x 4

SYSCLK to MCO

RCC_CFGR_MCO_HSI

0 x 5

HSI to MCO

RCC_CFGR_MCO_HSE

0 x 6

HSE to MCO

RCC_CFGR_MCO_PLL_DIV2

0 x 7

PLL ÷ 2 to MCO

Calling the routine rcc_set_mco() by itself is not enough. The GPIO PA8 must be configured for alternate function I/O:

rcc_periph_clock_enable(RCC_GPIOA);
gpio_set_mode(GPIOA,
    GPIO_MODE_OUTPUT_50_MHZ,
    GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, // ALTFN
    GPIO8);                         // PA8=MCO

HSI Demo

The example code for the HSI clock demo is located here:

$ cd ~/stm32f103c8t6/hsi
$ make clobber
$ make
$ make flash

Note that this demo does not use FreeRTOS. Its code is very basic and simply arranges to have the HSI clock brought out to GPIO pin PA8. Listing 15-2 shows the main program responsible.

Listing 15-2 The hsi.c Demonstration Program
0010: int
0011: main(void) {
0012:
0013:   // LED Configuration:
0014:   rcc_periph_clock_enable(RCC_GPIOC);
0015:   gpio_set_mode(GPIOC,GPIO_MODE_OUTPUT_2_MHZ,
0016:             GPIO_CNF_OUTPUT_PUSHPULL,GPIO13);
0017:   gpio_clear(GPIOC,GPIO13);    // LED Off
0018:
0019:   // MCO Configuration:
0020:   rcc_periph_clock_enable(RCC_GPIOA);
0021:   gpio_set_mode(GPIOA,
0022:       GPIO_MODE_OUTPUT_50_MHZ,
0023:       GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
0024:       GPIO8);             // PA8=MCO
0025:
0026:   rcc_set_mco(RCC_CFGR_MCO_HSI);
0027:
0028:   gpio_set(GPIOC,GPIO13); // LED On
0029:   for (;;);
0030:   return 0;
0031: }

Aside from configuring the LED PC13, the main elements are as follows:

  1. The GPIOA peripheral clock is enabled in line 20.

  2. The GPIOA to which pin PA8 is configured for output (max 50 MHz, line 22) is an alternate function (line 23) in push/pull mode.

  3. The HSI clock is directed to PA8 in line 26.

After flashing the STM32, you should be able to see the HSI clock on PA8 with a scope or DSO as soon as power is applied or after reset (Figure 15-4). From the figure, you can see that the HSI clock is near 8 MHz.

A465982_1_En_15_Fig4_HTML.jpg
Figure 15-4 The HSI MCO trace

HSE Demo

The example code for the HSE clock demo is located here:

$ cd ~/stm32f103c8t6/hse
$ make clobber
$ make
$ make flash

Note that this demo also does not use FreeRTOS. Its code is basic and simply arranges to have the HSE clock brought out to GPIO pin PA8. The only difference between this demo program and the HSI demo is one line:

rcc_set_mco(RCC_CFGR_MCO_HSE);

After flashing the STM32, you should be able to see the HSE clock on PA8 with a scope or DSO as soon as power is applied (Figure 15-5). In the figure, the frequency is more accurate to 8 MHz.

A465982_1_En_15_Fig5_HTML.jpg
Figure 15-5 The HSE MCO trace (note how similar this is to Figure 15-4)

PLL ÷ 2 Demo

The example code for the PLL ÷ 2 clock demo is located here:

$ cd ~/stm32f103c8t6/mco_pll2
$ make clobber
$ make
$ make flash

Note again that this demo also does not use FreeRTOS. Its code is basic and simply arranges to have the PLL ÷ 2 clock brought out to GPIO pin PA8. The only difference between this demo program and the HSE demo is one line:

rcc_set_mco(RCC_CFGR_MCO_PLL_DIV2);

Having the PLL ÷ 2 clock sent out to PA8 is helpful because the GPIO pin is limited to driving 50 MHz. You could attempt to send 72 MHz out, but the signal would be badly degraded and perhaps stress the active components involved. But 36 MHz is well within the acceptable performance range.

After flashing the STM32, you should be able to see the PLL ÷ 2 clock on PA8 with a scope or DSO as soon as power is applied. Notice that the frequency shown is near 36 MHz, as expected (72 MHz ÷ 2), in Figure 15-6.

A465982_1_En_15_Fig6_HTML.jpg
Figure 15-6 The PLL ÷ 2 MCO trace

Summary

In this chapter, the overview of the clock-tree system was presented, starting with the main clock sources: HSI and HSE for the system clock, and HSE, LSE, and LSI for the real-time clock. Clock LSI was also used by the watchdog timer.

The next main category of clocks stem from the system clock. The system clock is able to employ the use of the PLL, which is capable of multiplying its input clock up to 72 MHz. From the system clock, an AHB clock is derived. Then, from the AHB clock are derived APB1 and APB2 clocks.

Finally, it was noted that each peripheral needing a clock has its own gate that it must enable in order to use a given clock. This design saves power by leaving unneeded clocks disabled.

The HSI, HSE, and PLL ÷ 2 demos illustrated how to check a clock that is otherwise internal and unseen. It is also possible that a clock placed on PA8 may have its application to external peripherals needing an input clock.

Bibliography

  1. “Advanced Microcontroller Bus Architecture.” Wikipedia. December 16, 2017. Accessed December 29, 2017. https://en.wikipedia.org/wiki/Advanced_Microcontroller_Bus_Architecture

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.69.255