📄 initboot.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 : FB 23/10/2002 */
/* */
/*----------------------------------------------------------------------------*/
#include "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 MASTER_CLOCK 59904000
// #define MASTER_CLOCK 45000000
#define QUARTZ_18432 1
#if QUARTZ_18432
#define PLLAR 0x20263E04 /* 180 MHz for PLLA */
#define PLLBR 0x10483E0E /* 48,054857 MHz (divider by 2 for USB) */
#else /* 4.608MHZ */
#define PLLAR 0x20263E03 /* 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 MCKR 0x0000302 /* PLLA=180 , == CPU = 180MHZ, MASTER_CLOCK = 45MHZ */
#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_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_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_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_LowLevelInit */
/* \brief This function performs very low level HW initialization */
/*----------------------------------------------------------------------------*/
void AT91F_LowLevelInit()
{
AT91PS_USART pUSART = (AT91PS_USART)AT91C_BASE_DBGU;
AT91PS_PDC pPdc;
unsigned char status;
/*---------------------------------------------------------------------------- */
/* Step 2. */
/* Checking the Main Oscillator Frequency (Optional) */
/*---------------------------------------------------------------------------- */
status = AT91F_WaitForMainClockFrequency();
/*---------------------------------------------------------------------------- */
/* Step 3. to 5. */
/*---------------------------------------------------------------------------- */
AT91F_InitFlash();
status = AT91F_InitClocks(PLLAR,PLLBR, MCKR);
/*---------------------------------------------------------------------------- */
/* SDRAM & Flash AT49BV1614 Initialisations */
/*---------------------------------------------------------------------------- */
AT91F_InitSDRAM();
/*---------------------------------------------------------------------------- */
/* Test PMC Initialization. */
/*---------------------------------------------------------------------------- */
/* 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();
#ifdef DEBUG
AT91F_DBGU_Printk("\n\rLow Level Init performed\n\r");
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -