Modified version of the mbed library for use with the Nucleo boards.

Dependents:   EEPROMWrite Full-Project

Fork of mbed-src by mbed official

Revision:
613:bc40b8d2aec4
Parent:
612:fba1c7dc54c0
Child:
614:9d86c2ae5de0
--- a/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/system/clock/clock_samd21_r21/gclk.c	Tue Aug 18 15:00:09 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,476 +0,0 @@
-#include <gclk.h>
-#include <clock.h>
-#include <system_interrupt.h>
-
-/**
- * \brief Determines if the hardware module(s) are currently synchronizing to the bus.
- *
- * Checks to see if the underlying hardware peripheral module(s) are currently
- * synchronizing across multiple clock domains to the hardware bus, This
- * function can be used to delay further operations on a module until such time
- * that it is ready, to prevent blocking delays for synchronization in the
- * user application.
- *
- * \return Synchronization status of the underlying hardware module(s).
- *
- * \retval false if the module has completed synchronization
- * \retval true if the module synchronization is ongoing
- */
-static inline bool system_gclk_is_syncing(void)
-{
-    if (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {
-        return true;
-    }
-
-    return false;
-}
-
-/**
- * \brief Initializes the GCLK driver.
- *
- * Initializes the Generic Clock module, disabling and resetting all active
- * Generic Clock Generators and Channels to their power-on default values.
- */
-void system_gclk_init(void)
-{
-    /* Turn on the digital interface clock */
-    system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBA, PM_APBAMASK_GCLK);
-
-    /* Software reset the module to ensure it is re-initialized correctly */
-    GCLK->CTRL.reg = GCLK_CTRL_SWRST;
-    while (GCLK->CTRL.reg & GCLK_CTRL_SWRST) {
-        /* Wait for reset to complete */
-    }
-}
-
-/**
- * \brief Writes a Generic Clock Generator configuration to the hardware module.
- *
- * Writes out a given configuration of a Generic Clock Generator configuration
- * to the hardware module.
- *
- * \note Changing the clock source on the fly (on a running
- *       generator) can take additional time if the clock source is configured
- *       to only run on-demand (ONDEMAND bit is set) and it is not currently
- *       running (no peripheral is requesting the clock source). In this case
- *       the GCLK will request the new clock while still keeping a request to
- *       the old clock source until the new clock source is ready.
- *
- * \note This function will not start a generator that is not already running;
- *       to start the generator, call \ref system_gclk_gen_enable()
- *       after configuring a generator.
- *
- * \param[in] generator  Generic Clock Generator index to configure
- * \param[in] config     Configuration settings for the generator
- */
-void system_gclk_gen_set_config(
-    const uint8_t generator,
-    struct system_gclk_gen_config *const config)
-{
-    /* Sanity check arguments */
-    Assert(config);
-
-    /* Cache new register configurations to minimize sync requirements. */
-    uint32_t new_genctrl_config = (generator << GCLK_GENCTRL_ID_Pos);
-    uint32_t new_gendiv_config  = (generator << GCLK_GENDIV_ID_Pos);
-
-    /* Select the requested source clock for the generator */
-    new_genctrl_config |= config->source_clock << GCLK_GENCTRL_SRC_Pos;
-
-    /* Configure the clock to be either high or low when disabled */
-    if (config->high_when_disabled) {
-        new_genctrl_config |= GCLK_GENCTRL_OOV;
-    }
-
-    /* Configure if the clock output to I/O pin should be enabled. */
-    if (config->output_enable) {
-        new_genctrl_config |= GCLK_GENCTRL_OE;
-    }
-
-    /* Set division factor */
-    if (config->division_factor > 1) {
-        /* Check if division is a power of two */
-        if (((config->division_factor & (config->division_factor - 1)) == 0)) {
-            /* Determine the index of the highest bit set to get the
-             * division factor that must be loaded into the division
-             * register */
-
-            uint32_t div2_count = 0;
-
-            uint32_t mask;
-            for (mask = (1UL << 1); mask < config->division_factor;
-                    mask <<= 1) {
-                div2_count++;
-            }
-
-            /* Set binary divider power of 2 division factor */
-            new_gendiv_config  |= div2_count << GCLK_GENDIV_DIV_Pos;
-            new_genctrl_config |= GCLK_GENCTRL_DIVSEL;
-        } else {
-            /* Set integer division factor */
-
-            new_gendiv_config  |=
-                (config->division_factor) << GCLK_GENDIV_DIV_Pos;
-
-            /* Enable non-binary division with increased duty cycle accuracy */
-            new_genctrl_config |= GCLK_GENCTRL_IDC;
-        }
-
-    }
-
-    /* Enable or disable the clock in standby mode */
-    if (config->run_in_standby) {
-        new_genctrl_config |= GCLK_GENCTRL_RUNSTDBY;
-    }
-
-    while (system_gclk_is_syncing()) {
-        /* Wait for synchronization */
-    };
-
-    system_interrupt_enter_critical_section();
-
-    /* Select the correct generator */
-    *((uint8_t*)&GCLK->GENDIV.reg) = generator;
-
-    /* Write the new generator configuration */
-    while (system_gclk_is_syncing()) {
-        /* Wait for synchronization */
-    };
-    GCLK->GENDIV.reg  = new_gendiv_config;
-
-    while (system_gclk_is_syncing()) {
-        /* Wait for synchronization */
-    };
-    GCLK->GENCTRL.reg = new_genctrl_config | (GCLK->GENCTRL.reg & GCLK_GENCTRL_GENEN);
-
-    system_interrupt_leave_critical_section();
-}
-
-/**
- * \brief Enables a Generic Clock Generator that was previously configured.
- *
- * Starts the clock generation of a Generic Clock Generator that was previously
- * configured via a call to \ref system_gclk_gen_set_config().
- *
- * \param[in] generator  Generic Clock Generator index to enable
- */
-void system_gclk_gen_enable(
-    const uint8_t generator)
-{
-    while (system_gclk_is_syncing()) {
-        /* Wait for synchronization */
-    };
-
-    system_interrupt_enter_critical_section();
-
-    /* Select the requested generator */
-    *((uint8_t*)&GCLK->GENCTRL.reg) = generator;
-    while (system_gclk_is_syncing()) {
-        /* Wait for synchronization */
-    };
-
-    /* Enable generator */
-    GCLK->GENCTRL.reg |= GCLK_GENCTRL_GENEN;
-
-    system_interrupt_leave_critical_section();
-}
-
-/**
- * \brief Disables a Generic Clock Generator that was previously enabled.
- *
- * Stops the clock generation of a Generic Clock Generator that was previously
- * started via a call to \ref system_gclk_gen_enable().
- *
- * \param[in] generator  Generic Clock Generator index to disable
- */
-void system_gclk_gen_disable(
-    const uint8_t generator)
-{
-    while (system_gclk_is_syncing()) {
-        /* Wait for synchronization */
-    };
-
-    system_interrupt_enter_critical_section();
-
-    /* Select the requested generator */
-    *((uint8_t*)&GCLK->GENCTRL.reg) = generator;
-    while (system_gclk_is_syncing()) {
-        /* Wait for synchronization */
-    };
-
-    /* Disable generator */
-    GCLK->GENCTRL.reg &= ~GCLK_GENCTRL_GENEN;
-    while (GCLK->GENCTRL.reg & GCLK_GENCTRL_GENEN) {
-        /* Wait for clock to become disabled */
-    }
-
-    system_interrupt_leave_critical_section();
-}
-
-/**
- * \brief Determins if the specified Generic Clock Generator is enabled.
- *
- * \param[in] generator  Generic Clock Generator index to check
- *
- * \return The enabled status.
- * \retval true The Generic Clock Generator is enabled
- * \retval false The Generic Clock Generator is disabled
- */
-bool system_gclk_gen_is_enabled(
-    const uint8_t generator)
-{
-    bool enabled;
-
-    system_interrupt_enter_critical_section();
-
-    /* Select the requested generator */
-    *((uint8_t*)&GCLK->GENCTRL.reg) = generator;
-    /* Obtain the enabled status */
-    enabled = (GCLK->GENCTRL.reg & GCLK_GENCTRL_GENEN);
-
-    system_interrupt_leave_critical_section();
-
-    return enabled;
-}
-
-/**
- * \brief Retrieves the clock frequency of a Generic Clock generator.
- *
- * Determines the clock frequency (in Hz) of a specified Generic Clock
- * generator, used as a source to a Generic Clock Channel module.
- *
- * \param[in] generator  Generic Clock Generator index
- *
- * \return The frequency of the generic clock generator, in Hz.
- */
-uint32_t system_gclk_gen_get_hz(
-    const uint8_t generator)
-{
-    while (system_gclk_is_syncing()) {
-        /* Wait for synchronization */
-    };
-
-    system_interrupt_enter_critical_section();
-
-    /* Select the appropriate generator */
-    *((uint8_t*)&GCLK->GENCTRL.reg) = generator;
-    while (system_gclk_is_syncing()) {
-        /* Wait for synchronization */
-    };
-
-    /* Get the frequency of the source connected to the GCLK generator */
-    uint32_t gen_input_hz = system_clock_source_get_hz(
-                                (enum system_clock_source)GCLK->GENCTRL.bit.SRC);
-
-    *((uint8_t*)&GCLK->GENCTRL.reg) = generator;
-
-    uint8_t divsel = GCLK->GENCTRL.bit.DIVSEL;
-
-    /* Select the appropriate generator division register */
-    *((uint8_t*)&GCLK->GENDIV.reg) = generator;
-    while (system_gclk_is_syncing()) {
-        /* Wait for synchronization */
-    };
-
-    uint32_t divider = GCLK->GENDIV.bit.DIV;
-
-    system_interrupt_leave_critical_section();
-
-    /* Check if the generator is using fractional or binary division */
-    if (!divsel && divider > 1) {
-        gen_input_hz /= divider;
-    } else if (divsel) {
-        gen_input_hz >>= (divider+1);
-    }
-
-    return gen_input_hz;
-}
-
-/**
- * \brief Writes a Generic Clock configuration to the hardware module.
- *
- * Writes out a given configuration of a Generic Clock configuration to the
- * hardware module. If the clock is currently running, it will be stopped.
- *
- * \note Once called the clock will not be running; to start the clock,
- *       call \ref system_gclk_chan_enable() after configuring a clock channel.
- *
- * \param[in] channel   Generic Clock channel to configure
- * \param[in] config    Configuration settings for the clock
- *
- */
-void system_gclk_chan_set_config(
-    const uint8_t channel,
-    struct system_gclk_chan_config *const config)
-{
-    /* Sanity check arguments */
-    Assert(config);
-
-    /* Cache the new config to reduce sync requirements */
-    uint32_t new_clkctrl_config = (channel << GCLK_CLKCTRL_ID_Pos);
-
-    /* Select the desired generic clock generator */
-    new_clkctrl_config |= config->source_generator << GCLK_CLKCTRL_GEN_Pos;
-
-    /* Disable generic clock channel */
-    system_gclk_chan_disable(channel);
-
-    /* Write the new configuration */
-    GCLK->CLKCTRL.reg = new_clkctrl_config;
-}
-
-/**
- * \brief Enables a Generic Clock that was previously configured.
- *
- * Starts the clock generation of a Generic Clock that was previously
- * configured via a call to \ref system_gclk_chan_set_config().
- *
- * \param[in] channel   Generic Clock channel to enable
- */
-void system_gclk_chan_enable(
-    const uint8_t channel)
-{
-    system_interrupt_enter_critical_section();
-
-    /* Select the requested generator channel */
-    *((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
-
-    /* Enable the generic clock */
-    GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_CLKEN;
-
-    system_interrupt_leave_critical_section();
-}
-
-/**
- * \brief Disables a Generic Clock that was previously enabled.
- *
- * Stops the clock generation of a Generic Clock that was previously started
- * via a call to \ref system_gclk_chan_enable().
- *
- * \param[in] channel  Generic Clock channel to disable
- */
-void system_gclk_chan_disable(
-    const uint8_t channel)
-{
-    system_interrupt_enter_critical_section();
-
-    /* Select the requested generator channel */
-    *((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
-
-    /* Sanity check WRTLOCK */
-    Assert(!GCLK->CLKCTRL.bit.WRTLOCK);
-
-    /* Switch to known-working source so that the channel can be disabled */
-    uint32_t prev_gen_id = GCLK->CLKCTRL.bit.GEN;
-    GCLK->CLKCTRL.bit.GEN = 0;
-
-    /* Disable the generic clock */
-    GCLK->CLKCTRL.reg &= ~GCLK_CLKCTRL_CLKEN;
-    while (GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN) {
-        /* Wait for clock to become disabled */
-    }
-
-    /* Restore previous configured clock generator */
-    GCLK->CLKCTRL.bit.GEN = prev_gen_id;
-
-    system_interrupt_leave_critical_section();
-}
-
-/**
- * \brief Determins if the specified Generic Clock channel is enabled.
- *
- * \param[in] channel  Generic Clock Channel index
- *
- * \return The enabled status.
- * \retval true The Generic Clock channel is enabled
- * \retval false The Generic Clock channel is disabled
- */
-bool system_gclk_chan_is_enabled(
-    const uint8_t channel)
-{
-    bool enabled;
-
-    system_interrupt_enter_critical_section();
-
-    /* Select the requested generic clock channel */
-    *((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
-    enabled = GCLK->CLKCTRL.bit.CLKEN;
-
-    system_interrupt_leave_critical_section();
-
-    return enabled;
-}
-
-/**
- * \brief Locks a Generic Clock channel from further configuration writes.
- *
- * Locks a generic clock channel from further configuration writes. It is only
- * possible to unlock the channel configuration through a power on reset.
- *
- * \param[in] channel   Generic Clock channel to enable
- */
-void system_gclk_chan_lock(
-    const uint8_t channel)
-{
-    system_interrupt_enter_critical_section();
-
-    /* Select the requested generator channel */
-    *((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
-
-    /* Lock the generic clock */
-    GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_WRTLOCK;
-
-    system_interrupt_leave_critical_section();
-}
-
-/**
- * \brief Determins if the specified Generic Clock channel is locked.
- *
- * \param[in] channel  Generic Clock Channel index
- *
- * \return The lock status.
- * \retval true The Generic Clock channel is locked
- * \retval false The Generic Clock channel is not locked
- */
-bool system_gclk_chan_is_locked(
-    const uint8_t channel)
-{
-    bool locked;
-
-    system_interrupt_enter_critical_section();
-
-    /* Select the requested generic clock channel */
-    *((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
-    locked = GCLK->CLKCTRL.bit.WRTLOCK;
-
-    system_interrupt_leave_critical_section();
-
-    return locked;
-}
-
-/**
- * \brief Retrieves the clock frequency of a Generic Clock channel.
- *
- * Determines the clock frequency (in Hz) of a specified Generic Clock
- * channel, used as a source to a device peripheral module.
- *
- * \param[in] channel  Generic Clock Channel index
- *
- * \return The frequency of the generic clock channel, in Hz.
- */
-uint32_t system_gclk_chan_get_hz(
-    const uint8_t channel)
-{
-    uint8_t gen_id;
-
-    system_interrupt_enter_critical_section();
-
-    /* Select the requested generic clock channel */
-    *((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
-    gen_id = GCLK->CLKCTRL.bit.GEN;
-
-    system_interrupt_leave_critical_section();
-
-    /* Return the clock speed of the associated GCLK generator */
-    return system_gclk_gen_get_hz(gen_id);
-}