很久前的代码(初学时写的,比较乱,望见谅),希望对阅读本文的读者有所帮助。
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
效果:
源码下载:点击打开链接