A Digital Frequency Locked Loop can be used to generate a highly accurate frequency from a slower-running reference clock, in much the same way as a PLL.
DFLLs typically have shorter startup times and less jitter. They can also be used in open-loop mode to generate a less accurate frequency without the use of a reference clock.
There may be significant variations between platforms in the support for certain features.
The following example shows how to configure and enable DFLL0 in closed-loop mode using the default parameters specified through configuration symbols.
To configure and enable DFLL0 in closed-loop mode using the default parameters and to enable specific feature like dithering for better accuracy, you can use this initialization process.
When the last function call returns, DFLL0 is running at a frequency which matches the default configuration as accurately as possible. Any additional alterations to the default configuration can be added at the same place as the call to dfll_config_enable_dithering(), but note that the DFLL will never achieve "accurate" lock if dithering is disabled.
Data Structures | |
struct | dfll_config |
Hardware-specific representation of DFLL configuration. More... | |
Macros | |
#define | DFLL_CALIB_VALUE (0x0B) |
#define | DFLL_COARSE_MAX (255) |
#define | DFLL_FINE_HALF (255) |
#define | DFLL_FINE_MAX (511) |
#define | DFLL_MAX_KHZ (DFLL_MAX_HZ / 1000) |
#define | DFLL_MAX_RANGE1 (110000000) |
#define | DFLL_MAX_RANGE2 (55000000) |
#define | DFLL_MAX_RANGE3 (30000000) |
#define | DFLL_MIN_KHZ (DFLL_MIN_HZ / 1000) |
#define | DFLL_RANGE0 (0) |
#define | DFLL_RANGE1 (1) |
#define | DFLL_RANGE2 (2) |
#define | DFLL_RANGE3 (3) |
Typedefs | |
typedef enum genclk_source | dfll_refclk_t |
Type used for identifying a reference clock source for the DFLL. More... | |
Functions | |
static void | dfll_config_tune_for_target_hz (struct dfll_config *cfg, uint32_t target_hz) |
Tune the DFLL configuration for a specific target frequency. More... | |
void | dfll_disable_closed_loop (uint32_t dfll_id) |
void | dfll_disable_open_loop (uint32_t dfll_id) |
void | dfll_enable_closed_loop (const struct dfll_config *cfg, uint32_t dfll_id) |
void | dfll_enable_config_defaults (uint32_t dfll_id) |
void | dfll_enable_open_loop (const struct dfll_config *cfg, uint32_t dfll_id) |
static bool | dfll_is_accurate_locked (uint32_t dfll_id) |
static bool | dfll_is_coarse_locked (uint32_t dfll_id) |
static bool | dfll_is_fine_locked (uint32_t dfll_id) |
static uint32_t | dfll_priv_get_source_hz (dfll_refclk_t src) |
static void | dfll_priv_set_frequency_range (struct dfll_config *cfg, uint32_t freq) |
Chip-specific DFLL characteristics | |
#define | NR_DFLLS 1 |
Number of on-chip DFLLs. More... | |
#define | DFLL_MIN_HZ 20000000UL |
Minimum frequency that the DFLL can generate. More... | |
#define | DFLL_MAX_HZ 150000000UL |
Maximum frequency that the DFLL can generate. More... | |
DFLL Configuration | |
static void | dfll_config_set_max_step (struct dfll_config *cfg, uint16_t coarse, uint16_t fine) |
Set the maximum VCO tuning step size. More... | |
static void | dfll_config_init_open_loop_mode (struct dfll_config *cfg) |
Configure the DFLL configuration cfg for open-loop mode. More... | |
static void | dfll_config_set_initial_tuning (struct dfll_config *cfg, uint16_t coarse, uint16_t fine) |
Set initial VCO tuning. More... | |
static void | dfll_config_enable_ssg (struct dfll_config *cfg, uint16_t amplitude, uint16_t step_size) |
Enable Spread Spectrum Generator. More... | |
static void | dfll_config_disable_ssg (struct dfll_config *cfg) |
Disable Spread Spectrum Generator. More... | |
#define | dfll_config_defaults(cfg, dfll_id) |
Initialize DFLL configuration using default parameters. More... | |
#define | dfll_get_default_rate(dfll_id) |
Return the default rate in Hz of dfll_id. More... | |
Interaction with the DFLL hardware | |
static void | dfll_enable_source (dfll_refclk_t src) |
Enable the source of the dfll. More... | |
static int | dfll_wait_for_coarse_lock (unsigned int dfll_id) |
Wait for the DFLL identified by dfll_id to achieve coarse lock. More... | |
static int | dfll_wait_for_fine_lock (unsigned int dfll_id) |
Wait for the DFLL identified by dfll_id to achieve fine lock. More... | |
static int | dfll_wait_for_accurate_lock (unsigned int dfll_id) |
Wait for the DFLL identified by dfll_id to achieve accurate lock. More... | |
#define DFLL_CALIB_VALUE (0x0B) |
#define DFLL_COARSE_MAX (255) |
Referenced by dfll_config_tune_for_target_hz().
#define dfll_config_defaults | ( | cfg, | |
dfll_id | |||
) |
Initialize DFLL configuration using default parameters.
After this function returns, cfg will contain a configuration which will make the DFLL run at (CONFIG_DFLLx_MUL / CONFIG_DFLLx_DIV) times the frequency of CONFIG_DFLLx_SOURCE. The default configuration will always use closed-loop mode with no fractional multiplier.
cfg | The DFLL configuration to be initialized. |
dfll_id | Use defaults for this DFLL. |
Referenced by run_pll_dfll_test().
#define DFLL_FINE_HALF (255) |
Referenced by dfll_config_tune_for_target_hz().
#define DFLL_FINE_MAX (511) |
Referenced by dfll_config_tune_for_target_hz().
#define dfll_get_default_rate | ( | dfll_id | ) |
Return the default rate in Hz of dfll_id.
Referenced by sysclk_get_main_hz().
#define DFLL_MAX_HZ 150000000UL |
Maximum frequency that the DFLL can generate.
#define DFLL_MAX_KHZ (DFLL_MAX_HZ / 1000) |
Referenced by dfll_config_tune_for_target_hz().
#define DFLL_MAX_RANGE1 (110000000) |
Referenced by dfll_priv_set_frequency_range().
#define DFLL_MAX_RANGE2 (55000000) |
Referenced by dfll_priv_set_frequency_range().
#define DFLL_MAX_RANGE3 (30000000) |
Referenced by dfll_priv_set_frequency_range().
#define DFLL_MIN_HZ 20000000UL |
Minimum frequency that the DFLL can generate.
#define DFLL_MIN_KHZ (DFLL_MIN_HZ / 1000) |
Referenced by dfll_config_tune_for_target_hz().
#define DFLL_RANGE0 (0) |
Referenced by dfll_priv_set_frequency_range().
#define DFLL_RANGE1 (1) |
Referenced by dfll_priv_set_frequency_range().
#define DFLL_RANGE2 (2) |
Referenced by dfll_priv_set_frequency_range().
#define DFLL_RANGE3 (3) |
Referenced by dfll_priv_set_frequency_range().
#define NR_DFLLS 1 |
Number of on-chip DFLLs.
Type used for identifying a reference clock source for the DFLL.
|
inlinestatic |
Disable Spread Spectrum Generator.
cfg | The DFLL configuration to be modified. |
References dfll_config::ssg.
|
inlinestatic |
Enable Spread Spectrum Generator.
cfg | The DFLL configuration to be modified. |
amplitude | The amplitude of the spread spectrum. |
step_size | The step size of the spread spectrum. |
References dfll_config::ssg.
|
inlinestatic |
Configure the DFLL configuration cfg for open-loop mode.
cfg | The DFLL configuration to be initialized. |
References dfll_config::conf, dfll_config::freq_range, genclk_config_defaults(), dfll_config::mul, dfll_config::ref_cfg, dfll_config::ssg, dfll_config::step, and dfll_config::val.
Referenced by main().
|
inlinestatic |
Set initial VCO tuning.
In open loop mode, this will determine the frequency of the output.
In closed loop mode, this will provide an initial estimate of the VCO tuning. While the DFLL will automatically adjust these values to match the desired output frequency, careful selection of initial values might reduce the time to achieve coarse and fine lock.
cfg | The DFLL configuration to be modified. |
coarse | Coarse tuning of the frequency generator. |
fine | Fine tuning of the frequency generator. |
References dfll_config::val.
Referenced by dfll_config_tune_for_target_hz().
|
inlinestatic |
Set the maximum VCO tuning step size.
This function has no effect in open-loop mode.
By default, both of these values are set to 50% of their respective maximums. It is not recommended to set the values any higher than this, but setting them lower might reduce the frequency overshoot at the expense of longer time to achieve coarse and/or fine lock.
cfg | The DFLL configuration to be modified |
coarse | The maximum step size of the coarse VCO tuning. |
fine | The maximum step size of the fine VCO tuning. |
References dfll_config::step.
|
inlinestatic |
Tune the DFLL configuration for a specific target frequency.
This will set the initial coarse and fine DFLL tuning to match the given target frequency. In open loop mode, this will cause the DFLL to run close to the specified frequency, though it may not match exactly. In closed loop mode, the DFLL will automatically tune itself to the target frequency regardless of the initial tuning, but this function may be used to set a starting point close to the desired frequency in order to reduce the startup time.
\begin{eqnarray*} f_{DFLL} &=& \left[f_{min} + \left(f_{max} - f_{min}\right) \frac{\mathrm{COARSE}}{\mathrm{COARSE}_{max}}\right] \left(1 + x \frac{\mathrm{FINE} - \mathrm{FINE}_{half}}{\mathrm{FINE}_{max}}\right) = f_{coarse} \left(1 + x \frac{\mathrm{FINE} - \mathrm{FINE}_{half}}{\mathrm{FINE}_{max}}\right) \\ \mathrm{COARSE} &=& \frac{\left(f_{DFLL} - f_{min}\right)} {f_{max} - f_{min}} \mathrm{COARSE}_{max} \\ f_{coarse} &=& f_{min} + \left(f_{max} - f_{min}\right) \frac{\mathrm{COARSE}}{\mathrm{COARSE}_{max}} \\ \mathrm{FINE} &=& \left(10 \frac{f_{DFLL} - f_{coarse}} {f_{coarse}} + \mathrm{FINE}_{half}\right) / 4 \end{eqnarray*}
cfg | The DFLL configuration to be tuned. |
target_hz | Target frequency in Hz. |
References DFLL_COARSE_MAX, dfll_config_set_initial_tuning(), DFLL_FINE_HALF, DFLL_FINE_MAX, DFLL_MAX_KHZ, DFLL_MIN_KHZ, and dfll_priv_set_frequency_range().
Referenced by main().
void dfll_disable_closed_loop | ( | uint32_t | dfll_id | ) |
References dfll_write_reg, genclk_disable(), and UNUSED.
Referenced by cleanup_pll_dfll_test(), and main().
void dfll_disable_open_loop | ( | uint32_t | dfll_id | ) |
References dfll_write_reg, genclk_disable(), and UNUSED.
Referenced by main().
void dfll_enable_closed_loop | ( | const struct dfll_config * | cfg, |
uint32_t | dfll_id | ||
) |
References dfll_config::conf, cpu_irq_restore(), cpu_irq_save(), dfll_write_reg, genclk_enable(), dfll_config::mul, dfll_config::ref_cfg, dfll_config::ssg, dfll_config::step, and UNUSED.
Referenced by dfll_enable_config_defaults(), main(), and run_pll_dfll_test().
void dfll_enable_config_defaults | ( | uint32_t | dfll_id | ) |
void dfll_enable_open_loop | ( | const struct dfll_config * | cfg, |
uint32_t | dfll_id | ||
) |
References dfll_config::conf, cpu_irq_restore(), cpu_irq_save(), dfll_write_reg, dfll_config::mul, dfll_config::ssg, UNUSED, and dfll_config::val.
Referenced by main().
|
inlinestatic |
Enable the source of the dfll.
The source is enabled, if the source is not already running.
dfll_source | src The ID of the DFLL source to enable. |
References Assert, GENCLK_SRC_OSC0, GENCLK_SRC_OSC32K, GENCLK_SRC_RC32K, GENCLK_SRC_RC80M, GENCLK_SRC_RCSYS, osc_enable(), OSC_ID_OSC0, OSC_ID_OSC32, OSC_ID_RC32K, OSC_ID_RC80M, osc_is_ready(), and osc_wait_ready().
Referenced by dfll_enable_config_defaults().
|
inlinestatic |
References dfll_is_coarse_locked(), dfll_is_fine_locked(), and UNUSED.
Referenced by dfll_wait_for_accurate_lock().
|
inlinestatic |
References UNUSED.
Referenced by dfll_is_accurate_locked(), and dfll_wait_for_coarse_lock().
|
inlinestatic |
References UNUSED.
Referenced by dfll_enable_config_defaults(), dfll_is_accurate_locked(), dfll_wait_for_fine_lock(), and run_pll_dfll_test().
|
inlinestatic |
|
inlinestatic |
References dfll_config::conf, DFLL_MAX_RANGE1, DFLL_MAX_RANGE2, DFLL_MAX_RANGE3, DFLL_RANGE0, DFLL_RANGE1, DFLL_RANGE2, DFLL_RANGE3, and dfll_config::freq_range.
Referenced by dfll_config_tune_for_target_hz().
|
inlinestatic |
Wait for the DFLL identified by dfll_id to achieve accurate lock.
dfll_id | The ID of the DFLL to wait for. |
STATUS_OK | The DFLL has achieved accurate lock. |
ERR_TIMEOUT | Timed out waiting for lock. |
References dfll_is_accurate_locked().
|
inlinestatic |
Wait for the DFLL identified by dfll_id to achieve coarse lock.
dfll_id | The ID of the DFLL to wait for. |
STATUS_OK | The DFLL has achieved coarse lock. |
ERR_TIMEOUT | Timed out waiting for lock. |
References dfll_is_coarse_locked().
|
inlinestatic |
Wait for the DFLL identified by dfll_id to achieve fine lock.
dfll_id | The ID of the DFLL to wait for. |
STATUS_OK | The DFLL has achieved fine lock. |
ERR_TIMEOUT | Timed out waiting for lock. |
References dfll_is_fine_locked().
Referenced by main().