ARM S5PV210的SD卡启动实战

news2024/9/21 14:37:47

一、S5PV210的SD卡启动实战1

1、任务:大于16KB的bin文件使用 SD 卡启动

(1) 总体思路:将我们的代码分为 2 部分:第一部分 BL1 ≤ 16KB,第二部分为任意大小。
iROM 代码执行完成后,从 SD 卡启动会自动读取 BL1 到 SRAM 中执行;BL1 执行时负责初始化 DDR,然后手动将 BL2 从 SD 卡 copy 到 DDR 中正确位置,然后 BL1 远跳转到 BL2 中执行 BL2.

(2) 细节1:程序怎么安排?程序整个分为 2 个文件夹 BL1 和 BL2,各自管理各自的项目。

(3) 细节2:BL1 中要完成:关看门狗、设置栈、开iCache、初始化 DDR、从 SD 卡复制 BL2 到 DDR 中特定位置,跳转执行 BL2.

(4) 细节3:BL1 在 SD 卡中必须从 Block1 开始(Block0 不能用,这个是三星官方规定的),长度为 16KB 内,我们就定为 16KB(也就是 32 个block);BL1 理论上可以从 33 扇区开始,但是实际上为了安全,都会留一些空扇区作为隔离,譬如可以从 45 扇区开始,长度由自己定(实际根据自己的 BL2 大小来分配长度,我们实验时 BL1 非常小,因此我们定义 BL1 长度为 16KB,也就是 32 扇区)。
在这里插入图片描述

(5) 细节4:DDR 初始化好之后,整个 DDR 都可以使用了,这时在其中选择一段长度足够 BL2 的 DDR 空间即可。我们选 0x23E00000(因为我们 BL1 中只初始化了 DDR1,地址空间范围是0x20000000~0x2FFFFFFF)。
在这里插入图片描述


2、代码划分为 2 部分(BL1 和 BL2)

在这里插入图片描述


文件名:write2sd

$ cat write2sd
#!/bin/sh
# sudo dd iflag=dsync oflag=dsync if=210.bin of=/dev/sdb seek=1

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

文件名:Makefile

$ cat Makefile
all:
        make -C ./BL1
        make -C ./BL2
clean:
        make clean -C ./BL1
        make clean -C ./BL2

3、BL1 中的重定位

文件名: start.S

$ cat start.S

/*
 * 文件名:     start.S
 * 描述:       演示重定位(在SRAM内部重定位)
 */

#define WTCON           0xE2700000

#define SVC_STACK       0xd0037d80

.global _start                                  // 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:
        // 第1步:关看门狗(向WTCON的bit5写入0即可)
        ldr r0, =WTCON
        ldr r1, =0x0
        str r1, [r0]

        // 第2步:设置SVC栈
        ldr sp, =SVC_STACK

        // 第3步:开/关icache
        mrc p15,0,r0,c1,c0,0;                   // 读出cp15的c1到r0中
        //bic r0, r0, #(1<<12)                  // bit12 置0  关icache
        orr r0, r0, #(1<<12)                    // bit12 置1  开icache
        mcr p15,0,r0,c1,c0,0;

        // 第4步:初始化ddr
        bl sdram_asm_init

        // 第5步:重定位,从SD卡第45扇区开始,复制32个扇区内容到DDR的 0x23E0,0000
        bl copy_bl2_2_ddr


// 汇编最后的这个死循环不能丢
        b .

文件名:BL1/link.lds

$ cat link.lds
SECTIONS
{
        . = 0xd0020010;

        .text : {
                start.o
                sdram_init.o
                * (.text)
        }

        .data : {
                * (.data)
        }

        bss_start = .;
        .bss : {
                * (.bss)
        }

        bss_end  = .;
}


文件名:BL2/link.lds

$ cat ../BL2/link.lds
SECTIONS
{
        . = 0x23E00000;

        .text : {
                start.o
                * (.text)
        }

        .data : {
                * (.data)
        }

        bss_start = .;
        .bss : {
                * (.bss)
        }

        bss_end  = .;
}


4、BL2 远跳转

(1) 因为我们 BL1 和 BL2 其实是 2 个独立的程序,链接时也是独立分开链接的,所以不能像以前一样使用 ldr pc, =main 这种方式来通过链接地址实现远跳转到 BL2.

(2) 我们的解决方案是,使用地址进行强制跳转。因为我们知道 BL2 在内存地址 0x23E00000 处,所以直接去执行这个地址即可。

文件名:sd_relocate.c

#define  SD_START_BLOCK     (45)
#define  SD_BLOCK_CNT       (32)
#define  DDR_START_ADDR     (0x23E00000)

typedef unsigned int bool;

//通道号: 0, 或者 2
//开始扇区号: 45
//读取扇区个数: 32
//读取后放入内存地址: 0x23E00000
//with_init:0
typedef  bool (*pCopySDMMC2Mem)(int, unsigned int, unsigned short, unsigned int*, bool);
//#define CopySDMMCtoMem(z,a,b,c,e)(((bool(*)(int, unsigned int, unsigned short, unsigned int*, bool))(*((unsigned int *)0xD0037F98)))(z,a,b,c,e))


typedef  void (*pBL2Type)(void);

//从SD卡第45扇区开始, 复制 32 个扇区内容到 DDR 的 0x23E00000, 然后跳转到 0x23E00000 去执行.
void copy_bl2_2_ddr(void)
{
    //第一步,读取 SD 卡扇区到 DDR 中
    pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)(*(unsigned int*)0xD0037F98);

    p1(2, SD_START_BLOCK, SD_BLOCK_CNT, (unsigned int*)DDR_START_ADDR, 0); //读取 SD 卡到 DDR 中

    //第二步,跳转到 DDR 中的 BL2 去执行
    pBL2Type p2 = (pBL2Type)DDR_START_ADDR;
    p2();
}


二、S5PV210的SD卡启动实战2

1、烧录启动实验

  • 确定将 U 盘连接到虚拟机。

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


  • 在 VM Ware 识别到读卡器U盘。

在这里插入图片描述


  • 确定 读卡器U盘的盘符。

sda 是 VM Ware 中的硬盘,sda1~sda5 代表硬盘的 5 个分区。
sdb 就是我们新插入的读卡器 U 盘,只有一个分区 sdb1。

在这里插入图片描述


  • 执行 make 编译整个 BL1/BL2 之后,确定我们程序中的脚本写的是 sdb ,与 VM Ware 识别到的读卡器 U 盘名称相同。

在这里插入图片描述


  • 执行 write2sd 脚本,烧写 U 盘。
    在这里插入图片描述

  • 破坏 iNand 中的 bootloader 以从 SD2 启动。
    进入 android 系统控制台,执行如下指令:
busybox dd if=/dev/zero of=/dev/block/mmcblk0 bs=512 seek=1 count=1 conv=sync
sync

解释:这句话的意思就是说把板载的 iNand 的第一个扇区用全 0 来填充,其实就是擦除它,这样我们板载的 iNand 的 bootloader 的开始第 1 个扇区就被破坏了。将来启动时 iROM 还是会先从 iNand 中读取前 16KB,然后计算校验和。这时候因为有 1 个扇区被擦掉了,所以校验和不通过,所以启动失败(会从 SD2 去执行 2nd 启动)。

在这里插入图片描述


  • 最后,将 U 盘插入 SD 通道 2,即可看到 BL2 中的代码 LED 灯闪烁的现象。

在这里插入图片描述


2、代码分为 2 部分启动(上一节讲的)的缺陷

(1) 代码分为 2 部分,这种技术叫分散加载。这种分散加载的方法可以解决问题,但是比较麻烦。

(2) 分散加载的缺陷:第一,代码完全分 2 部分,完全独立,代码编写和组织上麻烦;第二,无法让工程项目兼容 SD 卡启动和 Nand 启动、NorFlash 启动等各种启动方式。


3、uboot 中的做法

(1) 第二种思路:程序代码仍然包括 BL1 和 BL2 两部分,但是组织形式上不分为 2 部分,而是作为一个整体来组织。它的实现方式是:iROM 启动,然后从 SD 卡的扇区 1 开始读取 16KB 的 BL1,然后去执行 BL1,BL1 负责初始化 DDR,然后从 SD 卡中读取整个程序(BL1 + BL2)到 DDR 中,然后从 DDR 中执行(利用 ldr pc, =main 这种方式以远跳转从 SRAM 中运行的 BL1 跳转到 DDR 中运行的 BL2)。


4、再来分析 uboot 的 SD 卡启动细节

(1) uboot 编译好之后有 200 多KB,超出了 16KB。uboot 的组织方式就是前面 16KB 为 BL1,剩下的部分为 BL2.

(2) uboot 在烧录到 SD 卡的时候,先截取 uboot.bin 的前 16KB(实际脚本截取的是 8KB)烧录到 SD 卡的 block1~bolck32;然后将整个 uboot 烧录到 SD 卡的某个扇区中(譬如49扇区)。

(3) 实际 uboot 从 SD 卡启动时是这样的:iROM 先执行,根据 OMpin 判断出启动设备是 SD 卡,然后从 SD 卡的 block1 开始读取 16KB(8KB)到 SRAM 中执行 BL1,BL1 执行时负责初始化 DDR,并且从 SD 卡的 49 扇区开始复制整个 uboot 到 DDR 中指定位置(0x23E00000)去备用;然后 BL1 继续执行直到 ldr pc, =main 时,BL1 跳转到 DDR 上的 BL2 中接着执行 uboot 的第二阶段。

总结:uboot 中的这种启动方式比上节讲的分散加载的好处在于:能够兼容各种启动方式。


源自朱有鹏老师.

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

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

相关文章

多核缓存一致性问题及解决方案MESI协议《深入浅出计算机组成原理》学习笔记 Day 4

系列文章目录 这是本周期内系列打卡文章的所有文章的目录 《Go 并发数据结构和算法实践》学习笔记 Day 1《Go 并发数据结构和算法实践》学习笔记 Day 2《说透芯片》学习笔记 Day 3 文章目录系列文章目录前言一、多核缓存一致性从何而来&#xff08;What&#xff09;二、怎么解…

学习TinyRenderer

1图形学图形学&#xff0c;简单来讲是将3D数据以各个视觉效果呈现在2D画布&#xff08;屏幕&#xff09;上&#xff1b;2 TinyRendererTinyRenderer从零开始实现了一个渲染器&#xff1b;TinyRenderer代码地址&#xff1a;https://github.com/ssloy/tinyrenderer内容介绍在&…

ThreeDXF预览DXF文件集成到vue项目中

由于网上资料都是html的&#xff0c;而自己需要嵌入到vue项目中&#xff0c;查找资料都是在index.html引入script脚本&#xff0c;在写到Vue文件中&#xff0c;但是我尝试过了&#xff0c;各种报错&#xff0c;找不到&#xff0c;window. 根本无法用&#xff0c;于是改注入main…

主动服务再升级!这个品牌引领智慧生活进入“深度体验”

文|智能相对论作者| 佘凯文1月15日&#xff0c;一档央视新闻的新概念科技节目《KU A &#xff01;酷啊未来 | 中国科技创新之夜》正式播出&#xff0c;来自中国科学院的多领域顶级科学家及许多科技企业、青年科研人员代表&#xff0c;共同分享了科技创新之路上的成果和突破。不…

EDI文件处理失败如何汇总?

知行之桥EDI系统在后台自动运行的时候&#xff0c;有时会遇到处理文件失败的情况&#xff0c;导致失败的原因有很多&#xff0c;部分客户希望把处理失败的文件都汇总起来&#xff0c;便于分析失败原因&#xff0c;减少未来再出现类似的错误&#xff0c;同时也能够方便后期排查&…

ERD Online 4.0.7 在线数据库建模、元数据管理(免费、私有部署)

4.0.7❝ feat(erd): 增加新春火红主题feat(erd): 增加团队协作人员进入、退出提示fix(erd): 修复权限配置页面显示混乱doc(erd): 修改更新通告地址❞变化一览 增加新春火红主题 新春主题所有按钮、菜单、元素由原来的蓝色改为火红色修复权限配置页面显示混乱 团队功能增加团队协…

【算法基础】快速排序

目录 一、快速排序核心思想 二、快速排序步骤 (1)暴力做法 (2)双指针做法 三、代码模板 四、边界问题 五、总结 一、快速排序核心思想 分治&#xff0c;即将一个序列划分成左部分小于等于x,右部分大于等于x 二、快速排序步骤 ①确定一个分界点x。分界点可以是左端 a[l]、右…

【Linux】两个故事带你使用git命令行

目录一.历史故事背景经过git的诞生二.git版本管理1.小故事2.理解版本管理三.git的使用1.仓库的创建2.安装git和仓库克隆3.上传代码三板斧addcommitpushgithub和gitee是代码的托管平台&#xff0c;我们上传代码或文件在其中&#xff0c;来管理我们的代码和不同版本软件。 在多人…

【操作系统】——主流的操作系统(带你快速了解)

&#x1f4dc; “作者 久绊A” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴。 &#x1f341; 操作系统【带你快速了解】对于电脑来说&#xff0c;如果说…

【Java IO流】字符集使用详解

文章目录前言ASCIIGBKUnicode为什么会出现乱码前言 上一节关于字节流的文章中&#xff0c;在使用字节流读取本地文件中的数据时&#xff0c;文件中只存放了英文&#xff0c;而并没有存放中文数据。我们还提到了不建议使用字节流读取纯文本文件的数据&#xff0c;否则会出现乱码…

Elasticsearch7.8.0版本高级查询—— 匹配查询文档

目录一、初始化文档数据二、匹配查询文档示例2.1、概述2.2、示例一、初始化文档数据 在 Postman 中&#xff0c;向 ES 服务器发 POST 请求 &#xff1a;http://localhost:9200/user/_doc/1&#xff0c;请求体内容为&#xff1a; {"name":"张三","age&…

浅谈php原生类的利用 2(ErrorSoapClientSimpleXMLElement)

除了上篇文章浅谈 php原生类的利用 1(文件操作类)_php spl原生类_葫芦娃42的博客-CSDN博客 里提到的原生利用文件操作类读文件的功能&#xff0c;在CTF题目中&#xff0c;还可以利用php原生类来进行XSS,反序列化&#xff0c;SSRF&#xff0c;XXE。 常用内置类&#xff1a; Dire…

【SAP Abap】X档案:SAP Native SQL 简介及实现方式(EXEC SQL、ADBC、AMDP)

SAP Native SQL 简介及实现方式&#xff08;EXEC SQL、ADBC、AMDP&#xff09;1、SAP Open SQL 与 Native SQL 的特点2、Native SQL 的实现方式方式一&#xff1a;Exec SQL&#xff08;1&#xff09;获取单值&#xff08;2&#xff09;获取多行&#xff08;3&#xff09;游标应…

TCP协议的长连接和短连接详解

一 前言TCP在真正开始进行数据传输之前&#xff0c;Server 和 Client 之间必须建立一个连接。当数据传输完成后&#xff0c;双方不再需要这个连接时&#xff0c;就可以释放这个连接。TCP连接的建立是通过三次握手&#xff0c;而连接的释放是通过四次挥手。所以说&#xff0c;每…

【SpringCloud】Eureka的基本原理与使用

【SpringCloud】Eureka的基本原理与使用 一、Eureka-提供者与消费者 【问】如果服务A调用了服务B&#xff0c;而服务B又调用了服务C&#xff0c;服务B的角色是什么&#xff1f; 二、Eureka的结构和作用 什么是Eureka&#xff1f; Eureka 解决服务调用的问题 order-servic…

博物馆3d数字化全景展示设计方案

作为近几年新兴的营销方式&#xff0c;交互式营销能够让消费者对产品从主动感兴趣到互动体验&#xff0c;甚至自主自发传播&#xff0c;达到“在销售中传播&#xff0c;在传播中销售”的目的。进入数字体验经济时代&#xff0c;当3d数字化展示技术遇上传统行业&#xff0c;3d数…

Redis原理篇(三)通信协议

一、RESP协议 1、定义 Redis是一个cs架构的软件&#xff0c;通信一般分两步&#xff1a; 客户端client向服务端server发送一条命令服务端解析并执行命令&#xff0c;返回响应结果给客户端 因此客户端发送命令的格式、服务端响应结果的格式必须有一个规范&#xff0c;这个规…

HashMap源码学习:JDK1.8版本源码解析

文章导航 HashMap源码学习&#xff1a;红黑树原理详解 HashMap源码学习&#xff1a;JDK1.8版本源码解析 目录文章导航前言正文HashMap重要属性HashMap构造方法HashMap扩容方法HashMap链表迁移HashMap红黑树迁移HashMap链表转红黑树HashMap红黑树转链表HashMap添加数据HashMap移…

让你彻底明白Java SPI与SpringBoot自动配置,内附实例代码演示

一、Java SPI的概念和术语 SPI&#xff1a;全称是Service Provider Interface&#xff1a;是一种基于ClassLoader来发现并加载服务的机制 SPI由三个组件构成&#xff1a;Service、Service Provider、ServiceLoader Service&#xff1a;是一个公开的接口或抽象类&#xff0c;定…

数说菊风2022

春风传捷报&#xff0c; 梅韵贺新年&#xff01; 2022&#xff0c;已悄然划过&#xff0c; 就让我们用数字说话&#xff0c; 述说这年的精彩&#xff01; 树十大标杆案例 国际运营商战略合作——Telkomsel 携手印尼运营商Telkomsel在RCS融合通信和RTC实时音视频领域形成合…