首页>>论坛 >>技术社区 >>OpenHW社区论坛 >>ZYNQ及嵌入式操作系统
|
我要发帖  | 我要投票  | 我要回复  | 收藏
1

ArmLinux bootloader 全程详解2

版主: Jerry Fan  玄剑  jennyzheng  XUPteam 
ArmLinux bootloader 全程详解2
 

2410init.c file

int main(int argc,char **argv)

{

u32 test = 0;

void (*theKERNEL)(int zero, int arch, unsigned long params_addr) = (void (*)(int, int, unsigned long))RAM_COMPRESSED_KERNEL_BASE; //压缩后的IMAGE地址

int i,k=0;

// downPt=(RAM_COMPRESSED_KERNEL_BASE);

chkBs=(_RAM_STARTADDRESS);//SDRAM开始的地方

// fromPt=(FLASH_LINUXKERNEL);

MMU_EnableICache();

ChangeClockDivider(1,1); // 1:2:4

ChangeMPllValue(M_MDIV,M_PDIV,M_SDIV); //Fin=12MHz FCLK=200MHz

Port_Init();//设置I/O端口,在使用com口前,必须调用这个函数,否则通信芯片根本得不到数据

Uart_Init(PCLK, 115200);//PCLK使用默认的200000,拨特率115200

/*******************(检查ram空间)*******************/

Uart_SendString("\n\tLinux S3C2410 Nor BOOTLOADER\n");

Uart_SendString("\n\tChecking SDRAM 2410loader.c...\n");

for(;chkBs<0x33FA0140;chkBs=chkBs+0x4,test++)//


//根据我的经验,最好以一个字节为递增,我们的板子,在256byte递增检测的时候是没问题的,但是

//以1byte递增就出错了,第13跟数据线随几的会冒”1”,检测出来是硬件问题,现象如下

// 用仿真器下代码测试SDRAM,开始没贴28F128A3J FLASH片子,测试结果很好,但在上了FLASH片子//之后,测试数据(data)为0x00000400连续成批写入读出时,操作大约1k左右内存空间就会出错,//而且随机。那个出错数据总是变为0x00002400,数据总线10位和13位又没短路发生。用其他数据//测试比如 0x00000200;0x00000800没这问题。dx帮忙。

//至今没有解决,所以我用不了Flash.

{

chkPt1 = chkBs;

*(u32 *)chkPt1 = test;//写数据

if(*(u32 *)chkPt1==1024))//读数据和写入的是否一样?

{

chkPt1 += 4;

Led_Display(1);

Led_Display(2);

Led_Display(3);

Led_Display(4);

}

else

goto error;

}

Uart_SendString("\n\tSDRAM Check Successful!\n\tMemory Maping...");

get_memory_map();

//获得可用memory 信息,做成列表,后面会作为启动参数传给KERNEL

//所谓内存映射就是指在4GB 物理地址空间中有哪些地址范围被分配用来寻址系统的 RAM 单元。

Uart_SendString("\n\tMemory Map Successful!\n");

//我用仿真器把KERNEL,RAMDISK直接放在SDRAM上,所以下面这段是不需要的,但是如果KERNEL,RAMDISK在FLASH里,那就需要.

/*******************(copy linux KERNEL)*******************/

Uart_SendString("\tLoading KERNEL IMAGE from FLASH... \n ");

Uart_SendString("\tand copy KERNEL IMAGE to SDRAM at 0x31000000\n");

Uart_SendString("\t\tby LEIJUN DONG dongleijun4000@hotmail.com \n");

for(k = 0;k < 196608;k++,downPt += 1,fromPt += 1)//3*1024*1024/32linux KERNEL des,src,length=3M

* (u32 *)downPt = * (u32 *)fromPt;

/*******************(load RAMDISK)*******************/

Uart_SendString("\t\tloading COMPRESSED RAMDISK...\n");

downPt=(RAM_COMPRESSED_RAMDISK_BASE);

fromPt=(FLASH_RAMDISK_BASE);

for(k = 0;k < 196608;k++,downPt += 1,fromPt += 1)//3*1024*1024/32linux KERNEL des,src,length=3M

* (u32 *)downPt = * (u32 *)fromPt;

/******jffs2文件系统,在开发中如果用不到FLASH,这段也可以不要********/

Uart_SendString("\t\tloading jffs2...\n");

downPt=(RAM_JFFS2);

fromPt=(FLASH_JFFS2);

for(k = 0;k < (1024*1024/32);k++,downPt += 1,fromPt += 1)

* (u32 *)downPt = * (u32 *)fromPt;

Uart_SendString( "Load Success...Run...\n ");

/*******************(setup param)*******************/

setup_start_tag();//开始设置启动参数

setup_memory_tags();//内存印象

setup_commandline_tag("console=ttyS0,115200n8");//启动命令行

setup_initrd2_tag();//root device

setup_RAMDISK_tag();//ramdisk image

setup_end_tag();

/*关I-cache */

asm ("mrc p15, 0, %0, c1, c0, 0": "=r" (i));

i &= ~0x1000;

asm ("mcr p15, 0, %0, c1, c0, 0": : "r" (i));

/* flush I-cache */

asm ("mcr p15, 0, %0, c7, c5, 0": : "r" (i));

//下面这行就跳到了COMPRESSED KERNEL的首地址

theKERNEL(0, ARCH_NUMBER, (unsigned long *)(RAM_BOOT_PARAMS));

//启动kernel时候,I-cache可以开也可以关,r0必须是0,r1必须是CPU型号

(可以从linux/arch/arm/tools/mach-types中找到),r2必须是参数的物理开始地址

/*******************END*******************/

error:

Uart_SendString("\n\nPanic SDRAM check error!\n");

return 0;

}

static void setup_start_tag(void)

{

params = (struct tag *)RAM_BOOT_PARAMS;//启动参数开始的地址

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);

}



static void setup_memory_tags(void)

{

int i;


for(i = 0; i < NUM_MEM_AREAS; i++) {

if(memory_map[i].used) {

params->hdr.tag = ATAG_MEM;

params->hdr.size = tag_size(tag_mem32);

params->u.mem.start = memory_map[i].start;

params->u.mem.size = memory_map[i].len;

params = tag_next(params);

}

}

}



static void setup_commandline_tag(char *commandline)

{

int i = 0;

/* skip non-existent command lines so the kernel will still

* use its default command line.

*/

params->hdr.tag = ATAG_CMDLINE;

params->hdr.size = 8;

//console=ttyS0,115200n8

strcpy(params->u.cmdline.cmdline, p);

params = tag_next(params);

}



static void setup_initrd2_tag(void)

{

/* an ATAG_INITRD node tells the kernel where the compressed

* ramdisk can be found. ATAG_RDIMG is a better name, actually.

*/

params->hdr.tag = ATAG_INITRD2;

params->hdr.size = tag_size(tag_initrd);

params->u.initrd.start = RAM_COMPRESSED_RAMDISK_BASE;

params->u.initrd.size = 2047;//k byte

params = tag_next(params);

}



static void setup_ramdisk_tag(void)

{

/* an ATAG_RAMDISK node tells the kernel how large the

* decompressed ramdisk will become.

*/

params->hdr.tag = ATAG_RAMDISK;

params->hdr.size = tag_size(tag_ramdisk);

params->u.ramdisk.start = RAM_DECOMPRESSED_RAMDISK_BASE;

params->u.ramdisk.size = 7.8*1024; //k byte

params->u.ramdisk.flags = 1; // automatically load ramdisk

params = tag_next(params);

}



static void setup_end_tag(void)

{

params->hdr.tag = ATAG_NONE;

params->hdr.size = 0;

} void Uart_Init(int pclk,int baud)//串口是很重要的

{

int i;

if(pclk == 0)

pclk = PCLK;

rUFCON0 = 0x0; //UART channel 0 FIFO control register, FIFO disable

rUMCON0 = 0x0; //UART chaneel 0 MODEM control register, AFC disable


//UART0

rULCON0 = 0x3; //Line control register : Normal,No parity,1 stop,8 bits

下面这段samsung好象写的不太对,但是我按照Normal,No parity,1 stop,8 bits算出来的确是0x245


// [10] [9] [8] [7] [6] [5] [4] [3:2] [1:0]

// Clock Sel, Tx Int, Rx Int, Rx Time Out, Rx err, Loop-back, Send break, Transmit Mode, Receive Mode

// 0 1 0 , 0 1 0 0 , 01 01

// PCLK Level Pulse Disable Generate Normal Normal Interrupt or Polling

rUCON0 = 0x245; // Control register

rUBRDIV0=( (int)(PCLK/16./ baud) -1 ); //Baud rate divisior register 0

delay(10);

}

经过以上的折腾,接下来就是kernel的活了.能不能启动kernel,得看你编译kernel的水平了.

这个BOOTLOADER不象blob那样需要交互信息,使用虚拟地址,总的来说非常简洁明了.

 
相关主题
一个人之所以快乐,不是因为他得到的多,而是因为他计较的少
回复 链接 收藏
 
我要发帖  | 我要投票  | 我要回复  | 收藏
1