基于proteus的ARM7TDMI引导uclinux的bootloader

很久前的代码(初学时写的,比较乱,望见谅),希望对阅读本文的读者有所帮助。

main.c

#include"config.h"
//注意volatile关键字不能少,否则变量不能正常赋值读取。
extern volatile unsigned int maxnum;//防止被优化掉
extern volatile unsigned char f;
extern volatile unsigned char tmp;
int ins;

int main()
{
	int cnt=0;
	LCR=0x83;
	DLM=0x0;
	DLL=0x01;
	LCR=0x03;
	
	IER=0x1;		//使能接收中断
	maxnum=5;
	
	CNT=0;			//清CNT,以供reboot时使用
	CNTINT=0x0;		//清零计数器中断
    INTFLG=0x03;	//清零中断标志位,以供reboot时使用
    
	pISR_USART=(unsigned)USARTinterrupt;
	pISR_CNT=(unsigned)CNTinterrupt;
	
	
	putS("\r\nARM7TDMI proteus Lab by Chen Qianyi");
	putS("\r\nverion 1.8.0");
	putS("\r\nbootloader test!");
	putS("\r\na sample bootloader!");
	putS("\r\njust boot linux kernel image!");
	putS("\r\nHit any key to stop autoboot: ");
	
	BUF=maxnum+'0';
	while(!(LSR&0x40));
	INTMSK=0x03;//使能中断
	
	while(((f&0x01)==0)&&(maxnum>0));

	
	if(f==1)
		putS("\b\b0\r\nMyBoot # ");
	else
	{
		bootm();
		putS("\r\nMyBoot # ");
	}
	f=0;
	
	while(1)
	{
		
		if(f==1)
		{
			f=0;
			if(cnt==0)
			{
				
				if((tmp&0xff)==0xd)
					putS("MyBoot # ");
				else
				{
					if((tmp&0xff)=='\b')
						putS(" ");
					else
					{
						ins=tmp;
						cnt++;
					}
				}
			}else{
				cnt=0;
				if((tmp&0xff)!='\b')
				{
					if((tmp&0xff)!=0xd)
						putS("\r\nWrong MyBoot command...");
					else
					{
						parse_cmd(ins);
					}
					putS("\r\nMyBoot # ");
				}
			}
		}
		
	}
	
	return 0;
}
boot.c

#include"config.h"

static struct tag *params=(struct tag *)0xc0ff0000;
char commandline[44]="devfs=mount root=romfs console=ttyS0,115200";


typedef struct image_header 
{
	uint32_t	ih_magic;					/* Image Header Magic Number	*/
	uint32_t	ih_hcrc;					/* Image Header CRC Checksum	*/
	uint32_t	ih_time;					/* Image Creation Timestamp		*/
	uint32_t	ih_size;					/* Image Data Size				*/
	uint32_t	ih_load;					/* Data  Load  Address			*/
	uint32_t	ih_ep;						/* Entry  Point  Address		*/
	uint32_t	ih_dcrc;					/* Image Data CRC Checksum		*/
	uint8_t		ih_os;						/* Operating System				*/
	uint8_t		ih_arch;					/* CPU architecture				*/
	uint8_t		ih_type;					/* Image Type					*/
	uint8_t		ih_comp;					/* Compression Type				*/
	uint8_t		ih_name[IH_NMLEN];			/* Image Name					*/
} image_header_t;

struct tag_header 
{
	u32 size;
	u32 tag;
};
struct tag_core 
{
	u32 flags;			/* bit 0 = read-only */
	u32 pagesize;
	u32 rootdev;
};
struct tag_mem32 
{
	u32	size;
	u32	start;			/* physical start address */
};
struct tag_videotext 
{
	u8		x;
	u8		y;
	u16		video_page;
	u8		video_mode;
	u8		video_cols;
	u16		video_ega_bx;
	u8		video_lines;
	u8		video_isvga;
	u16		video_points;
};
struct tag_ramdisk 
{
	u32 flags;			/* bit 0 = load, bit 1 = prompt */
	u32 size;			/* decompressed ramdisk size in _kilo_ bytes */
	u32 start;			/* starting block of floppy-based RAM disk image */
};
/* describes where the compressed ramdisk image lives (physical address) */
struct tag_initrd 
{
	u32 start;			/* physical start address */
	u32 size;			/* size of compressed ramdisk image in bytes */
};
struct tag_serialnr 
{
	u32 low;
	u32 high;
};
struct tag_revision 
{
	u32 rev;
};
struct tag_videolfb 
{
	u16		lfb_width;
	u16		lfb_height;
	u16		lfb_depth;
	u16		lfb_linelength;
	u32		lfb_base;
	u32		lfb_size;
	u8		red_size;
	u8		red_pos;
	u8		green_size;
	u8		green_pos;
	u8		blue_size;
	u8		blue_pos;
	u8		rsvd_size;
	u8		rsvd_pos;
};
struct tag_cmdline 
{
	char	cmdline[1];	/* this is the minimum size */
};
struct tag_acorn 
{
	u32 memc_control_reg;
	u32 vram_pages;
	u8 sounddefault;
	u8 adfsdrives;
};
struct tag_memclk 
{
	u32 fmemclk;
};

struct tag 
{
	struct tag_header hdr;
	union 
	{
		struct tag_core	core;
		struct tag_mem32	mem;
		struct tag_videotext	videotext;
		struct tag_ramdisk	ramdisk;
		struct tag_initrd	initrd;
		struct tag_serialnr	serialnr;
		struct tag_revision	revision;
		struct tag_videolfb	videolfb;
		struct tag_cmdline	cmdline;
		struct tag_acorn	acorn;
		struct tag_memclk	memclk;
	} u;
};



int strlen(const char *s)
{
	int i = 0;

	for(;*s != '\0'; s++)
		i++;
	
	return i;
}
char * strcpy(char * dest,const char *src)
{
	char *tmpr = dest;

	while ((*dest++ = *src++) != '\0')
		/* nothing */;
	return tmpr;
}
void memcpy(char *s1, const char *s2, int n)
{
	int i;

	for (i = 0; i < n; i++)
		((char *)(s1))[i] = ((const char *)(s2))[i];
}


void bootArg(void)
{
	int c;
	params->hdr.tag = ATAG_CORE;
    params->hdr.size = tag_size(tag_core);
    params->u.core.flags = 0;
    params->u.core.pagesize = 0;
    params->u.core.rootdev = 0;
    params = tag_next(params);
	
    params->hdr.tag = ATAG_CMDLINE;
    params->hdr.size = (sizeof(struct tag_header) + 44) >> 2; 
    for(c=0;c<44;c++)
    {
    	*(params->u.cmdline.cmdline+c)=commandline[c];
    }
    params = tag_next(params);

	params->hdr.tag = ATAG_NONE;
    params->hdr.size = 0;
}


void Int2HexStr(unsigned long n,char *str)
{
    int i = 0;
    unsigned char tp;			
	unsigned long temp=0; //  int temp = n < 0 ? -n: n;// temp为n的绝对值
	
	for(i=4;i>0;i--)
	{
		temp=temp+(unsigned long)((n%256)<<(8*(i-1)));
		n=n/256;
	}
	
	if (str == NULL)
	{
	   return;
	}
	i=7;
	while(i>=0)
	{
		tp=(unsigned char)(temp % 16);
		if(tp>9)
		{
			str[i--] =tp-10+'A';
		}
		else
		{
			str[i--] =tp+'0';
		}
		temp = temp / 16;				
	}

}
	
void int2str(unsigned long n,char *str)
{
    char buf[30] = "";
    int i = 0;
    int len = 0;			
	unsigned long temp=0; //  int temp = n < 0 ? -n: n;// temp为n的绝对值
	
	for(i=4;i>0;i--)
	{
		temp=temp+(unsigned long)((n%256)<<(8*(i-1)));
		n=n/256;
	}
	
	if (str == NULL)
	{
	   return;
	}
	while(temp)
	{
	   buf[i++] = (temp % 10) + '0'; 	//把temp的每一位上的数存入buf
	   temp = temp / 10;				//相当于十进制数据每次右移一位
	}
	
//	len = n < 0 ? ++i: i;  				//如果n是负数,则多需要一位来存储负号
	len = i;
    str[i] = 0;            				//末尾是结束符0
    while(1)
    {
       i--;
       if (buf[len-i-1] ==0)
       {
           break;
       }
       str[i] = buf[len-i-1];  			//把buf数组里的字符拷到字符串
	}
	if (i == 0 ) 
	{
	   str[i] = '-';          			//如果是负数,添加一个负号
	}
}

unsigned long byteSW(unsigned long num)
{
	int i;
	unsigned long ret=0;//必须初始化
	for(i=4;i>0;i--)
	{
		ret=ret+(unsigned long)((num%256)<<(8*(i-1)));//必须用上强制类型转换保持类型的一致性,不然会出转换不正确的问题的
		num=num/256;
	}
	return ret;
} 

void gon()
{
	char *cmdline="devfs=mount root=romfs console=ttyS0,115200";
	void (*fp)(int,int);
	image_header_t *hdr1=(image_header_t *)0x10000000;
	int len=0,i,j=0;
	volatile unsigned long *star=(volatile unsigned long *)(byteSW(hdr1->ih_load));
	len=byteSW(hdr1->ih_size);
	putS("   Cmdline:   ");
	putS(cmdline);
	bootArg();
	putS("\r\n   Loading kernel image..........");
	
	for(i=0;iih_magic))
		putS("0x27051956");	
	else
	{
		int2str(hdr->ih_magic,tempStr);
		putS(tempStr);
		putS("\r\n       error magic Number");
		return;
	}
	
	putS("\r\n   Image Name:   ");
	putS((char *)hdr->ih_name);
	putS("\r\n   Image Type:   ");
	
	if(IH_CPU_ARM==hdr->ih_arch)
		putS("ARM ");
	else
		putS("Not ARM ");
		
	if(IH_OS_ARTOS==hdr->ih_os)
		putS("ARTOS ");
	else if(IH_OS_LINUX==hdr->ih_os)
		putS("Linux OS ");
	else
		putS("Unknown OS ");
		
	if(IH_TYPE_KERNEL==hdr->ih_type)
		putS("Kernel Image ");
	else
		putS("Not Kernel Image ");
		
	if(IH_COMP_NONE==hdr->ih_comp)
		putS("(uncompressed)");
	else
		putS("(Not uncompressed)");	
	
	putS("\r\n   Data  Size:   ");
	int2str(hdr->ih_size,tempStr);
	putS(tempStr);
	putS("Bytes");
	
	putS("\r\n   Load Address:   ");
	Int2HexStr(hdr->ih_load,tempStr);
	putS(tempStr);
	
	putS("\r\n   Entry  Point:   ");
	Int2HexStr(hdr->ih_ep,tempStr);
	putS(tempStr);
	putS("\r\n");
	gon();
}
sh.c

#include"config.h"

struct	Cmd {
    char    name;		
    void	(*func)();		
    char    *helptxt;	
	};

struct	Cmd tst[Number]=
{
	{'h',(void(*)())help,"print help information!\r\n"},
	{'?',(void(*)())help,"=help information!\r\n"},
	{'b',(void(*)())bootm,"run application program!\r\n"},
	{'r',(void(*)())reboot,"reboot MyBoot system!\r\n"},
};
void help(void)
{
	int i;
	putS("\r\n");
	for(i=0;i0;x--)
		for(y=110;y>0;y--);
}

void putS(char *s)
{
	while(*s!='\0')
	{
		BUF = *s++;
		while(!(LSR&0x40));
	}
}

void parse_cmd(char para)
{
	int i;
	for(i=0;i
init.s

_ISR_STARTADDRESS   EQU   0xc0dfff00

INTFLG		EQU 0x80000008
INTMSK		EQU 0x8000000c

CNTINT		EQU 0x80000004

IRQMODE	    EQU	0x12
SVCMODE	    EQU	0x13
MODEMASK    EQU	0x1f
NOINT	    EQU	0xc0

		    IMPORT	|Image$$RO$$Limit|  	; End of ROM code (=start of ROM data)
		    IMPORT	|Image$$RW$$Base|   	; Base of RAM to initialise
		    IMPORT	|Image$$ZI$$Base|   	; Base and limit of area
		    IMPORT	|Image$$ZI$$Limit|  	; to zero initialise
			IMPORT main						;从外部引入的标识
			EXPORT  __ENTRY					;从内部引出的标识
			AREA	Example,CODE,READONLY	;声明代码段Example 
			ENTRY							;标识程序入口
			CODE32							;声明32位ARM指令
__ENTRY			
	    b ResetHandler  ;for debug
	    b HandlerUndef  ;handlerUndef
	    b HandlerSWI    ;SWI interrupt handler
	    b HandlerPabort ;handlerPAbort
	    b HandlerDabort ;handlerDAbort
	    b .		    	;handlerReserved
	    b HandlerIRQ
	    b HandlerFIQ
HandlerIRQ
		sub		lr, lr, #4
		stmfd   sp!,{r0-r12,lr} 
		mrs		r0, spsr
		stmfd	sp!,{r0}

	    ldr	    r0,=INTMSK
		ldr	    r1,=0x00  ;all interrupt disable
		str	    r1,[r0]
		
		ldr	    r9,=INTFLG
		ldr	    r9,[r9]
		mov	    r8,#0x0
0
		movs    r9,r9,lsr #1
		bcs	    %F1
		add	    r8,r8,#4
		b	    %B0

1
		ldr	    r9,=HandleCNT
		add	    r9,r9,r8
		ldr	    r9,[r9]
		cmp		r9, #0
		movne	lr, pc
		movne	pc, r9
2 		

	    
	    ldr	    r0,=INTFLG
		ldr	    r1,=0x03  
		str	    r1,[r0]
    	
		ldmfd	sp!, {r0}		;从IRQ返回
		msr		spsr_cxsf, r0
		ldmfd	sp!, {r0-r12, pc}^
				

ResetHandler
HandlerUndef
HandlerSWI
HandlerPabort
HandlerDabort
HandlerFIQ

		
		ldr	    r0,=INTMSK
		ldr	    r1,=0x00  ;all interrupt disable
		str	    r1,[r0]
		
		mrs	    r0,cpsr
    	bic	    r0,r0,#MODEMASK
		
		orr	    r1,r0,#IRQMODE|NOINT
		msr	    cpsr_cxsf,r1 	    	;IRQMode
		ldr	    sp,=IRQStack
		
		bic	    r0,r0,#MODEMASK|NOINT
		orr	    r1,r0,#SVCMODE
		msr	    cpsr_cxsf,r1 	    	;SVCMode
		ldr	    sp,=SVCStack
		
	    LDR	    r0, =0xc0f00000	
	    LDR		r1, =0x0		
	    LDR	    r2, =|Image$$ZI$$Limit|	;注意,此时的Image$$ZI$$Limit为设置的ro_base后的地址值
	    sub		r2,r2,r0				
3				
		ldmia	r1!,{r3-r7}
		stmia	r0!,{R3-R7}
		cmp		r1,r2
		bcc		%b3
		
		ldr		pc,=start_c
start_c			
		bl main
		b .

	ALIGN

	AREA RamData,DATA,READWRITE

	^	(_ISR_STARTADDRESS-0x300)
	
SVCStack	#	256				
IRQStack	#	256


	^	_ISR_STARTADDRESS
HandleCNT	#	4
HandleUSART	#	4			
			
			END
效果:
基于proteus的ARM7TDMI引导uclinux的bootloader_第1张图片

源码下载:点击打开链接


你可能感兴趣的:(arm)