自己写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
- 自己写bootloader(2)——main函数
- 自己写bootloader(1)——start.S
- 自己写bootloader(3)——实现printf
- 自己写bootloader(4)——实现字符界面
- 自己写bootloader(5)——命令的实现
- 自己写 bootloader
- 自己写bootloader
- 自己写BootLoader
- 自己写 bootloader
- 自己写 bootloader
- 自己写bootloader笔记2---start.S分析
- 自己写bootloader笔记2---start.S分析
- 用C#自己写WPF的Main函数
- 调试BootLoader无法跳转至main函数
- u-boot学习(六):自己写bootloader
- 自己写bootloader笔记1---流程分析
- 自己写bootloader笔记7---Makefile分析
- 自己写bootloader笔记1---流程分析
- 【IOS网络通信】socket第三方库 AsyncSocket(GCDAsyncSocket)
- wamp server的Apache无法启动,始终显示黄色的解决办法
- 双11,超现实的电商马拉松
- HR数据字典
- FPGA在医疗电子领域的应用及发展趋势
- 自己写bootloader(2)——main函数
- Servlet(一)第一个Servlet
- 网络爬虫的介绍
- 麻省理工学院公开课:算法导论15动态规划
- NSString的几种常用方法
- v$sqlarea和v$lock
- SQL SERVER DBA随笔
- 3D打印医疗应用
- 如何配置自己的服务器接入微信服务器