实现简单的 u-boot
根据u-boot-1.1.6启动流程来划分,u-boot功能主要划分为四个部分
1,硬件初始化 -->start.S init.c
2,从 flash 拷贝内核到 ram -->main.c
3,设置 tag 参数 -->tag.c tag.h
4,跳到内核,执行内核代码 --> main.c
start.s源码:
.extern main .text
.global _start
_start:
bl disable_watchdog
bl clock_init
bl open_icache
bl sdram_init
bl uart0_init
bl nand_init ldr sp, =0x34000000
ldr r0,=
ldr r1,=_start
ldr r2,=__bss_start @0x33f80000
sub r2,r2,r1
bl copy_uboot_to_sdram
ldr pc,=on_sdram on_sdram:
bl clean_bss
ldr lr,=main_return
ldr pc,=main
main_return:
b main_return
init.c源码:
//watchdog
#define WTCON (*(volatile unsigned long *)0x53000000) //clock
#define CLOCKTIME (*(volatile unsigned long *)0x4c000000)
#define MPLLCON (*(volatile unsigned long *)0x4c000004)
#define CLKDIVN (*(volatile unsigned long *)0x4c000014)
#define CAMDIVN (*(volatile unsigned long *)0x4c000018) //sdram
#define BWSCON (*(volatile unsigned long *)0x48000000)
#define BANKCON0 (*(volatile unsigned long *)0x48000004)
#define BANKCON1 (*(volatile unsigned long *)0x48000008)
#define BANKCON2 (*(volatile unsigned long *)0x4800000c)
#define BANKCON3 (*(volatile unsigned long *)0x48000010)
#define BANKCON4 (*(volatile unsigned long *)0x48000014)
#define BANKCON5 (*(volatile unsigned long *)0x48000018)
#define BANKCON6 (*(volatile unsigned long *)0x4800001c)
#define BANKCON7 (*(volatile unsigned long *)0x48000020)
#define REFRESH (*(volatile unsigned long *)0x48000024)
#define BANKSIZE (*(volatile unsigned long *)0x48000028)
#define MRSRB6 (*(volatile unsigned long *)0x4800002c)
#define MRSRB7 (*(volatile unsigned long *)0x48000030) //nand
#define NFCONF (*(volatile unsigned long *)0x4e000000)
#define NFCONT (*(volatile unsigned long *)0x4e000004)
#define NFCMMD (*(volatile unsigned char *)0x4e000008)
#define NFADDR (*(volatile unsigned char *)0x4e00000C)
#define NFDATA (*(volatile unsigned char *)0x4e000010)
#define NFSTAT (*(volatile unsigned char *)0x4e000020) //uart
#define ULCON0 (*(volatile unsigned long *)0x50000000)
#define UCON0 (*(volatile unsigned long *)0x50000004)
#define UFCON0 (*(volatile unsigned long *)0x50000008)
#define UMCON0 (*(volatile unsigned long *)0x5000000c)
#define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
#define UERSTAT0 (*(volatile unsigned long *)0x50000014)
#define UTXH0 (*(volatile unsigned char *)0x50000020)
#define URXH0 (*(volatile unsigned char *)0x50000024)
#define UBRDIV0 (*(volatile unsigned long *)0x50000028) //GPH
#define GPHCON (*(volatile unsigned long *)0x56000070)
#define GPHDAT (*(volatile unsigned long *)0x56000074)
#define GPHUP (*(volatile unsigned long *)0x56000078) /**************************************** watchdog_init ********************************************/
void disable_watchdog(void)
{
WTCON=;
} /****************************************** colck_init ********************************************/
void clock_init(void)
{
MPLLCON = ((0x5c<<)|(0x01<<)|(0x02));
CLKDIVN = ((<<)|(<<)); //200 MHZ
// CAMDIVN = ((1<<1)|(1<<0)); //1:2:4 200M:100M:50M __asm__
(
" mrc p15,0,r1,c1,c0,0 \n"
" orr r1, r1,#0xc0000000 \n"
" mcr p15,0,r1,c1,c0,0 \n"
); } void open_icache(void)
{
__asm__
(
" mrc p15, 0, r0, c1, c0, 0 \n"
" orr r0, r0, #(1<<12) \n"
" mcr p15, 0, r0, c1, c0, 0 \n"
);
} /****************************************** sdram_init *******************************************/ void sdram_init(void)
{
BWSCON = 0x22011110 ; //BWSCON
BANKCON0 = 0x00000700; //BANKCON0
BANKCON1 =0x00000700; //BANKCON1
BANKCON2 = 0x00000700; //BANKCON2
BANKCON3 = 0x00000700; //BANKCON3
BANKCON4 = 0x00000700; //BANKCON4
BANKCON5 =0x00000700; //BANKCON5
BANKCON6 =0x00018005; //BANKCON6
BANKCON7 = 0x00018005; //BANKCON7
REFRESH =0x008C04F4 ; // REFRESH
BANKSIZE = 0x000000B1; //BANKSIZE
MRSRB6 = 0x00000030; //MRSRB6
MRSRB7 = 0x00000030 ; //MRSRB7
} /****************************************** nand_flash_init ********************************************/ void select_chip(void)
{
NFCONT &= ~(<<);
} void disselect_chip(void)
{
NFCONT |= (<<);
} void write_command(unsigned char cmd)
{
NFCMMD=cmd;
volatile int i;
for (i = ; i < ; i++); } unsigned char read_data(void)
{
return NFDATA;
} void write_addr(unsigned int addr)
{
unsigned int row,col;
int i=;
row=addr/;
col=addr%; NFADDR= 0xff & col;
for (i = ; i < ; i++);
NFADDR=(col>>)& 0xff;
for (i = ; i < ; i++); NFADDR=row& 0xff;
for (i = ; i < ; i++);
NFADDR=(row>>)& 0xff;
for (i = ; i < ; i++);
NFADDR=(row>>)& 0xff;
for (i = ; i < ; i++);
} int nand_ready(void) {
return (NFSTAT & );
} void nand_init(void)
{
NFCONF = (<<|<<|<<);
NFCONT = (<<|<<|<<);
} void nand_read(unsigned int sour,unsigned char* dest,int copy_size)
{
int col=sour % ;
int i=; select_chip();
while(i<copy_size)
{ write_command(0x00); write_addr(sour); write_command(0x30); while(!nand_ready()); for(; (col<)&&(i<copy_size);col++) //page read
{
dest[i]=read_data();
sour++; i++;
}
col=;
} disselect_chip();
} /****************************************** copy_uboot_to_sdram ********************************************/
int nand_boot(void)
{
volatile unsigned long* top = (volatile unsigned long *)0x00000000;
int value=*top;
*top=;
if(*top==)
{
*top=value;
return ;
}
else return ;
} void copy_uboot_to_sdram(unsigned char* sour1,unsigned char *dest,int copy_size)
{
int i=;
unsigned char *sour = sour1;
if(nand_boot()) // nand_boot
{
while(i<copy_size)
{
dest[i]=sour[i];i++;
}
}
else //nor_boot
{
nand_read((unsigned long)sour,dest,copy_size);
}
} /*********************************************clean_bss*************************************************/
void clean_bss(void)
{
extern long __bss_end, __bss_start;
int* p = &__bss_start;
for(;p < &__bss_end ;p++) *p=;
} /********************************************uart_init*****************************************************/ void uart0_init(void)
{
GPHCON|=0xa0;
GPHUP=0x0c; ULCON0=0x03;
UCON0=0x05;
UFCON0=0x00;
UMCON0=0x00;
UBRDIV0=((/(*))-);
} unsigned char getc(void)
{
while(!(UTRSTAT0 & 0x01));
return URXH0;
} void putc(unsigned char date)
{
while(!(UTRSTAT0 & 0x02));
UTXH0=date;
} void puts(char *str)
{
while(*str) putc(*str++); } void puthex(unsigned int val)
{
/* 0x1234abcd */
int i;
int j; puts("0x"); for (i = ; i < ; i++)
{
j = (val >> ((-i)*)) & 0xf;
if ((j >= ) && (j <= ))
putc('' + j);
else
putc('A' + j - 0xa); } }
tag.c源码:
/*****************************************string_lib***********************************************/
int strlen(char *str)
{
int i=;
while(str[i] != ) i++;
return i;
} void strcopy(char *dest,char *sour)
{
while((*dest++ = *sour++)!= );
} /*****************************************tag_init************************************************/
#define tag_next(type) (struct tag *) ((unsigned long *)(type) + (type)->hdr.size)
#define tag_size(size) ((sizeof(struct tag_header)+sizeof(struct size))>>2) struct tag_header
{
unsigned long size;
unsigned long tag_type;
}; struct tag_core
{
unsigned long flags;
unsigned long pagesize;
unsigned long rootdevf;
}; struct tag_mem32
{
unsigned long size;
unsigned long start;
}; struct tag_cmdline
{
char cmdline[];
}; struct tag
{
struct tag_header hdr;
union
{
struct tag_core core;
struct tag_mem32 mem32;
struct tag_cmdline cmdline;
}u;
}; static struct tag *params=(struct tag *)0x30000100; void set_start_tag(void)
{
params->hdr.size=tag_size(tag_core);
params->hdr.tag_type=0x54410001; params->u.core.flags= ;
params->u.core.pagesize= ;
params->u.core.rootdevf= ; params=tag_next(params);
} void set_memory_tag(void)
{
params->hdr.size= tag_size(tag_mem32);
params->hdr.tag_type = 0x54410002; params->u.mem32.size =**;
params->u.mem32.start =
0x30000000; params=tag_next(params); } void set_cmdline_tag(char *cmdline)
{
int len=strlen(cmdline)+;
params->hdr.size = (sizeof(struct tag_header)+len+)>>;
params->hdr.tag_type = 0x54410009;
strcopy(params->u.cmdline.cmdline ,cmdline); params=tag_next(params);
} void set_end_tag(void)
{
params->hdr.size = ;
params->hdr.tag_type = ;
}
tag.h源码:
#ifndef _TAG_H_
#define _TAG_H_ void set_cmdline_tag(char * cmdline);
void set_end_tag(void);
void set_memory_tag(void);
void set_start_tag(void); #endif
main.c源码:
extern void nand_read(unsigned long sour, unsigned char * dest, int copy_size);
extern void puts(char * str);
void putc(unsigned char date);
void puthex(unsigned int val); #include"tag.h" int main(void)
{
void (*thekernel)(int zero,int arch,unsigned int params); puts("bootloader start.....\n\r"); //copy kernel
puts("1. copy kernal to sdram\n\r");
nand_read(0x60000+,(unsigned char *)0x30008000,0x200000); //set params
set_start_tag();
set_memory_tag();
set_cmdline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");
set_end_tag();
puts("2. set kernel parameters\n\r"); //jump to kernel
puts("3. jump to kernel\n\r");
thekernel=(void (*)(int,int ,unsigned int))0x30008000;
thekernel(,,0x30000100); //error
puts("something wrong\n\r");
return ;
}
编译用的Makefile文件:
OBJS := start.o init.o tag.o main.o
CFLAGS := -O2 -Wall
CPPFLAGS := -nostdinc -fno-builtin CC = arm-linux-gcc
LD = arm-linux-ld
OBJCOPY = arm-linux-objcopy
OBJDUMP = arm-linux-objdump uboot.bin: ${OBJS}
${LD} -Tuboot.lds -o uboot.elf $^
${OBJCOPY} -O binary -S uboot.elf $@
${OBJDUMP} -D -m arm uboot.elf > uboot.dis %.o:%.c
${CC} ${CPPFLAGS} ${CFLAGS} -o $@ -c $< %.o:%.s
${CC} ${CPPFLAGS} ${CFLAGS} -o $@ -c $< clean:
rm -f *.o *.bin *.elf *.dis
连接脚本:
SECTIONS
{
. = 0x33f80000;
.text : {*(.text)} . = ALIGN();
.rodata : {*(.rodata*)} . = ALIGN();
.data : {*(.data)} . = ALIGN();
__bss_start = .;
.bss : {*(.bss) *(COMMON)}
__bss_end = .;
}
实现简单的 u-boot的更多相关文章
- 构建一个简单的Spring Boot项目
11 构建一个简单的Spring Boot项目 这个章节描述如何通过Spring Boot构建一个"Hello Word"web应用,侧重介绍Spring Boot的一些重要功能. ...
- 一个简单的spring boot程序
搭建一个spring boot项目十分的方便,网上也有许多,可以参考 https://www.cnblogs.com/ityouknow/p/5662753.html 进行项目的搭建.在此我就不详细介 ...
- 【Spring Boot】创建一个简单的Spring Boot的 Demo
走进Spring Boot 文章目录 走进Spring Boot 环境搭建 新建Spring Boot项目 开始创建项目 配置JDK版本 和 Initializr Service URL 配置Proj ...
- 简单的Spring Boot项目——实现连接Mysql数据库
一.创建Spring Boot项目 参考:使用IntelliJ IDEA创建简单的Spring Boot项目 二.数据库.表的创建 三.项目开发 3.1 pom.xml文件配置 <?xml ve ...
- 一步一步实现一个简单的OS(简单的让boot载入setup)
这次直接写用boot载入setup模块. 文件系统就先不弄了,以后再说, 咱先整个转简单的载入器. 我把软盘引导改成硬盘了,由于硬盘的读扇区函数简单一些. 这里没有做硬盘的mbr区,我认为在如今我的这 ...
- 超简单,spring boot 添加mybatis
看了很多人写的博客,要么太复杂,要么没有添加xml的方式,自己亲自配置了一下,供各位参考. 项目截图 1.添加pom文件 <!-- 设置mybatis --> <dependency ...
- 最简单的spring boot web项目
搭建效果为: 直接在网页输入请求,在页面中显示一行文字:Hello,Spring Boot 与一般的wen项目不同的地方: 1.不需要配置web.xml 文件,但需要注解@SpringBootAppl ...
- 简单使用Spring Boot+JpaRepository+hibernate搭建项目
sql: -- -------------------------------------------------------- -- 主机: 127.0.0.1 -- 服务器版本: 10.3.9-M ...
- 手把手教你手写一个最简单的 Spring Boot Starter
欢迎关注微信公众号:「Java之言」技术文章持续更新,请持续关注...... 第一时间学习最新技术文章 领取最新技术学习资料视频 最新互联网资讯和面试经验 何为 Starter ? 想必大家都使用过 ...
- 使用IntelliJ IDEA创建简单的Spring Boot项目
方法一: File - New -Project 创建结束后进行测试运行,修改代码如下: package com.springboot.testone; import org.springframew ...
随机推荐
- Unity5 AssetBundle系列——简单的AssetBundleManager
一个AssetBundle同时只能加载一次,所以实际使用中一般会伴随着AssetBundle包的管理. 下面是一个简单的AssetBundle管理器,提供了同步和异步加载函数: using Unity ...
- 转载 :配置ssh密钥认证自动登录
原文地址 :https://segmentfault.com/a/1190000000481249 在客户端来看,SSH提供两种级别的安全验证.[摘自wikipedia] 第一种级别(基于密码的安全验 ...
- 【转】使用Log4Net进行日志记录
首先说说为什么要进行日志记录.在一个完整的程序系统里面,日志系统是一个非常重要的功能组成部分.它可以记录下系统所产生的所有行为,并按照某种规范表达出来.我们可以使用日志系统所记录的信息为系统进行排错, ...
- Ubuntu 实践
Ubuntu 安装中文支持 开始装的是Ubuntu Server,后来需要某些图形工具,所以装了个Gnome,没想到无论如何都显示不了中文,按照网上的方法试了一堆,装了Synaptic,KDE和GNO ...
- 多线程开发之一 NSThread
每个 iOS 应用程序都有个专门用来更新显示 UI 界面.处理用户的触摸事件的主线程,因此不能将其他太耗时的操作放在主线程中执行,不然会造成主线程堵塞(出现卡机现象),带来不好的用户体验. 一般的解决 ...
- QT 中Widgets-Scene3d例子学习
QT中自带的例子widgets-scene3d实现在基于Widget的应用程序中使用qml 3d场景的功能,我在此基础上,将basicshapes-cpp的例子加以嵌入: 相关代码如下: C++ C ...
- Linux里的2>&1究竟是什么
我们在Linux下经常会碰到nohup command>/dev/null 2>&1 &这样形式的命令.首先我们把这条命令大概分解下首先就是一个nohup表示当前用户和系统 ...
- 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验二:按键模块① - 消抖
实验二:按键模块① - 消抖 按键消抖实验可谓是经典中的经典,按键消抖实验虽曾在<建模篇>出现过,而且还惹来一堆麻烦.事实上,笔者这是在刁难各位同学,好让对方的惯性思维短路一下,但是惨遭口 ...
- python3之文件操作
一 打开文件 根目录在d盘的文件名为‘学习资料.txt’的文件 a)绝对路径(最开始的,根目录文件)例: e:\学习资料.txt 相对路径 直接用文件名字 b)操作方式 只读 只 ...
- 在PowerShell中使用Vim
1.需要去Vim官网下载并安装一个可运行于Win8系统的执行文件(ftp://ftp.vim.org/pub/vim/pc/gvim74.exe). 2.设置PowerShell环境,使能“allow ...