⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 init.c

📁 at91rm9200的启动代码,开发环境ads1.2,这是本人学习过程中产生de
💻 C
📖 第 1 页 / 共 2 页
字号:
//*----------------------------------------------------------------------------
//*         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           : init.c
//* Object              : Low level initialisations written in C
//* Creation            : ODi   06/26/2002
//*
//*----------------------------------------------------------------------------

#include "AT91RM9200.h"
#include "lib_AT91RM9200.h"


// [DOC1768.PDF 23.6.9 PMC Clock Generator PLL A Register]
//    31   30   29   28   27   26   25   24   23   22   21   20   19   18   17   16
//  +----+----+----+----+----+------------------------------------------------------+
//  | -  | -  | -  | -  | -  |                   MULA                               |
//  +----+----+----+----+----+------------------------------------------------------+
//
//    15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
//  +---------+-----------------------------+---------------------------------------+
//  |   OUTA  |       PLLACOUNT             |               DIVA                    |
//  +---------+-----------------------------+---------------------------------------+
//
//  :DIVA: Divider A
//     0       = Divider output is 0
//     1       = Divider is bypassed
//     2 - 255 = Divider output is the Main Clock divided by DIVA.
//
//  :PLLACOUNT: PLL A Counter
//     Specifies the number of Slow Clock cycles before the LOCKA bit is set in PMC_SR
//     after CKGR_PLLAR is written.
//
//  :OUTA: PLL A Clock Frequency Range
//     0 0 : 80 MHz to 160 MHz
//     0 1 : Reserved
//     1 0 : 150 MHz to 240 MHz
//     1 1 : Reserved
//
//  :MULA: PLL A Multiplier
//    0            = The PLL A is deactivated.
//    1 up to 2047 = The PLL A Clock frequency is the PLL A input frequency multiplied by MULA + 1.


// [DOC1768.PDF 23.6.11 PMC Master Clock Register]
//    31   30   29   28   27   26   25   24   23   22   21   20   19   18   17   16
//  +-------------------------------------------------------------------------------+
//  |                                    -                                          |
//  +-------------------------------------------------------------------------------+
//
//    15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
//  +-----------------------------+---------+--------------+--------------+---------+
//  |           -                 |   MDIV  |      -       |      PRES    |   CSS   |
//  +-----------------------------+---------+--------------+--------------+---------+
//
//  :CSS: Master Clock Selection
//     0 0 = Slow Clock is selected
//     0 1 = Main Clock is selected
//     1 0 = PLL A Clock is selected
//     1 1 = PLL B Clock is selected
//
//  :PRES: Master Clock Prescaler
//     0 0 0 = Selected clock
//     0 0 1 = Selected clock divided by 2
//     0 1 0 = Selected clock divided by 4
//     0 1 1 = Selected clock divided by 8
//     1 0 0 = Selected clock divided by 16
//     1 0 1 = Selected clock divided by 32
//     1 1 0 = Selected clock divided by 64
//     1 1 1 = Reserved
//
//  :MDIV: Master Clock Division (on ARM9-based systems only)
//     0 = The Master Clock and the Processor Clock are the same.
//     1 = The Processor Clock is twice as fast as the Master Clock.
//     2 = The Processor Clock is three times faster than the Master Clock.
//     3 = The Processor Clock is four times faster than the Master Clock.


#define LSB(x) ((~(x))+1) & (x))

/* shift val to the position indicated by mask*/
#define MASK_SHIFT(mask,val) ( (val)*LSB(mask)&(mask) )

/* get field(indicated by mask) value in data*/
#define MASK_RD(mask,data) ( ((data)&(mask))/LSB(mask) )

/* these inline function only change the bits indicated by mask to val*/
#define MASK_WR(var,mask,val) do{var = ((var)&(~(mask))) | mask_shift(mask,val)}while(0)


/////////////////////////////////////////////////////////////////////////////////////////////////////
// Configuration for a Quartz 18.432000 MHz
/////////////////////////////////////////////////////////////////////////////////////////////////////
//PLLAR perhaps 0x2026be04 because plla vco range in 150-240 MHz
#define	PLLAR 					0x20263E04	//* 179,712000 MHz for PCK     (18.432/4)*(38+1) = 179.712
#define	PLLBR 					0x10483E0E	//* 48,054857 MHz (divider by 2 for USB)   (18.432/14)*(72+1)/2 = 48.054857
#define	MCKR  					0x00000202	//* PCK/3 = MCK Master Clock = 59,904000MHz with PLLA selected
#define SLOWCLOCK				32768		//* In Hz

#define MAINOSC                 18432000


#define	MCK			59904000
#define	BAUDRATE	115200


#define PLL_INPUT_FREQ_MIN      900000
#define PLL_INPUT_FREQ_MAX      32000000

#define BASE_EBI_CS0_ADDRESS    0x10000000	//* base address to access memory on CS0
#define BASE_EBI_CS1_ADDRESS    0x20000000	//* base address to access memory on CS1

#define PLL_OUTPUT_FREQ_MIN     80000000
#define PLL_OUTPUT_FREQ_MAX     240000000


#define	FALSE					0
#define	TRUE					1
#define	DELAY_PLL				100
#define DELAY_MAIN_FREQ			100



// [DOC1768.PDF   23.6.8 PMC Clock Generator Main Clock Frequency Register]
//    31   30   29   28   27   26   25   24   23   22   21   20  19  18  17    16
//  +-----------------------------------------------------------------------+-------+
//  |                                    -                                  |MAINRDY|
//  +-----------------------------------------------------------------------+-------+
//
//    15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
//  +-------------------------------------------------------------------------------+
//  |                                     MAINF                                     |
//  +-------------------------------------------------------------------------------+
//
//  :MAINF: Main Clock Frequency
//     Gives the number of Main Clock cycles within 16 Slow Clock periods.
//  :MAINRDY: Main Clock Ready
//     0 = MAINF value is not valid or the Main Oscillator is disabled.
//     1 = The Main Oscillator has been enabled previously and MAINF value is available.
//*----------------------------------------------------------------------------
//* \fn    AT91F_WaitForMainClockFrequency
//* \brief This function performs very low level HW initialization
//*----------------------------------------------------------------------------
unsigned char AT91F_WaitForMainClockFrequency()
{
	volatile char	tmp	= 0;

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Step 2.
// Checking the Main Oscillator Frequency (Optional)
/////////////////////////////////////////////////////////////////////////////////////////////////////

	//* Determine the main clock frequency
	while(!(AT91C_BASE_CKGR->CKGR_MCFR & AT91C_CKGR_MAINRDY) && (tmp++ < DELAY_MAIN_FREQ));

	if (tmp >= DELAY_MAIN_FREQ)
		return FALSE;

	return TRUE;
}

//*----------------------------------------------------------------------------
//* \fn    AT91F_CheckPLL_FrequencyRange
//* \brief This function performs very low level HW initialiszation
//*----------------------------------------------------------------------------
unsigned char AT91F_CheckPLL_FrequencyRange(int MainClock,int pllDivider ,int pllMultiplier)
{
	if(pllDivider == 0)
		return FALSE;

	//* Check Input Frequency
	if( ((MainClock/pllDivider) < PLL_INPUT_FREQ_MIN)
	 || ((MainClock/pllDivider) > PLL_INPUT_FREQ_MAX) )
		return FALSE;

	//* Check Output Frequency
	if( ((MainClock/pllDivider*pllMultiplier) < PLL_OUTPUT_FREQ_MIN)
	 || ((MainClock/pllDivider*pllMultiplier) > PLL_OUTPUT_FREQ_MAX) )
		return FALSE;

	return TRUE;
}


//*----------------------------------------------------------------------------
//* \fn    AT91F_InitClocks
//* \brief This function performs very low level HW initialization
//*  Setting PLLA and Divider A
//*  Setting PLLB and Divider B
//*  Selection of Master Clock MCK (and Processor Clock PCK)
//*----------------------------------------------------------------------------
unsigned char AT91F_InitClocks(int PLLAR_Register,int PLLBR_Register ,int MCKR_Register)
{
	volatile char 	tmp = 0;
	unsigned int    t;
	unsigned int	MainClock;
	unsigned int 	pllDivider,pllMultiplier;

	//禁止PMC的所有中断源
	 AT91C_BASE_PMC->PMC_IDR = 0xFFFFFFFF;

	/* --- Optionnal
	 * -------------------------
	 */
	/* Check if Input & Output Frequencies are in the correct range (PLLA and PLLB)*/
	MainClock 		= AT91F_CKGR_GetMainClock(AT91C_BASE_CKGR,SLOWCLOCK);

	pllDivider    	= (PLLAR_Register  & AT91C_CKGR_DIVA);
	pllMultiplier 	= ((PLLAR_Register  & AT91C_CKGR_MULA) >> 16) + 1;
	if(AT91F_CheckPLL_FrequencyRange(MainClock, pllDivider , pllMultiplier) == FALSE)
		return FALSE;

	pllDivider    	= (PLLBR_Register  & AT91C_CKGR_DIVB);
	pllMultiplier 	= ((PLLBR_Register  & AT91C_CKGR_MULB) >> 16) + 1;
	if(AT91F_CheckPLL_FrequencyRange(MainClock, pllDivider , pllMultiplier) == FALSE)
		return FALSE;

	/* --- Step 3.
	 * -------------------------
	 */
	t = AT91C_BASE_CKGR->CKGR_PLLAR;
	if ( ( t & (AT91C_CKGR_DIVA|AT91C_CKGR_MULA) ) != ( PLLAR_Register & (AT91C_CKGR_DIVA|AT91C_CKGR_MULA) ) ) {
		AT91C_BASE_CKGR->CKGR_PLLAR = PLLAR_Register;
		//* Wait for PLLA stabilization LOCKA bit in PMC_SR
		tmp = 0;
		while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKA) && (tmp++ < DELAY_PLL) ) ;
	}
	/* --- Step 4.
	 * -------------------------
	 */
	t = AT91C_BASE_CKGR->CKGR_PLLBR;
	if ( ( t & (AT91C_CKGR_DIVB|AT91C_CKGR_MULB) ) != ( PLLBR_Register & (AT91C_CKGR_DIVB|AT91C_CKGR_MULB) ) ) {
		AT91C_BASE_CKGR->CKGR_PLLBR = PLLBR_Register;
		//* Wait for PLLB stabilization LOCKB bit in PMC_SR
		tmp = 0;
		while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKB) && (tmp++ < DELAY_PLL) ) ;
	}
	/* --- Step 5.
	 * -------------------------
	 */
	/* Constraints of the Master Clock selection sequence */
	/* Write in the MCKR dirty value concerning the clock selection CSS then overwrite it in a second sequence*/

	t = AT91C_BASE_PMC->PMC_MCKR;
	if ( (t&(AT91C_PMC_PRES|AT91C_PMC_CSS)) != (MCKR_Register&(AT91C_PMC_PRES|AT91C_PMC_CSS)) ) {
		if ( (MCKR_Register & AT91C_PMC_MDIV) != 0 ) { /*PCK > MCK then PRES field should be written first*/
			if ( (MCKR_Register & AT91C_PMC_PRES) != (t & AT91C_PMC_PRES) ) { /*PRES field must be changed*/
				/*first only change pres. may be include mdiv*/
				AT91C_BASE_PMC->PMC_MCKR = 	(MCKR_Register & (AT91C_PMC_PRES|AT91C_PMC_MDIV))+(t&AT91C_PMC_CSS);
				while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) );/* Wait until the master clock is established*/
			}
			if ( (MCKR_Register & AT91C_PMC_CSS) != (t & AT91C_PMC_CSS) ){ /*CSS field should be changed*/
				/*just change css*/
				AT91C_BASE_PMC->PMC_MCKR = 	MCKR_Register;
				/* Wait until the master clock is established*/
				while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) );
			}
		} else { /*PCK == MCK then CSS field should be written first*/
			if ( (MCKR_Register & AT91C_PMC_CSS) != (t & AT91C_PMC_CSS) ) { /*CSS field must be changed*/
				/*first only change CSS. may be include mdiv*/
				AT91C_BASE_PMC->PMC_MCKR = 	(MCKR_Register & (AT91C_PMC_CSS|AT91C_PMC_MDIV))+(t&AT91C_PMC_PRES);
				/* Wait until the master clock is established*/
				while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) );
			}
			if ( (MCKR_Register & AT91C_PMC_PRES) != (t & AT91C_PMC_PRES) ) { /*PRES field should be changed*/
				/*just change pres*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -