📄 clock_switching_driver.c
字号:
//*----------------------------------------------------------------------------
//* ATMEL Microcontroller Software Support - ROUSSET -
//*----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*----------------------------------------------------------------------------
//* File Name : clock_switching_driver.c
//* Object : Driver to switch the clock source in the AT91M42800A
//*
//* 1.0 08/01/01 S.C : Creation
//* Note : The switching times are specified in the software.
//* 1.1 09/07/01 PF : Add Prescaler setting.
//*----------------------------------------------------------------------------
/*------------------ Files to be included Definition ------------------------*/
#include "parts/m42800/lib_m42800.h"
#include "periph/power_saving/lib_power_save.h"
#include "clock_switching_driver.h"
/*---------------------------- Global Variable ------------------------------*/
char switching_conducted = 0 ; //* Allows to know when the switching is achieved
//*----------------------------------------------------------------------------
//* Function Name : Prescaler_switching
//* Object : Prescaler switching
//* Input Parameters : <pres> Prescaler value (2 to 64)
//* Output Parameters : none
//*----------------------------------------------------------------------------
void prescaler_switching (int pres)
{
u_int PMC_cgmr_temp ;
if (pres == PMC_PRES_NONE)
{
PMC_cgmr_temp = ((at91_clock_generator_state () & 0xFFFFFFF0 ) | PMC_PRES_NONE ) ;
PMC_BASE->PMC_CGMR = PMC_cgmr_temp ;
}
if (pres == PMC_PRES_DIV2)
{
PMC_cgmr_temp = ((at91_clock_generator_state () & 0xFFFFFFF0) | PMC_PRES_DIV2 ) ;
PMC_BASE->PMC_CGMR = PMC_cgmr_temp ;
}
if (pres == PMC_PRES_DIV4)
{
PMC_cgmr_temp = ((at91_clock_generator_state () & 0xFFFFFFF0) | PMC_PRES_DIV4 ) ;
PMC_BASE->PMC_CGMR = PMC_cgmr_temp ;
}
if (pres == PMC_PRES_DIV8)
{
PMC_cgmr_temp = ((at91_clock_generator_state () & 0xFFFFFFF0) | PMC_PRES_DIV8 ) ;
PMC_BASE->PMC_CGMR = PMC_cgmr_temp ;
}
if (pres == PMC_PRES_DIV16)
{
PMC_cgmr_temp = ((at91_clock_generator_state () & 0xFFFFFFF0) | PMC_PRES_DIV16 ) ;
PMC_BASE->PMC_CGMR = PMC_cgmr_temp ;
}
if (pres == PMC_PRES_DIV32)
{
PMC_cgmr_temp = ((at91_clock_generator_state () & 0xFFFFFFF0) | PMC_PRES_DIV32 ) ;
PMC_BASE->PMC_CGMR = PMC_cgmr_temp ;
}
if (pres == PMC_PRES_DIV64)
{
PMC_cgmr_temp = ((at91_clock_generator_state () & 0xFFFFFFF0) | PMC_PRES_DIV64 ) ;
PMC_BASE->PMC_CGMR = PMC_cgmr_temp ;
}
}
//*----------------------------------------------------------------------------
//* Function Name : mck_clock_speed
//* Object : Driver to choice the clock source and the PLL
//* frequency output
//* Input Parameters :<target_source> clock source
//* 'source' = 0 : low frequency oscillator output => MCK
//* 'source' = 1 : main oscillator output => MCK
//* 'source' = 2 : PLL output =MCK
//* <frequency_multiplier> allows to multiply the main
//* oscillator frequency ( field B_MUL +1).
//* : pres = Prescaler NEW.
//* Output Parameters : None
//*----------------------------------------------------------------------------
void mck_clock_speed (short target_source, u_int frequency_multiplier, u_int prescaler)
{
u_int pmc_cgmr_status ;
u_int switch_choice ;
u_int loop ;
switching_conducted = FALSE ;
frequency_multiplier = frequency_multiplier - 1 ;
pmc_cgmr_status = at91_clock_generator_state () ; //* PMC_CGMR reading NEW
switch_choice = pmc_cgmr_status & CSS_MASK ;
switch (switch_choice)
{
case PMC_CSS_LF: //* The actual source clock is the LF osc.
switch (target_source)
{
case TO_LF_OSCILLATOR : //* It's the actual clock source
prescaler_switching (prescaler);
break ;
case TO_PLL_OUTPUT : //* To the PLL output ((Switching Time = 18 ms
//* with PLLCOUNT = 3 and
//* OSCOUNT = 0x2f)
frequency_multiplier = (frequency_multiplier <<B_MUL) ;
pmc_cgmr_status &= 0xFFF000FF ;
pmc_cgmr_status |= frequency_multiplier ;
at91_clock_generator_mode ( pmc_cgmr_status ) ;
while ((at91_clock_get_pll_status () & PMC_PLL_LOCK) ==0 ) {} ;
at91_clock_generator_mode ( pmc_cgmr_status | PMC_CSS_PLL ) ;
prescaler_switching (prescaler);
break ;
}
break ;
case PMC_CSS_PLL: //* The actual source clock is the internal PLL
switch (target_source)
{
case TO_LF_OSCILLATOR : //* To the LF osc.(Switching Time = 14 ms)
pmc_cgmr_status &= ~CSS_MASK ;
/* Switching to the LF output oscillator */
at91_clock_generator_mode ( pmc_cgmr_status ) ;
for (loop = 5000; loop > 0; loop--);
pmc_cgmr_status &= ~0x7FF00 ;
at91_clock_generator_mode ( pmc_cgmr_status ) ;
prescaler_switching (prescaler);
break ;
case TO_PLL_OUTPUT : //* It's the actual clock source
/* First: PLL start-up */
frequency_multiplier = (frequency_multiplier <<B_MUL) ;
pmc_cgmr_status &= 0xFFF000FF ;
pmc_cgmr_status |= frequency_multiplier ;
at91_clock_generator_mode ( pmc_cgmr_status ) ;
while ((at91_clock_get_pll_status () & PMC_PLL_LOCK) ==0 ) {} ;
prescaler_switching (prescaler);
break ;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -