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 58 of file pm_conf_clocks.c.

Referenced by pm_configure_clocks().


Function Documentation

void flashc_set_wait_state ( unsigned int  wait_state  ) 

Referenced by pm_configure_clocks().

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 61 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().

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

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 228 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().

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


Generated on Thu Dec 17 19:58:59 2009 for AVR32 UC3 - Power Manager Driver Example 1 by  doxygen 1.5.5