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.
- Example: Setting up DFLL0 with default parameters and dithering enabled
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.
dfll_config_enable_dithering(&dfllcfg);
dfll_enable(&dfllcfg, 0);
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.
#define DFLL_CALIB_VALUE (0x0B) |
#define DFLL_COARSE_MAX (255) |
#define dfll_config_defaults |
( |
|
cfg, |
|
|
|
dfll_id |
|
) |
| |
Value:dfll_config_init_closed_loop_mode(cfg, \
CONFIG_DFLL##dfll_id##_SOURCE, \
CONFIG_DFLL##dfll_id##_DIV, \
CONFIG_DFLL##dfll_id##_MUL)
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.
- Parameters
-
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) |
#define DFLL_FINE_MAX (511) |
#define dfll_get_default_rate |
( |
|
dfll_id | ) |
|
Value:
* CONFIG_DFLL##dfll_id##_MUL) \
/ CONFIG_DFLL##dfll_id##_DIV)
static uint32_t dfll_priv_get_source_hz(dfll_refclk_t src)
Definition: sam4l/dfll.h:164
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_RANGE1 (110000000) |
#define DFLL_MAX_RANGE2 (55000000) |
#define DFLL_MAX_RANGE3 (30000000) |
#define DFLL_MIN_HZ 20000000UL |
Minimum frequency that the DFLL can generate.
Type used for identifying a reference clock source for the DFLL.
void dfll_config_disable_ssg |
( |
struct dfll_config * |
cfg | ) |
|
|
inlinestatic |
Disable Spread Spectrum Generator.
- Parameters
-
cfg | The DFLL configuration to be modified. |
References dfll_config::ssg.
void dfll_config_enable_ssg |
( |
struct dfll_config * |
cfg, |
|
|
uint16_t |
amplitude, |
|
|
uint16_t |
step_size |
|
) |
| |
|
inlinestatic |
Enable Spread Spectrum Generator.
- Parameters
-
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.
void dfll_config_init_open_loop_mode |
( |
struct dfll_config * |
cfg | ) |
|
|
inlinestatic |
void dfll_config_set_initial_tuning |
( |
struct dfll_config * |
cfg, |
|
|
uint16_t |
coarse, |
|
|
uint16_t |
fine |
|
) |
| |
|
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.
- Parameters
-
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().
void dfll_config_set_max_step |
( |
struct dfll_config * |
cfg, |
|
|
uint16_t |
coarse, |
|
|
uint16_t |
fine |
|
) |
| |
|
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.
- Parameters
-
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.
static void dfll_config_tune_for_target_hz |
( |
struct dfll_config * |
cfg, |
|
|
uint32_t |
target_hz |
|
) |
| |
|
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.
- Calculating the DFLL frequency
\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*}
- Parameters
-
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().
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 |
|
) |
| |
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(), 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 |
|
) |
| |
Enable the source of the dfll.
The source is enabled, if the source is not already running.
- Parameters
-
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().
static bool dfll_is_accurate_locked |
( |
uint32_t |
dfll_id | ) |
|
|
inlinestatic |
static bool dfll_is_coarse_locked |
( |
uint32_t |
dfll_id | ) |
|
|
inlinestatic |
static bool dfll_is_fine_locked |
( |
uint32_t |
dfll_id | ) |
|
|
inlinestatic |
static void dfll_priv_set_frequency_range |
( |
struct dfll_config * |
cfg, |
|
|
uint32_t |
freq |
|
) |
| |
|
inlinestatic |
static int dfll_wait_for_accurate_lock |
( |
unsigned int |
dfll_id | ) |
|
|
inlinestatic |
Wait for the DFLL identified by dfll_id to achieve accurate lock.
- Parameters
-
dfll_id | The ID of the DFLL to wait for. |
- Return values
-
STATUS_OK | The DFLL has achieved accurate lock. |
ERR_TIMEOUT | Timed out waiting for lock. |
References dfll_is_accurate_locked().
static int dfll_wait_for_coarse_lock |
( |
unsigned int |
dfll_id | ) |
|
|
inlinestatic |
Wait for the DFLL identified by dfll_id to achieve coarse lock.
- Parameters
-
dfll_id | The ID of the DFLL to wait for. |
- Return values
-
STATUS_OK | The DFLL has achieved coarse lock. |
ERR_TIMEOUT | Timed out waiting for lock. |
References dfll_is_coarse_locked().
static int dfll_wait_for_fine_lock |
( |
unsigned int |
dfll_id | ) |
|
|
inlinestatic |
Wait for the DFLL identified by dfll_id to achieve fine lock.
- Parameters
-
dfll_id | The ID of the DFLL to wait for. |
- Return values
-
STATUS_OK | The DFLL has achieved fine lock. |
ERR_TIMEOUT | Timed out waiting for lock. |
References dfll_is_fine_locked().