万字连载(上):如何 Bringup SoC 芯片
我一直认为战略上蔑视技术,战术上重视技术是很有必要的学习态度。这是一篇 Bringup SoC 芯片的指导手册,更是一篇了解整个系统流程的地图。不会深入了解每个模块的细节,但提供了整个系统的宏观描述,让你站在上帝视角俯视每个知识点,为了对读者更负责,我打算以付费的方式和大家见面,对技术细节有需求的小伙伴欢迎加我微信(rrjike)交流,保证超有所值。
系统在启动的时候,无论是 ROM 加载 Uboot(SPL + Bootloader),还是 Uboot 加载 Kernel,都是把相关的镜像放到对应的内存不同地址,然后运行启动。这个过程看起来很简单,但中间涉及到多个知识点,了解各个子过程对理解启动的本质有很大的帮助作用,对 bring up 芯片更是有必要。我们先从镜像的结构开始,后面逐一介绍 ROM->SPL->UBoot->Kernel 的全过程。
ELF 文件
在介绍加载镜像之前,需要先了解下 ELF 文件的格式定义。
从图中可以看出,一个 ELF 文件是由 4 部分组成,分别是:
ELF 头部,程序头表,节,节头表。
有 3 种类型的 ELF 文件:
目标文件:被链接器读取,用来产生一个可执行文件或者共享库文件;
可执行文件:被操作系统中的加载器从硬盘上读取,载入到内存中去执行;
共享库文件:在动态链接的时候,由 ld-linux.so 来读取;
ELF 头部
描述 ELF header 的结构体:
typedef struct elfhdr{unsigned char e_ident[EI_NIDENT]; /* ELF Identification */Elf32_Half e_type; /* object file type */Elf32_Half e_machine; /* machine */Elf32_Word e_version; /* object file version */Elf32_Addr e_entry; /* virtual entry point */Elf32_Off e_phoff; /* program header table offset */Elf32_Off e_shoff; /* section header table offset */Elf32_Word e_flags; /* processor-specific flags */Elf32_Half e_ehsize; /* ELF header size */Elf32_Half e_phentsize; /* program header entry size */Elf32_Half e_phnum; /* number of program header entries */Elf32_Half e_shentsize; /* section header entry size */Elf32_Half e_shnum; /* number of section header entries */Elf32_Half e_shstrndx; /* section header table's "sectionheader string table" entry offset */
} Elf32_Ehdr;
看下 ELF 头部的信息:
$ readelf -h vmlinux
ELF Header:Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00Class: ELF64Data: 2's complement, little endianVersion: 1 (current)OS/ABI: UNIX - System VABI Version: 0Type: DYN (Shared object file)Machine: AArch64Version: 0x1Entry point address: 0xffff200008080000Start of program headers: 64 (bytes into file)Start of section headers: 29609944 (bytes into file)Flags: 0x0Size of this header: 64 (bytes)Size of program headers: 56 (bytes)Number of program headers: 4Size of section headers: 64 (bytes)Number of section headers: 35Section header string table index: 32
这个内容与结构体 Elf32_Ehdr 中的成员变量是一一对应的。
程序头表
描述 Program header table 的结构体:
typedef struct {Elf32_Word p_type; /* segment type */Elf32_Off p_offset; /* segment offset */Elf32_Addr p_vaddr; /* virtual address of segment */Elf32_Addr p_paddr; /* physical address - ignored? */Elf32_Word p_filesz; /* number of bytes in file for seg. */Elf32_Word p_memsz; /* number of bytes in mem. for seg. */Elf32_Word p_flags; /* flags */Elf32_Word p_align; /* memory alignment */
} Elf32_Phdr;
看下程序头表的信息:
$ readelf -l vmlinuxElf file type is DYN (Shared object file)
Entry point 0xffff200008080000
There are 4 program headers, starting at offset 64Program Headers:Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags AlignLOAD 0x0000000000010000 0xffff200008080000 0xffff200008080000 0x0000000000f534c8 0x0000000000f534c8 R E 10000LOAD 0x0000000000f70000 0xffff200008fe0000 0xffff200008fe0000 0x00000000007dda00 0x000000000106af20 RWE 10000NOTE 0x000000000133a028 0xffff2000093aa028 0xffff2000093aa028 0x0000000000000024 0x0000000000000024 R 4GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 10Section to Segment mapping:Segment Sections...00 .head.text .text01 .rodata .init___kcrctab+sort .init__ksymtab_strings .pci_fixup __ksymtab __ksymtab_gpl __kcrctab __kcrctab_gpl __ksymtab_strings __param __modver __ex_table .notes .init.text .exit.text .altinstructions .altinstr_replacement .init.data .data..percpu .rela.dyn .data .got.plt .init___ksymtab+sort __bug_table .mmuoff.data.write .mmuoff.data.read .pecoff_edata_padding .bss02 .notes03
可以看出该 vmlinux 的入口地址是 0xffff200008080000。一共有 4个段(segment),前两个需要 load 到内存的段,它们分别是代码段和数据段,属性是读、执行(RE)和读、写、执行(RWE)。
代码段包含了两个 section。数据段包含了很多 section。
节
text 段
代码段,通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定。
data 段
数据段,通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。
bss 段
通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。BSS段属于静态内存分配。
init 段
linux定义的一种初始化过程中才会用到的段,一旦初始化完成,那么这些段所占用的内存会被释放掉,后续会继续说明。
节头表
描述 Section header table 的结构体:
typedef struct {Elf32_Word sh_name; /* name - index into section headerstring table section */Elf32_Word sh_type; /* type */Elf32_Word sh_flags; /* flags */Elf32_Addr sh_addr; /* address */Elf32_Off sh_offset; /* file offset */Elf32_Word sh_size; /* section size */Elf32_Word sh_link; /* section header table index link */Elf32_Word sh_info; /* extra information */Elf32_Word sh_addralign; /* address alignment */Elf32_Word sh_entsize; /* section entry size */
} Elf32_Shdr;
看下节头表的信息:
$ readelf -S vmlinux
There are 35 section headers, starting at offset 0x1c3cfd8:Section Headers:[Nr] Name Type Address Offset Size EntSize Flags Link Info Align[ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0[ 1] .head.text PROGBITS ffff200008080000 00010000 0000000000001000 0000000000000000 AX 0 0 4096[ 2] .text PROGBITS ffff200008081000 00011000 0000000000f524c8 0000000000000008 AX 0 0 2048[ 3] .rodata PROGBITS ffff200008fe0000 00f70000 0000000000358380 0000000000000000 WA 0 0 4096[ 4] .init___kcrctab+s PROGBITS ffff200009338380 012c8380 0000000000000004 0000000000000000 A 0 0 1[ 5] .init__ksymtab_st PROGBITS ffff200009338384 012c8384 0000000000000005 0000000000000000 A 0 0 1[ 6] .pci_fixup PROGBITS ffff200009338390 012c8390 0000000000000018 0000000000000000 A 0 0 8[ 7] __ksymtab PROGBITS ffff2000093383a8 012c83a8 00000000000155c0 0000000000000000 A 0 0 8[ 8] __ksymtab_gpl PROGBITS ffff20000934d968 012dd968 0000000000014fe0 0000000000000000 A 0 0 8[ 9] __kcrctab PROGBITS ffff200009362948 012f2948 0000000000005570 0000000000000000 A 0 0 1[10] __kcrctab_gpl PROGBITS ffff200009367eb8 012f7eb8 00000000000053f8 0000000000000000 A 0 0 1 [11] __ksymtab_strings PROGBITS ffff20000936d2b0 012fd2b0 00000000000358d8 0000000000000000 A 0 0 1[12] __param PROGBITS ffff2000093a2b88 01332b88 0000000000003548 0000000000000000 A 0 0 8[13] __modver PROGBITS ffff2000093a60d0 013360d0 0000000000000f30 0000000000000000 A 0 0 8[14] __ex_table PROGBITS ffff2000093a7000 01337000 0000000000003028 0000000000000000 A 0 0 8[15] .notes NOTE ffff2000093aa028 0133a028 0000000000000024 0000000000000000 A 0 0 4[16] .init.text PROGBITS ffff2000093b0000 01340000 0000000000080af8 0000000000000000 AX 0 0 8[17] .exit.text PROGBITS ffff200009430af8 013c0af8 000000000000421c 0000000000000000 AX 0 0 4[18] .altinstructions PROGBITS ffff200009434d14 013c4d14 000000000001e3b4 0000000000000000 A 0 0 1[19] .altinstr_replace PROGBITS ffff2000094530c8 013e30c8 000000000000a36c 0000000000000000 AX 0 0 4[20] .init.data PROGBITS ffff20000945e000 013ee000 000000000001f580 0000000000000000 WA 0 0 4096[21] .data..percpu PROGBITS ffff20000947e000 0140e000 0000000000014018 0000000000000000 WA 0 0 128[22] .rela.dyn RELA ffff200009492018 01422018 00000000001d9c10 0000000000000018 A 0 0 8[23] .data PROGBITS ffff200009670000 01600000 0000000000137868 0000000000000000 WA 0 0 4096[24] .got.plt PROGBITS ffff2000097a7868 01737868 0000000000000018 0000000000000008 WA 0 0 8 [25] .init___ksymtab+s PROGBITS ffff2000097a7880 01737880 0000000000000010 0000000000000000 WA 0 0 8 [26] __bug_table PROGBITS ffff2000097a7890 01737890 00000000000150b4 0000000000000000 WA 0 0 4[27] .mmuoff.data.writ PROGBITS ffff2000097bd000 0174d000 000000000000000c 0000000000000000 WA 0 0 2048[28] .mmuoff.data.read PROGBITS ffff2000097bd800 0174d800 0000000000000008 0000000000000000 WA 0 0 8[29] .pecoff_edata_pad PROGBITS ffff2000097bd808 0174d808 00000000000001f8 0000000000000000 WA 0 0 1[30] .bss NOBITS ffff2000097be000 0174da00 000000000088cf20 0000000000000000 WA 0 0 4096[31] .comment PROGBITS 0000000000000000 0174da00 0000000000000027 0000000000000001 MS 0 0 1[32] .shstrtab STRTAB 0000000000000000 01c3ce4a 000000000000018b 0000000000000000 0 0 1[33] .symtab SYMTAB 0000000000000000 0174da28 00000000002ea610 0000000000000018 34 92369 8[34] .strtab STRTAB 0000000000000000 01a38038 0000000000204e12 0000000000000000 0 0 1
Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings)I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)O (extra OS processing required) o (OS specific), p (processor specific)
最后用一幅图总结 ELF 文件 vmlinux 的分布:
镜像的生成
ELF 文件格式是 Linux 环境下的可执行文件格式,在 Linux 环境下,加载器根据 ELF 文件里的地址信息,就可以把它加载到内存指定的地址运行,但是系统启动过程中并没有 ELF 文件的执行环境,需要将 ELF 文件转换为二进制纯指令文件,即 Image。
万字连载(上):如何 Bringup SoC 芯片相关推荐
- 阿里平头哥研发专用 SoC 芯片;部分 MacBook Pro 被禁止上飞机;VS Code 1.37 发布 | 极客头条...
快来收听极客头条音频版吧,智能播报由标贝科技提供技术支持. 「CSDN 极客头条」,是从 CSDN 网站延伸至官方微信公众号的特别栏目,专注于一天业界事报道.风里雨里,我们将每天为朋友们,播报最新鲜有 ...
- 多核片上系统(SoC)架构的嵌入式DSP软件设计
多核片上系统(SoC)架构的嵌入式DSP软件设计 Multicore a System-on-a-Chip (SoC) Architecture SoCs的软件开发涉及到基于最强大的计算模型在各种处理 ...
- 概要设计实例_多核片上系统(SoC)架构的嵌入式DSP软件设计
多核片上系统(SoC)架构的嵌入式DSP软件设计 Multicore a System-on-a-Chip (SoC) Architecture SoCs的软件开发涉及到基于最强大的计算模型在各种处理 ...
- vivado SOC——hello word(上)建立SOC系统
引言 本节为了熟悉vivado的SOC使用,由于我也是开始学,所以请一起学的人点评指点. 软件:vivado 2016.4 板子:米联客701A mini 开发板介绍 创建工程 选择ZYNQ的型号和封 ...
- 5W无线充发射IC芯片方案XPM7105、XPM7305 无线充SOC芯片
FS68001A是泛海微推出的一款无线充电发射端控制SoC芯片, 兼容 WPC Qi v1.2.4 最新标准,支持 A11线圈, 支持 5W .苹果 5W .三星 5W充电 .只需要一个SOP8的主控 ...
- 嵌入式学习(二)之SoC芯片的开发流程
SoC芯片的开发流程 SoC芯片开发流程大致分为四个阶段,其中大部分工作都是借助于电子设计自动化(EDA)工具完成的. 总体设计 总体设计阶段的任务是按照系统需求说明书确定SoC的性能参数,并据此进行 ...
- 2.4G SOC芯片CI2451/CI2454应用于遥控玩具汽车的应用方案
Ci2451 是一款集成无线收发器和 8 位 RISC(精简指令集)MCU 的 SOC 芯片. 优点:超低睡眠功耗,极少外围器件,降低系统应用成本,拥有精简指令集架构,可以很容易做编程和控制. 主 ...
- ASR6601:国产M4内核LoRa SoC芯片替代SX1262/SX1278
目录 LoRa简介 ASR6601关键特性 ASR6601 Soc及LPWAN原理图 ASR6601开发环境搭建与编译下载 ASR6601硬件设计注意事项 ASR6601SE 测试板 LoRa简介 L ...
- 蓝牙室内定位,SOC芯片NRF52832
本次就来深入分析下Nordic的最新蓝牙芯片nRF52832. 目前有很多的芯片原厂发布了自己的BLE SoC芯片,其中NORDIC半导体的nRF52832是知名的nRF51822的后续作品,它将BL ...
最新文章
- Linux软件安装包中devel与非devel包之间的区别
- CSharpGL(22)实现顺序无关的半透明渲染(Order-Independent-Transparency)
- js作用域及作用域链概念理解及使用
- .Net Core添加分布式Session
- java怎么看具体被挂起的线程_Java线程的挂起、恢复和终止
- scp连接计算节点操作
- 浅析神经网络为什么能够无限逼近任意连续函数
- Windows中查看端口占用情况
- cpu是32位的 这指的是数据总线还是地址总线是32条?另外,电脑操作系统是3位的这指的是什么意思?指令是32...
- 批处理批量更改文件名并排序
- Louvain算法在反作弊上的应用
- C++MFC实现win10标准计算器
- 机器学习_高偏差(High bias)与高方差(High vars)
- Vue3.0调用PC端本地摄像头录像
- 计算机本科生优秀毕业论文,本科毕业论文计算机
- 资源暂时不可用错误(Out of memery)完美解决方案
- 怎么释放mysql连接_数据库连接释放问题
- Mysql为什么使用B+树(一)之红黑树简述
- 渡阡科技Edu——梦开始的地方
- vue项目模拟后台数据
热门文章
- cordova打印机插件_phonegap/cordova plugin
- 第二章 davinci 大数据分析平台 安装
- gcc的-g,-o,-c,-D,-w,-W,-Wall,-O3等参数的意义
- MATLAB概率分布函数
- flutter 使用百度定位进行定位以及配置
- 安装Navicat时出现Missing required library libmysql_e.dll,126报错解决方法
- 前端html小技巧—input标签详解
- 织梦dedecms - 织梦5.7版本后台去除版权
- 企企通携手塑料新材料行业龙头【佛塑科技】,以数字化采购引领行业转型升级
- leetcode 875. 爱吃香蕉的珂珂