Skip to content

Instantly share code, notes, and snippets.

@ChuckM
Created December 12, 2014 18:57
Show Gist options
  • Save ChuckM/0429f13af59415682e7e to your computer and use it in GitHub Desktop.
Save ChuckM/0429f13af59415682e7e to your computer and use it in GitHub Desktop.
RCC functions for libopencm3

Overview

Setting up the clock tree is fundamental for the Cortex M family but it isn't an often used capability. Generally these functions are called once in a piece of startup code and then forgotten. In the ST Micro family of Cortex-M processors, support for their clock trees has varied from family to family, both in name and in features. This proposal is to unify that support around some key API calls that would be available on all members of the family.

RCC Setup

Generally there are a small number of clocks that can be used as the system clock for the ST Micro processors, these usually include a default "High Speed" internal (HSI) RC oscillator, a high speed, externally supplied, clock (HSE), and a PLL which is primed by either HSI or HSE and provides a system clock frequency that is different than the input frequency. The Lx family has added a medium speed internal clock (MSI) to this mix.

This proposal suggests that setup of all these clocks should be done in a function named: rcc_XXX_clock_setup(...) where XXX is one of HSI, MSI, PLL, HSI16, or HSI4*. This function would be responsible for configuring the clock to the desired settings and activating it as the system clock. Additionally, this function is responsible for setting the three internal variables rcc_ahb_frequency, rcc_apb1_frequency, and rcc_apb2_frequency. Those frequencies, stored as Hertz (so 8MHZ is 8000000), are used by other parts of the library (notably USART and TIMERs) in calculating clock related values. They also enable a simpler SysTick interface where one parameter can be used to specify the system tick rate as the base clock frequency is already available in the library.

The simplest clocks require no parameters, for example rcc_hsi_clock_setup(void), as the clock frequency is fixed. The most complex function, rcc_pll_clock_setup(pll_frequency, source_frequency) requires both an indication of what frequency the PLL should generate, and the frequency of the source of that frequency. This data is required for the function to compute the final rcc_ahb_frequency value and to pre-set the APB prescalers correctly.

* HSI4 is a 'psuedo' clock that occurs because the L0 offers the 16Mhz HSI clock with an optional "divide by 4" prescaler attached making it, for all intents, a second option of a 4Mhz high speed internal RC clock.

Prescalers

The second set of functions common to all members are rcc_set_ppre1, rcc_set_ppre2, and rcc_set_hpre. These functions allow the programmer to scale the clocks to the APB1 bus and APB2 bus, as well as the main system clock. The clock setup functions above will configure the prescalers to the maximum allowable frequency (based on the datasheet) and these functions provide an option for changing that choice once the clock is set up.

Note that if you change hpre it scales the system clock and that will change the values of both rcc_apb1_frequency and rcc_apb2_frequency as well.

Clock Manipulation

The third set of functions involve the selection and activation of clocks, and descriptions of them. In this part the RCC subsystem defines an enum named rcc_osc which has values HSI, HSI16, HSI4, PLL, HSE, MSI, etc. One for each possible clock on the chip. The function rcc_get_sysclk(void) returns the oscillator currently being used as the system clock, the function rcc_set_sysclk(osc) switches the system to the specified clock source. rcc_osc_on(osc) and rcc_osc_off(osc) turn on and off the specified oscillator. They are 'unsafe' in that they are not checked to see if they would shut down the system (turning off the current system clock). Finally there is rcc_osc_bypass which is used to control whether an active oscillator is running or if the source is simply a clock input source.

Miscellaneous Functions

There will continue to be family specific clock manipulation. Specifically HSI48 support for USB clocks, or LSE and LSI clock support for setting up real time clocks. As the details of these clocks vary markedly from chip family to chip family they will be different depending on the chip being used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment