⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 at91rm9200 bios v1.1 源码
💻 C
字号:
#include "AT91RM9200.h"
#include "lib_AT91RM9200.h"
#include "def.h"
#include "config.h"
#include "slib.h"
#include "console.h"
#include "twi.h"
#include "params.h"



// The following DBGU ASM handler is defined in asm_isr.s
//extern void AT91F_ASM_DBGU_Handler(void);

U32 downloadAddress, downloadFileSize;

//char hex_ch[16] = {'0','1','2','3','4','5','6','7',
//				   '8','9','a','b','c','d','e','f'};

static U8 OurEmacAddr[6] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};

volatile U32 StTick;
void (*StIrqHandler)(void);
void (*DbguIrqHandler)(void);

static void SysIrqHandler(void)
{
	/* ========== Systimer interrupt ============== */
	if(AT91F_ST_GetInterruptMaskStatus(AT91C_BASE_ST) & AT91C_ST_PITS) {
		if (AT91C_BASE_ST->ST_SR & AT91C_ST_PITS) {
			StTick++;
			if(*StIrqHandler)
				(*StIrqHandler)();
			return;
		}
	}
	
	if(*DbguIrqHandler)
		(*DbguIrqHandler)();
}

//统一的中断入口处理
void __irq irq_handler(void)
{	
	void (*svr)(void);
	AT91PS_AIC ptr = AT91C_BASE_AIC;
	U32 i;
//	U8 irq_idx;

//取得中断入口地址可用AIC_IVR或用AIC_ISR作索引得到AIC_SVR数组中的地址
	i = ptr->AIC_IVR;		//read AIC_IVR
//	irq_idx = ptr->AIC_ISR&0x1f;
//边沿触发中断必须以此清中断
//	AT91F_AIC_ClearIt(AT91C_BASE_AIC, irq_idx);	

// Write in the IVR to support Protect Mode
// No effect in Normal Mode
// De-assert the NIRQ and clear the source in Protect Mode	
	ptr->AIC_IVR = (AT91_REG)ptr;
	
//	putch('I');
//	printf("%x,%x,%x\n", irq_idx, ptr->AIC_IPR, ptr->AIC_CISR);

	svr = (void (*)(void))i;//ptr->AIC_SVR[irq_idx];
	(*svr)();
	AT91F_AIC_AcknowledgeIt(ptr);	//退出中断前必须应答
}

static void InitPio(void)
{
	//led
	//AT91F_PIO_CfgOutput(AT91C_BASE_PIOC, AT91C_PIO_PC0|AT91C_PIO_PC2|AT91C_PIO_PC4|AT91C_PIO_PC5);
	//AT91F_PIO_ClearOutput(AT91C_BASE_PIOC, AT91C_PIO_PC0|AT91C_PIO_PC2|AT91C_PIO_PC4|AT91C_PIO_PC5);
	
	AT91F_PIO_CfgOutput(AT91C_BASE_PIOB, AT91C_PIO_PB25|AT91C_PIO_PB26);
	AT91F_PIO_ClearOutput(AT91C_BASE_PIOB, AT91C_PIO_PB25|AT91C_PIO_PB26);
	//key
//	AT91F_PIO_CfgInput(AT91C_BASE_PIOB, AT91C_PIO_PB6|AT91C_PIO_PB7|AT91C_PIO_PB8|AT91C_PIO_PB9);
	//buzzer
	AT91F_PIO_CfgOutput(AT91C_BASE_PIOB, AT91C_PIO_PB22);
	AT91F_PIO_SetOutput(AT91C_BASE_PIOB, AT91C_PIO_PB22);	
		delay(200);		
	AT91F_PIO_ClearOutput(AT91C_BASE_PIOB, AT91C_PIO_PB22);

/*	AT91F_PIO_CfgPeriph(
		AT91C_BASE_PIOB, // PIO controller base address
		((unsigned int) AT91C_PB27_PCK0    ), // Peripheral A
		0); // Peripheral B
	AT91F_PMC_EnablePCK(AT91C_BASE_PMC,
		0, 	//PCK0
		AT91C_PMC_CSS_SLOW_CLK,	//32768
		AT91C_PMC_PRES_CLK_16);	//1/16
	delay(200);
	AT91F_PIO_CfgInput(AT91C_BASE_PIOB, AT91C_PIO_PB27);*/
	
	//delay(200);
}

U32 GetFlashID(void);
int SectorProg(U32 begin, U16 *data, U32 size);
int SectorRead(U32 begin, U16 *data, U32 size);

void start_kernel(U32, U32);

static void InitNorFlash(void)
{
#ifdef	NOR_SUPPORT
	// Setup MEMC to support CS0 = static memory
	AT91C_BASE_EBI->EBI_CSA &= ~1;
	// [D15:0] pull-up
	AT91C_BASE_EBI->EBI_CFGR = (AT91C_EBI_DBPUC & 0x00) | (AT91C_EBI_EBSEN & 0x00);

	// Setup Flash 存储器参数设置CS0-CS7对应SMC2_CSR[0]-SMC2_CSR[7]
	AT91C_BASE_SMC2->SMC2_CSR[0] = (AT91C_SMC2_NWS & 0x7f)  | AT91C_SMC2_WSEN |
	                               (AT91C_SMC2_TDF & 0x200)| AT91C_SMC2_BAT  |
	                                AT91C_SMC2_DBW_16 | AT91C_SMC2_ACSS_STANDARD;/* |
	                                AT91C_SMC2_RWSETUP | AT91C_SMC2_RWHOLD; */
	printf("FLASH ID = %x\n", GetFlashID());
#endif
}

static void RunProgFrNor(U32 addr, U32 size)
{int i;
	int *temp;
//#ifdef	NOR_SUPPORT
	//temp=(int *)0x20008000;
	//for (i=0;i<0x8000;i++)
	//{ 	
	//	*temp=i;
	//	temp++;}	
	addr=0x21f00000;
	size=0x15000;
	printf("Write Data From 0x%8x, Size 0x%x to Nor Flash\n", addr, size);
	SectorProg(0x10000, (U16 *)addr, size);
//		SectorProg(0x1f0000, (U16 *)addr, size);
//#endif

//#ifdef	NOR_SUPPORT	
	/* downloadAddress  = 0x20800000;
	downloadFileSize = 0x200000;
	printf("Read Program From Nor Flash to 0x%8x, Size 0x%x\n", 
			downloadAddress, downloadFileSize);
	SectorRead(0x100000, (U16 *)downloadAddress, downloadFileSize);
	start_kernel(downloadAddress, 0);*/
//#endif
}


static void WrFileToNor(U32 addr, U32 size){
	
	int i;
	int *temp;
//#ifdef	NOR_SUPPORT
	//temp=(int *)0x20008000;
	//for (i=0;i<0x8000;i++)
	//{ 	
	//	*temp=i;
	//	temp++;}	
	addr=0x21f00000;
	size=0x15000;
	printf("Write Data From 0x%8x, Size 0x%x to Nor Flash\n", addr, size);
	SectorProg(0x0, (U16 *)addr, size);
//#endif
}


void GetNandFlashChip(void);

static void InitNandFlash(void)
{
#ifdef	NAND_SUPPORT
	AT91F_PIO_CfgPeriph(
		AT91C_BASE_PIOC, // PIO controller base address
		(unsigned int) AT91C_PC1_BFRDY_SMOE | (unsigned int) AT91C_PC3_BFBAA_SMWE,	// Peripheral A
		0);	// Peripheral B
	
	// Setup MEMC to support CS3 = NAND Flash
	AT91C_BASE_EBI->EBI_CSA |= AT91C_EBI_CS3A_SMC_SmartMedia;
	// [D15:0] pull-up
	AT91C_BASE_EBI->EBI_CFGR = (AT91C_EBI_DBPUC & 0x00) | (AT91C_EBI_EBSEN & 0x00);

	// Setup Flash 存储器参数设置CS0-CS7对应SMC2_CSR[0]-SMC2_CSR[7]
	AT91C_BASE_SMC2->SMC2_CSR[3] = (AT91C_SMC2_NWS & 0x4)  | AT91C_SMC2_WSEN |
	                               (AT91C_SMC2_TDF & 0x200)| AT91C_SMC2_BAT  |
	                                AT91C_SMC2_DBW_8;
	// Enable PIOC clock for input
	AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, ((unsigned int) 1 << AT91C_ID_PIOC));
	AT91F_PIO_CfgInput (AT91C_BASE_PIOC, AT91C_PIO_PC14);
	AT91F_PIO_CfgPullup(AT91C_BASE_PIOC, AT91C_PIO_PC14);
	AT91F_PIO_CfgOutput (AT91C_BASE_PIOC, AT91C_PIO_PC15);
//	AT91F_PIO_GetInput(AT91C_BASE_PIOC) & AT91C_PIO_PC14;

	GetNandFlashChip();
#endif
}

#ifdef	IIC_SUPPORT
#define	EEP_RW_CHK_CNT	32
#endif	/* IIC_SUPPORT */

static void InitTwi(void)
{
#ifdef	IIC_SUPPORT
	int loop;
	char data[EEP_RW_CHK_CNT];

	// Configure TWI PIOs
	AT91F_TWI_CfgPIO ();
	AT91F_PIO_CfgOpendrain(AT91C_BASE_PIOA, (unsigned int) AT91C_PA25_TWD);

	// Configure PMC by enabling TWI clock
	AT91F_TWI_CfgPMC ();
	
	// Configure TWI in master mode
	AT91F_TWI_Configure (AT91C_BASE_TWI);
		
	// Set TWI Clock Waveform Generator Register	
	AT91F_SetTwiClock(AT91C_BASE_TWI);

	// IIC启动,先测试IIC读
	printf("AT91RM9200 TWI EEPREOM Test, address is 0x%x\n", AT91C_EEPROM_I2C_ADDRESS);
	
//	for(loop=0; loop<EEP_RW_CHK_CNT; loop++)
//		data[loop] = loop;

	// Write and read iic
//	AT91F_TWI_Write(AT91C_BASE_TWI, 0x0, data, EEP_RW_CHK_CNT);
	
	// Wait 10 ms before data is written into EEPROM
//	puts("Wait at least 10 ms before value is written into EEPROM\n");
//	for (loop=0; loop<100000; loop++);
	
	for(loop=0; loop<EEP_RW_CHK_CNT; loop++)
		data[loop] = 0;	

	AT91F_TWI_Read(AT91C_BASE_TWI, 0x0, data, EEP_RW_CHK_CNT);
	
	for(loop=0; loop<EEP_RW_CHK_CNT; loop++)
		if(data[loop]!=loop)
			break;
	
	printf("Check data %s\n", (loop==EEP_RW_CHK_CNT)?"success":"fail");
	
#endif	/* IIC_SUPPORT */
}

static void ShowLed(U32 led)
{
	U8 set = 0, clr = 0;
	
	if(led&1)
		set |= 1;
	else
		clr |= 1;
		
	if(led&2)
		set |= 4;
	else
		clr |= 4;
		
	if(led&4)
		set |= 0x10;
	else
		clr |= 0x10;
		
	if(led&8)
		set |= 0x20;
	else
		clr |= 0x20;

	AT91F_PIO_SetOutput (AT91C_BASE_PIOC, set);
	AT91F_PIO_ClearOutput (AT91C_BASE_PIOC, clr);
}

void ComDownload(U32 a1, U32 a2);
void Program_eep(U32 addr, U32 size);
void WrFileToNF(U32 FileAddr, U32 FileSize);
void RdFileFrNF(U32 FileAddr, U32 FileSize);
void XmodemDownload(U32 a1, U32 a2);
//void TestNandFlash(U32 a1, U32 a2);
void EraseNandPart(U32 a1, U32 a2);
void RunProgFrNor(U32 addr, U32 size);
void tftp_main(U32 addr, U32 dummy);

static struct {
	void (*FuncAddr)(U32, U32);
	char *str;
} Functions[] = {
		{ComDownload, "Download File By Uart(DNW)"},
		{tftp_main, "Download File By Tftp"},
		{XmodemDownload, "Download File By Xmodem"},
		{Program_eep, "Write File To IIC Rom"},
		{WrFileToNF, "Write File To Nand Flash"},
		{RdFileFrNF, "Run Pragram From Nand Flash"},		
		{EraseNandPart, "Erase Nand Flash Partition"},
		{WrFileToNor, "Write File To Nor Flash for 0x0"},
		{RunProgFrNor, "Write File To Nor Flash for 0x10000"},
//		{TestNandFlash, "Test nand flash"},
		{0, 0}
	};

//*----------------------------------------------------------------------------
//* \fn    main
//* \brief 
//* 
//*----------------------------------------------------------------------------
int main(void)
{
	AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
	
	AT91F_RTC_InterruptDisable(AT91C_BASE_RTC, 0x1f);
	AT91F_ST_DisableIt(AT91C_BASE_ST, 0xf);

	AT91C_BASE_ST->ST_PIMR = 328;	// 328/32768 S
//	*AT91C_PMC_IDR = 0xf0f;	//disabled in InitSDRAM(init.c)
//	printf("\nST_PIMR = 0x%08x\n", AT91C_BASE_ST->ST_PIMR);
//	AT91F_ST_EnableIt(AT91C_BASE_ST, AT91C_ST_PITS);
	
	//设置网口MAC地址,先使能EMAC时钟,启动linux前要设置好MAC地址.
	AT91F_EMAC_CfgPMC();
	pEmac->EMAC_SA1L = ((int)OurEmacAddr[2] << 24) | ((int)OurEmacAddr[3] << 16) | ((int)OurEmacAddr[4] << 8) | OurEmacAddr[5];
	pEmac->EMAC_SA1H = ((int)OurEmacAddr[0] << 8) | OurEmacAddr[1];
	
	//when set an irq handler, the irq will be disabled in AT91F_AIC_ConfigureIt,
	//so enable it after AT91F_AIC_ConfigureIt!!!
	AT91F_AIC_ConfigureIt (
		AT91C_BASE_AIC,							// AIC base address
		AT91C_ID_SYS,							// System peripheral ID
		AT91C_AIC_PRIOR_HIGHEST,				// Max priority
		AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE,	// Level sensitive
		SysIrqHandler );						// 将设置处理函数地址填入AIC_SVC[AT91C_ID_SYS]
	//使能系统中断(包括ST,DBGU等)
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS);
	
	MMU_EnableICache();
	
	downloadAddress = LINUX_KERNEL_ADDR;

/*	while(1) {	//读NAND FLASH 的BUSY脚状态
		if(AT91F_PIO_GetInput(AT91C_BASE_PIOC)&AT91C_PIO_PC14)
			putch('1');
		else
			putch('0');
		delay(100);	
	}*/
	
/*	while(1) {
		delay(300);
		putch('a');
	}*/	
	
	puts("\n*********************************************\n");
	puts("*                                           *\n");
	puts("*           BIOS For AT91RM9200             *\n");
	puts("*                                           *\n");
	puts("*********************************************\n");

	//get counter from CKGR_MCFR
	printf("Set Processor Clock = %dHz, Master Clock = %dHz\n", 
			AT91F_PMC_GetProcessorClock(AT91C_BASE_PMC, AT91C_BASE_CKGR, 32768), 
			AT91F_PMC_GetMasterClock(AT91C_BASE_PMC, AT91C_BASE_CKGR, 32768));
	
	printf("Test by kim\n");		
	InitPio();
	printf("Test by kim  3.31\n");
	//InitTwi();
	InitNorFlash();
	/*InitNandFlash();  */
	
	while(1) {
		U16 i;
		U8 c;
		
		puts("Select\n");
		for(i=0; Functions[i].FuncAddr; i++)
			printf("%d : %s\n", i, Functions[i].str);
		putch('\n');	
		c = getch();
		if((c>='0')&&(c<('0'+i)))
			(*Functions[c-'0'].FuncAddr)(downloadAddress, downloadFileSize);
	}
}

static volatile U8 *RxTmp;

void DBGU_Rx_Isr(void)
{
	//读完状态寄存器后才清掉中断源
	unsigned int csr = (((AT91PS_USART)AT91C_BASE_DBGU)->US_CSR & ((AT91PS_USART)AT91C_BASE_DBGU)->US_IMR);
	if (csr & AT91C_US_RXRDY) {
		*RxTmp = AT91F_US_GetChar((AT91PS_USART) AT91C_BASE_DBGU);
//		putch(*RxTmp);
		RxTmp++;
	}
}

U32 WaitComDownload(void);

void ComDownload(U32 a1, U32 a2)
{
	U8 sel;

	puts("Select\n1: Kernel\n2: initrd\n3: boot\nEsc: exit\n");
	while(1) {
		sel = getch();
		if(sel=='1') {
			downloadAddress = LINUX_KERNEL_ADDR;
			break;
		}
		if(sel=='2') {
			downloadAddress = INITRD_START;
			break;
		}
		if(sel=='3') {
			downloadAddress = BOOT_PORG_ADDR;
			break;
		}
		if(sel==0x1b)
			return;
	}
	
	if(WaitComDownload())
		return;
	
	if(sel=='2')
		return;
	
	if(sel=='3')
		start_kernel(downloadAddress, 0);
		
	puts("Do you want to run it ?\n1: boot without initrd\n2: boot wiht initrd\nEsc: exit\n");
	while(1) {
		char c = getch();
		if(c==0x1b)
			break;
		if((c=='1')||(c=='2'))
			start_kernel(downloadAddress, (c=='1')?0:INITRD_START);
	}
}
/*
void RunProg(U32 addr, U32 size)
{
	start_kernel(downloadAddress, 0);
}*/

void Program_eep(U32 addr, U32 size)
{
#ifdef	IIC_SUPPORT
	char *pdata;
	U32 eep_addr;
	int bytes, len;
	U32 loop;
	char data[EEP_RW_CHK_CNT];
	
	eep_addr = 0;
	pdata = (char *)addr;
	len = size;

	while(len>0) {
		putchar('.');
		bytes = (len>EEP_RW_CHK_CNT)?EEP_RW_CHK_CNT:len;
		AT91F_TWI_Write(AT91C_BASE_TWI, eep_addr, pdata, bytes);
		eep_addr += bytes;
		pdata += bytes;
		len -= bytes;				
		//for (loop=0; loop<30000; loop++);
		delay(5);
	}
	puts("end\n");
	
	eep_addr = 0;
	pdata = (char *)addr;
	len = size;
	
	while(len) {
		bytes = (len>EEP_RW_CHK_CNT)?EEP_RW_CHK_CNT:len;
		AT91F_TWI_Read(AT91C_BASE_TWI, eep_addr, data, bytes);
		for(loop=0; loop<bytes; loop++)
			if(data[loop]!=pdata[loop]) {
				puts("Program EEPROM fail!\n");
				printf("%x,%x\n", loop, data[loop]);
				return;
			}
		eep_addr += bytes;
		pdata += bytes;
		len -= bytes;
	}
	puts("Program EEPROM Success!\n");
#endif	
}

U32 WaitComDownload(void)
{
	U32 size;
	U16 dnCS, CheckSum;
	U8 *buf;

	puts("Now downloadfile from uart0...\n");
	buf    = (U8 *)downloadAddress;
	RxTmp  = buf-4;
	
	//设置调试串口中断处理程序入口,使能属于调试串口的子中断
	DbguIrqHandler = DBGU_Rx_Isr;
	AT91F_US_EnableIt((AT91PS_USART) AT91C_BASE_DBGU, (AT91C_US_RXRDY | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE));
	
	while((U32)RxTmp<(U32)buf) {
		ShowLed(0);
		delay(80);
		ShowLed(15);
		delay(80);
    }							//接收文件长度,4 bytes
   	size = *(U32 *)(buf-4);
	downloadFileSize = size-6;
	printf("Download File Size = %d\n", size);

	while(((U32)RxTmp-(U32)buf)<(size-4)) {
		ShowLed(0);
		delay(80);
		ShowLed(15);
		delay(80);
	}
	
	AT91F_US_DisableIt((AT91PS_USART) AT91C_BASE_DBGU, (AT91C_US_RXRDY | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE));
	DbguIrqHandler = NULL;
	
	dnCS = (buf[downloadFileSize+1]<<8)|buf[downloadFileSize];
	CheckSum = 0;
	for(size=0; size<downloadFileSize; size++)
		CheckSum += buf[size];
	if(dnCS!=CheckSum) {
		puts("\nCheckSum error!\n");
		return 1;
	}
	
	puts("\nDwonload success\n");
	return 0;	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -