📄 lowinit.c
字号:
#include "AT91RM9200.h"
#define LOWINIT_GLOBALS
#include "lowinit.h"
#undef LOWINIT_GLOBLAS
#define EBI_CS0_BASE_ADDRESS (0x10000000)
#define EBI_CS1_BASE_ADDRESS (0x20000000)
#define AT91C_SLOW_CLOCK (32768)
//#define AT91C_PCK (199065600) // = 66355200 * 3
//#define AT91C_MCK (66355200) // = 115200 * 16 * 36 = 18432000 * 3.6
#define AT91C_PCK (160000000) // = 80000000 * 2 = 18432000 / 72 * 625
#define AT91C_MCK (80000000) // = 18432000 / 144 * 625
#define AT91C_DBG_BAND_RATE (115200)
/*-------------------------------------------------------------------------------------------------*
*- These macros definition determine clock output by pmc, including master clock (MCK), processor
*- clock, programmable clock and USB port clock, which must be 48Mhz.
*- main clock -> pll A -> master clock controller -> master clock & processor clock
*- main clock -> pll B -> programmable clock & USB port clock
;- PLLA output is set to 199.0656 MHz with setting below (160000000 = 18432000 / 72 * 625)
;- PLLB output is set to 48.054857 MHz with setting below (96000000 = 18432000 / 72 * 375)
*-------------------------------------------------------------------------------------------------*/
#define CKGR_PLLRA_CFG (0x270 << 16 | AT91C_CKGR_OUTA_2 | AT91C_CKGR_PLLACOUNT | 0x48)
#define CKGR_PLLRB_CFG (0x01 << 28 | 0x176 << 16 | AT91C_CKGR_OUTB_0 | AT91C_CKGR_PLLBCOUNT | 0x48)
#define PMC_MCKR_CFG (AT91C_PMC_CSS_PLLA_CLK | AT91C_PMC_PRES_CLK | AT91C_PMC_MDIV_2)
#define PMC_SYSCLK_CFG (AT91C_PMC_PCK | AT91C_PMC_UDP | AT91C_PMC_MCKUDP)
void SpuriousHandler(void);
void SpuriousInt(void) {
AT91F_DEBUG_Printk("\n\r-F- Spurious Interrupt detected\n\r");
while (1);
}
void UndExcp(void) {
AT91F_DEBUG_Printk("\n\r-F- Undefine Indicator Interrupt detected\n\r");
while (1);
}
void SwiExcp(void) {
AT91F_DEBUG_Printk("\n\r-F- Software Interrupt detected\n\r");
while (1);
}
void PreAbtExcp(void) {
AT91F_DEBUG_Printk("\n\r-F- Indicator Prefetch Abort Interrupt detected\n\r");
while (1);
}
void DataAbtExcp(void) {
AT91F_DEBUG_Printk("\n\r-F- Data Abort Interrupt detected\n\r");
while (1);
}
void AT91F_LowLevel_Init(void) {
PMCLowLevleInit(AT91C_BASE_PMC, AT91C_BASE_CKGR, AT91C_SLOW_CLOCK);
AICLowLevelInit(AT91C_BASE_AIC, SpuriousHandler);
SDRAMLowLevelInit();
FlashLowLevelInit();
DebugLowLevelInit();
DebugPrint("\n\rAT91RM9200 LowLevelInit Complete!\n\r");
}
void AICLowLevelInit(AT91PS_AIC preg, PINTHDL phdl) {
preg->AIC_IDCR = 0xFFFFFFFF;
preg->AIC_ICCR = 0xFFFFFFFF;
preg->AIC_EOICR = preg->AIC_EOICR;
preg->AIC_EOICR = preg->AIC_EOICR;
preg->AIC_EOICR = preg->AIC_EOICR;
preg->AIC_EOICR = preg->AIC_EOICR;
preg->AIC_EOICR = preg->AIC_EOICR;
preg->AIC_EOICR = preg->AIC_EOICR;
preg->AIC_EOICR = preg->AIC_EOICR;
preg->AIC_EOICR = preg->AIC_EOICR;
preg->AIC_SPU = (AT91_REG)phdl;
}
/*------------------------------------------------------------------------------------------------*
*- Function: PMCLowLevleInit
*- Parameter: preg, Start Address of PMC register group
*- Return: void
*- Brief: Low level init PMC, including main clock, pll clock, master clock, processor clock
*------------------------------------------------------------------------------------------------*/
void PMCLowLevleInit(AT91PS_PMC pmcreg, AT91PS_CKGR pckgreg, unsigned int slk) {
unsigned int mainclk;
// Make sure system clocks is enabled
pmcreg->PMC_SCER = PMC_SYSCLK_CFG;
// Switch MCK source to slow clock if neccessory
if(pmcreg->PMC_MCKR != 0) {
pmcreg->PMC_MCKR = 0;
}
// Enable Main Oscillator if neccessory
if(!(pckgreg->CKGR_MOR & AT91C_CKGR_MOSCEN)) {
pckgreg->CKGR_MOR = AT91C_CKGR_MOSCEN | AT91C_CKGR_OSCOUNT;
// Loop until Main Oscillator is stable
while((pmcreg->PMC_SR & AT91C_PMC_MOSCS) && (pckgreg->CKGR_MCFR & AT91C_CKGR_MAINRDY));
mainclk = ((pckgreg->CKGR_MCFR & 0xFFFF) * slk) >> 4;
}
// Configure PLLA and PLLB
pckgreg->CKGR_PLLAR = CKGR_PLLRA_CFG;
pckgreg->CKGR_PLLBR = CKGR_PLLRB_CFG;
while(!(pmcreg->PMC_SR & AT91C_PMC_LOCKA) && !(pmcreg->PMC_SR & AT91C_PMC_LOCKB));
// Switch MCK back to PLLA clock
pmcreg->PMC_MCKR = PMC_MCKR_CFG;
while(!(pmcreg->PMC_SR & AT91C_PMC_MCKRDY));
}
/*------------------------------------------------------------------------------------------------*
*- Function: FlashLowLevelInit
*- Parameter: void
*- Return: void
*- Brief: Initialize flash
*------------------------------------------------------------------------------------------------*/
void FlashLowLevelInit(void) {
//* Setup MEMC to support CS0 == Flash
AT91C_BASE_EBI->EBI_CSA &= (~AT91C_EBI_CS0A_BFC);
AT91C_BASE_EBI->EBI_CFGR = (AT91C_EBI_DBPUC & 0x00) | (AT91C_EBI_EBSEN & 0x00);
//* Setup Flash
AT91C_BASE_SMC->SMC_CSR[0] = (FLASH_SMC_NWS | FLASH_SMC_WSEN | FLASH_SMC_TDF | FLASH_SMC_BAT | FLASH_SMC_DBW | FLASH_SMC_DRP | FLASH_SMC_ACCS | FLASH_SMC_RWSETUP | FLASH_SMC_RWHOLD);
}
/*------------------------------------------------------------------------------------------------*
*- Function: SDRAMLowLevelInit
*- Parameter: void
*- Return: void
*- Brief: Initialize SDRAM
*------------------------------------------------------------------------------------------------*/
void SDRAMLowLevelInit(void) {
unsigned int i;
unsigned int* pSDRAM = (unsigned int *)EBI_CS1_BASE_ADDRESS;
//* Configure PIOC as peripheral (D16/D31)
AT91F_PIO_CfgPeriph(AT91C_BASE_PIOC, AT91C_PIOC_D16_D31, 0);
//* Setup MEMC to support CS1=SDRAM
AT91C_BASE_EBI->EBI_CSA |= AT91C_EBI_CS1A;
AT91C_BASE_EBI->EBI_CFGR = (AT91C_EBI_DBPUC & 0x00) | (AT91C_EBI_EBSEN & 0x00);
//* Init SDRAM
//* 1. A minimum pause of 200us is provided to precede any signal toggle
AT91C_BASE_SDRC->SDRC_CR = AT91C_SDRC_NC_9 | AT91C_SDRC_NR_12 | AT91C_SDRC_NB_4_BANKS | AT91C_SDRC_CAS_2
| 0x100 | 0x4000 | 0x8000
| 0x880000
| 0x21000000;
//* 2. A Precharge All command is issued to the SDRAM
AT91C_BASE_SDRC->SDRC_MR = AT91C_SDRC_MODE_PRCGALL_CMD;
*pSDRAM = 0;
//* 3. Eight Auto-refresh are provided
AT91C_BASE_SDRC->SDRC_MR = AT91C_SDRC_MODE_RFSH_CMD;
for(i=0; i < 8; i++) {
*pSDRAM = 0;
}
//* 4. A mode register cycle is issued to program the SDRAM parameters
AT91C_BASE_SDRC->SDRC_MR = AT91C_SDRC_MODE_LMR_CMD;
*(pSDRAM + 0x80) = 0;
//* 5. Write refresh rate into SDRAMC refresh timer COUNT register
AT91C_BASE_SDRC->SDRC_TR = (AT91C_SDRC_COUNT & 0x2E0);
*pSDRAM = 0;
//* 6. A Normal Mode Command is provided, 3 clocks after tMRD is set
AT91C_BASE_SDRC->SDRC_MR = AT91C_SDRC_MODE_NORMAL_CMD;
*pSDRAM = 0;
}
/*------------------------------------------------------------------------------------------------*
*- Function: DebugLowLevelInit
*- Parameter: void
*- Return: void
*- Brief: Enable main debug port
*------------------------------------------------------------------------------------------------*/
void DebugLowLevelInit(void) {
AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, AT91C_PA31_DTXD | AT91C_PA30_DRXD, 0);
AT91F_US_Configure((AT91PS_USART)AT91C_BASE_DBGU, 80000000, AT91C_US_ASYNC_MODE, 115200, 0);
AT91C_BASE_DBGU->US_CR = AT91C_US_RSTRX | AT91C_US_TXEN | AT91C_US_RXEN;
}
/*------------------------------------------------------------------------------------------------*
*- Function: DebugPrintk
*- Parameter: buffer, points at charator buffer
*- Return: void
*- Brief: Send charactors through debug USART port
*------------------------------------------------------------------------------------------------*/
void DebugPrint(char *buffer) {
while(*buffer != '\0') {
while(!AT91F_US_TxReady((AT91PS_USART)AT91C_BASE_DBGU));
AT91F_US_PutChar((AT91PS_USART)AT91C_BASE_DBGU, *buffer++);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -