uboot启动之BL1阶段的分析1

2023-10-31

对uboot启动的BL1阶段的主体代码分析1 

BL1阶段代码的分析以start.s文件作为主要的目标,此篇博文主要对整个个流程进行分析。

总体分析:

BL1阶段的代码固化在IROM中的BL0调用执行,在上电之后会会执行,他的主要主要工作就是初始化soc,为uboot的主体代码也就是BL2阶段做好一切准备。  

BL1中重要的几个功能:

(1)CPU相关的一些基础的初始化;
 (2)初始化DRAM;
 (3)从sd卡中拷贝BL2(其实是拷贝整个uboot)到DRAM中;
 (4)设置三次不同用处的栈;
 (5)初始化MMU,虚拟地址映射的建立;
 (6)最后通过长跳转执行BL2阶段的代码。

 

下面是对start.S文件的具体分析:

1.镜像文件的16字节校验头:

#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
	.word 0x2000
	.word 0x0
	.word 0x0
	.word 0x0
#endif

在裸机开发时,mkv210image.c完成了这个功能,进行镜像前16字节的填充占位。在之后被填充为坏牛肉:deadbeef

        .balignl 16,0xdeadbeef

 

2.构建异常向量表:

.globl _start
	_start: b	reset
		ldr	pc, _undefined_instruction
		ldr	pc, _software_interrupt
		ldr	pc, _prefetch_abort
		ldr	pc, _data_abort
		ldr	pc, _not_used
		ldr	pc, _irq
		ldr	pc, _fiq

cpu有异常事件发生时会在此向量表内进行查找,然后执行对应的函数,而这些函数具体的实现是参照硬件来实现。 在uboot中的异常向量表较少,因为他的主要工作是驱动硬件,而对于各种异常的处理不是主要的目标。

 

3.链接地址的指定:

_TEXT_BASE:
	.word	TEXT_BASE

这里的TEXT_BASE  就是我们配置阶段分析的 make 时传入的变量。

注:对于这里的汇编的语法做简单的说明:类似于定义了一个名为_TEXT_BASE的指针,而这个指针指向的是一个四字节的名为 TEXT_BASE 的变量

 

4.指定了uboot代码的运行地址:

TEXT_PHY_BASE:
	.word	CFG_PHY_UBOOT_BASE
#define CFG_PHY_UBOOT_BASE	MEMORY_BASE_ADDRESS + 0x3e00000

指定一个uboot进行运行的物理地址,而这个物理地址经过分析为:0x33e0000。 这个地址也是_TEXT_BASE指定的0xc3e00000链接地址所实际对应的物理地址,在之后的MMU初始化之后会将两个地址进行映射。

 

5.定义了一些全局的指针变量:

.globl _armboot_start
	.globl _bss_end
	.globl IRQ_STACK_START
	.globl FIQ_STACK_START

这些全局变量在之后的程序中会被调用

 

6.复位的实现函数,设置CPU的状态:

msr	cpsr_c, #0xd3		@ I & F disable, Mode: 0x13 - SVC

    cpsr:程序状态寄存器,向程序状态寄存器的c位写入0xd3。而0xd3对应的寄存器的含义是:将cpu设置为禁止FIQ IRQ,ARM状态,SVC模式。CPU在复位时默认会进入SVC模式,但是这里为了保险起见通过软件再次设置。

 

7.进行CPU的初始化,获取boot的启动方式:

    一些比较底层的初始化:

cpu_init_crit:

	bl	disable_l2cache

    bl	set_l2cache_auxctrl
	
	bl	enable_l2cache

禁用MMU的东西和缓存:

	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 12 (Z---) BTB
        mcr 	p15, 0, r0, c1, c0, 0	

读取boot的启动方式信息:

  ldr	r0, =PRO_ID_BASE
        ldr	r1, [r0,#OMR_OFFSET]
        bic	r2, r1, #0xffffffc1

S5PV210启动方式由SOC的OM5~OM0这6个引脚的高低电平决定,在芯片中地址为0xe0000004的区域有一个特殊功能寄存器,这个寄存器的值是硬件根据OM引脚的设置而自动设置的,所以通过读取这个寄存器的值可以得知硬件的启动方式。

然后在后面的程序中通过与一些已设置的值进行比对以具体的确定启动的方式:

/* 以 SD/MMC BOOT 的一部分为例*/
	cmp     r2, #0xc
	moveq   r3, #BOOT_MMCSD	

 

8. uboot启动方式信息的存储: 

	/* Uart BOOTONG failed */
	cmp     r2, #(0x1<<4)
	moveq   r3, #BOOT_SEC_DEV
	
	ldr	r0, =INF_REG_BASE
	str	r3, [r0, #INF_REG3_OFFSET] 

将前一步中r3中的值也就是BOOT_MMCSD放进一个名为INF_REG_BASE的寄存器中进行存储,在后面重定位是会用到这个寄存器

 

 

9.第一设置栈,在IRAM中设置栈,用来运行lowlevel_init 函数(函数内初始化了DRAM):

ldr	sp, =0xd0036000 /* end of sram dedicated to u-boot */
	sub	sp, sp, #12	/* set stack */
	mov	fp, #0
	
	bl	lowlevel_init	/* go setup pll,mux,memory */

此阶段属于启动的BL1阶段,代码运行在SRAM中,所以设置的栈也就是在SRAM中(内存分布图的查找得知是在SRAM中)。 对于 lowlevel_init 的分析请看关于 lowlevel_init 的具体分析

 

10.再次进行开发板的供电索存(上一次在 lowlevel_init 中):

ldr	r0, =0xE010E81C  /* PS_HOLD_CONTROL register */
	ldr	r1, =0x00005301	 /* PS_HOLD output high	*/
	str	r1, [r0]

 

11.第二次设置栈,在DRAM1中设置栈,为执行BL2阶段做准备:

ldr	sp, _TEXT_PHY_BASE	/* setup temp stack pointer */
	sub	sp, sp, #12
	mov	fp, #0			/* no previous frame, so fp=0 */

这里的_TEXT_PHY_BASE前面已经分析过,为ox33e00000,刚好紧挨着uboot的链接地址,但又因为uboot中的栈是满减栈,所以不会对uboot的代码段造成影响。

这里设置栈的主要原因是SRAM中内存仅为96kb,所以将栈设置到内存较大的DRAM1中以避免因为内存溢出等内存不够造成的安全问题,然后设置完栈就可以调用c函数进行初始化。

 

12.再次对运行地址进行确认以进行重定位,开始准备BL2阶段的启动:

ldr	r0, =0xff000fff
	bic	r1, pc, r0		/* r0 <- current base addr of code */
	ldr	r2, _TEXT_BASE		/* r1 <- original base addr in ram */
	bic	r2, r2, r0		/* r0 <- current base addr of code */
	cmp     r1, r2                  /* compare r0, r1                  */
	beq     after_copy		/* r0 == r1 then skip flash copy   */

再次判断此时刻程序运行的地址,如果是运行的地址与我们配置编译阶段指定TEXT_BASE链接地址相同的话,就执行下面的重定向函数,将BL2阶段的程序加载前面lowlevel_init函数中已经初始化的DRAM内存空间中去运行。

 

13.重定向的实现:

在这里有两种方式都可以进入我们的重定位函数:

(1)通过读取 0xD0037488 (SRAM一个名为V210_SDMMC_BASE 的,存储启动方式的寄存器)的寄存器的值然后与一个已设置的值进行比对已确定启动的方式进而进入重定位函数:

	#if defined(CONFIG_EVT1)
		/* If BL1 was copied from SD/MMC CH2 */
		ldr	r0, =0xD0037488
		ldr	r1, [r0]
		ldr	r2, =0xEB200000
		cmp	r1, r2
		beq     mmcsd_boot

(2)通过比对第8步中赋值的寄存器(储存uboot启动方式信息)的值来判断是否为sd卡启动:

	ldr	r0, =0xff000fff
		bic	r1, pc, r0		/* r0 <- current base addr of code */
		ldr	r2, _TEXT_BASE		/* r1 <- original base addr in ram */
		bic	r2, r2, r0		/* r0 <- current base addr of code */
		cmp     r1, r2                  /* compare r0, r1                  */
		beq     after_copy		/* r0 == r1 then skip flash copy   */

		ldr	r0, =INF_REG_BASE
		ldr	r1, [r0, #INF_REG3_OFFSET]
		cmp	r1, #BOOT_NAND		/* 0x0 => boot device is nand */
		beq	nand_boot
		cmp	r1, #BOOT_ONENAND	/* 0x1 => boot device is onenand */
		beq	onenand_boot
		cmp     r1, #BOOT_MMCSD
		beq     mmcsd_boot
		cmp     r1, #BOOT_NOR
		beq     nor_boot
		cmp     r1, #BOOT_SEC_DEV
		beq     mmcsd_boot

最后都是调用mmcsd_boot。

 

    
14.对mmcsd_boot 的实现函数movi_bl2_copy的分析:

追踪mmcsd_boot 函数指针可知他的实现主要靠movi_bl2_copy函数来实现:

#if defined(CONFIG_EVT1)
	ch = *(volatile u32 *)(0xD0037488);
	copy_sd_mmc_to_mem copy_bl2 =
	    (copy_sd_mmc_to_mem) (*(u32 *) (0xD0037F98));

首先定义了一个0xD0037488所指向的函数类型的函数

else if (ch == 0xEB200000) {
		ret = copy_bl2(2, MOVI_BL2_POS, MOVI_BL2_BLKCNT,
			CFG_PHY_UBOOT_BASE, 0);

和13步第一种方法一样的比对方式,重点是执行copy_bl2()函数。

值得一提的是copy_bl2()这个函数:这个函数是实现重定向的具体函数,函数传入五个参数,分别是sd卡的通道号、sd卡的开始扇区号、读取扇区的个数、读取后放入的地址内存(BL2在DRAM中的储存地址)以及以一个无关的数,最后重定位的位置是0x33e00000

 

15.进行MMU虚拟地址映射,从此开始使用虚拟地址:

/* enable domain access */
			ldr	r5, =0x0000ffff
			mcr	p15, 0, r5, c3, c0, 0		@load domain access register

			/* Set the TTB register */
			ldr	r0, _mmu_table_base
			ldr	r1, =CFG_PHY_UBOOT_BASE
			ldr	r2, =0xfff00000
			bic	r0, r0, r2
			orr	r1, r0, r1
			mcr	p15, 0, r1, c2, c0, 0

			/* Enable the MMU */
		mmu_on:
			mrc	p15, 0, r0, c1, c0, 0
			orr	r0, r0, #1
			mcr	p15, 0, r0, c1, c0, 0
			nop
			nop
			nop
			nop
		#endif

    分析虚拟地址映射之前不得不说说虚拟地址映射相关的一些知识:
 (1)MMU是一个内存管理单元,是SOC中的一个硬件设备,主要完成的功能就是实现虚拟地址到物理地址的映射。
 (2)MMU通过对cp15协处理器进行控制,从而实现虚拟地址的映射,也就是说操作MMU进行虚拟地址映射的方法就是对cp15协处理器的寄存器进行编程;
(3)虚拟地址映射在完成物理地址到虚拟地址的映射外还实现了访问控制,访问控制就是:对内存进行分块处理,然后每一块虚拟地址单独的进行映射,同时实现了读、写、执行的控制;
(4)cach的工作也与虚拟地址映射有关,cpu将自己比较常用的一些数据存储在cach中,然后在需要的时间直接从cach中进行读取。

在这里设置了虚拟地址映射的转换表TTB:

转换表是建立虚拟地址映射的关键,转换表分为表索引和表项两部分,表索引对应虚拟地址映射,表项对应物理地址,一个表索引和表项构成一个转换单元,能够对一个内存块进行虚拟地址转换。(内存管理和映射以快为单位)转换表放置在内存之中,放置时要求起始地址在内存之中要xx位对齐,转换表不需要软件的支持,而是将基地址TTB设置到cp15的c2寄存器之中,然后MMU工作时会自动查询转换表。

进过分析转换表的可知:虚拟地址映射只是把虚拟地址的c0000000开头的256MB映射到了DMC0的30000000开头的256MB物理内存上去了。其他的虚拟地址空间根本没动,还是原样映射的。

   c0000000-d0000000    30000000-40000000        256MB    3G-3.25G

 

16.第三次设置栈:

skip_hw_init:
			/* Set up the stack						    */
		stack_setup:
		#if defined(CONFIG_MEMORY_UPPER_CODE)
			ldr	sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0x1000)

本次设置栈主要是为了设置一个更加安全的栈,设置了栈的起始位置,设置了栈的大小:
 栈的起始位置:CFG_UBOOT_BASE + CFG_UBOOT_SIZE:uboot起始地址0x33e00000上方2MB处
 栈的大小:CFG_UBOOT_BASE + CFG_UBOOT_SIZE-0x1000  约为1.8MB
 这次设置使得这个栈离我们uboot的源码储存的地方尽量的近,从而紧凑而不浪费的使用了内存空间。(uboot中的栈是满减栈,向下进行储存,所以设置的栈在减去uboot源码的空间之后有着巨大的空间可以供开发使用)
 而bss段的开头和结尾地址的符号是从链接脚本u-boot.lds得来的。

 

17.跳转至BL2阶段,BL1光荣退休:

   ldr    pc, _start_armboot
        _start_armboot:
            .word start_armboot        

 这个远跳转是uboot启动过程第一阶段和第二阶段的分界线,直接跳转至DDR中的第二阶段开始的地址处。  而start_armboot是一个指针,指向的是uboot启动源码第二部分在DDR之中存放的地址。它存放在uboot/lib_arm/board.c中。

 

END...........

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

uboot启动之BL1阶段的分析1 的相关文章

  • 如何在navicat for mysql画图(建模型)并直接生成

    1 登录进数据库后 点击模型 新建模型 如下 2 点击 小手 下面的图标 双击右边的空白处 即出现一个表格 可命名 此时我们命名为A 3 双击A表下空白处 即可设计A表属性 点确定 如下 4 同理 生成一个B表 加粗样式 5 如何让A B表
  • 特征归一化优点

    什么是特征归一化 数据的标准化 normalization 是将数据按比例缩放 使之落入一个小的特定区间 在某些比较和评价的指标处理中经常会用到 去除数据的单位限制 将其转化为无量纲的纯数值 便于不同单位或量级的指标能够进行比较和加权其中最
  • dsolve函数的功能_为什么Mathematica的DSolve函数会解不出显式解??

    In 6 DSolve v t 3 v t 2 v t 2 v t 2 2 v t v t v t t Out 6 v t gt E t Sqrt C 1 Tan E t Sqrt C 1 C 2 说明书里面是这么说的 DSolve inc
  • 43. 字符串相乘

    43 字符串相乘 注意 不能使用任何内置的 BigInteger 库或直接将输入转换为整数 示例 1 输入 num1 2 num2 3 输出 6 示例 2 输入 num1 123 num2 456 输出 56088 提示 1 lt num1
  • 判断Android主题是否为深色主题

    fun isDarkTheme context Context Boolean val flag context resources configuration uiMode and Configuration UI MODE NIGHT
  • java.lang.NoClassDefFoundError:com/google/common/base/Moreobjects

    项目所属环境不同 解决方案不一定适合所有人 见谅 java lang NoClassDefFoundError com google common base Moreobjects 编译可以通过 运行报错 很无奈 突然蹦出这鬼东西 经过一番
  • ESP32S2+ES8388移植过程及问题

    电路图如下 有点小瑕疵ES8388 VMID PIN10 19 20电容没有忘加 查资料应该不影响语言输出 可能噪音大 如果能导致不输出请告诉我一下 ESP32S2管脚映射 这里主要问题是我不确定MCLK 放到S2的PIN33是否合适 查资
  • C++ 类的静态成员和非静态成员

    类的静态成员不占据类对象的字节数 1 一个空类占用字节数为1 2 int整形变量占据的字节数为4 class Person int m A 非静态成员变量 属于类的对象上 static int m B 静态成员变量 不属于类的对象上 voi
  • JSP三大指令,六个动作,九个内置对象,四大作用域

    一 JSP三大指令 1 1 page指令 page指令 后面跟着三个属性 分别是language contentType pageEncoding 属性名 取值范围 描述 language Java 解释该JSP文件时采用的语言 一般为Ja
  • 少样本学习概述及三种经典方法

    从迁移学习讲起 Pre train Fine tune 不同领域数据规模不同 模型表现并不理想 但是 模型浅层可以学到通用特征 深层才学到更为复杂的分类特征 在大规模数据上训练的模型 其底层特征保持较高的通用性 迁移学习的下游任务仍然受限于
  • 计算机键盘正确指法操作方法,键盘指法,图文详解键盘指法练习方法

    随着时代的发展 现在越来越多的工作都是用电脑来完成的了 这就需要我们会打字了 很多朋友打字很慢是因为键盘指法不对 为了让您能更好的打字 今天小编就教您键盘指法练习方法 很多打字很快的朋友都是采用的盲打的方式 这就要求对键盘上的按键很熟悉 同
  • 二叉树之重建(js)

    二叉树之重建 输入一颗二叉树的先序遍历和中序遍历 输出它的后序遍历 输入 DBACEGF ABCDEFG BCAD CBAD 输出 ACBFGED CDAB var root value null left null right null
  • 【华为面试题】栈(二)

    题目 代码 function getMinElectricBoxes input str const n input str length const powerBoxPositions let lastPowerBoxUsed false
  • requests 实现模拟登录,获取cookie

    有个需求需要模拟登录csdn获取cookie 对csdn进行后续系列操作 刚开始使用的selenium 功能可以实现 但是效率有点低 后来改用的requests 遇到不少坑 今天来总结一下 首先找到csdn登录的url 在故意输错密码的情况
  • size函数 matlab 含义,size()函数的使用

    matlab中对于矩阵的计算是十分方便的 其中关于矩阵的函数有很多 size 在c c 中sizeof用来求某变量所占用的字节数 在matlab中size 则可以用来求矩阵的 长度 矩阵的长度有两方面 1 行数 2 列数 所以size 也有
  • [创业之路-73] :如何判断一个公司或团队是熵减:凝聚力强、上下一心,还是,熵增:一盘散沙、乌合之众?

    目录 前言 一盘散沙 乌合之众 凝聚力强 上下一心 一 股权结构与利益分配 一盘散沙 乌合之众 凝聚力强 上下一心 二 组织架构与岗位职责 一盘散沙 乌合之众 凝聚力强 上下一心 三 战略目标 一盘散沙 乌合之众 凝聚力强 上下一心 四 规
  • Cloudflare 重定向配置

    最近把之前的一个网站域名换成另一个域名 想要添加一下重定向 避免流量流失 虽然本来就没流量 然后在 Cloudflare 配置时尝试多次都失败了 遇到各种 Your connection is not private 或者 Webpage
  • 代码审查常见问题,建议收藏

    最近某宝弹窗事件导致其APP被大量用户删除 影响极其恶劣 我在想 如果他们的内部代码审查更加严格一点 少走形式 就能将隐患扼杀在摇篮里了 基于此 我们部门专门成立了由小组长和核心成员组成的代码评审组 将以前的代码评审模式进行了一些优化 加强
  • Win10 设备管理器一个USB设备描述符请求失败解决方法

    问题 进入设备管理器 发现 通用串行总线控制器 下有一项带有黄色 未知USB设备 设备描述符请求失败 或者 解决方法如下 1 点击Windows键 R或者 点击系统桌面左下角 开始 在开始菜单中点击 运行 在运行对话框中输入 service

随机推荐

  • 彻底学会IO流

    概述 IO流就是用来处理设备间数据传输问题的 常见的应用 文件复制 文件上传 文件下载 IO的数据传输 可以看做是一种数据的流动 按照流动的方向 已内存为参照物 进行读写操作 IO可以保存到文件 其实就是内存在读取 内存在写入 而且不会消失
  • Linux常用命令记录

    1 查询当前文件夹下各个文件尺寸大小 du h max depth 1 查看当前目录下文件总共占用的空间 du sh 查看当前目录下各个文件或目录分别占用的空间大小 du sh 2 查询端口占用 lsof i xxxx 3 防火墙允许端口
  • Jaspersoft 报表: 基于JDBC填充报表数据

    第一步 在Jaspersoft Studio工具中新建JDBC数据源 然后Next 选择 Database JDBC Connection 点击Test 显示 Successful 然后Finish 第二步 新建报表模板 1 新建报表模板人
  • IMU标定算法流程

    由于VIO中 普遍使用的是精度较低的imu 所以其需要一个较为准确的内参数和noise的估计 Noise大家通常使用Allan方差进行估计可以得到较为可信的结果 这里不赘述了 内参数标定比较方便的一个工具就是imu tk 所以本篇文章主要详
  • qml扩展插件的创建与使用(添加qml文档)

    前言 笔者之前记录过如何使用qml模块 qml自定义Quick模块 使用qml源码 白杨树下 的博客 CSDN博客 在设计器中使用qml自定义Quick模块 使用qml源码 白杨树下 的博客 CSDN博客 qml设计器 笔者也没计划要再复制
  • 程序员该如何学习技术

    程序员该如何学习技术 前言 学习是第一生产力 我从来都是这么认为的 人只有只有不断地学习才能意识到自己的缺点和不足 身为程序员 我更认为人们应当抱着终身学习的想法实践下去 这是我所一直践行且相信的 高处不胜寒 只有站在更高的地方 才能欣赏更
  • 前端面试题:精灵图和base64如何选择?

    前端面试题 精灵图和base64如何选择 精灵图 是网页处图图片的一种方式 它是把多张小图整合到一张 利用background position属性定位某个图片的位置 来达到在大图片中引用某个小图片的效果 当页面访问时 可以减少向服务器的y
  • 关于RFC2544中的Cut-Through和Store-and-Forward模式

    Layer 2 Forwarding Both store and forward and cut through Layer 2 switches base their forwarding decisions on the destin
  • 项目四推荐系统源码(十二万字)

    目录 背景指路 0 pom xml 大概的项目框架 1 0 资源 1 1 sparkml2pmml properties 1 2 core site xml 1 3 hdfs site xml 1 4 hive site xml 1 5 y
  • Android Studio导入其它目录Module

    在Android Studio导入Module过程中发现 会自动将选择Module的文件夹导入到项目目录中 但是实际开发中 在导入公共Module时是不希望移动文件夹的 因为公共的目录可能被多个项目依赖 如果有改动 同步就非常麻烦 下面介绍
  • Postman(一)--接口测试知识准备

    1 0 前言 应用程序编程接口 Application Programming Interface API 是这些年来最流行的技术之一 强大的Web应用程序和领先的移动应用程序都离不开后端强大的API API技术的应用给系统开发带来了便利
  • error:Failed connect to github.com:443 错误解决(centos6)

    error Failed connect to github com 443 错误解决 在使用git 命令下载下载pyenv项目到本地时 出现错误 绞尽脑汁查了好久也无法解决 最后找到了解决方法 error Failed connect t
  • 腾讯云标准型S6/SA3/SR1/S5/SA2服务器CPU处理器大全

    腾讯云服务器CVM标准型CPU处理器大全 包括标准型S6 SA3 SR1 S5 S5se SA2 S4 SN3ne S3 SA1 S2ne实例CPU处理器型号大全 标准型S6云服务器CPU采用Intel Ice Lake 2 7GHz 3
  • MySQL第八讲 MySQL集群扩容与半同步复制

    集群扩容 我们现在已经搭建成功了一主一从的MySQL集群架构 那要扩展到一主多从的集 群架构 其实就比较简单了 只需要增加一个binlog复制就行了 但是如果我们的集群是已经运行过一段时间 这时候如果要扩展新的从节点就有 一个问题 之前的数
  • STM32超级蓝牙小车——基于STM32F103C8T6的多功能蓝牙小车(PID循迹、跟踪、有源蜂鸣器播放音乐、蓝牙遥控、AD采集+DMA转运等超多元素小车)

    一 项目时间 2023 7 24 11 26 二 实现效果 通过蓝牙控制小车运动与模式转换 模式一 循迹模式 模式二 跟踪模式 模式三 音乐模式 模式四 控制运动模式 三 使用模块 STM32F103C8T6核心板 1 L298N电机驱动模
  • cocos2d-x系列教程

    1 官网 http www cocos com 2 论坛 http www cocoachina com bbs thread php fid 48 3 官网下载 http www cocos2d x org download versio
  • 【如何注销华为云账号(解绑合作伙伴)】

    如何注销华为云账号 解绑合作伙伴 一 解绑合作伙伴 1 1 注意事项 1 2 创建工单 二 账号关闭 三 账号注销 一 解绑合作伙伴 首先进入华为云官网 https www huaweicloud com 登录账号 将鼠标拖至页面右上角 选
  • MySQL 事务

    事务特性 ACID 事务隔离中的脏读 幻读问题 隔离级别 一 事务特性 ACID 原子性 Atomicity 一个事务内多个操作语句 不可被分割 一个事务的执行结果 要么全部成功 要么全部失败 一致性 Consistency 一个事务操作之
  • CURL 宏定义列表

    列表CURL库一共有17个函数 curl close 关闭CURL会话 curl copy handle 复制一个CURL会话句柄 同时3复制其所有参数 curl errno 返回最后一个错误码 curl error 返回一个字符串 用以描
  • uboot启动之BL1阶段的分析1

    对uboot启动的BL1阶段的主体代码分析1 BL1阶段代码的分析以start s文件作为主要的目标 此篇博文主要对整个个流程进行分析 总体分析 BL1阶段的代码固化在IROM中的BL0调用执行 在上电之后会会执行 他的主要主要工作就是初始