📄 clock_switching.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.c
//* Object : Driver to switch the clock source in the AT91M55800A
//*
//* 1.0 08/01/01 S.C : Creation
//* 1.1 05/mar/03/JPP : Port for new include
//* Note : The switching times are specified in he software.
//*----------------------------------------------------------------------------
/*------------------ Files to be included Definition ------------------------*/
#include "eb55.h"
#include "clock_switching.h"
/*----- Assembler Handler files for SLCKIRQ and APMC interrupt source ----------*/
extern void osc32k_asm_handler (void) ; //* .asm handler
extern void osc32k_osc16m_asm_handler (void) ; //* .asm handler
extern void osc32k_pll_asm_handler (void) ; //* .asm handler
/*---------------------------- Global Variable ------------------------------*/
char switching_conducted = 0 ; //* Allows to know when the switching is achieved
//*-----------------------------------------------------------------------------
//* --------------------------- Interrupt Function ----------------------------
//*-----------------------------------------------------------------------------
//*----------------------------------------------------------------------------
//* Function Name : osc32k_c_handler
//* Object : C Handler to switch to 32kHz oscillator and stop other
//* : sources
//* Input Parameters : none
//* Output Parameters : none
//*----------------------------------------------------------------------------
void osc32k_c_handler (void)
{
AT91PS_APMC pAPMC = AT91C_BASE_APMC;
//* Shutdown the PLL by default
pAPMC->APMC_CGMR = (pAPMC->APMC_CGMR & (~MAX_MUL) ) ;
//* Shutdown the Main Oscillator by default
pAPMC->APMC_CGMR = (pAPMC->APMC_CGMR & (~APMC_MOSC_EN)) ;
AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_SLCK);
switching_conducted = TRUE ;
}
//*----------------------------------------------------------------------------
//* Function Name : osc32k_osc16m_c_handler
//* Object : C Handler to switch to 32k oscillator before to switch
//* : to 16 MHz and shutdown the PLL.
//* Input Parameters : none
//* Output Parameters : none
//*----------------------------------------------------------------------------
void osc32k_osc16m_c_handler (void)
{
unsigned int apmc_cgmr_status ;
AT91PS_APMC pAPMC = AT91C_BASE_APMC;
//* Shutdown the PLL by default
pAPMC->APMC_CGMR = (pAPMC->APMC_CGMR & (~MAX_MUL) ) ;
//* APMC_CGMR reading
apmc_cgmr_status = pAPMC->APMC_CGMR ;
//* Switching to the HF output oscillator
pAPMC->APMC_CGMR = ( apmc_cgmr_status | APMC_CSS_MOSC) ;
AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_SLCK);
switching_conducted = TRUE ;
}
//*----------------------------------------------------------------------------
//* Function Name : osc32k_pll_c_handler
//* Object : C Handler to switch to 32k oscillator before to switch
//* : to PLL output.
//* Input Parameters : none
//* Output Parameters : none
//*----------------------------------------------------------------------------
void osc32k_pll_c_handler (void)
{
AT91PS_APMC pAPMC = AT91C_BASE_APMC;
pAPMC->APMC_CGMR =( pAPMC->APMC_CGMR | APMC_CSS_PLL ) ;
AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_SLCK);
switching_conducted = TRUE ;
}
//*-----------------------------------------------------------------------------
//* ---------------------------- External Function ----------------------------
//*-----------------------------------------------------------------------------
//*----------------------------------------------------------------------------
//* Function Name : set_Prescaler
//* Object : Set the Prescaler with Erata
//* Input Parameters : none
//* Output Parameters : none
//*----------------------------------------------------------------------------
void set_Prescaler (unsigned int Prescaler)
{
unsigned int i;
AT91PS_APMC pAPMC = AT91C_BASE_APMC;
pAPMC->APMC_CGMR =( pAPMC->APMC_CGMR & (~MASK_PRESCALER) ) | (0X01 << SHIFT_PRESCALER);
for( i=0; i<64 ;i++){}
pAPMC->APMC_CGMR =( pAPMC->APMC_CGMR & (~MASK_PRESCALER) )| (Prescaler << SHIFT_PRESCALER) ;
}
//*----------------------------------------------------------------------------
//* 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).
//* Output Parameters : None
//*----------------------------------------------------------------------------
void mck_clock_speed (short target_source, char frequency_multiplier)
{
unsigned int apmc_cgmr_status ;
unsigned int switch_choice ;
AT91PS_APMC pAPMC = AT91C_BASE_APMC;
switching_conducted = FALSE ;
frequency_multiplier = frequency_multiplier - 1 ;
apmc_cgmr_status = pAPMC->APMC_CGMR ; //* APMC_CGMR reading NEW
switch_choice = apmc_cgmr_status & CSS_MASK ;
switch (switch_choice)
{
case APMC_CSS_LF: //* The actual source clock is the LF osc.
switch (target_source)
{
case TO_LF_OSCILLATOR : //* It's the actual clock source
break ;
case TO_HF_OSCILLATOR : //* To the HF osc.(Switching Time = 15.5 ms)
apmc_cgmr_status |= APMC_MOSC_EN ;
//* Main oscillator start-up
pAPMC->APMC_CGMR =( apmc_cgmr_status ) ;
/* It's no good to enable interrupt because the handling by interrupt, approximately , cost
the same time (32kHz clock) that the oscillator startup */
while ((pAPMC->APMC_SR & APMC_MOSCS) == 0) {} ;
//* Switching to the HF output oscillator
pAPMC->APMC_CGMR = ( apmc_cgmr_status | APMC_CSS_MOSC ) ;
break ;
case TO_PLL_OUTPUT : //* To the PLL output ((Switching Time = 18 ms
apmc_cgmr_status |= APMC_MOSC_EN ;
//* First part : Main oscillator start-up
pAPMC->APMC_CGMR = ( apmc_cgmr_status ) ;
while ((pAPMC->APMC_SR & APMC_MOSCS) ==0 ) {} ;
//* Second part : PLL starting
apmc_cgmr_status |= (frequency_multiplier <<B_MUL) ;
pAPMC->APMC_CGMR = ( apmc_cgmr_status ) ;
while ((pAPMC->APMC_SR & APMC_PLL_LOCK) ==0 ) {} ;
pAPMC->APMC_CGMR = ( apmc_cgmr_status | APMC_CSS_PLL ) ;
break ;
}
break ;
case APMC_CSS_MOSC: //* The actual source clock is the HF osc.
switch (target_source)
{
case TO_LF_OSCILLATOR : //* To the LF osc.(Switching Time = 14 ms)
//* Switching from interrupt event (SLCKIRQ)
//* open Usart 0 interrupt
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_SLCK, MCK_INTERRUPT_LEVEL,AIC_SRCTYPE_EXT_LOW_LEVEL, osc32k_asm_handler);
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SLCK);
apmc_cgmr_status &= ~CSS_MASK ;
//* Switching to the HF output oscillator
pAPMC->APMC_CGMR = ( apmc_cgmr_status ) ;
while (switching_conducted != TRUE ) {} ;
break ;
case TO_HF_OSCILLATOR : //* It's the actual clock source
break ;
case TO_PLL_OUTPUT ://* To the PLL output(Switching Time = 5.8 ms with
/* First: PLL start-up */
apmc_cgmr_status |= (frequency_multiplier << B_MUL) ;
pAPMC->APMC_CGMR = ( apmc_cgmr_status ) ;
while ((pAPMC->APMC_SR & APMC_PLL_LOCK) ==0 ) {} ;
/* Second: switching to 32 kHz */
apmc_cgmr_status &= ~CSS_MASK ;
/* Switching to the LF output oscillator */
pAPMC->APMC_CGMR = ( apmc_cgmr_status ) ;
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_SLCK, MCK_INTERRUPT_LEVEL,AIC_SRCTYPE_EXT_LOW_LEVEL, osc32k_pll_asm_handler);
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SLCK);
while (switching_conducted != TRUE ) {} ;
break ;
}
break ;
case APMC_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)
/* Switching when the dedicated interrupt occures */
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_SLCK, MCK_INTERRUPT_LEVEL,AIC_SRCTYPE_EXT_LOW_LEVEL, osc32k_asm_handler);
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SLCK);
apmc_cgmr_status &= ~CSS_MASK ;
/* Switching to the LF output oscillator */
pAPMC->APMC_CGMR = ( apmc_cgmr_status ) ;
while (switching_conducted != TRUE ) {} ;
break ;
case TO_HF_OSCILLATOR : //* To the HF osc.(Switching Time = 7 ms)
//* Switching from interrupt event (32k_mode)
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_SLCK, MCK_INTERRUPT_LEVEL,AIC_SRCTYPE_EXT_LOW_LEVEL, osc32k_osc16m_asm_handler);
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SLCK);
apmc_cgmr_status &= ~CSS_MASK ;
//* Switching to the LF output oscillator
pAPMC->APMC_CGMR = ( apmc_cgmr_status ) ;
while (switching_conducted != TRUE ) {} ;
break ;
case TO_PLL_OUTPUT : //* It's the actual clock source
//* Second part : PLL starting
apmc_cgmr_status = (apmc_cgmr_status & (~MAX_MUL))|(frequency_multiplier <<B_MUL) ;
pAPMC->APMC_CGMR = ( apmc_cgmr_status ) ;
break ;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -