ok6410下的uboot分析与实现
uboot 由两阶段代码组成:
•第一阶段主要步骤:
1.将cpu设置为svc模式
2.关闭mmu
3.设置外设端口地址
4.关闭watchdog
5.关闭中断
6.初始化时钟
7.初始化内存DRAM
8.把 nandflash 中的代码搬移到链接地址处
9.初始化堆栈
10.清bss段
11.使用与地址相关的跳转指令,跳转到 c 入口处。
OK6410上的启动代码如下:
@start.S
.text
.global _start
_start:
/*set the cpu to svc32 mode*/
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0 /*disable_mmu*/
mcr p15,0,r0,c7,c7,0
mrc p15,0,r0,c1,c0,0
bic r0,r0,#0x00000007
mcr p15,0,r0,c1,c0,0
/*peri port setup*/
ldr r0,=0x70000000
orr r0,r0,#0x13
mcr p15,0,r0,c15,c2,4
/*Disable Watchdog
*if you don't disable watchdog,because you don't to feed dog,so the CPU will conti *nue reboot.
*/
ldr r0,=0x7e000000
orr r0,r0,#0x4000
mov r1,#0
str r1,[r0]
/*Disable interrupt*/
mvn r1,#0
ldr r0,=0x71200014
str r1,[r0] ldr r0,=0x71300014
str r1,[r0] /*Init clock*/
#define APLL_LOCK 0x7e00f000
#define MPLL_LOCK 0x7e00f004
#define EPLL_LOCK 0x7e00f008
#define LOCK_TIME 0xffff #define OTHERS 0x7e00f900 #define CLK_DIV0 0x7e00f020 #define CLK_SRC 0x7e00f01c @ set the lock time to max
ldr r0, =LOCK_TIME
ldr r1, =APLL_LOCK
str r0, [r1]
ldr r1, =MPLL_LOCK
str r0, [r1]
ldr r1, =EPLL_LOCK
str r0, [r1] @ set async mode
ldr r0, =OTHERS
ldr r1, [r0]
bic r1, #0xc0
str r1, [r0] loop1:
ldr r0, =OTHERS
ldr r1, [r0]
and r1, #0xf00
cmp r1, #0
bne loop1 @ set the divider #define DIV_VAL ( (0)|(1<<4)|(1<<8)|(1<<9)|(3<<12) )
ldr r0, =CLK_DIV0
ldr r1, =DIV_VAL
str r1, [r0] @ set APLL, MPLL, EPLL
#define SDIV 1
#define PDIV 3
#define MDIV 266
#define PLL_ENABLE ( 1 << 31 )
#define APLL_VAL ( (SDIV<<0)|(PDIV<<8)|(MDIV<<16)|(PLL_ENABLE) )
#define MPLL_VAL APLL_VAL
#define EPLL0_VAL ( (2<<0)|(1<<8)|(32<<16)|PLL_ENABLE)
#define EPLL1_VAL ( 0 ) #define APLL_CON 0x7e00f00c
#define MPLL_CON 0x7e00f010
#define EPLL_CON0 0x7e00f014
#define EPLL_CON1 0x7e00f018 ldr r0, =APLL_CON
ldr r1, =APLL_VAL
str r1, [r0] ldr r0, =MPLL_CON
ldr r1, =MPLL_VAL
str r1, [r0] ldr r0, =EPLL_CON0
ldr r1, =EPLL0_VAL
str r1, [r0] ldr r0, =EPLL_CON1
ldr r1, =EPLL1_VAL
str r1, [r0] @ select the source
ldr r0, =CLK_SRC
mov r1, #7
str r1, [r0] init_mem:
ldr r0,=0x7e00f120
mov r1, #0x8
str r1, [r0] ldr r0, =0x7e001004
mov r1, #0x4
str r1, [r0] ldr r0, =0x7e001010
ldr r1, =( ( 7800 / ( 1000000000/133000000 ) + 1 ) )
str r1, [r0] ldr r0, =0x7e001014
mov r1, #(3 << 1)
str r1, [r0] ldr r0, =0x7e001018
mov r1, #0x1
str r1, [r0] ldr r0, =0x7e00101c
mov r1, #0x2
str r1, [r0] ldr r0, =0x7e001020
ldr r1, =( ( 45 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0] ldr r0, =0x7e001024
ldr r1, =( ( 68 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0] ldr r0, =0x7e001028
ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0] ldr r0, =0x7e00102c
ldr r1, =( ( 80 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0] ldr r0, =0x7e001030
ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0] ldr r0, =0x7e001034
ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0] ldr r0, =0x7e001038
ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0] ldr r0, =0x7e00103c
mov r1, #0x07
str r1, [r0] ldr r0, =0x7e001040
mov r1, #0x02
str r1, [r0] ldr r0, =0x7e001044
ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0] ldr r0, =0x7e001048
ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0] ldr r0, =0x7e00100c
ldr r1, =0x00010012
str r1, [r0] ldr r0, =0x7e00104c
ldr r1, =0x0b45
str r1, [r0] ldr r0, =0x7e001200
ldr r1, =0x150f8
str r1, [r0] ldr r0, =0x7e001304
mov r1, #0x0
str r1, [r0] ldr r0, =0x7e001008
ldr r1, =0x000c0000
str r1, [r0] ldr r1, =0x00000000
str r1, [r0] ldr r1, =0x00040000
str r1, [r0] ldr r1, =0x000a0000
str r1, [r0] ldr r1, =0x00080032
str r1, [r0] ldr r0, =0x7e001004
mov r1, #0x0
str r1, [r0] check_dmc1_ready: ldr r0, =0x7e001000
ldr r1, [r0]
mov r2, #0x3
and r1, r1, r2
cmp r1, #0x1
bne check_dmc1_ready
nop /*prepare C language environment*/ /*
*copy_to_ram:
* ldr r0,=0x0c000000
* ldr r1,=0x50000000
* add r3,r0,#1024*4
*copy_loop:
* ldr r2,[r0],#4
* str r2,[r1],#4
* cmp r0,r3
* bne copy_loop
*/ init_stack:
ldr sp,=0x54000000 copy_to_ram:
adr r0, _start /* »ñµÃ_startÖ¸ÁǰËùÔڵĵØÖ· : 0*/
ldr r1, =_start /* _startµÄÁ´½ÓµØÖ· 0x51000000 */ ldr r2, =bss_start /* bss¶ÎµÄÆðʼÁ´½ÓµØÖ· */ sub r2, r2, r1 cmp r0,r1
beq clean_bss bl copy2ddr
cmp r0, #0
bne halt
clean_bss:
ldr r0,=bss_start
ldr r1,=bss_end
cmp r0,r1
beq to_ddr
clean_loop:
mov r2,#0
str r2,[r0],#4
cmp r0,r1
bne clean_loop to_ddr:
bl light_led
ldr pc,=main light_led:
ldr r1, =0x7F008820
ldr r0, =0x1111
str r0, [r1] ldr r1, =0x7F008824
mov r0,#0xe
str r0,[r1]
mov pc, lr halt:
b halt
//nand.c #define MEM_SYS_CFG (*((volatile unsigned long *)0x7E00F120))
#define NFCONF (*((volatile unsigned long *)0x70200000))
#define NFCONT (*((volatile unsigned long *)0x70200004))
#define NFCMMD (*((volatile unsigned long *)0x70200008))
#define NFADDR (*((volatile unsigned long *)0x7020000C))
#define NFDATA (*((volatile unsigned char *)0x70200010))
#define NFSTAT (*((volatile unsigned long *)0x70200028)) #define NAND_DISABLE_CE() (NFCONT |= (1 << 1))
#define NAND_ENABLE_CE() (NFCONT &= ~(1 << 1))
#define NF_TRANSRnB() do { while(!(NFSTAT & (1 << 0))); } while(0) #define NAND_CMD_RESET 0xff
#define NAND_CMD_READID 0x90
#define NAND_CMD_READ0 0
#define NAND_CMD_READSTART 0x30 void nand_select(void)
{
NFCONT &= ~(1<<1);
} void nand_deselect(void)
{
NFCONT |= (1<<1);
} void nand_cmd(unsigned char cmd)
{
NFCMMD = cmd;
} void nand_addr(unsigned char addr)
{
NFADDR = addr;
} unsigned char nand_get_data(void)
{
return NFDATA;
} void wait_ready(void)
{
while ((NFSTAT & 0x1) == 0);
} void nand_reset(void)
{
/* Ñ¡ÖÐ */
nand_select(); /* ·¢³ö0xffÃüÁî */
nand_cmd(0xff); /* µÈ´ý¾ÍÐ÷ */
wait_ready(); /* È¡ÏûÑ¡ÖÐ */
nand_deselect();
} void nand_init(void)
{
/* ÈÃxm0csn2ÓÃ×÷nand flash cs0 ƬѡÒý½Å */
MEM_SYS_CFG &= ~(1<<1); /* ÉèÖÃʱ¼ä²ÎÊý:hclk = 7.5ns */
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 1
NFCONF &= ~((1<<30) | (7<<12) | (7<<8) | (7<<4));
NFCONF |= ((TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4)); /* ʹÄÜnand flash controller */
NFCONT |= 1; nand_reset();
} void nand_send_addr(unsigned int addr)
{
#if 0
unsigned int page = addr / 2048;
unsigned int colunm = addr & (2048 - 1); /* ÕâÁ½¸öµØÖ·±íʾ´ÓÒ³ÄÚÄÄÀ↑ʼ */
nand_addr(colunm & 0xff);
nand_addr((colunm >> 8) & 0xff); /* ÏÂÃæÈý¸öµØÖ·±íʾÄÄÒ»Ò³ */
nand_addr(page & 0xff);
nand_addr((page >> 8) & 0xff);
nand_addr((page >> 16) & 0xff);
#else
nand_addr(addr & 0xff); /* a0~a7 */
nand_addr((addr >> 8) & 0x7); /* ³ÌÐòµÄ½Ç¶È: a8~a10 */ nand_addr((addr >> 11) & 0xff); /* ³ÌÐòµÄ½Ç¶È: a11~a18 */
nand_addr((addr >> 19) & 0xff); /* ³ÌÐòµÄ½Ç¶È: a19~a26 */
nand_addr((addr >> 27) & 0xff); /* ³ÌÐòµÄ½Ç¶È: a27 ~ */ #endif
} int nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
unsigned int addr = nand_start;
int i, count = 0;
unsigned char *dest = (unsigned char *)ddr_start; /* Ñ¡ÖÐоƬ */
nand_select(); while (count < len)
{
/* ·¢³öÃüÁî0x00 */
nand_cmd(0x00); /* ·¢³öµØÖ· */
nand_send_addr(addr); /* ·¢³öÃüÁî0x30 */
nand_cmd(0x30); /* µÈ´ý¾ÍÐ÷ */
wait_ready(); /* ¶ÁÊý¾Ý */
for (i = 0; i < 2048 && count < len; i++)
{
dest[count++] = nand_get_data();
} addr += 2048;
} /* È¡ÏûƬѡ */
nand_deselect();
return 0;
} static int nandll_read_page (unsigned char *buf, unsigned long addr, int large_block)
{
int i;
int page_size = 512; if (large_block==2)
page_size = 4096; NAND_ENABLE_CE(); // Ñ¡ÖÐnand NFCMMD = NAND_CMD_READ0; /* Write Address */
NFADDR = 0; if (large_block)
NFADDR = 0; NFADDR = (addr) & 0xff;
NFADDR = (addr >> 8) & 0xff;
NFADDR = (addr >> 16) & 0xff; if (large_block)
NFCMMD = NAND_CMD_READSTART; NF_TRANSRnB(); for(i=0; i < page_size; i++) {
*buf++ = NFDATA;
} NAND_DISABLE_CE(); return 0;
} int copy2ddr(unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
unsigned char *dest = (unsigned char *)ddr_start;
int i; /* ³õʼ»¯nand flash controller */
nand_init(); /* ¶Ánand flash */
/* Read pages */
for (i = 0; i < 4; i++, dest+=2048){
nandll_read_page(dest, i, 2);
} /* Read pages */
for (i = 4; i < ((len+4096)>>13); i++, dest+=8192) {
nandll_read_page(dest, i, 2);
} return 0;
}
//main.c #define rGPMCON (*(volatile unsigned *)(0x7F008820))
#define rGPMDAT (*(volatile unsigned *)(0x7F008824))
#define rGPMPUD (*(volatile unsigned *)(0x7F008828)) void msDelay(int time)
{
volatile unsigned int i,j;
for (i=0;i<20000;i++)
for(j=0;j<time;j++);
} void GPIO_Init(void)
{
rGPMCON = 0x11111;
rGPMPUD = 0x00;
rGPMDAT = 0x1F;
} void LedTest(void)
{
volatile unsigned int i;
while(1)
{
for(i=0;i<4;i++)
{
rGPMDAT =~(1<<i);
msDelay(10);
}
}
}
int main()
{
GPIO_Init();
LedTest(); return 0;
}
总结如下:
第一阶段启动代码主要完成此阶段所需硬件的初始化。初始化 c 语言运行环境,即初始化堆栈。进入 c 语言,跳到第二阶段。
ok6410下的uboot分析与实现的更多相关文章
- 记录Ok6410 sd 启动uboot
1\参考资料https://github.com/SeanXP/ARM-Tiny6410/tree/master/no-os/sd-no-os/u-boot 2\参考资料https://blog.cs ...
- u-boot分析(十)----堆栈设置|代码拷贝|完成BL1阶段
u-boot分析(十) 上篇博文我们按照210的启动流程,分析到了初始化nand flash,由于接下来的关闭ABB比较简单所以跳过,所以我们今天按照u-boot的启动流程继续进行分析. 今天我们会用 ...
- u-boot分析(九)----nand flash初始化|nand flash读写分析
u-boot分析(九) 上篇博文我们按照210的启动流程,分析到了初始化串口,由于接下来的取消存储保护不是很重要,所以我们今天按照u-boot的启动流程对nand flash初始化进行分析. 今天我们 ...
- u-boot分析(八)----串口初始化
u-boot分析(八) 上篇博文我们按照210的启动流程,分析到了内存初始化,今天我们继续按照u-boot的启动流程对串口的初始化进行分析. 今天我们会用到的文档: 1. 2440芯片手 ...
- u-boot分析(六)----时钟初始化
u-boot分析(六) 上篇博文我们按照210的启动流程,分析到了关闭看门狗,今天我们继续按照u-boot的启动流程进行分析,今天我们会主要分析时钟的初始化. 今天我们会用到的文档: 1. ...
- u-boot分析(五)----I/D cache失效|关闭MMU和cache|关闭看门狗
u-boot分析(五) 上篇博文我们按照210的启动流程,对u-boot启动中的设置异常向量表,设置SVC模式进行了分析,今天我们继续按照u-boot的启动流程对以下内容进行分析. 今天我们会用到的文 ...
- u-boot分析(四)---设置异常向量表|设置SVC模式
u-boot分析(四) 通过前三篇的分析,我们对u-boot已经有了整体的认识和掌握,但是我们仍然对于其部分硬件是如何初始化的不太清楚,所以接下来几篇博文我将会对我们在http://www.cnblo ...
- u-boot分析(二)----工作流程分析
u-boot分析(二) 由于这两天家里有点事,所以耽误了点时间,没有按时更新,今天我首先要跟大家说说我对于u-boot分析的整体的思路,然后呢我以后的博客会按照这个内容更新,希望大家关注. 言归正传, ...
- Apache Spark源码走读之15 -- Standalone部署模式下的容错性分析
欢迎转载,转载请注明出处,徽沪一郎. 概要 本文就standalone部署方式下的容错性问题做比较细致的分析,主要回答standalone部署方式下的包含哪些主要节点,当某一类节点出现问题时,系统是如 ...
随机推荐
- android 开发 实现RecyclerView的列表单选功能
实现思维: 1.首先在一行的xml布局中添加一个选中效果的icon图片,未选中的情况下INVISIBLE或者GONE 都可以,推荐使用INVISIBLE它会占用布局位置但是不显示,这样可以避免布局中其 ...
- <spark> ~/spark/conf/spark-default.conf 配置文件
因为看到我参考的Hadoop/spark集群搭建的文档中的都没有对 /spark-default.conf 的配置 合理地对 /spark-default.conf 进行配置,能够提高执行效率 -- ...
- code signing is required for product type 'Application' in SDK 'iOS 8.1' 错误分析以及解决方案
在真机测试的时候往往会突然出现这样一个错误,code signing is required for product type 'Application' in SDK 'iOS 7.0' ,就是说 ...
- kvm云主机使用宿主机usb设备
有些时候KVM客户机还是要使用USB设备,比如USB密钥等 KVM命令行参数 -usb 打开usb驱动程序,启动客户机usb支持-usbdevice devname 为客户机增加usb设备,devna ...
- wgrib读grib数据
该文章来自博客:http://windforestwing.blog.163.c ... 412007103084743804/如有错误 ,大家及时指出啊!ps:meteoinfo可以直接处理grib ...
- 《算法》第四章部分程序 part 9
▶ 书中第四章部分程序,包括在加上自己补充的代码,两种拓扑排序的方法 ● 拓扑排序 1 package package01; import edu.princeton.cs.algs4.Digraph ...
- zookeeper(4)--zookeeper分布式锁原理
目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题.分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency).可用性( ...
- Android自定义View学习笔记(一)
绘制基础 参考:HenCoder Android 开发进阶: 自定义 View 1-1 绘制基础 Paint详解 参考:HenCoder Android 开发进阶: 自定义 View 1-2 Pain ...
- RxJava学习(一)——简介及其优势
参考:给 Android 开发者的 RxJava 详解 RxJava是什么 RxJava 在 GitHub 主页上的自我介绍是 "a library for composing asynch ...
- Python基础1 介绍、基本语法
---恢复内容开始--- 本节内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc是个什么鬼? 数据类型初识 数据运算 表 ...