开发板——在X210开发板上进行裸机开发的细节

 以下内容是学习裸机开发过程中的一些细节内容的记录。

1、汇编语言函数细节

用汇编写的函数,末尾应该添加mov pc,lr语句。

2、裸机代码相关文件

3、关于链接地址

4、关于重定位的理解

(1)在sram内部重定位

这是在sram内部重定位,因此不需要初始化DDR。

根据S5PV210地址映射图,链接脚本(略)指定的链接地址0xd0024000是在SRAM中。

/** 描述:	演示重定位(在SRAM内部重定位)*/#define WTCON		0xE2700000
#define SVC_STACK	0xd0037d80.global _start	// 把_start链接属性改为外部,这样其他文件就可以看见_start了_start:// 第1步:关看门狗(向WTCON的bit5写入0即可)ldr r0, =WTCONldr r1, =0x0str r1, [r0]// 第2步:设置SVC栈ldr sp, =SVC_STACK// 第3步:开/关icachemrc p15,0,r0,c1,c0,0;			// 读出cp15的c1到r0中//bic r0, r0, #(1<<12)			// bit12 置0  关icacheorr r0, r0, #(1<<12)			// bit12 置1  开icachemcr p15,0,r0,c1,c0,0;// 第4步:重定位。(这里的代码细节说明adr是与运行相关的,ldr是与链接相关的。)adr r0, _start     // adr指令用于加载_start当前运行地址             // adr加载时就叫短加载	 			ldr r1, =_start    // ldr指令用于加载_start的链接地址:0xd0024000    // ldr加载时如果目标寄存器是pc就叫长跳转,如果目标寄存器是r1等就叫长加载// bss段的起始地址ldr r2, =bss_start	// 就是我们重定位代码的结束地址,重定位只需重定位代码段和数据段即可cmp r0, r1			// 比较_start的运行时地址和链接地址是否相等beq clean_bss		// 如果相等说明不需要重定位,所以跳过copy_loop,直接到clean_bss// 如果不相等说明需要重定位,那么直接执行下面的copy_loop进行重定位// 重定位完成后继续执行clean_bss。// 用汇编来实现的一个while循环
copy_loop:ldr r3, [r0], #4    // 源str r3, [r1], #4	// 目的   这两句代码就完成了4个字节内容的拷贝cmp r1, r2			// r1和r2都是用ldr加载的,都是链接地址,所以r1不断+4总能等于r2bne copy_loop// 清bss段,其实就是在链接地址处把bss段全部清零
clean_bss:ldr r0, =bss_start					ldr r1, =bss_endcmp r0, r1				// 如果r0等于r1,说明bss段为空(即不存在bss段),直接下去beq run_on_dram			// 清除bss完之后的地址mov r2, #0clear_loop:str r2, [r0], #4		// 先将r2中的值放入r0所指向的内存地址(r0中的值作为内存地址),cmp r0, r1				// 然后r0 = r0 + 4bne clear_looprun_on_dram:	// 长跳转到led_blink开始第二阶段ldr pc, =led_blink				// ldr指令实现长跳转//bl led_blink					// bl指令实现短跳转// 汇编最后的这个死循环不能丢b .

(2)重定位至DDR

这里重定位至DDR,因此需要初始化DDR。

根据S5PV210地址映射图,链接脚本(略)指定的链接地址0x2000 0000 在DDR中。

/** 文件名:	led.s	* 作者:	朱老师* 描述:	演示重定位*/#define WTCON		0xE2700000
#define SVC_STACK	0xd0037d80.global _start	
_start://..............// 第4步:初始化ddrbl sdram_asm_init //此函数末尾记得添加mov pc,lr// 第5步:重定位,后面的代码和之前的完全一样。故不写。

(3)总结

对比可知,两者没有什么区别,重定位至DDR只是多了一个内存初始化操作而已。

5、SRAM的地址0xd002_0010映射到0x0000_0000地址

Makefile用 -Ttext 0x0 指定链接地址为0x0。这意味着我们认为这个程序将来会放在0x0地址中运行,但实际上运行时的地址是0xd0020010(我们用dnw下载时指定的下载地址)。

这两个地址看似不同但实际相同,因为S5PV210内部把SRAM的地址0xd002_0010映射到地址0x0000_0000。把链接地址设为0x0000_0000,就等价于链接地址是0xd002_0010。

BL0执行完后会自动跳转到0xd0020010这个地址开始运行,这个地址是CPU设计决定的。

6、S5PV210内置的拷贝函数

关注下0xD0037F98这个地址,它是S5PV210内置的拷贝函数的入口地址。该函数的参数之一是从哪个通道拷贝(SD0还是SD2,对应着inand和SD卡),参数之二是从哪个扇区开始拷贝,参数之三是拷贝至哪里,参数之四是拷贝多少。

BL0内部利用这个函数,将16KB(由参数之四决定)的BL1,从SD卡或者inand(由参数之一决定)的第一个扇区(由参数之二决定),拷贝到 SRAM 的 0xd002_0010 地址(由参数之三决定)。由于BL0是写死在IROM中的,我们唯一能做的就是通过启动介质拨码开关来决定参数之一,参数之二、三、四是固定的。

BL1中如果需要拷贝SD卡中的某些内容,则还是使用S5PV210内置的拷贝函数,只不过因为BL1是我们编写的,我们可以自由设置参数一、二、三、四。

比如将一个大文件分成两个文件BL1和BL2,先将BL1烧写至SD卡第1扇区,BL2烧写至SD卡合适的扇区位置即可(假如烧录至第49扇区)。

上电后IROM中的BL0将利用拷贝函数,把BL1从SD卡第1扇区拷贝到 SRAM的 0xd002_0010地址。BL1在执行时也利用拷贝函数,将BL2从SD卡的第49扇区拷贝到一个合适的地址(这个地址可能位于IRAM或者DDR中,它是由链接脚本规定的,我们从链接脚本得知这个地址,然后作为参数传入拷贝函数),最后BL1代码末尾处执行跳转语句,跳转到这个地址,就可以接着执行BL2。

7、验证6中所讲述的内容

(1)BL1的相关内容

首先,BL1的链接脚本的链接地址是0xd0020010。这就很合理,这个地址就是BL1该呆在的地方,因为CPU设计时规定的一开始运行的地址就是0xd0020010。

SECTIONS
{. = 0xd0020010;.text : {start.osdram_init.o* (.text)}.data : {* (.data)}bss_start = .; .bss : {* (.bss)}bss_end  = .;	
}

其次,BL1的Makefile中,需要把BL1做16字节填充的,这也很合理。

接着,start.S中初始化DDR后,利用拷贝函数把存储在SD卡中的BL2,复制到DDR的某个位置,并跳转到该位置执行BL2。

#define WTCON		0xE2700000
#define SVC_STACK	0xd0037d80.global _start	// 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:// 第1步:关看门狗(向WTCON的bit5写入0即可)ldr r0, =WTCONldr r1, =0x0str r1, [r0]// 第2步:设置SVC栈ldr sp, =SVC_STACK// 第3步:开/关icachemrc p15,0,r0,c1,c0,0;			// 读出cp15的c1到r0中//bic r0, r0, #(1<<12)			// bit12 置0  关icacheorr r0, r0, #(1<<12)			// bit12 置1  开icachemcr p15,0,r0,c1,c0,0;// 第4步:初始化ddrbl sdram_asm_init// 第5步:重定位,从SD卡第45扇区开始,复制32个扇区内容到DDR的0x23E00000bl copy_bl2_2_ddr// 汇编最后的这个死循环不能丢b .
#define SD_START_BLOCK	45
#define SD_BLOCK_CNT	32
#define DDR_START_ADDR	0x23E00000 //这地址在DDR中,不在IRAM中typedef unsigned int bool;// 通道号:0或者2
// 开始扇区号:这里设为45
// 读取扇区个数:这里设备32
// 读取后放入的地址:这里设为0x23E00000
// with_init:0
typedef bool(*pCopySDMMC2Mem)(int, unsigned int, unsigned short, \unsigned int*, bool);
typedef void (*pBL2Type)(void);//从SD卡第45扇区开始,复制32个扇区内容到DDR的0x23E00000,然后跳转到23E00000去执行
void copy_bl2_2_ddr(void)
{// 第一步,读取SD卡扇区到DDR中//定义一个函数指针并指向拷贝函数pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)0xD0037F98);//给(指向拷贝函数的)函数指针传入参数,开始读取SD卡到DDR中p1(2, SD_START_BLOCK, SD_BLOCK_CNT, (unsigned int *)DDR_START_ADDR, 0);	// 第二步,跳转到DDR中的BL2去执行//定义一个函数指针并指向BL2的下载地址pBL2Type p2 = (pBL2Type)DDR_START_ADDR;//通过函数指针这种方式跳转到DDR中的BL2的下载地址,去执行BL2数p2();
}

(2)BL2的相关内容

首先,链接地址应该由BL1的拷贝函数将BL2拷贝到哪里决定。由BL1代码可知BL2被拷贝到了0x23E00000,那么BL2的链接地址应该是0x23E00000。

另外,BL2有main函数文件、start.S文件等文件,怎么知道先执行start.S文件呢?这是由链接脚本中的.o文件的顺序决定的。

SECTIONS
{. = 0x23E00000;.text : {start.o* (.text)}.data : {* (.data)}bss_start = .; .bss : {* (.bss)}bss_end  = .;	
}

其次,BL2的makefile中不会再添加16字节填充的操作,经查验果真如此。

start.S文件内容如下,可知接下来会到main函数的文件中执行main函数。

#define WTCON		0xE2700000
#define SVC_STACK	0xd0037d80.global _start	_start:ldr pc, =main				// ldr指令实现长跳转// 汇编最后的这个死循环不能丢b .

(3)总结

BL1所使用的拷贝函数还是BL0所使用的拷贝函数,即S5PV210内置的拷贝函数。

BL2的入口地址,是BL2的链接脚本指定链接地址。该地址由BL1将BL2拷贝到哪里决定。

BL2链接脚本中.o的顺序,决定了BL2众多的程序文件中,先执行哪些文件。

8、将数据烧写至SD卡的方式

方式1:在linux中利用write2sd文件

write2sd文件内容如下,可知BL1和BL2分别烧录至第1扇区、第45扇区开始的地方。

#!/bin/sh
sudo dd iflag=dsync oflag=dsync if=./BL1/BL1.bin of=/dev/sdb seek=1
sudo dd iflag=dsync oflag=dsync if=./BL2/BL2.bin of=/dev/sdb seek=45

方式2:利用九鼎提供的烧写软件

它只能将一个文件(uboot.bin或者裸机镜像文件)烧写至SD卡的第1扇区开始的地方。

注意,它只能烧写一个文件,而且必须烧写至SD卡第1扇区。

方式3:利用三星提供的sd_fusing文件夹

具体见利用三星提供的sd_fusing.sh将uboot烧写到SD卡。

注意,这个文件夹是将uboot.bin烧写至sd的方法,特指烧写uboot镜像,而非其他的?错误的认识,可以烧写其他镜像,但得16字节的校验头。

补充说明

其实方式3最后也利用方式1作为方式3的最后一个步骤。方式3前面还包括将sd卡分区、截取uboot.bin前8k作为BL1(而整个uboot.bin作为BL2)等步骤。将sd卡分区的意义何在呢?sd卡不是本身就已经分区了吗?(待解决)

9、裸机代码中的前几个固定步骤

裸机代码的前几个步骤比较固定,都是一些初始化操作,而且有些操作在BL0中已经完成,这里重新再设置一遍也不会出错。另外,ddr的初始化和重定位这两个步骤看情况是否需要。

(0)开发板制锁

如果不进行这个步骤,得一直按着POWER键。

	// 第0步:开发板置锁ldr r0, =0xE010E81Cldr r1, [r0]ldr r2, =0x301orr r1, r1, r2str r1, [r0]

(1)关看门狗

开启看门狗是为了防止机器故障时自动复位。如果开启看门狗后,没有及时去喂狗,则系统会自动复位。没有操作系统前,喂狗这个操作需要编写代码完成,因此为了减少编码工作,这里选择直接把看门狗关闭。(其实BL0已经关了看门狗,这里重新设置一遍。)

    // WTCON(0xE2700000),其中bit5是看门狗的开关:0代表关,1代表开// 第1步:关看门狗(向WTCON的bit5写入0即可)ldr r0, =WTCONldr r1, =0x0str r1, [r0]

(2)初始化时钟

这一部分的内容,见博客:S5PV210的时钟系统_天糊土的博客-CSDN博客

	// 第2步:初始化时钟bl clock_init

(3)设置SVC栈

C语言的运行需要一定的条件,这些条件由汇编来提供。C语言运行时主要是需要栈。比如C语言中的局部变量都是用栈来实现的。如果汇编部分没有给C部分设置合理的栈地址,那么C代码中定义的局部变量就会落空,整个程序就死掉了。

我们现在要设置栈,不可能也没有必要去设置所有的栈,我们先要设置自己的模式,然后设置自己的模式下的栈到合理合法的位置即可。

我们如何访问SVC模式下的SP呢?很简单,先把模式设置为SVC,再直接操作SP。但是因为我们复位后就已经是SVC模式了,所以直接设置SP即可。

由于栈必须是当前一段可用的内存(这段内存必须已经初始化,而且这段内存只会被我们用作栈,不会被其他程序征用),当前CPU刚启动时,外部的SDRAM尚未初始化,目前可用的内存只有内部的SRAM(因为它不需初始化即可使用)。因此只能在SRAM中找一段内存来作为SVC的栈。结合iROM_application_note中的memory map,可知SVC栈应该设置为0xd0037D80。

	// 第3步:设置SVC栈ldr sp, =SVC_STACK //#define SVC_STACK	0xd0037d80

(4)开关icache

iROM中的BL0已经打开了icache,我们这里重新设置一遍也没有错。

	// 第4步:开/关icachemrc p15,0,r0,c1,c0,0;			// 读出cp15的c1到r0中//bic r0, r0, #(1<<12)			// bit12 置0  关icacheorr r0, r0, #(1<<12)			// bit12 置1  开icachemcr p15,0,r0,c1,c0,0;

寄存器和SDRAM之间的读取速度差异太大,SDRAM的读取速度远不能满足寄存器的需要,没有cache的话,会拉低系统的整体速度。210内部有32KB icache和32kb dcache,icache是用来缓存指令的;dcache是用来缓存数据的。

(5)DDR的初始化(可能需要)

见S5PV210——SDRAM的初始化_天糊土的博客-CSDN博客

(6)代码的重定位(可能需要)

见重定位的简介与操作(涉及位置无关码)_天糊土的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461034.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux报网络设备繁忙,【分享】linux常用命令

压缩与备份:bzip2/bunzip2 .bz2文件的压缩/解压缩程序cpio 备份文件dump 备份文件系统gzip/gunzip .gz文件的压缩/解压缩程序gzexe 压缩可执行文件restore 还原由倾倒(Dump)操作所备份下来的文件或整个文件系统(一个分区)tar 将若干文件存档或读取存档文件unarj 解压缩.…

HDU-4454 Stealing a Cake 三分枚举

题意&#xff1a;给定一个点&#xff0c;一个圆&#xff0c;以及一个矩形&#xff0c;现在问从一个点到一个圆再到一个矩形的最短距离为多少&#xff1f;到达一个目标可以只挨着或者穿过它。 解法&#xff1a;目前只知道从一个点到圆上按照[0,PI]&#xff0c;[PI,2*PI]的两个半…

VIP - virtual IP address

virtual IP address (虚拟 IP 地址)1、是集群的ip地址&#xff0c;一个vip对应多个机器2、与群集关联的唯一 IP 地址see wiki&#xff1a; A virtual IP address (VIP or VIPA) is an IP address assigned to multiple applications residing on a single server, multiple dom…

linux上perl怎么传输参数,如何在perl子函数中传递参数?

慕村225694Perl 可以通过函数元型在编译期进行有限的参数类型检验。如果你声明sub mypush ()那么 mypush() 对参数的处理就同内置的 push() 完全一样了。函数声明必须要在编译相应函数调用之前告知编译器(编译器在编译函数调用时会对相应函数用 prototype来查询它的元型来进行参…

Android中级之网络数据解析一之Json解析

本文来自http://blog.csdn.net/liuxian13183/ &#xff0c;引用必须注明出处&#xff01; 在网络传输的时候&#xff0c;经常用到的解析方式有xml和json两种&#xff0c;今天我们主要来说下json、解析&#xff0c;以及其要点。 首先json格式&#xff1a; “[”标识json解析开始…

Struts2中ValueStack结构和总结

【ValueStack和ActionContext的关系】首先&#xff0c;从结构上来看ValueStack是ActionContext的一个组成部分&#xff0c;是对ActionContext功能的扩展。ActionContext是一个容器结构&#xff0c;是Struts2中用于数据存储的的场所&#xff0c;而ValueStack则是一个具备表达式引…

将USB-WiFi网卡移植到X210开发板

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、移植前的准备工作 1、搭建开发环境 &#xff08;1&#xff09;虚拟机运行着ubuntu14.04系统。 &#xff08;2&#xff09;X210开发板运行着linux内核镜像、QT4.8文件系统镜像。相关的镜像文件在…

文件读取ini文件另一种读取办法

时间紧张&#xff0c;先记一笔&#xff0c;后续优化与完善。 Windows下的ini文件的读取可以应用系统提供的api来实现 GetPrivateProfileString GetPrivateProfileInt ... 现实应用中, 如果不应用一种同一的方法来包装一下会让源代码看起来很乱。 所以,须要计划一个便利&#xf…

浅谈mysql数据库引擎

2019独角兽企业重金招聘Python工程师标准>>> 数据库是数据的集合&#xff0c;计算机中的数据库是存储器上一些文件的集合或者是内存数据的集合。Mysql,SQL server数据库都是可以存储数据&#xff0c;并提供数据查询&#xff0c;更新功能的数据库管理系统。Mysql数据…

网络摄像机简介

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 一、网络摄像机定义 &#xff08;1&#xff09;网络摄像机&#xff0c;也叫IP摄像机&#xff0c;即IPCamera&#xff0c;简称IPC&#xff0c;近几年得益于网络带宽&#xff0c;芯片技术&#xff0c;算法技术…

如今的移动操作系统,写在2013年——android篇 by 伊一线天

前奏&#xff1a; 曾在2011年&#xff0c;我写过一篇同样题材的文章。时隔2年后&#xff0c;如今的移动操作系统领域跌宕起伏&#xff0c;2年前的一些系统变得更加强大&#xff0c;一些已经昙花一现。现在让我再来总结一些2013年移动操作系统。 第一讲&#xff1a;android 自从…

linux qt ping,Qt5.2中使用ping命令实现Ip扫描功能

在实现类似于Free IP Scanner 2.1的Ip扫描器软件中&#xff0c;会用到ping命令。如果使用Qt编程实现&#xff0c;主要会用QThread、QProcess这两个类。关于这两个类的具体用法可以查阅Qt助手或者QT官网。在QT中为了扫描大量的Ip&#xff0c;通常需要将扫描Ip的任务放在一个单独…

Python安装模块出错(ImportError: No module named setuptools)解决方法

原地址&#xff1a;http://www.cnblogs.com/BeginMan/archive/2013/05/28/3104928.html 在window平台下安装第三方模块时&#xff0c;出现这样的错误&#xff1a; Google了以下&#xff0c;才知道原来Python里少了这个模块。 我们可以在Python官网去查找 其中 Package Index中查…

kali linux 2.0 ssh,Kali 2.0使用SSH进行远程登录(示例代码)

一、配置SSH参数修改sshd_config文件&#xff0c;命令为&#xff1a;vim /etc/ssh/sshd_config将#PasswordAuthentication no的注释去掉&#xff0c;并且将NO修改为YES //kali中默认是yes将PermitRootLogin without-password修改为PermitRootLogin yes二、启动SSH服务命令为&am…

数据库课程设计报告

课程设计报告内容 封面&#xff08;注明组员及分工&#xff09; 目录 1&#xff0e;系统概述 – 系统的特点 – 系统设计环境 2&#xff0e;系统需求分析 – 系统设计的目标 – 系统需求分析&#xff08;给出&#xff1a;数据流图、数据字典&#xff09; – 系统功能…

基于Hi3516A的H265 IPC LIVE555 开发

转载于http://m.blog.csdn.net/faihung/article/details/73008742&#xff0c;如有侵权请告知删除。 1 系统工作原理 系统以Hi3516A开发平台&#xff08;由高分辨率1080 p的AR0330摄像头模块、带千兆以太网功能的Hi3516A控制器模块组成硬件平台&#xff0c;并在硬件平台上烧写了…

教材配套PPT初稿

1&#xff0d;10章初稿&#xff0c;基本完整。有些粗糙&#xff0c;后面可能会稍作调整。 附更新情况如下&#xff1a; 1.增加了第10章内容&#xff1b; 2.第5章增加了一些内容&#xff1b; 3.第3章内容部分更新&#xff1b; 4.增加了第8&#xff0d;9章内容。 订正&#xff1a…

linux ssh抓包,如何在SSH连接Linux系统的环境下使用wireshark抓包?

TSINGSEE青犀视频云边端架构EasyNVR、EasyDSS、EasyGBS等都是有两种操作系统的版本&#xff0c;一种是linux&#xff0c;一种是windows。而大多数开发者用户都会使用linux版本进行安装。对于安装部署出现的问题&#xff0c;TSINGSEE青犀视频团队研发的经常为客户远程调试&#…

Gearman 启动日志文件提示协议出错的BUG

如果直接以gearmand -d 启动 /usr/local/var/log/gearmand.log 里提示 Address family not supported by protocol ERROR 2014-11-20 20:05:49.000000 [ main ] socket()(Address family not supported by protocol) -> libgearman-server/gearmand.cc:468 ERROR 2014-11-20…