imx6ul:uboot-2013.10启动过程解析

2023-10-27

1.源码结构分析

     首先一个问题,老版本的u-boot是没有SPL这个文件的,新版u-boot开始包含SPL文件,原来u-boot启动比如放到nand中,在cpu内部有一个stepping stone,可以拷贝nand中的u-boot到ram中运行,然后u-boot自己再启动第二阶段在对应内存中好到系统的image启动。现在加了这个SPL之后,我的理解这是一个u-boot的loader。及cpu上电后,首先运行这个spl,然后通过这个spl再将u-boot放到对应的位置运行,之后的操作就和老版本基本一样了。至于为什么这样做,暂时还不明白,后期再研究下。

编译成功的u-boot-2013.10共有19个子目录,大约15个有用的文件,其中各个子目录和重要文件功能见下表:

名称

类型

功能说明

api

通用

U-boot提供的一些接口函数

arch

平台相关

当前U-BOOT重要的目录,arch下每个子目录代表一种处理器类型

board

平台相关

里面有很多支持的开发板型号,这里关注具体开发板和config.mk

common

通用

主要跟U-BOOT的命令有关,cmd_xxx.c以及环境变量的处理代码env_xxx.c

spl

平台相关

u-boot的第一阶段相关,搬运第二阶段代码到内存中

disk

通用

磁盘驱动的分区处理代码

doc

说明文档

可以用来做配置参考

drivers

通用

设备的驱动程序,每种类型一个子目录包括网卡,USB,LCD等

dts

通用

设备树的控制,主要是由于LINUX 3.X中去除了很多冗余的代码,引入device tree,许多硬件细节可以直接传递给LINUX,是新的东西

examples

通用

一些示例程序

fs

通用

文件系统支持

include

通用

头文件和开发板的配制,configs子目录重要

lib

通用

通用的库文件

Licenses

通用

可以忽略。。。

nand_spl

平台相关

支持了部分平台的nand启动

net

通用

网络相关的代码,小型的协议栈

post

通用

加电自检程序

scripts

通用

脚本程序

test

通用

测试程序

tools

通用

工具,mkimage就在这里

boards.cfg

文件,平台相关

修改添加开发板配置现在在此处

Makefile

MAKEALL

config.mk

rules.mk

mkconfig

文件,通用

整个U-BOOT编译过程的规则文件

kbuild

mkconfig

文件,通用

对Makefile功能的补充,使得编译更加高效

其余

文件,通用

介绍文档以及其他

    移植工作主要集中在一些编译规则文件,还有board和arch目录下。

2 Makefile分析

    u-boot的README里面其实讲的很清楚u-boot的移植过程,翻译过来如下:

    第一步:在boards.cfg里面添加自己的开发板,必须按照现有的规则添加。

    第二步:为自己的开发板建立一个目录,在目录下添加你需要的文件,这目录下必须要有以下几个文件,Makefile,<board>.c,flash.c和u-boot.lds

     第三步:为你的建立一个新的配置文件“include/configs/<board>.h”

    第四步:输入“make<board>_config”

    第五步:make

    第六步:调试并解决出现的问题(当然,这一步远比听起来的难很多)

    Makefile的分析可以了解整个U-boot的代码结构是怎样的,文件是如何编译、链接的。

2.1分析配置过程第一步

    在编译的时候第一步是输入:make wandboard_config,当输入这个指令的时候,Makefile就会调用以下语句:

    %_config:: unconfig

         @$(MKCONFIG) -A $(@:_config=)

    %通配符匹配到执行xxx_config的时候,就调用下面的@$(MKCONFIG),这个MKCONFIG可以搜索在以下定义:

    MKCONFIG := $(SRCTREE)/mkconfig

    export MKCONFIG

2.2分析mkconfig文件

    mkconfig为$(SRCTREE)/目录下的mkconfig文件,就是我们源码目录下的mkconfig文件,也就是说,我们输入了make wandboard_config之后,就执行了mkconfig。

    mkconfig里面其实就是根据输入的板子的型号,这里是wandboard,调用boards.cfg文件,将arch cpu soc vender board等信息全部读出来,然后解析这些信息,进行通用头文件和库文件的自动配置,比如arm平台,很多lib库和头文件都是可以共用的。就在这一步生成头文件和很多宏,并将我们的板子的宏配置进去,如下所示为boards.cfg和Imx6平台相关的内容:

boards.cfg文件与imx6相关配置 展开原码

expand source?

cat << EOF >> config.h

#define CONFIG_BOARDDIR board/$BOARDDIR

#include <config_cmd_defaults.h>

#include <config_defaults.h>

#include <configs/${CONFIG_NAME}.h>

#include <asm/config.h> #include <config_fallbacks.h>

#include <config_uncmd_spl.h>

 

   这里调用了boards.cfg文件,切进去查看该文件,这个文件里面其实定义了u-boot可以支持的所有开发板,如下图:

2.3分析建立软连接过程

mkconfig建立软连接 展开原码

expand source?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

if "$SRCTREE" != "$OBJTREE" ] ; then 

mkdir -p ${OBJTREE}/include 

mkdir -p ${OBJTREE}/include2 

cd ${OBJTREE}/include2 

rm -f asm 

ln -s ${SRCTREE}/arch/${arch}/include/asm asm 

LNPREFIX=${SRCTREE}/arch/${arch}/include/asm/ 

cd ../include 

mkdir -p asm

else

cd ./include 

rm -f asm 

ln -s ../arch/${arch}/include/asm asm

fi

rm -f asm/arch

if [ -z "${soc}" ] ; then 

ln -s ${LNPREFIX}arch-${cpu} asm/arch

else

ln -s ${LNPREFIX}arch-${soc} asm/arch

fi

if "${arch}" "arm" ] ; then 

rm -f asm/proc 

ln -s ${LNPREFIX}proc-armv asm/proc

fi

 

    以上是建立软连接的过程,if [ "$SRCTREE" != "$OBJTREE" ] ; then  表示判断源码目录是不是我们目标文件生产的目录,显然是的,我们生成的目标文件是在u-boot源码目录下的,所以直接跳到else后面,执行下面的语句:

    cd ./include

    rm -f asm

    ln -s ../arch/${arch}/include/asm asm

    切换到源码目录的include目录下,删除asm软连接,然后将上一级目录下arch/arm/include/asm目录链接到这个目录来,这是建立了第一个软连接。可以看得到:

    接着rm -f asm/arch删除asm目录下的arch软连接,下面的代码:

建立软连接2

?

1

2

3

4

5

6

7

8

9

if [ -z "${soc}" ] ; then 

ln -s ${LNPREFIX}arch-${cpu} asm/arch

else

ln -s ${LNPREFIX}arch-${soc} asm/arch

fi

if "${arch}" "arm" ] ; then

rm -f asm/proc 

ln -s ${LNPREFIX}proc-armv asm/proc

fi

 

    首先判断soc是否为空,这里soc显然不为空,执行ln -s ${LNPREFIX}arch-${soc} asm/arch ,这里LNPREFIX为空,所以这句其实就是ln -s ./arch-mx6 asm/arch,下面的同样是将arm相关的proc链接进去。

结果可以通过ls -l来查看:

2.4生成config.mk和头文件

生成config.mk文件

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

( echo "ARCH   = ${arch}"  

if [ ! -z "$spl_cpu" ] ; then 

echo 'ifeq ($(CONFIG_SPL_BUILD),y)'

echo "CPU    = ${spl_cpu}"

echo "else"

echo "CPU    = ${cpu}"

echo "endif"   

else

echo "CPU    = ${cpu}"   

fi    

echo "BOARD  = ${board}"

    "${vendor}" ] && echo "VENDOR = ${vendor}"  

"${soc}"    ] && echo "SOC    = ${soc}"  

exit 0 ) > config.mk

 

     上面的代码其实就是判断有没有定义spl_cpu如果定义了那就将spl_cpu信息输出到CPU,这里没有定义,因此依次就是确定了CPU.BOARD.SOC这些信息,最后一句> config.mk将以上信息输出到config.mk后退出。可以切换到./include/目录下,看到一个config.mk文件,打开看到如下内容:

    接着mkconfig文件还做了自动生成头文件的工作,这部分代码如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

if "$APPEND" "yes" ] # Append to existing config file then

echo >> config.h

else  > config.h  # Create new config file

fi

echo "/* Automatically generated - do not edit */" >>config.h

for i in ${TARGETS} ; do

i="`echo ${i} | sed '/=/ {s/=/ /;q; } ; { s/$/ 1/; }'`"

echo "#define CONFIG_${i}" >>config.h ; done

echo "#define CONFIG_SYS_ARCH  \"${arch}\""  >> config.h

echo "#define CONFIG_SYS_CPU   \"${cpu}\""   >> config.h

echo "#define CONFIG_SYS_BOARD \"${board}\"" >> config.h

"${vendor}" ] && echo "#define CONFIG_SYS_VENDOR \"${vendor}\"" >> config.h

"${soc}"    ] && echo "#define CONFIG_SYS_SOC    \"${soc}\""    >> config.h

cat << EOF >> config.h

#define CONFIG_BOARDDIR board/$BOARDDIR

#include <config_cmd_defaults.h>

#include <config_defaults.h>

#include <configs/${CONFIG_NAME}.h>

#include <asm/config.h>

#include <config_fallbacks.h>

#include <config_uncmd_spl.h>

EOF

exit 0

 

    首先检查config.h存在否,如果不存在就建立一个config,h,然后依次定义宏到config.h中,最后加入一些arm平台下通用的头文件,最后保存退出。打开config.h文件,可以清晰看到如下内容:

    这里并未定义文件里面的前四行内容,应该是手动添加进去的,确定mxl是否是有SPL启动,具体是哪个型号,然后根据具体型号再做一个配置,这里写到imx6image.cfg文件里查看。

imx6img.cfg

?

1

2

3

4

5

6

7

8

9

/* image version */

IMAGE_VERSION 2

/*  * Boot Device : one of  * spi, sd (the board has no nand neither onenand)  */

BOOT_FROM      sd

#define __ASSEMBLY__

#include <config.h>

#include "asm/arch/iomux.h"

#include "asm/arch/crm_regs.h"

#include "clocks.cfg"

 

这个文件加入了另外几个头文件,猜测这个文件是和启动方式有关的配置文件,这里又加入了clocks.cfg文件,配置了启动时候的时钟,这部分代码后面分析启动过程的时候再分析。

2.5编译

    这部分代码比较多,但是主要完成了以下几个剩余的工作:

    1.u-boot版本号确认及语言环境确认

    2.解析make后面传入的参数,例如make -v=1之类的,这里我们没有

    3.指定源码目录和目标目录

    4.获取machine号

    5.确定交叉编译工具链,制定了我们的shell名称:/bin/bash,编译器套件名称:gcc,以及一些编译参数,-Wall表示要提示所有的warning。

    6.设置头文件包含路径,输出目标制定目录,添加平台相关的头文件到指定目录。

    7.根据配置执行make以及depend的依赖关系分别调用各子目录,生成所有的obj文件。

    8.交代了u-boot是如何组装起来的,组装规则是u-boot.lds这个文件,把start.o和各个子目录makefile生成的库文件按照LDFLAGS连接在一起,生成ELF文件u-boot 和连接时内存分配图文件u-boot.map。这里,我们的u-boot.bin文件我理解的是从u-boot.elf拷贝过来的。

3.u-boot.lds

    u-boot的代码是根据u-boot.lds组装起来的,由于u-boot.lds的代码比较晦涩,不过不要紧,只要能找到每一个阶段的入口就可以了,该文件内容如下:

第一启动阶段代码入口

?

1

2

3

4

5

6

7

8

9

10

11

12

OUTPUT_FORMAT("elf32-littlearm""elf32-littlearm""elf32-littlearm")

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS {

  . = 0x00000000;

  . = ALIGN(4);

.text : 

*(.__image_copy_start)   //这里指定了影响文件复制的起始地址

arch/arm/cpu/armv7/start.o (.text*)  //指明了启动第一阶段的文件为制定目录下的start.s

*(.text*) 

}

 

    下面开始分析start.s和具体上电后的操作。

4.启动分析

start.S

?

22

23

.globl _start

_start: b reset

 

    这里声明一个连接入口_start,上电后或者复位后第一句就跳转到reset,切过去:

start.S

?

110

111

112

113

114

115

116

117

118

reset: 

bl save_boot_params   

mrs r0, cpsr  //将当前状态寄存器的值读到r0

and r1, r0, #0x1f //将r0的低五位状态赋值r1,也就是cpsr的低五位状态

teq r1, #0x1a  //比较CPSR的低五位状态是否等于0x1a,该状态说明对应HYP模式,一种非安全状态行运行的新模式。

bicne r0, r0, #0x1f //如果不等于那就清楚低五位 

orrne r0, r0, #0x13 //同样设置低五位为0x13,也就是10011,对应的是ARM的SVC管理模式

orr r0, r0, #0xc0  //11000000,禁止IRQ和FIQ

msr cpsr,r0//将r0的值读到CPSR,这时候am谁svc模式,中断被禁止。

 

    

                                                               CPSR寄存器

     这里先跳转到save_boot_params,bl跳转后会返回回来继续执行,还是切过去看save_boot_params做了什么。

save_boot_params

?

179

180

181

182

ENTRY(save_boot_params) 

bx lr   @ back to my caller

ENDPROC(save_boot_params) 

.weak save_boot_params

 

    这里bx lr就直接返回跳转来之前的地址,也就是什么都不做,下面的.weak关键字作用是如果其他地方定义了save_boot_params那就调用,如果没有定义,这就是个空函数。

    接着上面的代码段,具体做了什么已经注释的比较清楚了,接下来:

start.S

?

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD)) 

/* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */

mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register 

bic r0, #CR_V  @ V = 0

mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register

/* Set vector address in CP15 VBAR register */

ldr r0, =_start 

mcr p15, 0, r0, c12, c0, 0 @Set VBAR

#endif

#ifndef CONFIG_SKIP_LOWLEVEL_INIT 

bl cpu_init_cp15 

bl cpu_init_crit

#endif

bl _main

 

     这里我们没有定义CONFIG_OMAP44XX和CONFIG_SPL_BUILD,因此执行

    mrc p15, 0, r0, c1, c0, 0,这是协处理器操作,只有mrc和mcr才能对arm的协处理器进行操作:

          MRC {条件}协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,{协处理器操作码2}

          MCR {条件}协处理器编码,协处理器操作码1,源寄存器,目的寄存器1,目的寄存器2,{协处理器操作码2}

    这两个指令一般是成对使用,读出来在写进去,设置CP15协处理器的C1寄存器V位为0,查看寄存器手册:

   设置地段一场中断向量0x0~0x1c。

    然后将_start的地址给r0,再将该地址写到c12寄存器,也就是设置异常向量的基地址:

   

    紧接着,这里没有定义skip_lowlevel_init,跳入cpu_init_cp15 ,顾名思义还是对cp15协处理器的设置。代码如下:

cpu_init_cp15 展开原码

expand source?

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

ENTRY(cpu_init_cp15)

/* 

* Invalidate L1 I/D 

* 使无效整个数据和指令TLB,然后使无效整个指令cache,清空整个跳转目标的cache,清空预取缓冲区,清空写缓冲区   

*/

mov r0, #0   @ set up for MCR 

mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs 

mcr p15, 0, r0, c7, c5, 0 @ invalidate icache 

mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array 

mcr p15, 0, r0, c7, c10, 4 @ DSB 

mcr p15, 0, r0, c7, c5, 4 @ ISB

/*

* disable MMU stuff and caches  

* 设置低端异常中断向量,禁止MMU,禁止地址对齐检查,禁止数据Cache,前面已经禁止了指令cache。紧接着使能地址对齐检查,使能跳转预测功能   

*/

mrc p15, 0, r0, c1, c0, 0 

bic r0, r0, #0x00002000 @ clear bits 13 (--V-) 

bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) 

orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align 

orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB

#ifdef CONFIG_SYS_ICACHE_OFF 

bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache

#else 

orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache //这里没有定义ICACHE_OFF,因此这里使能指令Cache

#endif 

mcr p15, 0, r0, c1, c0, 0

#ifdef CONFIG_ARM_ERRATA_716044   //没有定义该号码的宏,跳过

mrc p15, 0, r0, c1, c0, 0 @ read system control register

orr r0, r0, #1 << 11 @ set bit #11 

mcr p15, 0, r0, c1, c0, 0 @ write system control register

#endif

/*

* 这里是对CP15的C15寄存器进行了操作,这里叫做诊断寄存器,然后将4,6,15都置位,这里我没找到c15寄存器的手册说明。

*/

#ifdef CONFIG_ARM_ERRATA_742230 

mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register

orr r0, r0, #1 << 4  @ set bit #4 

mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register

#endif

#ifdef CONFIG_ARM_ERRATA_743622 

mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register

orr r0, r0, #1 << 6  @ set bit #6 

mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register

#endif

#ifdef CONFIG_ARM_ERRATA_751472 

mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register

orr r0, r0, #1 << 11 @ set bit #11 

mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register

#endif

mov pc, lr   @ back to my caller ENDPROC(cpu_init_cp15)

 

    这部分首先对r0清零,然后使无效整个数据和指令TLB,然后使无效整个指令cache,清空整个跳转目标的cache,清空预取缓冲区,清空写缓冲区, 设置低端异常中断向量,禁止MMU,禁止地址对齐检查,禁止数据Cache,前面已经禁止了指令cache。紧接着使能地址对齐检查,使能跳转预测功能 。然后后面有三个勘误宏,这里定义了三个,分别作了以下事情:对CP15的C15寄存器进行了操作,这里叫做诊断寄存器,然后将4,6,15都置位,这里我没找到c15寄存器的手册说明,具体意义不明,不过应该不影响后面的启动过程。

    具体CP15的C0到C15寄存器信息参考下面的链接。

    http://blog.sina.com.cn/s/blog_858820890102v1gc.html

    完了之后,跳回子函数,然后顺序执行到函数cpu_init_crit:

cpu_init_crit 展开原码

expand source?

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

/************************************************************************* 

*

* CPU_init_critical registers 

* setup important registers 

* setup memory timing 

* *************************************************************************/

ENTRY(cpu_init_crit) 

/*  

* Jump to board specific initialization...  

* The Mask ROM will have already initialized  

* basic memory. Go here to bump up clock rate and handle  

* wake up conditions.   */

   b lowlevel_init  @ go setup pll,mux,memory

ENDPROC(cpu_init_crit)

#endif

 

     未定义SKIP_LOWLEVEL_INIT这部分代码其实就是跳转到lowlevel_init去了,lowlevel_init的作用就是引导加载c函数做进一步的初始化,切过去。

low_level_init.S

?

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

ENTRY(lowlevel_init) 

/*  

* Setup a temporary stack  

*/

ldr sp, =CONFIG_SYS_INIT_SP_ADDR 

bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

#ifdef CONFIG_SPL_BUILD 

ldr r9, =gdata

#else 

sub sp, #GD_SIZE 

bic sp, sp, #7 

mov r9, sp

#endif 

/*  

* Save the old lr(passed in ip) and the current lr to stack  

*/

push {ip, lr}

/*  

* go setup pll, mux, memory  

*/

bl s_init 

pop {ip, pc}

ENDPROC(lowlevel_init)

 

    这里首先设置了一个临时的堆空间,将CONFIG_SYS_INIT_SP_ADDR的地址送到SP,这个地址=(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET),CONFIG_SYS_INIT_RAM_ADDR 在

imx-regs.h里面定义了0x00900000,后面的CONFIG_SYS_INIT_SP_OFFSET未找到,忽略。

    设置SP八个字节对齐之后,这里定义了CONFIG_SPL_BUILD。将gdata赋值给r9,跳转到s_init函数中去。

    s_init在arch\arm\cpu\armv7\mx6的soc.c中,s_init主要是对IMX6的PFDs进行了板级设置。

    在调用结束s_init之后,程序跳转到到_main函数里面,搜索定位该感受在arch/arm/lib/crt0.S下,这里是main函数的入口,主要做了以下工作:

  • 重新对SP赋值, 确认sp是8字对齐
  • 在栈顶保留一个global_data的大小, 这个global_data是uboot里面的一个全局数据, 很多地方都会用到. 俗称 gd_t
  • 确认更新后的sp是8字对齐
  • r9指向global_data, 后面别的地方想用global_data时候, 可以直接从r9里面获取地址.
  • r0赋值0
  • bl board_init_f: 跳转到board_init_f. 在编译SPL时, 分析Makefile可以看出, 该函数的实现是在<arch/arm/lib/spl.c>.

    board_init_f在arch/arm/lib/spl.c中,主要做了以下事情:

  • 对BSS段进行清零操作
  • gd = &gdata;
    • gd的定义在DECLARE_GLOBAL_DATA_PTR <arch/arm/include/asm/global_data.h>
      • #define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r9")
        • r9之前初始化了
    • gdata的定义在本文件中: gd_t gdata __attribute__ ((section(".data"))); 
      • 它是一个 gd_t 也就是global_data类型的变量
      • __attribute__表示这个变量会被放到".data"这个输入段中. 连接器会把输入段按照链接脚本(u-boot-spl.lds)里面指定的规则存放到输出段

    接着跳转到board_init_r,在common/spl/spl.c下面,主要做了以下事情:

    对memory,timer初始化,选择在什么介质启动,最后判断image的类型,是u-boot还是linux。

5.总结

    (reset) <arch/arm/cpu/armv7/start.S-> (b lowlevel_init: arch/arm/cpu/armv7/lowlevel_init.S) (b _main) --> <arch/arm/lib/crt0.S> (bl board_init_f) --> <arch/arm/lib/spl.c> (board_init_r) --> <common/spl/spl.c> (jump_to_image_no_args去启动u-boot)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

imx6ul:uboot-2013.10启动过程解析 的相关文章

  • linux rootfs制作

    作一个嵌入式Linux rootfs 并且实现 web 服务 1 文件系统简介 理论上说一个嵌入式设备如果内核能够运行起来 且不需要运行用户进程的话 是不需要文件系统的 文件系统简单的说就是一种目录结构 由于 linux操作系统的设备在系统
  • STM32在线升级 (IAP)

    来自QQ群 Linux 技术分享 311078264 打开链接加入QQ群 https jq qq com wv 1027 k 5Gr3bAx 此文档由elikang整理 为了文章简单直接 许多细节未能在文章中体现 如有疑问请进群讨论 STM
  • Linux 和uboot下dd命令读写sd,mmc,mm读写内存命令

    Linux 和uboot下dd命令读写sd mmc名 mm读写内存命令 记录一下 后面写
  • 一些常见BootLoader介绍

    首先区分一下BootLoader和Monitor的概念 严格来说 BootLoader只是引导设备并且执行主程序的固件 而Monitor还提供了更多的命令行接口 可以进行调试 读写内存 烧写Flash 配置环境变量等 Monitor在嵌入式
  • 将uboot,kernel,rootfs下载到开发板上

    1 为什么要下载 所谓下载 也称烧录 部署 1 1 什么是u boot Hi3518EV200 单板的 Bootloader 采用 U boot u boot是一种普遍用于嵌入式系统中的Bootloader Bootloader是在操作系统
  • ARM qemu 系统模拟器可以在没有内核参数的情况下从卡映像启动吗?

    我看过很多如何运行 QEMU ARM 板模拟器的示例 在每种情况下 除了 SD 卡图像参数之外 QEMU 还始终提供内核参数 即 qemu system arm M versatilepb kernel vmlinuz 2 6 18 6 v
  • 所有磁盘扇区在汇编中是如何迭代的?

    在学习汇编的过程中 我正在编写一个操作系统 我已经成功编写了将第二个 512 字节扇区附加到初始 512 字节引导加载程序所需的代码 define KBDINT 0x16 define VIDINT 0x10 define DISKINT
  • 使用 GAS AT&T 指令计算引导扇区的填充长度?

    所以我想在引导扇区添加填充 比方说 目前只有一个无限循环 jmp 该扇区的长度需要为 512 字节 还有 神奇的数字0xaa55需要在最后添加 jmp skip 508 0 word 0xaa55 但是 如果我想打印一些内容 但不想计算所有
  • Sparkfun Edge 引导加载程序问题

    今天终于到了 Sparkfun 板边板 遵循这个写得很好的指南 https codelabs developers google com codelabs sparkfun tensorflow 3 https codelabs devel
  • 不使用预定义函数在汇编中打印字符串

    我必须在汇编中定义一个函数 该函数允许我循环遍历声明的字节字符串并使用 BIOS 中断打印它们 我处于 16 位实模式 这是一个根据教科书编写一个小引导加载程序的练习 但看起来这只是一个草稿 并且缺少一些东西 我得到了以下代码 org 0x
  • NASM:磁盘读取超时

    尝试从磁盘 从同一文件 读取数据 将另外 2 个 512 字节扇区加载到内存中 磁盘读取功能如下 read DH sectors to ES BX from drive DL disk read push dx push bx Tried
  • 找出 x86 引导加载程序中引导了哪个驱动器

    我正在为 x86 编写游戏引导加载程序 在启动早期的某一时刻 我需要将启动驱动器中的一些扇区加载到内存中 我使用中断 0x13 ah 02 来执行此操作 当我在虚拟机中尝试它时 它就像一个魅力 然而 当我将映像刻录到 USB 驱动器时 机器
  • 如何在启动操作系统之前进行一些安全验证?

    我有一个可启动闪存盘 其中包含定制的 Ubunto 我想将闪存盘传递给未知的人 但它存在一些安全问题 我想确保未知的人无法更改闪存盘内容 因此 我想计算闪存内容的哈希值并在每次启动时验证它 并在验证失败或哈希不匹配时防止启动操作系统 为此
  • 引导扇区编程中的无限跳转有什么用

    我正在读一本关于如何构建操作系统的书 我浏览了这段代码 所有代码所做的就是打印 hello 但我想了解更多关于无限跳转的信息 mov ah 0x0e mov al H int 0x10 mov al e int 0x10 mov al l
  • 在具有 4.14 内核的 IMX6 上使用 vivante GPU

    我正在使用 yocto rocko Linux 4 14 24 开发 IMX6QP 并尝试使用 GPU 我的 yocto 配置文件 MACHINE imx6qp tx6 emmc DL DIR BSPDIR downloads SSTATE
  • QT Creator 无法在 i.Mx6 (buildroot) 上远程运行和调试

    使用基于 Qt 5 7 0 的 Qt Creator 4 0 2 我的应用程序名称是test 主板 带有 buildroot 的 i M6Q Qt 5 9 问题 A 当我运行 qt app 时显示此错误 EGL library doesn
  • ARM 的启动过程是怎样的?

    我们知道 对于X86架构 按下电源按钮后 机器开始执行0xFFFFFFF0处的代码 然后开始执行BIOS中的代码以进行硬件初始化 BIOS 执行后 它使用引导加载程序将操作系统映像加载到内存中 最后 操作系统代码开始运行 对于ARM架构 使
  • 基于 BBB DT 的方法

    我已经使用平台设备模型成功为我的自定义协议实现了基于 GPIO 的驱动程序 我想使用设备树方法升级它 因此 对于初学者来说 我有一个 beaglebone black 并且我使用在 uboot 控制台消息显示期间启用和验证的设备树配置交叉编
  • 将引导加载程序存储在软盘映像上的哪里?

    我将编写并测试引导加载程序 为了做到这一点 我计划将引导加载程序复制到软盘映像文件上并将其安装在虚拟机中 但是 我不确定将引导加载程序的机器代码放在哪里 它是否只是转储到文件的前几个字节中 软盘的引导扇区是第一个扇区 如果您谈论的是原始软盘
  • MikeOS 引导加载程序中的堆栈段

    我不明白这段代码 mov ax 07C0h Set up 4K of stack space above buffer add ax 544 8k buffer 512 paragraphs 32 paragraphs loader cli

随机推荐

  • Apache commons digester简介说明

    转自 Apache commons digester简介说明 下文笔者讲述Apache commons digester组件的简介说明 如下所示 Apache commons digester组件简介说明 digester组件简化xml文件
  • 删除排序数组中的重复项

    给你一个有序数组 nums 请你 原地 删除重复出现的元素 使每个元素 只出现一次 返回删除后数组的新长度 不要使用额外的数组空间 你必须在 原地 修改输入数组 并在使用 O 1 额外空间的条件下完成 解题思路 双指针法 题目链接 初级算法
  • python语法--异常、模块、包的综合案例

    基本思路 1 新建python模块包my utils 其中内置了两个自定义模块模块 2 设置调用文件python基础语法 py去测试模块包是否有效 3 测试 txt文件仅用于测试 str util py文件内的代码如下 all str re
  • Navicat Premium 12注册表

    手动方式 关闭Navicat Win R 输入regedit回车 删除HKEY CURRENT USER Software PremiumSoft Data 这里是删除data整个文件夹 展开HKEY CURRENT USER Softwa
  • websocket 发送ping_那些很重要,但是不常用的技术,websocket

    1 为什么会有websocket 2 websocket协议格式 3 协议具体实现 一 为什么需要 WebSocket 初次接触 WebSocket 的人 都会问同样的问题 我们已经有了 HTTP 协议 为什么还需要另一个协议 它能带来什么
  • RocketMQ 部署不当导致磁盘空间不释放

    背景 生产环境采用 RocketMQ 三主三从集群搭建 6 个实例部署在 3 台 Linux 服务器上 节省资源 每台服务器部署一主一从 生产上运行一段时间后 发现磁盘空间报警 发现df与du显示的空间不一致 相差几十G 问题原因 Rock
  • logback异步日志,支持滚动策略

    logback properties error日志保存路径 LOG ERROR HOME logs error info日志保存路径 LOG INFO HOME logs info 最长保存天数 MAX HISTORY 7 日志文件最大
  • 《Openwrt开发》第一章:newifi3 刷自己编译的Openwrt固件

    最近在淘宝入手了一个二手的newifi3 主要是因为它内存大 而且性价比相当高 512M的ddr2和32M的flash买下来才100左右 好了 废话不多说 开始第一章的源码编译征程 1 准备 源码编译宿主机 ubuntu14 04 64位
  • 三个维度看全球半导体格局变迁

    来源 世纪证券 费城半导体指数 SOX 的发展阶段反应了全球半导体的走势与兴衰更替 费半指数涵盖全球半导体设计 设备 制造 材料等方向 其走势可以是衡量全球半导体行业景气程度的主要指标 费城半导体指数发行于在 1993 年12 月 1 日
  • Python基础_如何搭建起一个PyWeb项目(入门篇)

    一 介绍 本文介绍如何从零开始利用pyCharm搭建起一个可用的web项目 基于pychram2020 2版本 二 步骤 1 在开发前我们需要为py工具设置一个python的编译环境 通过 file gt settings gt proje
  • jmeter线程组 bzm - Arrivals Thread Group & 阶梯式压测

    简介 BZM Arrivals Thread Group是jmeter的一个插件 它可以模拟并发到达的用户流量 按时间加压 可以有效地帮助测试人员评估系统在高压力和高并发情况下的性能表现 插件下载地址 jmeter版本不低于 5 2 0 h
  • Mysql-JDBC配置LoadBalance协议

    Mysql JDBC长期以来提供了有效的手段在MySql集群 多主Replication部署的情况下分发读写负载 自从mysql jdbc 5 1 3以来 你可以在不停用服务的情况下动态配置loadBalance连接 进程中的事务不丢失 实
  • 箭头函数(=>)和普通函数(function)的区别

    JavaScript中箭头函数 gt 和普通函数function的区别 2021前端高频面试题 转载自 作者 阮一峰 ECMAScript6 入门和博客园 一 区别 1 箭头函数与普通函数写法不同 箭头函数 var声明变量时 var fn
  • 自学成材的黑客很多,但还是得掌握方法,给你黑客入门与进阶建议

    建议一 黑客七个等级 仅供参考 黑客 对很多人来说充满诱惑力 很多人可以发现这门领域如同任何一门领域 越深入越敬畏 知识如海洋 黑客也存在一些等级 参考知道创宇 CEO ic 世界顶级黑客团队 0x557 成员 的分享如下 Level 1
  • 时间序列分类算法_时间序列分类算法简介

    时间序列分类算法 A common task for time series machine learning is classification Given a set of time series with class labels c
  • 使用ICE建立C++与C#的通讯

    使用ICE建立C 与C 的通讯 版权 三夏健 https www cnblogs com liwei81730 archive 2012 08 21 2649476 html ICE的优势是作为通讯中间件可支持跨平台的通讯 目前支持C C
  • 基于深度学习Seq2Seq框架的技术总结

    随着互联网经济的普及定位技术的快速发展 人们在日常生活中产生了大量的轨迹数据 例如出租车的GPS数据 快递配送员PDA产生的轨迹数据等 轨迹数据是一种典型的时空数据 Spatial Temporal Data 是按照时间顺序索引且空间变化的
  • gitleb+hexo部署搭建博客

    当你想发布自己的想法 或者学习内容时 这个时候可能你的选择就是在各大平台发布 比如说 简书 csdn 掘金等一些公开的平台 但是这样你的数据就是属于别人了 如果有一天那个平台关闭了 那不是你的多年记录的内容都没有了 可想而知你当时的心情是多
  • WIN10环境下配置hadoop+spark并运行实例的教程

    WIN10环境下配置 hadoop spark 并运行开发实例的教程 前期准备 基本环境配置 虚拟机的安装 配置虚拟机中的静态网络 关闭并禁用防火墙 配置主机名 编辑host文件 使用ssh传输文件 SSH免密配置 解压文件 配置文件 配置
  • imx6ul:uboot-2013.10启动过程解析

    1 源码结构分析 首先一个问题 老版本的u boot是没有SPL这个文件的 新版u boot开始包含SPL文件 原来u boot启动比如放到nand中 在cpu内部有一个stepping stone 可以拷贝nand中的u boot到ram