?? init.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 : init.c
//* Object : Low level initialisations written in C
//* Creation : ODi 06/26/2002
//*
//*----------------------------------------------------------------------------
#include "AT91RM9200.h"
#include "lib_AT91RM9200.h"
#include "def.h"
#include "config.h"
#include "slib.h"
#include "console.h"
//偽中斷處理函數
//偽中斷是指電平出發時持續時間太短中斷,不能被被正常識別出來的情況
static void SpuriousHandler(void)
{
puts("Spurious Interrupt detected\n");
AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC); //應答并返回
}
//未設置處理函數的中斷
static void NonSvcHandler(void)
{
puts("Non-serviced irq detectd\n");
while(1);
}
static void SwiHandler(void)
{
puts("Swi Interrupt detected\n");
}
static void DataAbortHandler(void)
{
puts("Data Abort detected\n");
while (1);
}
static void FetchAbortHandler(void)
{
puts("Prefetch Abort detected\n");
while (1);
}
static void UndefHandler()
{
puts("Halt on Undefined instruction\n");
while (1);
}
static void FiqHandler(void)
{
puts("Halt on FIQ!\n");
while(1);
}
#define DELAY_PLL 1000
#define DELAY_MAIN_FREQ 1000
#define SLOWCLOCK 32768 //* In Hz
//*----------------------------------------------------------------------------
//* \fn AT91F_WaitForMainClockFrequency
//* \brief This function performs very low level HW initialization
//*----------------------------------------------------------------------------
unsigned char AT91F_WaitForMainClockFrequency(void)
{
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_InitFlash
//* \brief This function performs very low level HW initialization
//*----------------------------------------------------------------------------
void AT91F_InitFlash(void)
{
AT91C_BASE_MC->MC_PUIA[0] = AT91C_MC_PROT_PNAUNA;
AT91C_BASE_MC->MC_PUP = 0;
AT91C_BASE_MC->MC_PUER = 0; //* Memory controller protection unit disable
AT91C_BASE_MC->MC_ASR = 0; //* read only!
AT91C_BASE_MC->MC_AASR = 0; //* read only!
//* Setup MEMC to support CS0=Flash
AT91C_BASE_EBI->EBI_CSA |= AT91C_EBI_CS0A_SMC;
AT91C_BASE_EBI->EBI_CFGR = (AT91C_EBI_DBPUC & 0x00) | (AT91C_EBI_EBSEN & 0x00);
//* Setup Flash
AT91C_BASE_SMC2->SMC2_CSR[0] = (AT91C_SMC2_NWS & 0x4) | AT91C_SMC2_WSEN
| (AT91C_SMC2_TDF & 0x200) | AT91C_SMC2_BAT | AT91C_SMC2_DBW_16;
}
/*--------------------------------------------------------------------------------------*/
/* Function Name : AT91F_SetPLL() */
/* Object : Set the PLLA to 180MHz and Master Clock to 60Mhz */
/* Object : Set the PLLA to 200MHz and Master Clock to 66Mhz */
/*--------------------------------------------------------------------------------------*/
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Configuration for a Quartz 18.432000 MHz
/////////////////////////////////////////////////////////////////////////////////////////////////////
#if (PROCESSOR_CLOCK == 243302400)
#define AT91C_PLLA_VALUE 0x20C5BE0F //PLLA = 0xC6*18.432M/0xf = 243.3024M
#elif (PROCESSOR_CLOCK == 221184000)
#define AT91C_PLLA_VALUE 0x2077BE0A //PLLA = 0x78*18.432M/0xa = 221.184M
#elif (PROCESSOR_CLOCK == 203000000)
#define AT91C_PLLA_VALUE 0x21B8BE28 //PLLA = 0x1B8*18.432M/0x28 = 203M
#elif (PROCESSOR_CLOCK == 199065600)
#define AT91C_PLLA_VALUE 0x206BBE0A //PLLA = 0x6c*18.432M/0xa = 199.0656M
#elif (PROCESSOR_CLOCK == 176947200)
#define AT91C_PLLA_VALUE 0x205FBE0A //PLLA = 0x60*18.432M/0xa = 176.9472M
#elif (PROCESSOR_CLOCK == 154828800)
#define AT91C_PLLA_VALUE 0x2053BE0A //PLLA = 0x54*18.432M/0xa = 154.8288M
#endif
#define AT91C_PLLB_VALUE 0x10483E0E //* 48,054857 MHz (divider by 2 for USB)
#if (MASTER_CLOCK_DIVIDER == 1)
#define MCKR_VAL 0x002 //1/1
#elif (MASTER_CLOCK_DIVIDER == 2)
#define MCKR_VAL 0x102 //1/2
#elif (MASTER_CLOCK_DIVIDER == 3)
#define MCKR_VAL 0x202 //1/3
#elif (MASTER_CLOCK_DIVIDER == 4)
#define MCKR_VAL 0x302 //1/3
#endif
static void InitPLL_old(void)
{
volatile int tmp = 0;
/* APMC Initialization for Crystal */
AT91PS_PMC pApmc = (AT91PS_PMC)AT91C_BASE_PMC;
AT91PS_CKGR pCkgr = (AT91PS_CKGR)AT91C_BASE_CKGR;
//禁止PMC的所有中斷源
pApmc->PMC_IDR = 0xFFFFFFFF;
// Setting PLLB and Divider B
if((pCkgr->CKGR_PLLBR^AT91C_PLLB_VALUE)&0x07ff00ff) {
pCkgr->CKGR_PLLBR = AT91C_PLLB_VALUE;
//* Wait for PLLB stabilization LOCKB bit in PMC_SR
tmp = 0;
while(!(pApmc->PMC_SR & AT91C_PMC_LOCKB) && (tmp++ < DELAY_PLL));
}
//先選擇PLLB做為主時鐘
/* Write in the MCKR dirty value concerning the clock selection CSS then overwrite it in a second sequence */
pApmc->PMC_MCKR = 0x203;
/* Wait until the master clock is established */
tmp = 0;
while(!(pApmc->PMC_SR & AT91C_PMC_MCKRDY) && (tmp++ < DELAY_MAIN_FREQ));
//再設置PLLA,若原主時鐘為PLLA而在未切換到其他時鐘源時設置PLLA(值不變),啟動會等很久,why?
if((pCkgr->CKGR_PLLAR^AT91C_PLLA_VALUE)&0x07ff00ff) {
pCkgr->CKGR_PLLAR = AT91C_PLLA_VALUE;
//* Wait for PLLB stabilization LOCKB bit in PMC_SR
tmp = 0;
while(!(pApmc->PMC_SR & AT91C_PMC_LOCKA) && (tmp++ < DELAY_PLL));
}
//再把主時鐘源換到PLLA,設置同步模式,等待時鐘穩定
/* - Commuting Master Clock from PLLB to PLLA/3 */
pApmc->PMC_MCKR = MCKR_VAL; //master clock 為 PLLA,預分頻為1,Processor clock為master clock的2/3倍
/* Wait until the master clock is established */
tmp = 0;
while(!(pApmc->PMC_SR & AT91C_PMC_MCKRDY) && (tmp++ < DELAY_MAIN_FREQ));
MMU_SetAsyncBusMode(); //設置CPU總線同步模式
}
#define EXT_OSC_CLK 18432000
static struct{
U32 mckr;
U32 n1;
U32 n2;
} ClkPara;
static void InitPLL(void)
{
volatile int tmp = 0;
U32 freq;
/* APMC Initialization for Crystal */
AT91PS_PMC pApmc = (AT91PS_PMC)AT91C_BASE_PMC;
AT91PS_CKGR pCkgr = (AT91PS_CKGR)AT91C_BASE_CKGR;
ClkPara.plla=(440<<16)|40;
ClkPara.mckr=2<<8;
// if(((pCkgr->CKGR_PLLAR&0x7ff0000)==(ClkPara.plla&0x7ff0000)) &&
// ((pCkgr->CKGR_PLLAR&0xff)==(ClkPara.plla&0xff)) &&
// (pApmc->PMC_MCKR==))
// return
ClkPara.plla &= 0x7ff00ff;
ClkPara.plla |= (1<<29)|(0x3f<<8);
freq = (((ClkPara.plla>>16)&0x7ff)+1)*EXT_OSC_CLK/(ClkPara.plla&0xff);
if(freq>=150000000)
ClkPara.plla |= 1<<15;
ClkPara.mckr &= 0x300;
ClkPara.mckr |= 2;
//禁止PMC的所有中斷源
pApmc->PMC_IDR = 0xFFFFFFFF;
// Setting PLLB and Divider B
if((pCkgr->CKGR_PLLBR^AT91C_PLLB_VALUE)&0x07ff00ff) {
pCkgr->CKGR_PLLBR = AT91C_PLLB_VALUE;
//* Wait for PLLB stabilization LOCKB bit in PMC_SR
tmp = 0;
while(!(pApmc->PMC_SR & AT91C_PMC_LOCKB) && (tmp++ < DELAY_MAIN_FREQ));
}
//先選擇PLLB做為主時鐘
/* Write in the MCKR dirty value concerning the clock selection CSS then overwrite it in a second sequence */
pApmc->PMC_MCKR = 0x203;
/* Wait until the master clock is established */
tmp = 0;
while(!(pApmc->PMC_SR & AT91C_PMC_MCKRDY) && (tmp++ < DELAY_PLL));
//再設置PLLA,若原主時鐘為PLLA而在未切換到其他時鐘源時設置PLLA(值不變),啟動會等很久,why?
if((pCkgr->CKGR_PLLAR^ClkPara.plla)&0x07ff00ff) {
pCkgr->CKGR_PLLAR = ClkPara.plla;
//* Wait for PLLB stabilization LOCKB bit in PMC_SR
tmp = 0;
while(!(pApmc->PMC_SR & AT91C_PMC_LOCKA) && (tmp++ < DELAY_PLL));
}
//再把主時鐘源換到PLLA,設置同步模式,等待時鐘穩定
/* - Commuting Master Clock from PLLB to PLLA/3 */
pApmc->PMC_MCKR = ClkPara.mckr; //master clock 為 PLLA,預分頻為1,Processor clock為master clock的2/3倍
/* Wait until the master clock is established */
tmp = 0;
while(!(pApmc->PMC_SR & AT91C_PMC_MCKRDY) && (tmp++ < DELAY_MAIN_FREQ));
MMU_SetAsyncBusMode(); //設置CPU總線同步模式
// ClkPara.n1 = GetCpuClock();
// ClkPara.n2 = GetMasterClock();
}
/*--------------------------------------------------------------------------------------*/
/* Function Name : InitSDRAM */
/* Object : Initialize the SDRAM */
/*--------------------------------------------------------------------------------------*/
/*
DRAM_PARAMS dram_params[DRAM_BANKS] = { //在SDRAM初始化完成以前不要讀取
{DRAM_BASE, DRAM_SIZE}, //帶初始化值的全局變量!!!
};*/ //要么使用PIC編譯
static void InitSDRAM(void) //此類函數均為相對調用,可與地址無關
{
volatile int *pSDRAM = (int *)DRAM_BASE;
/* Configure PIOC as peripheral (D16/D31) */
AT91F_PIO_CfgPeriph( AT91C_BASE_PIOC, 0xFFFF0000, 0);
/*Setup MEMC to support all connected memories (CS0 = FLASH; CS1=SDRAM)*/
AT91C_BASE_EBI->EBI_CSA = AT91C_EBI_CS1A;
/*Init SDRAM*/
AT91C_BASE_SDRC->SDRC_CR = 0x2188c155;
AT91C_BASE_SDRC->SDRC_MR = 0x02;
*pSDRAM = 0;
AT91C_BASE_SDRC->SDRC_MR = 0x04;
*pSDRAM = 0;
*pSDRAM = 0;
*pSDRAM = 0;
*pSDRAM = 0;
*pSDRAM = 0;
*pSDRAM = 0;
*pSDRAM = 0;
*pSDRAM = 0;
AT91C_BASE_SDRC->SDRC_MR = 0x03;
*(pSDRAM + 0x80) = 0;
AT91C_BASE_SDRC->SDRC_TR= 0x2e0;
*pSDRAM = 0;
AT91C_BASE_SDRC->SDRC_MR = 0;
*pSDRAM = 0;
}
#define _ISR_STARTADDRESS 0x21ffff00
#define pISR_RESET *(U32 *)(_ISR_STARTADDRESS+0x0)
#define pISR_UNDEF *(U32 *)(_ISR_STARTADDRESS+0x4)
#define pISR_SWI *(U32 *)(_ISR_STARTADDRESS+0x8)
#define pISR_PABORT *(U32 *)(_ISR_STARTADDRESS+0xc)
#define pISR_DABORT *(U32 *)(_ISR_STARTADDRESS+0x10)
#define pISR_RESERVED *(U32 *)(_ISR_STARTADDRESS+0x14)
#define pISR_IRQ *(U32 *)(_ISR_STARTADDRESS+0x18)
#define pISR_FIQ *(U32 *)(_ISR_STARTADDRESS+0x1c)
static void InitISR(void)
{
int i;
pISR_UNDEF = (U32)UndefHandler;
pISR_SWI = (U32)SwiHandler;
pISR_PABORT = (U32)FetchAbortHandler;
pISR_DABORT = (U32)DataAbortHandler;
pISR_FIQ = (U32)FiqHandler;
// 禁止并清除所有中斷,設置所有中斷優先級,觸發模式和缺省處理函數
for (i = 0; i < 32; ++i) {
AT91F_AIC_DisableIt(AT91C_BASE_AIC, i);
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, i, AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, NonSvcHandler);
}
//設置偽中斷處理函數入口
AT91C_BASE_AIC->AIC_SPU = (U32)SpuriousHandler;
AT91C_BASE_AIC->AIC_DCR = 0; //nornal mode
/* Perform 8 End Of Interrupt Command to make s齬e AIC will not Lock out nIRQ */
for(i=0; i<8; i++)
AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC);
}
static void InitTimerCounter(void)
{
AT91PS_TC pTC = AT91C_BASE_TC0;
AT91F_TC0_CfgPMC();
pTC->TC_IDR = 0xff; //disable all interrupts
//select TIMER_CLOCK2 = MCK/8, CPCTRG, up mode, Waveform mode
pTC->TC_CMR = 1|(2<<13)|(1<<15); //Capture模式下,RC COMPARE也可復位計數器
pTC->TC_RC = (AT91F_PMC_GetMasterClock(AT91C_BASE_PMC, AT91C_BASE_CKGR, 32768)>>3)/1000;
pTC->TC_CCR = 5; //enable timer-counter and trig it
}
//*----------------------------------------------------------------------------
//* \fn AT91F_LowLevelInit
//* \brief This function performs very low level HW initialization
//*----------------------------------------------------------------------------
void LowLevelInit()
{
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Step 2.
// Checking the Main Oscillator Frequency (Optional)
/////////////////////////////////////////////////////////////////////////////////////////////////////
AT91F_WaitForMainClockFrequency();
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Flash AT49BV1614 Initialisation : must be done before change the clocks -> Set correct Wait States
/////////////////////////////////////////////////////////////////////////////////////////////////////
//AT91F_InitFlash();
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Step 3. to 5.
/////////////////////////////////////////////////////////////////////////////////////////////////////
//AT91F_InitClocks(AT91C_PLLA_VALUE, AT91C_PLLB_VALUE, MCKR_VAL);
InitPLL();
/* // Init Interrupt Controller
AT91F_AIC_Open(
AT91C_BASE_AIC, // pointer to the AIC registers
AT91C_AIC_BRANCH_OPCODE, // IRQ exception vector
AT91F_UndefHandler, // FIQ exception vector
AT91F_UndefHandler, // AIC default handler
AT91F_SpuriousHandler, // AIC spurious handler
0); // Protect mode
// Perform 8 End Of Interrupt Command to make s齬e AIC will not Lock out nIRQ
AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC);
AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC);
AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC);
AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC);
AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC);
AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC);
AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC);
AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC);
AT91F_AIC_SetExceptionVector((unsigned int *)0x0C, AT91F_FetchAbort);
AT91F_AIC_SetExceptionVector((unsigned int *)0x10, AT91F_DataAbort);
AT91F_AIC_SetExceptionVector((unsigned int *)0x4, AT91F_Undef);
*/
InitSDRAM();
InitISR();
//initialize timer-counter for other functions to call delay()
InitTimerCounter();
// Open PIO for DBGU
AT91F_DBGU_CfgPIO();
// Configure DBGU
AT91F_US_Configure (
(AT91PS_USART) AT91C_BASE_DBGU, // DBGU base address
AT91C_MASTER_CLOCK, //
AT91C_US_ASYNC_MODE, // mode Register to be programmed
UART_BAUD_RATE, // baudrate to be programmed
0); // timeguard to be programmed
// Enable Transmitter
AT91F_US_EnableTx((AT91PS_USART) AT91C_BASE_DBGU);
/* Enable Receiver */
AT91F_US_EnableRx((AT91PS_USART)AT91C_BASE_DBGU);
// puts("\n AT91F_LowLevelInit() done\n");
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -