自己写bootloader(2)——main函数

来源:互联网 发布:怎么在淘宝社区发帖 编辑:程序博客网 时间:2024/06/04 23:52

之前已经写过在main函数中

6.初始化串口

7.读内核到内存

8.设置参数

9.跳转执行



初始化串口

void uart0_init(void){    GPHCON  |= 0xa0;    // GPH2,GPH3用作TXD0,RXD0    GPHUP   = 0x0c;     // GPH2,GPH3内部上拉    ULCON0  = 0x03;     // 8N1(8个数据位,无较验,1个停止位)    UCON0   = 0x05;     // 查询方式,UART时钟源为PCLK    UFCON0  = 0x00;     // 不使用FIFO    UMCON0  = 0x00;     // 不使用流控    UBRDIV0 = UART_BRD; // 波特率为115200}
初始化串口的函数无非就是设置一些寄存器,参考2440手册

写一个打印字符串的函数,用于调试

void puts(char *str){int i = 0;while (str[i]){putc(str[i]);i++;}}
void putc(unsigned char c){    /* 等待,直到发送缓冲区中的数据已经全部发送出去 */    while (!(UTRSTAT0 & TXD0READY));        /* 向UTXH0寄存器中写入数据,UART即自动将它发送出去 */    UTXH0 = c;}

再写一个打印十六进制数的函数,用于打印某些数值

void puthex(unsigned int val){/* 0x1234abcd */int i;int j;puts("0x");for (i = 0; i < 8; i++){j = (val >> ((7-i)*4)) & 0xf;if ((j >= 0) && (j <= 9))putc('0' + j);elseputc('A' + j - 0xa);}}


读内核到内存

nand_read(0x60000+64, (unsigned char *)0x30008000, 0x200000);
读nand的函数之前写过了

内核存在0x60000处,加上64字节的头部

目的为0x30008000

长度为0x200000



设置参数

bootloader需要传递一些信息给内核,把这些信息放在一个约定的地点,内核运行的时候会从这个地方读

bootloader中有个结构体名为tag,我们设置四个结构体放在约定的地方就可以了

setup_start_tag();setup_memory_tags();setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");setup_end_tag();
一个是起始tag

一个是存储内存信息的tag

一个是存储命令行参数的tag

一个是结束tag

void setup_start_tag(void){params = (struct tag *)0x30000100;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);}
void setup_memory_tags(void){params->hdr.tag = ATAG_MEM;params->hdr.size = tag_size (tag_mem32);params->u.mem.start = 0x30000000;params->u.mem.size  = 64*1024*1024;params = tag_next (params);}
int strlen(char *str){int i = 0;while (str[i]){i++;}return i;}void strcpy(char *dest, char *src){while ((*dest++ = *src++) != '\0');}void setup_commandline_tag(char *cmdline){int len = strlen(cmdline) + 1;params->hdr.tag  = ATAG_CMDLINE;params->hdr.size = (sizeof (struct tag_header) + len + 3) >> 2;strcpy (params->u.cmdline.cmdline, cmdline);params = tag_next (params);}
void setup_end_tag(void){params->hdr.tag = ATAG_NONE;params->hdr.size = 0;}
设置完一个tag会把params指向tag_next (params)




跳转执行

void (*theKernel)(int zero, int arch, unsigned int params);
定义一个函数指针

theKernel = (void (*)(int, int, unsigned int))0x30008000;theKernel(0, 362, 0x30000100);  
让函数指针指向一个地址

执行这个函数就会到指定的地址去执行






0 0
原创粉丝点击