嵌入式linux开发 (二十二) 内存管理(4) I.MX6ULL内存管理

  • 正点原子ARMLinux开发板 I.MX6ULL cortex-A7 ARMv7
	-内置
		sram:128KB 
			// 名字为OCRAM 
			// 0090_0000 0091_FFFF 128 KB OCRAM 128 KB
		srom:96KB,用户不可编程
			//0001_7000 0001_7FFF 4 KB Boot ROM—Protected 4 KB area
			//0000_0000 0001_6FFF 92 KB Boot ROM (ROMCP)
	-外扩
		NT5CC256M16EP-EK:512MB,DDR3L
			//8000_0000 FFFF_FFFF 2048 MB MMDC—x16 DDR Controller
		KLM8G1GET:8GB,EMMC
			// 通过sdio接口访问,没有编址.

硬件对内存的管理

  • 总述系统架构
The memory system consists of these components:
• Level 1 cache—32 KB instruction, 32 KB data cache
• Level 2 cache—unified instruction and data (128 KB)
• On-Chip Memory:
	• Boot ROM, including High-Assurance Boot (HAB, 96 KB)
	• Internal fast access RAM (OCRAM, 128 KB)
• External memory interfaces:16-bit LP-DDR2, 16-bit DDR3-400, and LV-DDR3-400 //8000_0000 FFFF_FFFF 2048 MB MMDC—x16 DDR Controller.8-bit NAND-flash, including support for Raw MLC/TLC, 2 KB ,4 KB, and 8 KB
	page size, BA-NAND, PBA-NAND, LBA-NAND, OneNAND™, and others
	• BCH ECC up to 40 bits
	• 16-bit NOR flash
	• 16-bit PSRAM, Cellular RAM
	• Dual-channel/single-channel QuadSPI flash
  • 1 sram
// 0090_0000 0091_FFFF 128 KB OCRAM 128 KB
  • 2 DDR3L
8000_0000 FFFF_FFFF 2048 MB
  • 3 BOOT配置
1. 上电
2. 根据 BOOT_MODE[1:0]的设置来选择 BOOT 方式 // 可以通过两种方式改变.一种是改写 eFUSE(熔丝),一种是修改相应的 GPIO 高低电平
	2.1 [00]从 FUSE 启动
	2.1 [01]串行下载
		2.1.1 简介:
			通过 USB 或者UART 将代码下载到板子上的外置存储设备中
		2.1.2 过程
				读取usb数据,下载到sram.
				从sram启动
		2.1.3 应用举例:
			DDR3 测试工具读取init scripts,会将测试使用的固件下载到 i.MX6X的内部 RAM 中,用于测试外部的 DDR3
	2.2 [11]保留
	2.3 [10]内部boot模式,从bootrom启动
		2.3.1 简介
			从bootrom启动,然后做相关初始化之后,探测BOOT_CFG1 BOOT_CFG2 BOOT_CFG4,得到需要加载的设备(QSPI WEIM Serial-ROM SD eMMC NAND 中的一种),然后从加载该设备(二级启动设备)的内容,并进行下一步动作
		2.3.2内部bootrom运行(figure8-3有bootrom的存储分布图)
			初始化时钟
			使能MMU和cache
			从指定的加载设备读取bin文件的头到sram.
			根据头初始化ddr
			然后根据头(bin文件位置a,大小b) 拷贝b大小字节(bin文件的大小)到a地址(在sdram或ocram中),开始运行bin中的代码(用户代码)
		2.3.3bin文件有什么内容
			1.image vector table(8)
			2.boot数据
			3.device configure data
			4.用户数据和代码

软件对内存的管理

  • 硬件(包括bootrom)已经做了什么
// 我们分析的是2.3 [10]内部boot模式,从bootrom启动的过程
1. 初始化时钟 使能MMU和cache // I.MX6ULL 不需要关看门狗
2. 初始化ddr
	// 虽然是读取的二级启动设备中的数据,并根据该数据 初始化了ddr, 我们也应该将其看为硬件做的部分
	// 注意: bootrom中读取的数据需要我们关心,因为初始化不同的ddr用到的数据不同
3. 将用户代码搬移到ram,并执行.
  • 软件(用户代码)还需要做什么(对比stm32)
1. stm32 
	内存映射启动
	stm32 代码 重定位(.data .bss .code .ro-data)
	初始化 .stack .heap 
	初始化c库
	调用用户main函数
2. imx6ull // 参考 汇编代码demo
	从 bootrom启动
	从SD卡外置存储中读取ddr信息,然后初始化ddr
	读取bin头部,并将bin文件拷贝到0X87800000(重定位.code) // 地址0X87800000 可以自定义
	然后pc=0X87800000.
	执行用户函数

stm32 官方的代码 和 imx6ull 硬件(固化代码bootrom)做的 我们都可以看做是 官方已经做好的.那么对比得到

不同点
1.stm32 多做了初始化 .data .bss  .ro-data .stack .heap 及 C库 .
2.imx6ull 多做了 初始化ddr

相同点
都初始化了.data段

imx6ull 用户代码还需要做的部分
	初始化  .bss   .stack .heap 及 C库 .
  • 软件(用户代码)主要怎么做
初始化 .bss  .stack .heap 及 C库

链接知识

-Ttext 0X87800000 是将 .bin文件中中的.text段 .ro-data .data 放在了 0X87800000.
// 虽然示例给的 .s 文件 只有 .text段, 没有其他段. 但其实还可以扩充 .ro-data .data 
// 注意不可以扩充 .bss .stack .heap 
// 编译一个文件的时候会生成一个.o文件,.o文件包括很多段,其中就有 .text .ro-data .data ,但不会有.bss .stack .heap
虽然 .o 会 有很多段,但是没有链接方法将各种段布局到最终的elf文件中去
然后可以通过链接文件解决这个问题.

那么需要做:
	创建链接文件(.s中的各种段布局到elf文件中)

需要补充的内容:
	gcc 会将 一个源文件编译成 .o
	链接文件怎么写

汇编代码demo

1、使能所有时钟
2、设置 GPIO1_IO03 复用为 GPIO1_IO03
3、配置 GPIO1_IO03 的 IO 属性
4、设置 GPIO1_IO03 为输出
5、设置 GPIO1_IO03 输出低电平
6、循环
// 代码中用到了一些指令,该指令为 位置相关代码
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf // elf 文件中会有 0X87800000 
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin // 因为 代码中有位置相关代码,所以bin文件中有 0X87800000 

//烧写 到sd卡
./imxdownload led.bin /dev/sdd
// 过程中生成一些初始化ddr的数据结构(用于bootrom读取并初始化ddr)及一个bin头部(有bin文件大小及位置信息0X87800000 ,用于指示bootrom将bin文件加载到0X87800000)(0X87800000这个信息是写到了 imxdownload软件中,具体在头文件)
// 然后和bin 重新组成一个bin文件,为load.imx(bin文件格式),然后用dd命令将bin文件直接写入sd卡

// 启动
bootrom启动
	从SD卡外置存储中读取ddr信息,然后初始化ddr
	读取bin头部,并将bin文件拷贝到0X87800000
	然后pc=0X87800000.

其他问题

问题:
	imx6ullreset 时CPSR状态
	0x600000d3  0110 0000  0000 0000  0000 0000  1101 0011 // 禁止IRQ 禁止FIQ ARM 状态 SVC(管理)模式
	bootrom有没有改 CPSR ???
	bootrom 执行用户代码时 CPSR 为多少???

	CPSR 的值对应不同的模式,而不同模式的SP寄存器是不一样的,所以设置SP的时候需要注意该SP是什么模式下的.

你可能感兴趣的:(I.MX6ULL开发板)