www.pudn.com > at91rm9200vxworksbsp.rar > boardInit.c
/*---------------------------------------------------------------------------- */
/* ATMEL Microcontroller AT91RM9200 Board */
/*---------------------------------------------------------------------------- */
/*---------------------------------------------------------------------------- */
/* File Name : init.c */
/* Object : Low level initialisations written in C */
/* Creation : yanyuan 07/03/2007 */
/* */
/*----------------------------------------------------------------------------*/
#include "AT91RM9200.h"
#include "lib_AT91RM9200.h"
#define FALSE 0
#define TRUE 1
#define DELAY_PLL 100
#define DELAY_MAIN_FREQ 100
#define INPUT_FREQ_MIN 900000
#define INPUT_FREQ_MAX 32000000
#define QUARTZ_18432 1
#if QUARTZ_18432
#define PLLAR 0x2026BE04 /* 180 MHz for PLLA */
#define PLLBR 0x10483E0E /* 48,054857 MHz (divider by 2 for USB) */
#else /* 4.608MHZ */
#define PLLAR 0x20263E01 /* 179,712000 MHz for PCK for 4.608 */
#define PLLBR 0x10673E05 /* 48,054857 MHz (divider by 2 for USB) */
#endif
#define MCKR 0x0000202 /* PLLA=180 , == CPU = 180MHZ, MASTER_CLOCK = 60MHZ */
#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 OUTPUT_FREQ_MIN 80000000
#define OUTPUT_FREQ_MAX 240000000
#define C1_IDC (1<<2) /* icache and/or dcache off/on */
/*---------------------------------------------------------------------------- */
/* \fn AT91F_DBGU_Printk */
/* \brief This function is used to send a string through the DBGU channel (Very low level debugging) */
/*----------------------------------------------------------------------------*/
void AT91F_DBGU_Printk(
char *buffer) /* \arg pointer to a string ending by \0 */
{
while(*buffer != '\0') {
while (!(((AT91PS_USART)AT91C_BASE_DBGU)->US_CSR & AT91C_US_TXRDY));
((AT91PS_USART)AT91C_BASE_DBGU)->US_THR = (*buffer++ & 0x1FF);
}
}
/*---------------------------------------------------------------------------- */
/* \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(unsigned int MainClock,unsigned int pllDivider , unsigned int pllMultiplier)
{
if(pllDivider == 0)
return FALSE;
/* Check Input Frequency */
if( ((MainClock/pllDivider) < INPUT_FREQ_MIN)
|| ((MainClock/pllDivider) > INPUT_FREQ_MAX) )
return FALSE;
/* Check Output Frequency */
if( ((MainClock/pllDivider*pllMultiplier) < OUTPUT_FREQ_MIN)
|| ((MainClock/pllDivider*pllMultiplier) > OUTPUT_FREQ_MAX) )
return FALSE;
return TRUE;
}
/*----------------------------------------------------------------------------*/
/* \fn AT91F_DataAbort*/
/* \brief This function reports an Abort*/
/*----------------------------------------------------------------------------*/
void AT91F_SpuriousHandler()
{
AT91F_DBGU_Printk("-F- Spurious Interrupt detected\n\r");
while (1);
}
/*----------------------------------------------------------------------------*/
/* \fn AT91F_DataAbort*/
/* \brief This function reports an Abort*/
/*----------------------------------------------------------------------------*/
void AT91F_DataAbort()
{
AT91F_DBGU_Printk("-F- Data Abort detected\n\r");
while (1);
}
/*----------------------------------------------------------------------------*/
/* \fn AT91F_FetchAbort*/
/* \brief This function reports an Abort*/
/*----------------------------------------------------------------------------*/
void AT91F_FetchAbort()
{
AT91F_DBGU_Printk("-F- Prefetch Abort detected\n\r");
while (1);
}
/*----------------------------------------------------------------------------*/
/* \fn AT91F_Undef*/
/* \brief This function reports an Abort*/
/*----------------------------------------------------------------------------*/
void AT91F_Undef()
{
AT91F_DBGU_Printk("-F- Undef detected\n\r");
while (1);
}
/*----------------------------------------------------------------------------*/
/* \fn AT91F_UndefHandler*/
/* \brief This function reports that no handler have been set for current IT*/
/*----------------------------------------------------------------------------*/
void AT91F_UndefHandler()
{
AT91F_DBGU_Printk("-F- Undef detected\n\r");
while (1);
}
/*----------------------------------------------------------------------------*/
/* \fn AT91F_InitClocks */
/* \brief This function performs very low level HW initialization */
/*----------------------------------------------------------------------------*/
unsigned char AT91F_InitClocks(int PLLAR_Register,int PLLBR_Register ,int MCKR_Register)
{
volatile char tmp = 0;
unsigned int MainClock;
unsigned int pllDivider,pllMultiplier;
/*---------------------------------------------------------------------------- */
/* Optionnal */
/*---------------------------------------------------------------------------- */
/* Check if Input & Output Frequencies are in the correct range */
/* Get Main Clock */
MainClock = (((AT91C_BASE_CKGR->CKGR_MCFR) & AT91C_CKGR_MAINF) * 32768) >> 4;
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. */
/* Setting PLLA and Divider A */
/*---------------------------------------------------------------------------- */
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. */
/* Setting PLLB and Divider B */
/*---------------------------------------------------------------------------- */
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. */
/* Selection of Master Clock MCK (and Processor Clock PCK) */
/*---------------------------------------------------------------------------- */
/* 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 */
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK;
/* Wait until the master clock is established */
tmp = 0;
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) && (tmp++ < DELAY_MAIN_FREQ) );
/* Second sequence */
AT91C_BASE_PMC->PMC_MCKR = MCKR_Register;
/* Wait until the master clock is established */
tmp = 0;
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) && (tmp++ < DELAY_MAIN_FREQ) );
return TRUE;
}
void AT91F_InitSDRAM()
{
volatile int *pRegister;
AT91PS_PIO pPio = AT91C_BASE_PIOC;
/* Configure PIOC as peripheral (D16/D31) */
pPio->PIO_ASR = 0xFFFF0000;
pPio->PIO_BSR = 0x0;
pPio->PIO_PDR = 0xFFFF0000;
/* Setup MEMC to support all connected memories (CS0 = FLASH; CS1=SDRAM) */
pRegister = (int *)0xFFFFFF60;
*pRegister = 0x02;
/* Init SDRAM */
pRegister = (int *)0xFFFFFF98;
*pRegister = 0x2188c155;
pRegister = (int *)0xFFFFFF90;
*pRegister = 0x2;
pRegister = (int *)0x20000000;
*pRegister = 0;
pRegister = (int *)0xFFFFFF90;
*pRegister = 0x4;
pRegister = (int *)0x20000000;
*pRegister = 0;
*pRegister = 0;
*pRegister = 0;
*pRegister = 0;
*pRegister = 0;
*pRegister = 0;
*pRegister = 0;
*pRegister = 0;
pRegister = (int *)0xFFFFFF90;
*pRegister = 0x3;
pRegister = (int *)0x20000080;
*pRegister = 0;
pRegister = (int *)0xFFFFFF94;
*pRegister = 0x2e0;
pRegister = (int *)0x20000000;
*pRegister = 0;
pRegister = (int *)0xFFFFFF90;
*pRegister = 0x00;
pRegister = (int *)0x20000000;
*pRegister = 0;
}
/*----------------------------------------------------------------------------*/
/* \fn AT91F_Read_p15_c1 */
/* \brief This function reads co-processor 15, register 1 (control register) */
/*----------------------------------------------------------------------------*/
unsigned int AT91F_Read_p15_c1(void)
{
unsigned int value;
__asm__ __volatile__(
"mrc p15, 0, %0, c1, c0, 0 @ read control reg\n"
: "=r" (value)
:
: "memory");
return value;
}
/*----------------------------------------------------------------------------*/
/* \fn AT91F_Write_p15_c1 */
/* \brief This function writes to co-processor 15, register 1 (control register) */
/*----------------------------------------------------------------------------*/
void AT91F_Write_p15_c1(unsigned int value)
{
__asm__ __volatile__(
"mcr p15, 0, %0, c1, c0, 0 @ write it back\n"
: "=r" (value)
:
: "memory");
AT91F_Read_p15_c1();
}
/*----------------------------------------------------------------------------*/
/* \fn AT91F_Enable_ICache */
/* \brief This function enables Instruction Cache */
/*----------------------------------------------------------------------------*/
void AT91F_Enable_ICache(void)
{
unsigned int i, reg;
reg = AT91F_Read_p15_c1();
for (i=0; i<100; i++);
AT91F_Write_p15_c1(reg | C1_IDC);
}
/*----------------------------------------------------------------------------*/
/* \fn AT91F_InitFlash */
/* \brief This function performs very low level HW initialization */
/*----------------------------------------------------------------------------*/
void AT91F_InitFlash()
{
#if 0
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);
#endif
/* 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;
}
/*---------------------------------------------------------------------------- */
/* \fn AT91F_LowLevelInit */
/* \brief This function performs very low level HW initialization */
/*----------------------------------------------------------------------------*/
void AT91F_LowLevelInit()
{
AT91PS_USART pUSART = (AT91PS_USART)AT91C_BASE_DBGU;
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
AT91PS_PDC pPdc;
#if 0
/* Checking the Main Oscillator Frequency (Optional) */
AT91F_WaitForMainClockFrequency();
#endif
/* Init Interrupt Controller */
AT91F_AIC_Open(
AT91C_BASE_AIC, /* pointer to the AIC registers */
AT91C_AIC_BRANCH_OPCODE, /* IRQ exception vector */
AT91C_AIC_BRANCH_OPCODE, /* FIQ exception vector */
AT91F_UndefHandler, /* AIC default handler */
AT91F_SpuriousHandler, /* AIC spurious handler */
0); /* Protect mode */
/* Perform 8 End Of Interrupt Command to make sure 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);
AT91F_InitFlash();
AT91F_InitClocks(PLLAR,PLLBR, MCKR);
pPMC->PMC_SCER = 0x00000001; /* Enables the Processor Clock. */
pPMC->PMC_SCDR = 0x00000F16; /* Disables the Programmable Clock, UDPCK and UHPCK. */
pPMC->PMC_PCDR = 0xFFFFFFFC; /* Disables 30 Peripheral Clock. */
pPMC->PMC_PCER = 0x00022018; /* Enables Peripheral Clock : TC0/SPI/PIOC/PIOB */
/* SDRAM Initialisations */
AT91F_InitSDRAM();
/* Open PIO for DBGU */
AT91C_BASE_PIOA->PIO_ASR = AT91C_PA31_DTXD | AT91C_PA30_DRXD;
AT91C_BASE_PIOA->PIO_BSR = 0x0;
AT91C_BASE_PIOA->PIO_PDR = AT91C_PA31_DTXD | AT91C_PA30_DRXD;
/******************/
/* Configure DBGU */
/******************/
/* Disable interrupts */
pUSART->US_IDR = (unsigned int) -1;
/* Reset receiver and transmitter */
pUSART->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS;
/* Define the baudrate divisor register */
pUSART->US_BRGR = MASTER_CLOCK/(115200*16); /* 33 For 60 MHz and 24 for 45 MHz */
/* Write the timeguard register */
pUSART->US_TTGR = 0;
/* Clear Transmit and Receive counters */
pPdc = (AT91PS_PDC) &pUSART->US_RPR;
pPdc->PDC_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
pPdc->PDC_TNPR = 0;
pPdc->PDC_TNCR = 0;
pPdc->PDC_RNPR = 0;
pPdc->PDC_RNCR = 0;
pPdc->PDC_TPR = 0;
pPdc->PDC_TCR = 0;
pPdc->PDC_TPR = 0;
pPdc->PDC_TCR = 0;
pPdc->PDC_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN; /* Enable Rx and Tx */
/* Define the USART mode */
pUSART->US_MR = AT91C_US_CHMODE_NORMAL | AT91C_US_PAR_NONE;
/* Enable Transmitter */
pUSART->US_CR = AT91C_US_TXEN;
/* Enable I-Cache */
AT91F_Enable_ICache();
AT91F_DBGU_Printk("\n\rSystem booting......\n\r\r\n");
}