====== Purpose ======

This example shows how [[clock_management|clk module]] semantics can be used to describe the clock tree in an exemplary STM32F103x microcontroller. This uC was choosen in order to illustrate a reasonably complex, but not too complex case.

====== Clock tree in STM32F103 ======

The following figure taken from the datasheet illustrates the clock tree in STM32F103 microcontroller.

{{:clk_clk_example_stm32f103.png?direct&300|}}

We can see that there are many clock signals. We can group them:

Fixed clocks (we cannot change them from code):
  * HSI (built-in RC oscillator)
  * HSE (from external XTAL)
  * LSE (from external XTAL)
  * LSI (built-in RC oscillator)

Variable clocks (these are somehow controlled)
  * USBCLK
  * SYSCLK
  * PLLCLK
  * RTCCLK
  * IWDGCLK
  * HCLK
  * FCLK
  * PCLK1
  * PCLK2
  * TIMXCLK
  * TIM1CLK
  * ADCCLK

====== The approach ======

Now the approach is to declare a __new class__ for each of the clocks, __subclassing from the general Clock class__ if the clock is variable and __subclassing from the FixedClock class__ if the clock is fixed. Most of these classes will follow the [[http://en.wikipedia.org/wiki/Singleton_pattern|singleton]] design pattern, since only one such clock will be available, however this may not necessarily be always true. For example perhaps there may be a single class to describe both PCLK1 and PCLK2.

Next the clk module port should provide instances for all the available clocks. For fixed clocks, the FixedClock class shall be used.

====== Resulting class diagram ======

<uml>
class FixedClock<|-- HSI 
class FixedClock<|-- HSE 
class FixedClock<|-- LSE 
class FixedClock<|-- LSI 
class PLLClock {
-Clock clockSource
}
class USBClock {
-Clock clockSource
}
class SYSClock {
-Clock clockSource
}
class HClock {
-Clock clockSource
}
class PClock {
-Clock clockSource
}
Clock <|.. USBClock
Clock <|.. PLLClock 
Clock <|.. SYSClock 
Clock <|.. HClock 
Clock <|.. PClock 
</uml>

====== Exemplary object diagram ======

This is how objects may look like in a certain moment in time

<uml>
object pllclk
object usbclk
object hseclk
object sysclk
object hclk
object pclk1 
object pclk2
object timxclk 
object tim1clk 
object adcclk 
usbclk -- "clockSource" pllclk
pllclk -- "clockSource" hseclk
sysclk -- hseclk
hclk -- sysclk
pclk1 -- sysclk
pclk2 -- "clockSource" sysclk
timxclk -- sysclk
tim1clk -- sysclk
adcclk -- sysclk
</uml>

This diagram shows that object connections form the exact same tree as the clock tree described in the datasheet.

====== Exemplary code ======

<code cpp>
// Declaration of the HSE clock class (fixed clock)
class HSEClock : public hal::FixedClock
{
public:
    // singleton design pattern
    static constexpr HSEClock& getInstance() { return instance; }
private:
    HSEClock(uint32_t oscillatorFrequency) : FixedClock(oscillatorFrequency)
    {
        ;
    }
    static HSEClock instance;
};

// Declaration of the SYS clock class (variable clock)
class SYSClock : public hal::Clock
{
public:
    // singleton design pattern
    static constexpr SYSClock& getInstance() { return instance; }
    uint32_t getFrequency() override {
        uint32_t frequency;
        // here we calculate the actual frequency using information about clockSource and current register settings
        // ...
        return frequency;
    }
    bool setFrequency(uint32_t frequency) override {
        // here we set the desired frequency
        // ...
        return true;
    }
    bool setClockSource(Clock& clockSource) {
        // here we switch between possible clock sources - in this case HSI, HSE or PLLCLK
        // ...
        return true;
    }
    Clock& getClockSource {
        // here we check what is the clock source and return the right object, for example:
        return HSE::GetInstance();
    }
private:
    // singleton design pattern
    static SYSClock instance;
    SYSClock()
    {
        ;
    }    
};

// handy references
HSEClock& hseclk = HSEClock::getInstance();
SYSClock& sysclk = SYSClock ::getInstance();
</code>