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"); 
}