pm_conf_clocks.c File Reference


Detailed Description

Power Manager clocks configuration helper.

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

Definition in file pm_conf_clocks.c.

#include <string.h>
#include "compiler.h"
#include "pm.h"

Go to the source code of this file.

Defines

#define PM_MAX_MUL   ((1 << AVR32_PM_PLL0_PLLMUL_SIZE) - 1)

Functions

void flashc_set_wait_state (unsigned int wait_state)
int pm_configure_clocks (pm_freq_param_t *param)
 Automatically configure the CPU, PBA, PBB, and HSB clocks according to the user wishes.
void pm_configure_usb_clock (void)
 Automatically configure the USB clock.


Define Documentation

#define PM_MAX_MUL   ((1 << AVR32_PM_PLL0_PLLMUL_SIZE) - 1)

Definition at line 57 of file pm_conf_clocks.c.

Referenced by pm_configure_clocks().


Function Documentation

void flashc_set_wait_state ( unsigned int  wait_state  ) 

int pm_configure_clocks ( pm_freq_param_t param  ) 

Automatically configure the CPU, PBA, PBB, and HSB clocks according to the user wishes.

This function needs some parameters stored in a pm_freq_param_t structure:

  • cpu_f and pba_f are the wanted frequencies,
  • osc0_f is the oscillator 0 on-board frequency (e.g. FOSC0),
  • osc0_startup is the oscillator 0 startup time (e.g. OSC0_STARTUP).

The function will then configure the clocks using the following rules:

  • It first try to find a valid PLL frequency (the highest possible value to avoid jitter) in order to satisfy the CPU frequency,
  • It optimizes the configuration depending the various divide stages,
  • Then, the PBA frequency is configured from the CPU freq.
  • Note that HSB and PBB are configured with the same frequency as CPU.
  • Note also that the number of wait states of the flash read accesses is automatically set-up depending the CPU frequency. As a consequence, the application needs the FLASHC driver to compile.

The CPU, HSB and PBA frequencies programmed after configuration are stored back into cpu_f and pba_f.

Parameters:
param pointer on the configuration structure.
Return values:
PM_FREQ_STATUS_OK Mode successfully initialized.
PM_FREQ_STATUS_FAIL The configuration can not be done.

Definition at line 60 of file pm_conf_clocks.c.

References pm_freq_param_t::cpu_f, flashc_set_wait_state(), pm_freq_param_t::osc0_f, pm_freq_param_t::osc0_startup, pm_freq_param_t::pba_f, pm_cksel(), PM_FREQ_STATUS_FAIL, PM_FREQ_STATUS_OK, PM_MAX_MUL, pm_pll_enable(), pm_pll_set_option(), pm_pll_setup(), pm_switch_to_clock(), pm_switch_to_osc0(), and pm_wait_for_pll0_locked().

Referenced by pcl_configure_clocks().

00061 {
00062   // Supported frequencies:
00063   // Fosc0 mul div PLL div2_en cpu_f pba_f   Comment
00064   //  12   15   1  192     1     12    12
00065   //  12    9   3   40     1     20    20    PLL out of spec
00066   //  12   15   1  192     1     24    12
00067   //  12    9   1  120     1     30    15
00068   //  12    9   3   40     0     40    20    PLL out of spec
00069   //  12   15   1  192     1     48    12
00070   //  12   15   1  192     1     48    24
00071   //  12    8   1  108     1     54    27
00072   //  12    9   1  120     1     60    15
00073   //  12    9   1  120     1     60    30
00074   //  12   10   1  132     1     66    16.5
00075   //
00076   unsigned long in_cpu_f  = param->cpu_f;
00077   unsigned long in_osc0_f = param->osc0_f;
00078   unsigned long mul, div, div2_en = 0, div2_cpu = 0, div2_pba = 0;
00079   unsigned long pll_freq, rest;
00080   Bool b_div2_pba, b_div2_cpu;
00081 
00082   // Switch to external Oscillator 0
00083   pm_switch_to_osc0(&AVR32_PM, in_osc0_f, param->osc0_startup);
00084 
00085   // Start with CPU freq config
00086   if (in_cpu_f == in_osc0_f)
00087   {
00088     param->cpu_f = in_osc0_f;
00089     param->pba_f = in_osc0_f;
00090     return PM_FREQ_STATUS_OK;
00091   }
00092   else if (in_cpu_f < in_osc0_f)
00093   {
00094     // TBD
00095   }
00096 
00097   rest = in_cpu_f % in_osc0_f;
00098 
00099   for (div = 1; div < 32; div++)
00100   {
00101     if ((div * rest) % in_osc0_f == 0)
00102       break;
00103   }
00104   if (div == 32)
00105     return PM_FREQ_STATUS_FAIL;
00106 
00107   mul = (in_cpu_f * div) / in_osc0_f;
00108 
00109   if (mul > PM_MAX_MUL)
00110     return PM_FREQ_STATUS_FAIL;
00111 
00112   // export 2power from PLL div to div2_cpu
00113   while (!(div % 2))
00114   {
00115     div /= 2;
00116     div2_cpu++;
00117   }
00118 
00119   // Here we know the mul and div parameter of the PLL config.
00120   // . Check out if the PLL has a valid in_cpu_f.
00121   // . Try to have for the PLL frequency (VCO output) the highest possible value
00122   //   to reduce jitter.
00123   while (in_osc0_f * 2 * mul / div < AVR32_PM_PLL_VCO_RANGE0_MAX_FREQ)
00124   {
00125     if (2 * mul > PM_MAX_MUL)
00126       break;
00127     mul *= 2;
00128     div2_cpu++;
00129   }
00130 
00131   if (div2_cpu != 0)
00132   {
00133     div2_cpu--;
00134     div2_en = 1;
00135   }
00136 
00137   pll_freq = in_osc0_f * mul / (div * (1 << div2_en));
00138 
00139   // Update real CPU Frequency
00140   param->cpu_f = pll_freq / (1 << div2_cpu);
00141   mul--;
00142 
00143   pm_pll_setup(&AVR32_PM
00144   , 0   // pll
00145   , mul // mul
00146   , div // div
00147   , 0   // osc
00148   , 16  // lockcount
00149   );
00150 
00151   pm_pll_set_option(&AVR32_PM
00152   , 0 // pll
00153   // PLL clock is lower than 160MHz: need to set pllopt.
00154   , (pll_freq < AVR32_PM_PLL_VCO_RANGE0_MIN_FREQ) ? 1 : 0 // pll_freq
00155   , div2_en // pll_div2
00156   , 0 // pll_wbwdisable
00157   );
00158 
00159   rest = pll_freq;
00160   while (rest > AVR32_PM_PBA_MAX_FREQ ||
00161          rest != param->pba_f)
00162   {
00163     div2_pba++;
00164     rest = pll_freq / (1 << div2_pba);
00165     if (rest < param->pba_f)
00166       break;
00167   }
00168 
00169   // Update real PBA Frequency
00170   param->pba_f = pll_freq / (1 << div2_pba);
00171 
00172   // Enable PLL0
00173   pm_pll_enable(&AVR32_PM, 0);
00174 
00175   // Wait for PLL0 locked
00176   pm_wait_for_pll0_locked(&AVR32_PM);
00177 
00178   if (div2_cpu)
00179   {
00180     b_div2_cpu = TRUE;
00181     div2_cpu--;
00182   }
00183   else
00184     b_div2_cpu = FALSE;
00185 
00186   if (div2_pba)
00187   {
00188     b_div2_pba = TRUE;
00189     div2_pba--;
00190   }
00191   else
00192     b_div2_pba = FALSE;
00193 
00194   pm_cksel(&AVR32_PM
00195   , b_div2_pba, div2_pba // PBA
00196   , b_div2_cpu, div2_cpu // PBB
00197   , b_div2_cpu, div2_cpu // HSB
00198   );
00199 
00200   if (param->cpu_f > AVR32_FLASHC_FWS_0_MAX_FREQ)
00201   {
00202     flashc_set_wait_state(1);
00203 #if (defined AVR32_FLASHC_210_H_INCLUDED)
00204     if (param->cpu_f > AVR32_FLASHC_HSEN_FWS_1_MAX_FREQ)
00205       flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSEN, -1);
00206     else
00207       flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1);
00208 #endif
00209   }
00210   else
00211   {
00212     flashc_set_wait_state(0);
00213 #if (defined AVR32_FLASHC_210_H_INCLUDED)
00214     if (param->cpu_f > AVR32_FLASHC_HSEN_FWS_0_MAX_FREQ)
00215       flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSEN, -1);
00216     else
00217       flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1);
00218 #endif
00219   }
00220 
00221   pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCCTRL_MCSEL_PLL0);
00222 
00223   return PM_FREQ_STATUS_OK;
00224 }

void pm_configure_usb_clock ( void   ) 

Automatically configure the USB clock.

USB clock is configured to 48MHz, using the PLL1 from the Oscillator0, assuming a 12 MHz crystal is connected to it.

Definition at line 227 of file pm_conf_clocks.c.

References pm_gc_enable(), pm_gc_setup(), pm_pll_enable(), pm_pll_set_option(), pm_pll_setup(), and pm_wait_for_pll1_locked().

Referenced by pcl_configure_usb_clock().

00228 {
00229 #if UC3A3
00230 
00231   // Setup USB GCLK.
00232   pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_USBB, // gc
00233                   0,                  // osc_or_pll: use Osc (if 0) or PLL (if 1)
00234                   0,                  // pll_osc: select Osc0/PLL0 or Osc1/PLL1
00235                   0,                  // diven
00236                   0);                 // div
00237 
00238   // Enable USB GCLK.
00239   pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_USBB);
00240 #else
00241   // Use 12MHz from OSC0 and generate 96 MHz
00242   pm_pll_setup(&AVR32_PM, 1,  // pll.
00243       7,   // mul.
00244       1,   // div.
00245       0,   // osc.
00246       16); // lockcount.
00247 
00248   pm_pll_set_option(&AVR32_PM, 1, // pll.
00249       1,  // pll_freq: choose the range 80-180MHz.
00250       1,  // pll_div2.
00251       0); // pll_wbwdisable.
00252 
00253   // start PLL1 and wait forl lock
00254   pm_pll_enable(&AVR32_PM, 1);
00255 
00256   // Wait for PLL1 locked.
00257   pm_wait_for_pll1_locked(&AVR32_PM);
00258 
00259   pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_USBB,  // gc.
00260             1,  // osc_or_pll: use Osc (if 0) or PLL (if 1).
00261             1,  // pll_osc: select Osc0/PLL0 or Osc1/PLL1.
00262             0,  // diven.
00263             0); // div.
00264   pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_USBB);
00265 #endif
00266 }


Generated on Fri Feb 19 02:26:06 2010 for AVR32 UC3 - Power Manager Driver Example 2 by  doxygen 1.5.5