嵌入式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.用戶數據和代碼

軟件對內存的管理

  • 硬件已經做了什麼
// 我們分析的是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)
	然後pc=0X87800000.
	執行用戶函數

stm32 官方的代碼 和 imx6ull 硬件(固化代碼bootrom)做的 我們都可以看做是 官方已經做好的.那麼對比得到

不同點
1.stm32 多做了初始化 .data .bss  .ro-data .stack .heap 及 C庫 .
2.imx6ull 多做了 初始化ddr
相同點
都初始化了.data段


imx6ull 用戶代碼還需要做的部分
	初始化 .data .bss  .ro-data .stack .heap 及 C庫 .
  • 軟件(用戶代碼)主要怎麼做
-Ttext 0X87800000 只是將 (.text段).s中的_start符號(.text段的開始地址) 放在了 0X87800000.
但是 .s 文件(目前雖然有其他段,但是段大小都是0) 中還可以擴充 .ro-data .data .bss .stack .heap // 編譯一個文件的時候會生成一個.o文件,.o文件包括很多段,其中就有 .text .ro-data .data .bss .stack .heap
雖然 .o 會 有很多段,但是沒有鏈接方法將各種段佈局到最終的elf文件中去
然後可以通過鏈接文件解決這個問題.

那麼需要做:
1. 擴充.s中的段(目前只有.s中只有.text段)
2. 創建鏈接文件(.s中的各種段(包括原有的.text段)佈局到elf文件中)

需要補充的內容:
	gcc 會將 一個源文件編譯成 .o , .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是什麼模式下的.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章