久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Bootloader之uBoot简介(转)

發(fā)布時(shí)間:2023/12/18 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Bootloader之uBoot简介(转) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

來自http://blog.ednchina.com/hhuwxf/1915416/message.aspx,感謝作者

一、Bootloader的引入從前面的硬件實(shí)驗(yàn)可以知道,系統(tǒng)上電之后,需要一段程序來進(jìn)行初始化:關(guān)閉?WATCHDOG、改變系統(tǒng)時(shí)鐘、初始化存儲控制器、將更多的代碼復(fù)制到內(nèi)存中等等。如果它能將操作系統(tǒng)內(nèi)核(無論從本地,比如Flash;還是從遠(yuǎn)端,?比如通過網(wǎng)絡(luò))復(fù)制到內(nèi)存中運(yùn)行,就稱這段程序?yàn)锽ootloader。

簡單地說,Bootloader就是這么一小段程序,它在系統(tǒng)上電時(shí)開始執(zhí)行,初始化硬件設(shè)備、準(zhǔn)備好軟件環(huán)境,最后調(diào)用操作系統(tǒng)內(nèi)核。

可以增強(qiáng)Bootloader的功能,比如增加網(wǎng)絡(luò)功能、從PC上通過串口或網(wǎng)絡(luò)下載文件、?燒寫文件、將Flash上壓縮的文件解壓后再運(yùn)行等──這就是一個(gè)功能更為強(qiáng)大的Bootloader,也稱為Monitor。實(shí)際上,在最終產(chǎn)品中用戶?并不需要這些功能,它們只是為了方便開發(fā)。Bootloader的實(shí)現(xiàn)嚴(yán)重依賴于具體硬件,在嵌入式系統(tǒng)中硬件配置千差萬別,即使是相同的CPU,它的外設(shè)(比如Flash)也可能不同,所以不可能有一個(gè)Bootloader支持所有的CPU、所有的電路板。即使是支持CPU架構(gòu)比較多的U-Boot,也不是一拿來就可以使用的(除非里面的配置剛好與你的板子相同),需要進(jìn)行一些移植。

二、 Bootloader的啟動(dòng)方式CPU上電后,會(huì)從某個(gè)地址開始執(zhí)行。比如MIPS結(jié)構(gòu)的CPU會(huì)從0xBFC00000取?第一條指令,而ARM結(jié)構(gòu)的CPU則從地址0x0000000開始。嵌入式單板中,需要把存儲器件ROM或Flash等映射到這個(gè)地址,Bootloader就存放在這個(gè)地址開始處,這樣一上電就可以執(zhí)行。

在開發(fā)時(shí),通常需要使用各種命令操作Bootloader,一般通過串口來連接PC和開發(fā)板,可以在串口上輸入各種命令、觀察運(yùn)行結(jié)果等。這也只是對開發(fā)人員才有意義,用戶使用產(chǎn)品時(shí)是不用接串口來控制Bootloader的。從這個(gè)觀點(diǎn)來看,Bootloader可以分為兩種操作模式(Operation Mode):

(1)啟動(dòng)加載(Boot loading)模式。

上電后,Bootloader從板子上的某個(gè)固態(tài)存儲設(shè)備上將操作系統(tǒng)加載到RAM中運(yùn)行,整個(gè)過程并沒有用戶的介入。產(chǎn)品發(fā)布時(shí),Bootloader工作在這種模式下。

(2)下載(Downloading)模式。

在這種模式下,開發(fā)人員可以使用各種命令,通過串口連接或網(wǎng)絡(luò)連接等通信手段從主機(jī)(Host)下載文件(比如內(nèi)核映像、文件系統(tǒng)映像),將它們直接放在內(nèi)存運(yùn)行或是燒入Flash類固態(tài)存儲設(shè)備中。

板子與主機(jī)間傳輸文件時(shí),可以使用串口的xmodem/ymodem/zmodem協(xié)議,它們使用簡單,只是速度比較慢;還可以使用網(wǎng)絡(luò)通過tftp、nfs協(xié)議來傳輸,這時(shí),主機(jī)上要開啟tftp、nfs服務(wù);還有其他方法,比如USB等。像Blob或U-Boot等這樣功能強(qiáng)大的Bootloader通常同時(shí)支持這兩種工作模式,而且允許用戶在這兩種工作模式之間進(jìn)行切換。比如,U-Boot在啟動(dòng)時(shí)處于正常的啟動(dòng)加載模式,但是它會(huì)延時(shí)若干秒(這可以設(shè)置)等待終端用戶按下任意鍵而將U-Boot切換到下載模式。如果在指定時(shí)間內(nèi)沒有用戶按鍵,則U-Boot繼續(xù)啟動(dòng)Linux內(nèi)核。?]

15.1.2 Bootloader的結(jié)構(gòu)和啟動(dòng)過程

  • 1. 概述

在移植之前先了解Bootloader的一些通用概念,對理解它的代碼會(huì)有所幫助。

在一個(gè)嵌入式Linux系統(tǒng)中,從軟件的角度通??梢苑譃?個(gè)層次:

(1)引導(dǎo)加載程序,包括固化在固件(firmware)中的 boot 代碼(可選)和Bootloader兩大部分。

有些CPU在運(yùn)行Bootloader之前先運(yùn)行一段固化的程序(固件,firmware),比如x86結(jié)構(gòu)的CPU就是先運(yùn)行BIOS中的固件,然后才運(yùn)行硬盤第一個(gè)分區(qū)(MBR)中的Bootloader。

在大多嵌入式系統(tǒng)中并沒有固件,Bootloader是上電后執(zhí)行的第一個(gè)程序。

(2)Linux內(nèi)核。

特定于嵌入式板子的定制內(nèi)核以及內(nèi)核的啟動(dòng)參數(shù)。內(nèi)核的啟動(dòng)參數(shù)可以是內(nèi)核默認(rèn)的,或是由Bootloader傳遞給它的。

(3)文件系統(tǒng)。

包括根文件系統(tǒng)和建立于Flash內(nèi)存設(shè)備之上的文件系統(tǒng)。里面包含了Linux系統(tǒng)能夠運(yùn)行所必需的應(yīng)用程序、庫等,比如可以給用戶提供操作Linux的控制界面的shell程序,動(dòng)態(tài)連接的程序運(yùn)行時(shí)需要的glibc或uClibc庫,等等。

(4)用戶應(yīng)用程序。

特定于用戶的應(yīng)用程序,它們也存儲在文件系統(tǒng)中。有時(shí)在用戶應(yīng)用程序和內(nèi)核層之間可能還會(huì)包括一個(gè)嵌入式圖形用戶界面。常用的嵌入式 GUI 有:Qtopia 和 MiniGUI 等。

顯然,在嵌入系統(tǒng)的固態(tài)存儲設(shè)備上有相應(yīng)的分區(qū)來存儲它們。

“Boot?parameters”分區(qū)中存放一些可設(shè)置的參數(shù),比如IP地址、串口波特率、要傳遞給內(nèi)核的命令行參數(shù)等。正常啟動(dòng)過程中,Bootloader首先?

運(yùn)行,然后它將內(nèi)核復(fù)制到內(nèi)存中(也有些內(nèi)核可以在固態(tài)存儲設(shè)備上直接運(yùn)行),并且在內(nèi)存某個(gè)固定的地址設(shè)置好要傳遞給內(nèi)核的參數(shù),最后運(yùn)行內(nèi)核。內(nèi)核啟?
動(dòng)之后,它會(huì)掛接(mount)根文件系統(tǒng)(“Root filesystem”),啟動(dòng)文件系統(tǒng)中的應(yīng)用程序。

  • 2. Bootloader的兩個(gè)階段Bootloader的啟動(dòng)過程啟動(dòng)過程可以分為單階段(Single?Stage)、多階段(Multi-Stage)兩種。通常多階段的Bootloader能提供更為復(fù)雜的功能,以及更好的可移植性。從固態(tài)存儲設(shè)備上啟?動(dòng)的Bootloader大多都是 2 階段的啟動(dòng)過程。這從前面的硬件實(shí)驗(yàn)可以很好地理解這點(diǎn):第一階段使用匯編來實(shí)現(xiàn),它完成一些依賴于 CPU?體系結(jié)構(gòu)的初始化,并調(diào)用第二階段的代碼。第二階段則通常使用C語言來實(shí)現(xiàn),這樣可以實(shí)現(xiàn)更復(fù)雜的功能,而且代碼會(huì)有更好的可讀性和可移植性。

一般而言,這兩個(gè)階段完成的功能可以如下分類,但這不是絕對的:

(1)Bootloader第一階段的功能。

    • 硬件設(shè)備初始化。
    • 為加載Bootloader的第二階段代碼準(zhǔn)備RAM空間。
    • 拷貝Bootloader的第二階段代碼到 RAM 空間中。
    • 設(shè)置好棧。
    • 跳轉(zhuǎn)到第二階段代碼的C入口點(diǎn)。

在第一階段進(jìn)行的硬件初始化一般包括:關(guān)閉WATCHDOG、關(guān)中斷、設(shè)置CPU的速度和時(shí)鐘頻率、RAM初始化等。這些并不都是必需的,比如S3C2410/S3C2440的開發(fā)板所使用的U-Boot中,就將CPU的速度和時(shí)鐘頻率的設(shè)置放在第二階段。

甚至,將第二階段的代碼復(fù)制到RAM空間中也不是必需的,對于NOR Flash等存儲設(shè)備,完全可以在上面直接執(zhí)行代碼,只不過這相比在RAM中執(zhí)行效率大為降低。

(2)Bootloader第二階段的功能。

    • 初始化本階段要使用到的硬件設(shè)備。
    • 檢測系統(tǒng)內(nèi)存映射(memory map)。
    • 將內(nèi)核映像和根文件系統(tǒng)映像從Flash上讀到RAM空間中。
    • 為內(nèi)核設(shè)置啟動(dòng)參數(shù)。
    • 調(diào)用內(nèi)核。

為了方便開發(fā),至少要初始化一個(gè)串口以便程序員與Bootloader進(jìn)行交互。

所謂檢測內(nèi)存映射,就是確定板上使用了多少內(nèi)存,它們的地址空間是什么。由于嵌入式開發(fā)中,Bootloader多是針對某類板子進(jìn)行編寫,所以可以根據(jù)板子的情況直接設(shè)置,不需要考慮可以適用于各類情況的復(fù)雜算法。

Flash上的內(nèi)核映像有可能是經(jīng)過壓縮的,在讀到RAM之后,還需要進(jìn)行解壓。當(dāng)然,對于有自解壓功能的內(nèi)核,不需要Bootloader來解壓。

將根文件系統(tǒng)映像復(fù)制到RAM中,這不是必需的。這取決于是什么類型的根文件系統(tǒng),以及內(nèi)核訪問它的方法。

為內(nèi)核設(shè)置啟動(dòng)參數(shù)將在下一小節(jié)介紹。

將內(nèi)核存放在適當(dāng)?shù)奈恢煤?#xff0c;直接跳到到它的入口點(diǎn)即可調(diào)用內(nèi)核。調(diào)用內(nèi)核之前,下列條件要滿足:

(1)CPU 寄存器的設(shè)置。

    • R0=0
    • R1=機(jī)器類型ID;對于ARM結(jié)構(gòu)的CPU,其機(jī)器類型ID可以參見 linux/arch/arm/tools/mach-types。
    • R2=啟動(dòng)參數(shù)標(biāo)記列表在 RAM 中起始基地址

(2)CPU工作模式。

    • 必須禁止中斷(IRQs和FIQs)
    • CPU 必須 SVC 模式

(3)Cache 和 MMU 的設(shè)置。

    • MMU 必須關(guān)閉
    • 指令 Cache 可以打開也可以關(guān)閉
    • 數(shù)據(jù) Cache 必須關(guān)閉

如果用C語言,可以像下列示例代碼一樣來調(diào)用內(nèi)核:

void (*theKernel)(int zero, int arch, u32?
params_addr) = (void (*)(int, int, u32))KERNEL_RAM_BASE; ……?
theKernel(0, ARCH_NUMBER, (u32) kernel_params_start);

  • 3. Bootloader與內(nèi)核的交互

Bootloader與內(nèi)核的交互是單向的,Bootloader將各類參數(shù)傳給內(nèi)核。由于它們不能同時(shí)運(yùn)行,傳遞辦法只有一個(gè):Bootloader將參數(shù)放在某個(gè)約定的地方之后,再啟動(dòng)內(nèi)核,內(nèi)核啟動(dòng)后從這個(gè)地方獲得參數(shù)。除了約定好參數(shù)存放的地址外,還要規(guī)定參數(shù)的結(jié)構(gòu)。Linux 2.4.x?

以后的內(nèi)核都期望以標(biāo)記列表(tagged?list)的形式來傳遞啟動(dòng)參數(shù)。標(biāo)記,就是一種數(shù)據(jù)結(jié)構(gòu);標(biāo)記列表,就是挨著存放的多個(gè)標(biāo)記。標(biāo)記列表以標(biāo)記ATAG_CORE?開始,以標(biāo)記ATAG_NONE?結(jié)束。標(biāo)記的數(shù)據(jù)結(jié)構(gòu)為tag,它由一個(gè)tag_header結(jié)構(gòu)和一個(gè)聯(lián)合(union)組成。tag_header結(jié)構(gòu)表示標(biāo)記的類型及長度,比如是?表示內(nèi)存還是表示命令行參數(shù)等。對于不同類型的標(biāo)記使用不同的聯(lián)合(union),比如表示內(nèi)存時(shí)使用tag_mem32,表示命令行時(shí)使用?tag_cmdline。數(shù)據(jù)結(jié)構(gòu)tag和tag_header定義在Linux內(nèi)核源碼的include/asm/setup.h頭文件中:

?
1 2 3 4 5 6 7 8 struct?tag_header { u32 size; u32 tag; }; <br>struct?tag { struct?tag_header hdr; union?{ struct tag_corecore; struct?tag_mem32mem; struct?tag_videotextvideotext; struct?tag_ramdiskramdisk; struct?tag_initrdinitrd; struct tag_serialnrserialnr; struct?tag_revisionrevision; struct tag_videolfbvideolfb; struct?tag_cmdlinecmdline; <br>/* * Acorn specific */struct?tag_acornacorn; <br>/* * DC21285 specific */struct?tag_memclkmemclk; } u; };

下面以設(shè)置內(nèi)存標(biāo)記、命令行標(biāo)記為例說明參數(shù)的傳遞:

(1)設(shè)置標(biāo)記 ATAG_CORE。

標(biāo)記列表以標(biāo)記 ATAG_CORE開始,假設(shè)Bootloader與內(nèi)核約定的參數(shù)存放地址為0x30000100,則可以以如下代碼設(shè)置標(biāo)記 ATAG_CORE:

params = (struct tag *) 0x30000100;?
<br>params->hdr.tag = ATAG_CORE; params->hdr.size =?
tag_size (tag_core); <br>params->u.core.flags = 0;?
params->u.core.pagesize = 0; params->u.core.rootdev = 0;?
<br>params = tag_next (params);

其中,tag_next定義如下,它指向當(dāng)前標(biāo)記的末尾:

#define tag_next(t)((struct tag *)((u32 *)(t) + (t)->hdr.size))

(2)設(shè)置內(nèi)存標(biāo)記。

假設(shè)開發(fā)板使用的內(nèi)存起始地址為0x30000000,大小為0x4000000,則內(nèi)存標(biāo)記可以如下設(shè)置:

params->hdr.tag = ATAG_MEM;

params->hdr.size = tag_size (tag_mem32);

params->u.mem.start = 0x30000000;

params->u.mem.size = 0x4000000;

params = tag_next (params);

(3)設(shè)置命令行標(biāo)記。

命令行就是一個(gè)字符串,它被用來控制內(nèi)核的一些行為。比如"root=/dev?/mtdblock2 init=/linuxrc?console=ttySAC0"表示根文件系統(tǒng)在MTD2分區(qū)上,系統(tǒng)啟動(dòng)后執(zhí)行的第一個(gè)程序?yàn)?linuxrc,控制臺為ttySAC0(即第一個(gè)串口)。

命令行可以在Bootloader中通過命令設(shè)置好,然后如下構(gòu)造標(biāo)記傳給內(nèi)核:

char *p = "root=/dev/mtdblock2 init=/linuxrc console=ttySAC0";

params->hdr.tag = ATAG_CMDLINE;

params->hdr.size = (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;

strcpy (params->u.cmdline.cmdline, p);

params = tag_next (params);

(4)設(shè)置標(biāo)記ATAG_NONE。

標(biāo)記列表以標(biāo)記ATAG_NONE結(jié)束,如下設(shè)置:

params->hdr.tag = ATAG_NONE;

params->hdr.size = 0;

常用Bootloader介紹

現(xiàn)在Bootloader種類繁多,比如x86上有LILO、GRUB等。對于ARM架構(gòu)的CPU,有U-Boot、Vivi等。它們各有特點(diǎn),下面列出Linux的開放源代碼的Bootloader及其支持的體系架構(gòu),如表15.1所示。

開放源碼的Linux引導(dǎo)程序

<table fck__showtableborders?="">

Bootloader?
Monitor?
描述?
X86?
ARM?
PowerPC

LILO?
否?
Linux磁盤引導(dǎo)程序?
是?
否?

GRUB?
否?
GNU的LILO替代程序?
是?
否?

Loadlin?
否?
從DOS引導(dǎo)Linux?
是?
否?

ROLO?
否?
從ROM引導(dǎo)Linux而不需要BIOS?
是?
否?

Etherboot?
否?
通過以太網(wǎng)卡啟動(dòng)Linux系統(tǒng)的固件?
是?
否?

LinuxBIOS?
否?
完全替代BUIS的Linux引導(dǎo)程序?
是?
否?

BLOB?
是?
LART等硬件平臺的引導(dǎo)程序?
否?
是?

U-Boot?
是?
通用引導(dǎo)程序?
是?
是?

RedBoot?
是?
基于eCos的引導(dǎo)程序?
是?
是?

Vivi?
是?
Mizi公司針對SAMSUNG的ARM CPU設(shè)計(jì)的引導(dǎo)程序?
否?
是?

對于本書使用的S3C2410/S3C2440開發(fā)板,U-Boot和Vivi是兩個(gè)好選擇。Vivi是Mizi公司針對SAMSUNG的ARM架構(gòu)CPU專門設(shè)計(jì)的,基本上可以直接使用,命令簡單方便。不過其初始版本只支持串口下載,速度較慢。在網(wǎng)上出現(xiàn)了各種改進(jìn)版本:支持網(wǎng)絡(luò)功能、USB功能、燒寫YAFFS文件系統(tǒng)映像等。U-Boot則支持大多CPU,可以燒寫EXT2、JFFS2文件系統(tǒng)映像,支持串口下載、網(wǎng)絡(luò)下載,并提供了大量的命令。相對于Vivi,它的使用更復(fù)雜,但是可以用來更方便地調(diào)試程序。

2 U-Boot分析與移植

2.1 U-Boot工程簡介

U-Boot,全稱為Universal Boot?Loader,即通用Bootloader,是遵循GPL條款的開放源代碼項(xiàng)目。其前身是由德國DENX軟件工程中心的Wolfgang?Denk基于8xxROM的源碼創(chuàng)建的PPCBOOT工程。后來整理代碼結(jié)構(gòu)使得非常容易增加其他類型的開發(fā)板、其他架構(gòu)的CPU(原來只支持?PowerPC);增加更多的功能,比如啟動(dòng)Linux、下載S-Record格式的文件、通過網(wǎng)絡(luò)啟動(dòng)、通過PCMCIA/CompactFLash?/ATA disk/SCSI等方式啟動(dòng)。增加ARM架構(gòu)CPU及其他更多CPU的支持后,改名為U-Boot。

它的名字“通用”有兩層含義:可以引導(dǎo)多種操作系統(tǒng)、支持多種架構(gòu)的CPU。它支持如下操作?系統(tǒng):Linux、NetBSD、?VxWorks、QNX、RTEMS、ARTOS、LynxOS等,

支持如下架構(gòu)的CPU:PowerPC、MIPS、x86、ARM、NIOS、?XScale等。

U-Boot有如下特性:

  • 開放源碼;
  • 支持多種嵌入式操作系統(tǒng)內(nèi)核,如Linux、NetBSD、VxWorks、QNX、RTEMS、ARTOS、LynxOS;
  • 支持多個(gè)處理器系列,如PowerPC、ARM、x86、MIPS、XScale;
  • 較高的可靠性和穩(wěn)定性;
  • 高度靈活的功能設(shè)置,適合U-Boot調(diào)試、操作系統(tǒng)不同引導(dǎo)要求、產(chǎn)品發(fā)布等;
  • 豐富的設(shè)備驅(qū)動(dòng)源碼,如串口、以太網(wǎng)、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、鍵盤等;
  • 較為豐富的開發(fā)調(diào)試文檔與強(qiáng)大的網(wǎng)絡(luò)技術(shù)支持;
  • 支持NFS掛載、RAMDISK(壓縮或非壓縮)形式的根文件系統(tǒng)
  • 支持NFS掛載、從FLASH中引導(dǎo)壓縮或非壓縮系統(tǒng)內(nèi)核;
  • 可靈活設(shè)置、傳遞多個(gè)關(guān)鍵參數(shù)給操作系統(tǒng),適合系統(tǒng)在不同開發(fā)階段的調(diào)試要求與產(chǎn)品發(fā)布,尤對Linux支持最為強(qiáng)勁;
  • 支持目標(biāo)板環(huán)境變量多種存儲方式,如FLASH、NVRAM、EEPROM;
  • CRC32校驗(yàn),可校驗(yàn)FLASH中內(nèi)核、RAMDISK鏡像文件是否完好;
  • 上電自檢功能:SDRAM、FLASH大小自動(dòng)檢測;SDRAM故障檢測;CPU型號;
  • 特殊功能:XIP內(nèi)核引導(dǎo);

可以從http://sourceforge.net/projects/u-boot獲得U-Boot的最新版本,如果使用過程中碰到問題或是發(fā)現(xiàn)Bug,可以通過郵件列表網(wǎng)站http://lists.sourceforge.net/lists/listinfo/u-boot-users/獲得幫助。

最新的更新代碼地址http://www.denx.de/wiki/U-Boot/WebHome

2.2 U-Boot源碼結(jié)構(gòu)

本書在u-boot-1.1.6的基礎(chǔ)上進(jìn)行分析和移植,從sourceforge網(wǎng)站下載u-boot-1.1.6.tar.bz2后解壓即得到全部源碼。U-Boot源碼目錄結(jié)構(gòu)比較簡單、獨(dú)立,目錄結(jié)構(gòu)也比較淺,很容易全部掌握。

u-boot-1.1.6根目錄下共有26個(gè)子目錄,可以分為4類:

(1)平臺相關(guān)的或開發(fā)板相關(guān)的。

(2)通用的函數(shù)。

(3)通用的設(shè)備驅(qū)動(dòng)程序。

(4)U-Boot工具、示例程序、文檔。

先將這26個(gè)目錄的功能與作用如表15.2所示。

表2 U-Boot頂層目錄說明

<table fck__showtableborders?="">

目錄?
特性?
解釋說明

board?
開發(fā)板相關(guān)?
對應(yīng)不同配置的電路板(即使CPU相同),比如smdk2410、sbc2410x

cpu?
平臺相關(guān)?
對應(yīng)不同的CPU,比如arm920t、arm925t、i386等;在它們的子目錄下仍可以進(jìn)一步細(xì)分,比如arm920t下就有at91rm9200、s3c24x0

lib_i386類似?
某一架構(gòu)下通用的文件

include?
通用的函數(shù)?
頭文件和開發(fā)板配置文件,開發(fā)板的配置文件都放在include/configs目錄下,U-Boot沒有make menuconfig類似的萊單來進(jìn)行可視化配置,需要手動(dòng)地修改配置文件中的宏定義

lib_generic?
通用的庫函數(shù),比如printf等

common?
通用的函數(shù),多是對下一層驅(qū)動(dòng)程序的進(jìn)一步封裝

disk?
通用的設(shè)備驅(qū)動(dòng)程序?
硬盤接口程序

drivers?
各類具體設(shè)備的驅(qū)動(dòng)程序,基本上可以通用,它們通過宏從外面引入平臺/開發(fā)板相關(guān)的函數(shù)

dtt?
數(shù)字溫度測量器或者傳感器的驅(qū)動(dòng)

fs?
文件系統(tǒng)

nand_spl?
U-Boot一般從ROM、NOR Flash等設(shè)備啟動(dòng),現(xiàn)在開始支持從NAND Flash啟動(dòng),但是支持的CPU種類還不多

net?
各種網(wǎng)絡(luò)協(xié)議

post?
上電自檢程序

rtc?
實(shí)時(shí)時(shí)鐘的驅(qū)動(dòng)

doc?
文檔?
開發(fā)、使用文檔

examples?
示例程序?
一些測試程序,可以使用U-Boot下載后運(yùn)行

tools?
工具?
制作S-Record、U-Boot格式映像的工具,比如mkimage

U-Boot中各目錄間也是有層次結(jié)構(gòu)的,雖然這種分法不是絕對的,但是在移植過程中可以提供一些指導(dǎo)意義,如圖2所示。

2 U-Boot頂層目錄的層次結(jié)構(gòu)

比如common/cmd_nand.c文件提供了操作NAND?
Flash的各種命令,這些命令通過調(diào)用drivers/nand/nand_base.c中的擦除、讀寫函數(shù)來實(shí)現(xiàn)。這些函數(shù)針對NAND?
Flash的共性作了一些封裝,將平臺/開發(fā)板相關(guān)的代碼用宏或外部函數(shù)來代替。而這些宏與外部函數(shù),如果與平臺相關(guān),就要在下一層次的cpu?
/xxx(xxx表示某型號的CPU)中實(shí)現(xiàn);如果與開發(fā)板相關(guān),就要在下一層次的board/xxx目錄(xxx表示某款開發(fā)板)中實(shí)現(xiàn)。本書移植的?
U-Boot,就是在cpu/arm920t/s3c24x0目錄下增加了一個(gè)nand_flash.c文件來實(shí)現(xiàn)這些函數(shù)。

以增加燒寫yaffs文件系統(tǒng)映像的功能為例──就是在common目錄下的?
cmd_nand.c中增加命令,比如nand?
write.yaffs:這個(gè)命令要調(diào)用drivers/nand/nand_util.c中的相應(yīng)函數(shù),針對yaffs文件系統(tǒng)的特點(diǎn)依次調(diào)用擦除、燒?
寫函數(shù)。而這些函數(shù)依賴于drivers/nand/nand_base.c、cpu/arm920t/s3c24x0/nand_flash.c文件中?
的相關(guān)函數(shù)。

目前u-boot-1.1.6支持10種架構(gòu)──根目錄下有10個(gè)類似lib_i386的目?
錄、31個(gè)型號(類型)的CPU──cpu目錄下有31個(gè)子目錄,214種開發(fā)板──board目錄下有214個(gè)子目錄,很容易從中找到與自己的板子相似?
的配置,在上面稍作修改即可使用。

2.3 U-Boot的配置、編譯、連接過程

1. U-Boot初體驗(yàn)

u-boot-1.1.6中有幾千個(gè)文件,要想了解對于某款開發(fā)板,使用哪些文件、哪個(gè)文件首先執(zhí)行、可執(zhí)行文件占用內(nèi)存的情況,最好的方法就是閱讀它的Makefile。

根據(jù)頂層Readme文件的說明,可以知道如果要使用開發(fā)板board/<board_name>,就先執(zhí)行“make <board_name>_config”命令進(jìn)行配置,然后執(zhí)行“make all”,就可以生成如下3個(gè)文件:

  • u-boot.bin:二進(jìn)制可執(zhí)行文件,它就是可以直接燒入ROM、NOR Flash的文件。
  • u-boot:ELF格式的可執(zhí)行文件
  • u-boot.srec:Motorola S-Record格式的可執(zhí)行文件

對于S3C2410的開發(fā)板,執(zhí)行“make smdk2410_config”、“make all”后生成的u-boot.bin可以燒入NOR Flash中運(yùn)行。啟動(dòng)后可以看到串口輸出一些信息后進(jìn)入控制界面,等待用戶的輸入。

對于S3C2440的開發(fā)板,燒入上面生成的u-boot.bin,串口無輸出,需要修改代碼。

在修改代碼之前,先看看上面兩個(gè)命令“make smdk2410_config”、“make all”做了什么事情,以了解程序的流程,知道要修改哪些文件。

另外,編譯U-Boot成功后,還會(huì)在它的tools子目錄下生成一些工具,比如mkimage等。將它們復(fù)制到/usr/local/bin目錄下,以后就可以直接使用它們了,比如編譯內(nèi)核時(shí),會(huì)使用mkimage來生成U-Boot格式的內(nèi)核映像文件uImage。

2. U-Boot的配置過程

在頂層Makefile中可以看到如下代碼:

SRCTREE:= $(CURDIR)

……

MKCONFIG:= $(SRCTREE)/mkconfig

……

smdk2410_config:unconfig

@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0

假定我們在u-boot-1.1.6的根目錄下編譯,則其中的MKCONFIG就是根目錄下的mkconfig文件。$(@:_config=)的結(jié)果就是將“smdk2410_config”中的“_config”去掉,結(jié)果為?

“smdk2410”。所以“make smdk2410_config”實(shí)際上就是執(zhí)行如下命令:./mkconfig smdk2410 arm arm920t smdk2410 NULL s3c24x0

再來看看mkconfig的作用,在mkconfig文件開頭第6行給出了它的用法:

06 # Parameters: Target Architecture CPU Board [VENDOR] [SOC]

這里解釋一下概念,對于S3C2410、S3C2440,它們被稱為SoC(System?on Chip),上面除CPU外,還集成了包括UART、USB控制器、NAND?Flash控制器等等設(shè)備(稱為片內(nèi)外設(shè))。S3C2410/S3C2440中的CPU為arm920t。

以下,分步驟分析mkconfig的作用:

(1)確定開發(fā)板名稱BOARD_NAME。

?

?

?

11 APPEND=no# Default: Create new?config file 12 BOARD_NAME=""# Name to print in make output 13 14 while?[ $# -gt 0 ] ; do 15 case?"$1"?in 16 --) shift ; break?;; 17 -a) shift ; APPEND=yes ;; 18 -n) shift ; BOARD_NAME="${1%%_config}"?; shift ;;? 19 *) break?;; 20 esac 21 done 22 23 [ "${BOARD_NAME}"?] || BOARD_NAME="$1"

?

對于“./mkconfig smdk2410 arm arm920t smdk2410 NULL s3c24x0”命令,其中沒有“--”、“-a”、“-n”等符號,所以第14~22行沒做任何事情。第11、12行兩個(gè)變量仍維持原來的值。

執(zhí)行完第23行后,BOARD_NAME的值等于第1個(gè)參數(shù),即“smdk2410”。

(2)創(chuàng)建到平臺/開發(fā)板相關(guān)的頭文件的鏈接。

略過mkconfig文件中的一些沒有起作用的行:

?
30 # 31 # Create link to architecture specific headers 32 # 33 if?[ "$SRCTREE"?!= "$OBJTREE"?] ; then …… 45 else 46 cd ./include 47 rm -f asm 48 ln -s asm-$2 asm 49 fi 50

第33行判斷源代碼目錄和目標(biāo)文件目錄是否一樣,可以選擇在其他目錄下編譯U-Boot,這可以令源代碼目錄保持干凈,可以同時(shí)使用不同的配置進(jìn)行編譯。不過本書直接在源代碼目錄下編譯的,第33行的條件不滿足,將執(zhí)行else分支的代碼。

第46~48行進(jìn)入include目錄,刪除asm文件(這是上一次配置時(shí)建立的鏈接文件),然后再次建立asm文件,并令它鏈接向asm-$2目錄,即asm-arm。

繼續(xù)往下看代碼:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 51 rm -f asm-$2/arch 52 53 if?[ -z "$6"?-o "$6"?= "NULL"?] ; then 54 ln -s ${LNPREFIX}arch-$3 asm-$2/arch 55 else 56 ln -s ${LNPREFIX}arch-$6 asm-$2/arch 57 fi 58 59 if?[ "$2"?= "arm"?] ; then 60 rm -f asm-$2/proc 61 ln -s ${LNPREFIX}proc-armv asm-$2/proc 62 fi 63

第51行刪除asm-$2/arch目錄,即asm-arm/arch。

對于“./mkconfig smdk2410 arm arm920t smdk2410 NULL s3c24x0”命令,$6為“s3c24x0”,不為空,也不是“NULL”,所以第53行的條件不滿足,將執(zhí)行else分支。

第56行中,LNPREFIX為空,所以這個(gè)命令實(shí)際上就是:ln -s arch-$6 asm-$2/arch,即:ln -s arch-s3c24x0 asm-arm/arch。

第60、61行重新建立asm-arm/proc文件,并讓它鏈接向proc-armv目錄。

(3)創(chuàng)建頂層Makefile包含的文件include/config.mk。

對于“./mkconfig smdk2410 arm arm920t smdk2410 NULL s3c24x0”命令,上面幾行代碼創(chuàng)建的config.mk文件內(nèi)容如下:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 64 # 65 # Create include file for?Make 66 # 67 echo "ARCH = $2"?> config.mk 68 echo "CPU = $3"?>> config.mk 69 echo "BOARD = $4"?>> config.mk 70 71 [ "$5"?] && [ "$5"?!= "NULL"?] && echo "VENDOR = $5"?>> config.mk 72 73 [ "$6"?] && [ "$6"?!= "NULL"?] && echo "SOC = $6"?>> config.mk 74

ARCH = arm

CPU = arm920t

BOARD = smdk2410

SOC = s3c24x0

(4)創(chuàng)建開發(fā)板相關(guān)的頭文件include/config.h。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 75 # 76 # Create board specific header file 77 # 78 if?[ "$APPEND"?= "yes"?]# Append to existing config file 79 then 80 echo >> config.h 81 else 82 > config.h# Create new?config file 83 fi 84 echo "/* Automatically generated - do not edit */"?>>config.h 85 echo "#include <configs/$1.h>"?>>config.h 86

前面說過,APPEND維持原值“no”,所以config.h被重新建立,它的內(nèi)容如下:

/* Automatically generated - do not edit */

#include <configs/smdk2410.h>"

現(xiàn)在總結(jié)一下,配置命令“make?
smdk2410_config”,實(shí)際的作用就是執(zhí)行“./mkconfig smdk2410 arm arm920t smdk2410?
NULL s3c24x0”命令。假設(shè)執(zhí)行“./mkconfig $1 $2 $3 $4 $5 $6”命令,則將產(chǎn)生如下結(jié)果:

(1)開發(fā)板名稱BOARD_NAME等于$1;

(2)創(chuàng)建到平臺/開發(fā)板相關(guān)的頭文件的鏈接:

ln -s asm-$2 asm

ln -s arch-$6 asm-$2/arch

ln -s proc-armv asm-$2/proc# 如果$2不是arm的話,此行沒有

(3) 創(chuàng)建頂層Makefile包含的文件include/config.mk。

ARCH = $2

CPU = $3

BOARD = $4

VENDOR = $5# $5為空,或者是NULL的話,此行沒有

SOC = $6# $6為空,或者是NULL的話,此行沒有

(4)創(chuàng)建開發(fā)板相關(guān)的頭文件include/config.h。

/* Automatically generated - do not edit */

#include <configs/$1.h>"

從這4個(gè)結(jié)果可以知道,如果要在board目錄下新建一個(gè)開發(fā)?
板<board_name>的目錄,則在include/config目錄下也要建立一個(gè)文件<board_name>.h,里?
面存放的就是開發(fā)板<board_name>的配置信息。

U-Boot還沒有類似Linux一樣的可視化配置界面(比如使用make menuconfig來配置),要手動(dòng)修改配置文件include/config/<board_name>.h來裁減、設(shè)置U-Boot。

配置文件中有兩類宏:

(1)一類是選項(xiàng)(Options),前綴為“CONFIG_”,它們用于選擇CPU、SOC、開發(fā)板類型,設(shè)置系統(tǒng)時(shí)鐘、選擇設(shè)備驅(qū)動(dòng)等。比如:

#define CONFIG_ARM920T1/* This is an ARM920T Core*/

#defineCONFIG_S3C24101/* in a SAMSUNG S3C2410 SoC */

#define CONFIG_SMDK24101/* on a SAMSUNG SMDK2410 Board */

#define CONFIG_SYS_CLK_FREQ12000000/* the SMDK2410 has 12MHz input clock */

#define CONFIG_DRIVER_CS89001/* we have a CS8900 on-board */

(2)另一類是參數(shù)(Setting),前綴為“CFG_”,它們用于設(shè)置malloc緩沖池的大小、U-Boot的提示符、U-Boot下載文件時(shí)的默認(rèn)加載地址、Flash的起始地址等。比如:

#define CFG_MALLOC_LEN(CFG_ENV_SIZE + 128*1024)

#defineCFG_PROMPT"100ASK> "/* Monitor Command Prompt*/

#defineCFG_LOAD_ADDR0x33000000/* default load address*/

#define PHYS_FLASH_10x00000000 /* Flash Bank #1 */

從下面的編譯、連接過程可知,U-Boot中幾乎每個(gè)文件都被編譯和連接,但是這些文件是否包含有效的代碼,則由宏開關(guān)來設(shè)置。比如對于網(wǎng)卡驅(qū)動(dòng)drivers/cs8900.c,它的格式為:

#include <common.h>/* 將包含配置文件include/config/<board_name>.h */

……

#ifdef CONFIG_DRIVER_CS8900

/* 實(shí)際的代碼 */

……

#endif/* CONFIG_DRIVER_CS8900 */

如果定義了宏CONFIG_DRIVER_CS8900,則文件中包含有效的代碼;否則,文件被注釋為空。

可以這樣粗糙地認(rèn)為,“CONFIG_”除了設(shè)置一些參數(shù)外,主要用來設(shè)置U-Boot的功能、選擇使用文件中的哪一部分;而“CFG_”用來設(shè)置更細(xì)節(jié)的參數(shù)。

3. U-Boot的編譯、連接過程

配置完后,執(zhí)行“make all”即可編譯,從Makefile中可以了解U-Boot使用了哪些文件、哪個(gè)文件首先執(zhí)行、可執(zhí)行文件占用內(nèi)存的情況。

先確定用到哪些文件,下面只摘取Makefile中與arm相關(guān)的部分:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 117 include $(OBJTREE)/include/config.mk 118 exportARCH CPU BOARD VENDOR SOC 119 …… 127 ifeq ($(ARCH),arm) 128 CROSS_COMPILE = arm-linux- 129 endif …… 163 # load other configuration 164 include $(TOPDIR)/config.mk 165

第117、164行用于包含其他的config.mk文件,第117行所要包含文件的就是在?
上面的配置過程中制作出來的include/config.mk文件,其中定義了ARCH、CPU、BOARD、SOC等4個(gè)變量的值為arm、?
arm920t、smdk2410、s3c24x0。

第164行包含頂層目錄的config.mk文件,它根據(jù)上面4個(gè)變量的值確定了編譯器、編譯選項(xiàng)等。其中對我們理解編譯過程有幫助的是BOARDDIR、LDFLAGS的值,config.mk中:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 88 BOARDDIR = $(BOARD) …… 91 sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk# include board specific rules …… 143 LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds …… 189 LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)

在board/smdk2410/config.mk中,定義了“TEXT_BASE =?
0x33F80000”。所以,最終結(jié)果如下:BOARDDIR為smdk2410;LDFLAGS中有“-T?
board/smdk2410/u-boot.lds -Ttext 0x33F80000”字樣。

繼續(xù)往下看Makefile:

166 #########################################################################

167 # U-Boot objects....order is important (i.e. start must be first)

168

169 OBJS = cpu/$(CPU)/start.o

……

193 LIBS = lib_generic/libgeneric.a

194 LIBS += board/$(BOARDDIR)/lib$(BOARD).a

195 LIBS += cpu/$(CPU)/lib$(CPU).a

……

199 LIBS += lib_$(ARCH)/lib$(ARCH).a

200 LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \

201 fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a

202 LIBS += net/libnet.a

……

212 LIBS += $(BOARDLIBS)

213

……

從第169行得知,OBJS的第一個(gè)值為“cpu/$(CPU)/start.o”,即“cpu/arm920t/start.o”。

第193~213行指定了LIBS變量就是平臺/開發(fā)板相關(guān)的各個(gè)目錄、通用目錄下相應(yīng)的?
庫,比如:lib_generic/libgeneric.a、board/smdk2410/libsmdk2410.a、cpu/arm920t?
/libarm920t.a、lib_arm/libarm.a、fs/cramfs/libcramfs.a fs/fat/libfat.a等。

OBJS、LIBS所代表的.o、.a文件就是U-Boot的構(gòu)成,它們通過如下命令由相應(yīng)的源文件(或相應(yīng)子目錄下的文件)編譯得到。

268 $(OBJS):

269 $(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))

270

271 $(LIBS):

272 $(MAKE) -C $(dir $(subst $(obj),,$@))

273

274 $(SUBDIRS):

275 $(MAKE) -C $@ all

276

第268、269兩行的規(guī)則表示,對于OBJS中的每個(gè)成員,都將進(jìn)入cpu/$(CPU)目錄(即cpu/arm920t)編譯它們。現(xiàn)在OBJS為cpu/arm920t/start.o,它將由cpu/arm920t/start.S編譯得到。

第271、272兩行的規(guī)則表示,對于LIBS中的每個(gè)成員,都將進(jìn)入相應(yīng)的子目錄執(zhí)行“make”命令。這些子目錄中的Makefile,結(jié)構(gòu)相似,它們將Makefle中指定的文件編譯、連接成一個(gè)庫文件。

當(dāng)所有的OBJS、LIBS所表示的.o和.a文件都生成后,就剩最后的連接了,這對應(yīng)Makefile中如下幾行:

246 $(obj)u-boot.srec:$(obj)u-boot

247 $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@

248

249 $(obj)u-boot.bin:$(obj)u-boot

250 $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@

251

……

262 $(obj)u-boot:depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)

263 UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\

264 cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \

265 --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \

266 -Map u-boot.map -o u-boot

267

先使用第262~266的規(guī)則連接得到ELF格式的u-boot,最后轉(zhuǎn)換為二進(jìn)制格式u-?
boot.bin、S-Record格式u-boot.srec。LDFLAGS確定了連接方式,其中的“-T?
board/smdk2410/u-boot.lds -Ttext?
0x33F80000”字樣指定了程序的布局、地址。board/smdk2410/u-boot.lds文件如下:

28 SECTIONS

29 {

30 . = 0x00000000;

31

32 . = ALIGN(4);

33 .text :

34 {

35 cpu/arm920t/start.o(.text)

36 *(.text)

37 }

38

39 . = ALIGN(4);

40 .rodata : { *(.rodata) }

41

42 . = ALIGN(4);

43 .data : { *(.data) }

44

45 . = ALIGN(4);

46 .got : { *(.got) }

47

48 . = .;

49 __u_boot_cmd_start = .;

50 .u_boot_cmd : { *(.u_boot_cmd) }

51 __u_boot_cmd_end = .;

52

53 . = ALIGN(4);

54 __bss_start = .;

55 .bss : { *(.bss) }

56 _end = .;

57 }

從第35行可知,cpu/arm920t/start.o被放在程序的最前面,所以U-Boot的入口點(diǎn)在cpu/arm920t/start.S中。

現(xiàn)在來總結(jié)一下U-Boot的編譯流程:

(1)首先編譯cpu/$(CPU)/start.S,對于不同的CPU,還可能編譯cpu/$(CPU)下的其他文件。

(2)然后,對于平臺/開發(fā)板相關(guān)的每個(gè)目錄、每個(gè)通用目錄,都使用它們各自的Makefile生成相應(yīng)的庫。

(3)將1、2步驟生成的.o、.a文件按照board/$(BOARDDIR)/config.mk文件中指定的代碼段起始地址、board/$(BOARDDIR)/u-boot.lds連接腳本進(jìn)行連接。

(4)第3步得到的是ELF格式的U-Boot,后面Makefile還會(huì)將它轉(zhuǎn)換為二進(jìn)制格式、S-Record格式。

2.4 U-Boot的啟動(dòng)過程源碼分析

首先強(qiáng)調(diào),本書使用的U-Boot從NOR Flash啟動(dòng),下面以開發(fā)板smdk2410的U-Boot為例。

U-Boot屬于兩階段的Bootloader,第一階段的文件為cpu/arm920t/start.S和board/smdk2410/lowlevel_init.S,前者是平臺相關(guān),后者是開發(fā)板相關(guān)。

U-Boot第一階段代碼分析

它與1.2節(jié)中描述的Bootloader第一階段所完成的功能可以一一對應(yīng):

(1)硬件設(shè)備初始化。

依次完成如下設(shè)置:將CPU的工作模式設(shè)為管理模式(svc),關(guān)閉WATCHDOG,設(shè)置FCLK、HCLK、PCLK的比例(即設(shè)置CLKDIVN寄存器),關(guān)閉MMU、CACHE。

代碼都在cpu/arm920t/start.S中,注釋也比較完善,讀者有不明白的地方可以參考前面硬件實(shí)驗(yàn)的相關(guān)章節(jié)。

(2)為加載Bootloader的第二階段代碼準(zhǔn)備RAM空間。

所謂準(zhǔn)備RAM空間,就是初始化內(nèi)存芯片,使它可用。對于S3C2410/S3C2440,?
通過在start.S中調(diào)用lowlevel_init函數(shù)來設(shè)置存儲控制器,使得外接的SDRAM可用。代碼在board/smdk2410?
/lowlevel_init.S中。

注意:lowlevel_init.S文件是開發(fā)板相關(guān)的,這表示如果外接的設(shè)備不一樣,可以修改lowlevel_init.S文件中的相關(guān)宏。

lowlevel_init函數(shù)并不復(fù)雜,只是要注意這時(shí)的代碼、數(shù)據(jù)都只保存在NOR Flash上,內(nèi)存中還沒有,所以讀取數(shù)據(jù)時(shí)要變換地址。代碼如下:

129 _TEXT_BASE:

130 .wordTEXT_BASE

131

132 .globl lowlevel_init

133 lowlevel_init:

134 /* memory control configuration */

135 /* make r0 relative the current location so that it */

136 /* reads SMRDATA out of FLASH rather than memory ! */

137 ldr r0, =SMRDATA

138 ldrr1, _TEXT_BASE

139 subr0, r0, r1

140 ldrr1, =BWSCON/* Bus Width Status Controller */

141 add r2, r0, #13*4

142 0:

143 ldr r3, [r0], #4

144 str r3, [r1], #4

145 cmp r2, r0

146 bne 0b

147

148 /* everything is fine now */

149 movpc, lr

150

151 .ltorg

152 /* the literal pools origin */

153

154 SMRDATA:/* 13個(gè)寄存器的值 */

155 .word ……

156 .word ……

第137~139行進(jìn)行地址變換,因?yàn)檫@時(shí)候內(nèi)存中還沒有數(shù)據(jù),不能使用連接程序時(shí)確定的地址來讀取數(shù)據(jù):

第137行中SMRDATA 表示這13個(gè)寄存器的值存放的開始地址(連接地址),值為0x33F8xxxx,處于內(nèi)存中。

第138行獲得代碼段的起始地址,它就是第130行中的“TEXT_BASE”,其值在board/smdk2410/config.mk中定義:“TEXT_BASE = 0x33F80000”。

第139行將0x33F8xxxx與0x33F80000相減,這就是13個(gè)寄存器值在NOR Flash上存放的開始地址。

(3)拷貝Bootloader的第二階段代碼到 RAM 空間中。

這里將整個(gè)U-Boot的代碼(包括第一、第二階段)都復(fù)制到SDRAM中,這在cpu/arm920t/start.S中實(shí)現(xiàn):

164 relocate:/* 將U-Boot復(fù)制到RAM中 */

165 adrr0, _start/* r0 = 當(dāng)前代碼的開始地址 */

166 ldrr1, _TEXT_BASE/* r1 = 代碼段的連接地址 */

167 cmp r0, r1 /* 測試現(xiàn)在是在Flash中還是在RAM中 */

168 beq stack_setup/* 如果已經(jīng)在RAM中(這通常是調(diào)試時(shí),直接下載到RAM中),

* 則不需要復(fù)制

*/

169

170 ldrr2, _armboot_start/* _armboot_start在前面定義,是第一條指令的運(yùn)行地址 */

171 ldrr3, _bss_start/* 在連接腳本u-boot.lds中定義,是代碼段的結(jié)束地址 */

172 subr2, r3, r2/* r2 = 代碼段長度 */

173 addr2, r0, r2/* r2 = NOR Flash上代碼段的結(jié)束地址 */

174

175 copy_loop:

176 ldmiar0!, {r3-r10}/* 從地址[r0]處獲得數(shù)據(jù) */

177 stmiar1!, {r3-r10}/* 復(fù)制到地址[r1]處 */

178 cmpr0, r2/* 判斷是否復(fù)制完畢 */

179 blecopy_loop/* 沒復(fù)制完,則繼續(xù) */

(4)設(shè)置好棧。

棧的設(shè)置靈活性很大,只要讓sp寄存器指向一段沒有使用的內(nèi)存即可。

182 /* Set up the stack */

183 stack_setup:

184 ldr r0, _TEXT_BASE /* _TEXT_BASE為代碼段的開始地址,值為0x33F80000 */

185 sub r0, r0, #CFG_MALLOC_LEN /* 代碼段下面,留出一段內(nèi)存以實(shí)現(xiàn)malloc */

186 sub r0, r0, #CFG_GBL_DATA_SIZE /* 再留出一段內(nèi)存,存一些全局參數(shù) */

187 #ifdef CONFIG_USE_IRQ

188 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) /* IRQ、FIQ模式的棧 */

189 #endif

190 sub sp, r0, #12 /* 最后,留出12字節(jié)的內(nèi)存給abort異常,

* 往下的內(nèi)存就都是棧了

*/

191

到了這一步,讀者可以知道內(nèi)存的使用情況了,如下圖所示(圖中與上面的劃分稍有不同,這是因?yàn)樵赾pu/arm920t/cpu.c中的cpu_init函數(shù)中才真正為IRQ、FIQ模式劃分了棧): [[Image:]]

圖3 U-Boot內(nèi)存使用情況

(5)跳轉(zhuǎn)到第二階段代碼的C入口點(diǎn)。

在跳轉(zhuǎn)之前,還要清除BSS段(初始值為0、無初始值的全局變量、靜態(tài)變量放在BSS段),代碼如下:

192 clear_bss:

193 ldrr0, _bss_start/* BSS段的開始地址,它的值在連接腳本u-boot.lds中確定 */

194 ldrr1, _bss_end/* BSS段的結(jié)束地址,它的值在連接腳本u-boot.lds中確定 */

195 mov r2, #0x00000000

196

197 clbss_l:strr2, [r0]/* 往BSS段中寫入0值 */

198 addr0, r0, #4

199 cmpr0, r1

200 bleclbss_l

201

現(xiàn)在,C函數(shù)的運(yùn)行環(huán)境已經(jīng)完全準(zhǔn)備好,通過如下命令直接跳轉(zhuǎn)(這之后,程序才在內(nèi)存中執(zhí)行),它將調(diào)用lib_arm/board.c中的start_armboot函數(shù),這是第二階段的入口點(diǎn):

223 ldrpc, _start_armboot

224

225 _start_armboot:.word start_armboot

226

U-Boot第二階段代碼分析

它與15.1.2節(jié)中描述的Bootloader第二階段所完成的功能基本上一致,不過順序有點(diǎn)小差別。另外,U-Boot在啟動(dòng)內(nèi)核之前可以讓用戶決定是否進(jìn)入下載模式,即進(jìn)入U(xiǎn)-Boot的控制界面。

第二階段從lib_arm/board.c中的start_armboot函數(shù)開始,先看從這個(gè)函數(shù)開始的程序流程圖。

圖3 U-Boot第二階段流程圖

移植U-Boot的主要工作在于對硬件的初始化、驅(qū)動(dòng),所以下面講解時(shí)將重點(diǎn)放在硬件的操作上。

(1)初始化本階段要使用到的硬件設(shè)備。:最主要的是設(shè)置系統(tǒng)時(shí)鐘、初始化串口,只要這兩個(gè)設(shè)置好了,就可以從串口看到打印信息。

board_init函數(shù)設(shè)置MPLL、改變系統(tǒng)時(shí)鐘,它是開發(fā)板相關(guān)的函數(shù),在board/smdk2410/smdk2410.c中實(shí)現(xiàn)。值得注意的是,board_init函數(shù)中還保存了機(jī)器類型ID,這將在調(diào)用內(nèi)核時(shí)傳給內(nèi)核,代碼如下:

/* arch number of SMDK2410-Board */

gd->bd->bi_arch_number = MACH_TYPE_SMDK2410; /* 值為193 */

串口的初始化函數(shù)主要是serial_init,它設(shè)置UART控制器,是CPU相關(guān)的函數(shù),在cpu/arm920t/s3c24x0/serial.c中實(shí)現(xiàn)。

(2)檢測系統(tǒng)內(nèi)存映射(memory?
map)。對于特定的開發(fā)板,其內(nèi)存的分布是明確的,所以可以直接設(shè)置。board/smdk2410/smdk2410.c中的dram_init函數(shù)?
指定了本開發(fā)板的內(nèi)存起始地址為0x30000000,大小為0x4000000。代碼如下:

int dram_init (void)

{

gd->bd->bi_dram[0].start = PHYS_SDRAM_1;/* 即0x300000000 */

gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;/* 即0x4000000 */

return 0;

}

這些設(shè)置的參數(shù),將在后面向內(nèi)核傳遞參數(shù)時(shí)用到。

(3)U-Boot命令的格式。

從圖3可以知道,即使是內(nèi)核的啟動(dòng),也是通過U-Boot命令來實(shí)現(xiàn)的。U-Boot中每個(gè)命令都通過U_BOOT_CMD宏來定義,格式如下:

U_BOOT_CMD(name,maxargs,repeatable,command,"usage","help")

各項(xiàng)參數(shù)的意義為:

① name:命令的名字,注意,它不是一個(gè)字符串(不要用雙引號括起來)。

② maxargs:最大的參數(shù)個(gè)數(shù)

③ repeatable:命令是否可重復(fù),可重復(fù)是指運(yùn)行一個(gè)命令后,下次敲回車即可再次運(yùn)行。

④ command:對應(yīng)的函數(shù)指針,類型為(*cmd)(struct cmd_tbl_s *, int, int, char *[])。

⑤ usage:簡短的使用說明,這是個(gè)字符串。

⑥ help:較詳細(xì)的使用說明,這是個(gè)字符串。

宏U_BOOT_CMD在include/command.h中定義:

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \

cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}

Struct_Section也是在include/command.h中定義:

#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))

比如對于bootm命令,它如此定義:

U_BOOT_CMD(

bootm,CFG_MAXARGS,1,do_bootm,

“string1”,

“string2”

);

宏U_BOOT_CMD擴(kuò)展開后就是:

cmd_tbl_t __u_boot_cmd_bootm __attribute__?
((unused,section (".u_boot_cmd"))) = {“bootm”, CFG_MAXARGS, 1,?
do_bootm, “string1”, “string2”};

對于每個(gè)使用U_BOOT_CMD宏來定義的命令,其實(shí)都是在".u_boot_cmd"段中定義一個(gè)cmd_tbl_t結(jié)構(gòu)。連接腳本u-boot.lds中有這么一段:

__u_boot_cmd_start = .;

.u_boot_cmd : { *(.u_boot_cmd) }

__u_boot_cmd_end = .;

程序中就是根據(jù)命令的名字在內(nèi)存段__u_boot_cmd_start~__u_boot_cmd_end找到它的cmd_tbl_t結(jié)構(gòu),然后調(diào)用它的函數(shù)(請參考common/command.c中的find_cmd函數(shù))。

內(nèi)核的復(fù)制和啟動(dòng),可以通過如下命令來完成:bootm從內(nèi)存、ROM、NOR?
Flash中啟動(dòng)內(nèi)核,bootp則通過網(wǎng)絡(luò)來啟動(dòng),而nboot從NAND?
Flash啟動(dòng)內(nèi)核。它們都是先將內(nèi)核映像從各種媒介中讀出,存放在指定的位置;然后設(shè)置標(biāo)記列表以給內(nèi)核傳遞參數(shù);最后跳到內(nèi)核的入口點(diǎn)去執(zhí)行。具體實(shí)?
現(xiàn)的細(xì)節(jié)不再描述,有興趣的讀者可以閱讀common/cmd_boot.c、common/cmd_net.c、common/cmd_nand.c來?
了解它們的實(shí)現(xiàn)。

(4)為內(nèi)核設(shè)置啟動(dòng)參數(shù)。

與15.1.2小節(jié)中《Bootloader與內(nèi)核的交互》所描述的一樣,U-Boot也是?
通過標(biāo)記列表向內(nèi)核傳遞參數(shù)。并且,15.1.2小節(jié)中內(nèi)存標(biāo)記、命令行標(biāo)記的示例代碼就是取自U-Boot中的setup_memory_tags、?
setup_commandline_tag函數(shù),它們都是在lib_arm/armlinux.c中定義。一般而言,設(shè)置這兩個(gè)標(biāo)記就可以了,在配置文?
件include/configs/smdk2410.h中增加如下兩個(gè)配置項(xiàng)即可:

#define CONFIG_SETUP_MEMORY_TAGS 1

#define CONFIG_CMDLINE_TAG 1

對于ARM架構(gòu)的CPU,都是通過lib_arm/armlinux.c中的?
do_bootm_linux函數(shù)來啟動(dòng)內(nèi)核。這個(gè)函數(shù)中,設(shè)置標(biāo)記列表,最后通過“theKernel (0,?
bd->bi_arch_number,?
bd->bi_boot_params)”調(diào)用內(nèi)核。其中,theKernel指向內(nèi)核存放的地址(對于ARM架構(gòu)的CPU,通常是?
0x30008000),bd->bi_arch_number就是前面board_init函數(shù)設(shè)置的機(jī)器類型ID,而?
bd->bi_boot_params就是標(biāo)記列表的開始地址。

2.5 U-Boot的移植

開發(fā)板smdk2410的配置適用于大多數(shù)S3C2410單板,或是只需要極少的修改即可使用。但是目前U-Boot中沒有對S3C2440的支持,需要我們自己移植。

本書基于的S3C2410、S3C2440兩款開發(fā)板,它們的外接硬件相同:

  • BANK0外接容量為1MB,位寬為8的NOR Flash芯片AM29LV800
  • BANK3外接10M網(wǎng)卡芯片CS8900,位寬為16
  • BANK6外接兩片容量為32MB、位寬為16的SDRAM芯片K4S561632,組成容量為64MB、位寬為32的內(nèi)存
  • 通過NAND Flash控制器外接容量為64MB,位寬為8的NAND Flash芯片K9S1208

對于NOR Flash和NAND?
Flash,如圖15.4所示劃分它們的使用區(qū)域。由于NAND?
Flash的“位反轉(zhuǎn)”現(xiàn)象比較常見,為保證數(shù)據(jù)的正確,在讀寫數(shù)據(jù)時(shí)需要使用ECC較驗(yàn)。另外,NAND?
Flash在使用過程中、運(yùn)輸過程中還有可能出現(xiàn)壞塊。所以本書選擇在NOR Flash中保存U-Boot,在NAND?
Flash中保存內(nèi)核和文件系統(tǒng),并在使用U-Boot燒寫內(nèi)核、文件系統(tǒng)時(shí),進(jìn)行壞塊檢查、ECC較驗(yàn)。這樣,即使NAND?
Flash出現(xiàn)壞塊導(dǎo)致內(nèi)核或文件系統(tǒng)不能使用,也可以通過NOR Flash中的U-Boot來重新燒寫。 [[Image:]]

圖15.4 開發(fā)板固態(tài)存儲器分區(qū)劃分

smdk2410開發(fā)板已經(jīng)支持NOR?
Flash芯片AM29LV800,U-Boot本身也已經(jīng)支持jffs2文件系統(tǒng)映像的燒寫。下面一步一步移植U-Boot(所有的修改都在補(bǔ)丁文件?
u-boot-1.1.6_100ask24x0.patch里,讀者可以直接打補(bǔ)丁),增加如下新功能:

  • 同時(shí)支持本書使用的S3C2410和S3C2440開發(fā)板
  • 支持串口xmodem協(xié)議
  • 支持網(wǎng)卡芯片CS8900
  • 支持NAND Flash讀寫
  • 支持燒寫yaffs文件系統(tǒng)映像

1. 同時(shí)支持S3C2410和S3C2440

我們將在開發(fā)板smdk2410的基礎(chǔ)上進(jìn)行移植。

(1)新建一個(gè)開發(fā)板的相應(yīng)目錄和文件。

為了不破壞原來的代碼,在board目錄下將smdk2410復(fù)制為100ask24x0目錄,并將board/100ask24x0/smdk2410.c改名為100ask24x0.c。

根據(jù)前面描述的配置過程可知,還要在include/configs目錄下建立一個(gè)配置文件100ask24x0.h,可以將include/configs/smdk2410.h直接復(fù)制為100ask24x0.h。

還要修改兩個(gè)Makefile,首先在頂層Makefile中增加如下兩行:

100ask24x0_config:unconfig

@$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0

然后在board/100ask24x0/Makefile中,如下修改(因?yàn)榍懊鎸mdk2410.c文件改名為100ask24x0.c了):

COBJS:= smdk2410.o flash.o

改為:

COBJS:= 100ask24x0.o flash.o

(2)修改SDRAM的配置。

SDRAM的初始化在U-Boot的第一階段完成,就是在board/100ask24x0/lowlevel_init.S文件中設(shè)置存儲控制器。

檢查一下BANK6的設(shè)置:位寬為32──宏B6_BWSCON剛好為DW32(表示32位),無需改變;另外還要根據(jù)HCLK設(shè)置SDRAM的刷新參數(shù),主要是REFCNT寄存器。

本書所用開發(fā)板的HCLK都設(shè)為100MHz,需要根據(jù)SDRAM芯片的具體參數(shù)重新計(jì)算REFCNT寄存器的值(請參考第6章)。代碼修改如下:

126 #define REFCNT 1113/* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */

改為

126 #define REFCNT 0x4f4/* period=7.8125us, HCLK=100Mhz, (2048+1-7.8125*100) */

對于其他BANK,比如網(wǎng)卡芯片CS8900所在的BANK2,原來的設(shè)置剛好匹配,無需更改;而對于BANK1、2、4、5、7,在U-Boot中并沒有使用到它們外接的設(shè)備,也不需要理會(huì)。

(3)增加對S3C2440的支持。

S3C2440是S3C2410的改進(jìn)版,它們的操作基本相似。不過在系統(tǒng)時(shí)鐘的設(shè)置、?
NAND?
Flash控制器的操作等方面,有一些小差別。它們的MPLL、UPLL計(jì)算公式不一樣,FCLK、HCLK和PCLK的分頻化設(shè)置也不一樣,這在下面的?
代碼中可以看到。NAND Flash控制器的差別在增加對NAND Flash的支持時(shí)講述。

本章的目標(biāo)是令同一個(gè)U-Boot二進(jìn)制代碼既可以在S3C2410上運(yùn)行,也可以在?
S3C2440上運(yùn)行。首先需要在代碼中自動(dòng)識別是S3C2410還是S3C2440,這可以通過讀取GSTATUS1寄存器的值來分?
辨:0x32410000表示S3C2410,0x32410002表示S3C2410A,0x32440000表示?
S3C2440,0x32440001表示S3C2440A。S3C2410和S3C2410A、S3C2440和S3C2440A,對本書來說沒有區(qū)?
別。

對于S3C2410開發(fā)板,將FCLK設(shè)為200MHz,分頻比為?
FCLK:HCLK:PCLK=1:2:4;對于S3C2440開發(fā)板,將FCLK設(shè)為400MHz,分頻比為?
FCLK:HCLK:PCLK=1:4:8。還將UPLL設(shè)為48MHz,即UCLK為48MHz,以在內(nèi)核中支持USB控制器。

首先修改board/100ask24x0/100ask24x0.c中的board_init函數(shù),下面是修改后的代碼:

33 /* S3C2440: MPLL = (2*m * Fin) / (p * 2^s), UPLL = (m * Fin) / (p * 2^s)

34 * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2

35 */

36 #define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))

37 #define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02))

38 #define S3C2440_CLKDIV 0x05 /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL */

39

40 /* S3C2410: Mpll,Upll = (m * Fin) / (p * 2^s)

41 * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2

42 */

43 #define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))

44 #define S3C2410_UPLL_48MHZ ((0x28<<12)|(0x01<<4)|(0x02))

45 #define S3C2410_CLKDIV 0x03 /* FCLK:HCLK:PCLK = 1:2:4 */

46

上面幾行針對S3C2410、S3C2440分別定義了MPLL、UPLL寄存器的值。開發(fā)?
板輸入時(shí)鐘為12MHz(這在include/configs/100ask24x0.h中的宏CONFIG_SYS_CLK_FREQ中定義),讀者可?
以根據(jù)代碼中的計(jì)算公式針對自己的開發(fā)板修改系統(tǒng)時(shí)鐘。

下面是針對S3C2410、S3C2440,分別使用不同的宏設(shè)置系統(tǒng)時(shí)鐘:

58 int board_init (void)

59 {

60 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

61 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();

62

63 /* 設(shè)置GPIO */

64 gpio->GPACON = 0x007FFFFF;

65 gpio->GPBCON = 0x00044555;

66 gpio->GPBUP = 0x000007FF;

67 gpio->GPCCON = 0xAAAAAAAA;

68 gpio->GPCUP = 0x0000FFFF;

69 gpio->GPDCON = 0xAAAAAAAA;

70 gpio->GPDUP = 0x0000FFFF;

71 gpio->GPECON = 0xAAAAAAAA;

72 gpio->GPEUP = 0x0000FFFF;

73 gpio->GPFCON = 0x000055AA;

74 gpio->GPFUP = 0x000000FF;

75 gpio->GPGCON = 0xFF95FFBA;

76 gpio->GPGUP = 0x0000FFFF;

77 gpio->GPHCON = 0x002AFAAA;

78 gpio->GPHUP = 0x000007FF;

79

80 /* 同時(shí)支持S3C2410和S3C2440, www.100ask.net */

81 if ((gpio->GSTATUS1 == 0x32410000) || (gpio->GSTATUS1 == 0x32410002))

82 {

83 /* FCLK:HCLK:PCLK = 1:2:4 */

84 clk_power->CLKDIVN = S3C2410_CLKDIV;

85

86 /* 修改為異步總線模式 */

87 __asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */

88 "orr r1, r1, #0xc0000000\n" /* Asynchronous */

89 "mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */

90 :::"r1"

91 );

92

93 /* 設(shè)置PLL鎖定時(shí)間 */

94 clk_power->LOCKTIME = 0xFFFFFF;

95

96 /* 配置MPLL */

97 clk_power->MPLLCON = S3C2410_MPLL_200MHZ;

98

99 /* 配置MPLL后,要延時(shí)一段時(shí)間再配置UPLL */

100 delay (4000);

101

102 /* 配置UPLL */

103 clk_power->UPLLCON = S3C2410_UPLL_48MHZ;

104

105 /* 再延時(shí)一會(huì) */

106 delay (8000);

107

108 /* 機(jī)器類型ID,這在調(diào)用Linux內(nèi)核時(shí)用到 */

109 gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;

110 }

111 else

112 {

113 /* FCLK:HCLK:PCLK = 1:4:8 */

114 clk_power->CLKDIVN = S3C2440_CLKDIV;

115

116 /* 修改為異步總線模式 */

117 __asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */

118 "orr r1, r1, #0xc0000000\n" /* Asynchronous */

119 "mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */

120 :::"r1"

121 );

122

123 /* 設(shè)置PLL鎖定時(shí)間 */

124 clk_power->LOCKTIME = 0xFFFFFF;

125

126 /* 配置MPLL */

127 clk_power->MPLLCON = S3C2440_MPLL_400MHZ;

128

129 /* 配置MPLL后,要延時(shí)一段時(shí)間再配置UPLL */

130 delay (4000);

131

132 /* 配置UPLL */

133 clk_power->UPLLCON = S3C2440_UPLL_48MHZ;

134

135 /* 再延時(shí)一會(huì) */

136 delay (8000);

137

138 /* 機(jī)器類型ID,這在調(diào)用Linux內(nèi)核時(shí)用到,這個(gè)值要與內(nèi)核相對應(yīng) */

139 gd->bd->bi_arch_number = MACH_TYPE_S3C2440;

140 }

141

142 /* 啟動(dòng)內(nèi)核時(shí),參數(shù)存放位置。這個(gè)值在構(gòu)造標(biāo)記列表時(shí)用到 */

143 gd->bd->bi_boot_params = 0x30000100;

144

145 icache_enable();

146 dcache_enable();

147

148 return 0;

149 }

150

最后一步:獲取系統(tǒng)時(shí)鐘的函數(shù)需要針對S3C2410、S3C2440的不同進(jìn)行修改。

在后面設(shè)置串口波特率時(shí)需要獲得系統(tǒng)時(shí)鐘,就是在U-Boot的第二階?
段,lib_arm/board.c中start_armboot函數(shù)調(diào)用serial_init函數(shù)初始化串口時(shí),會(huì)調(diào)用get_PCLK函數(shù)。它在?
cpu/arm920t/s3c24x0/speed.c中定義,與它相關(guān)的還有g(shù)et_HCLK、get_PLLCLK等函數(shù)。

前面的board_init函數(shù)在識別出S3C2410或S3C2440后,設(shè)置了機(jī)器類型?
ID:gd->bd->bi_arch_number,后面的函數(shù)可以通過它來分辨是S3C2410還是S3C2440。首先要在程序的開頭?
增加如下一行,這樣才可以使用gd變量:

DECLARE_GLOBAL_DATA_PTR;

S3C2410和S3C2440的MPLL、UPLL計(jì)算公式不一樣,所以get_PLLCLK函數(shù)也需要修改:

56 static ulong get_PLLCLK(int pllreg)

57 {

58 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

59 ulong r, m, p, s;

60

61 if (pllreg == MPLL)

62 r = clk_power->MPLLCON;

63 else if (pllreg == UPLL)

64 r = clk_power->UPLLCON;

65 else

66 hang();

67

68 m = ((r & 0xFF000) >> 12) + 8;

69 p = ((r & 0x003F0) >> 4) + 2;

70 s = r & 0x3;

71

72 /* 同時(shí)支持S3C2410和S3C2440, by www.100ask.net */

73 if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)

74 return((CONFIG_SYS_CLK_FREQ * m) / (p << s));

75 else

76 return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s)); /* S3C2440 */

77 }

78

由于分頻系數(shù)的設(shè)置方法也不一樣,get_HCLK、get_PCLK也需要修改。對于S3C2410,沿用原來的計(jì)算方法,else分支中是S3C2440的代碼:

85 /* for s3c2440 */

86 #define S3C2440_CLKDIVN_PDIVN (1<<0)

87 #define S3C2440_CLKDIVN_HDIVN_MASK (3<<1)

88 #define S3C2440_CLKDIVN_HDIVN_1 (0<<1)

89 #define S3C2440_CLKDIVN_HDIVN_2 (1<<1)

90 #define S3C2440_CLKDIVN_HDIVN_4_8 (2<<1)

91 #define S3C2440_CLKDIVN_HDIVN_3_6 (3<<1)

92 #define S3C2440_CLKDIVN_UCLK (1<<3)

93

94 #define S3C2440_CAMDIVN_CAMCLK_MASK (0xf<<0)

95 #define S3C2440_CAMDIVN_CAMCLK_SEL (1<<4)

96 #define S3C2440_CAMDIVN_HCLK3_HALF (1<<8)

97 #define S3C2440_CAMDIVN_HCLK4_HALF (1<<9)

98 #define S3C2440_CAMDIVN_DVSEN (1<<12)

99

100 /* return HCLK frequency */

101 ulong get_HCLK(void)

102 {

103 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

104 unsigned long clkdiv;

105 unsigned long camdiv;

106 int hdiv = 1;

107

108 /* 同時(shí)支持S3C2410和S3C2440, by www.100ask.net */

109 if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)

110 return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());

111 else

112 {

113 clkdiv = clk_power->CLKDIVN;

114 camdiv = clk_power->CAMDIVN;

115

116 /* 計(jì)算分頻比 */

117

118 switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {

119 case S3C2440_CLKDIVN_HDIVN_1:

120 hdiv = 1;

121 break;

122

123 case S3C2440_CLKDIVN_HDIVN_2:

124 hdiv = 2;

125 break;

126

127 case S3C2440_CLKDIVN_HDIVN_4_8:

128 hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;

129 break;

130

131 case S3C2440_CLKDIVN_HDIVN_3_6:

132 hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;

133 break;

134 }

135

136 return get_FCLK() / hdiv;

137 }

138 }

139

140 /* return PCLK frequency */

141 ulong get_PCLK(void)

142 {

143 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

144 unsigned long clkdiv;

145 unsigned long camdiv;

146 int hdiv = 1;

147

148 /* 同時(shí)支持S3C2410和S3C2440, by www.100ask.net */

149 if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)

150 return((clk_power->CLKDIVN & 0x1) ? get_HCLK()/2 : get_HCLK());

151 else

152 {

153 clkdiv = clk_power->CLKDIVN;

154 camdiv = clk_power->CAMDIVN;

155

156 /* 計(jì)算分頻比 */

157

158 switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {

159 case S3C2440_CLKDIVN_HDIVN_1:

160 hdiv = 1;

161 break;

162

163 case S3C2440_CLKDIVN_HDIVN_2:

164 hdiv = 2;

165 break;

166

167 case S3C2440_CLKDIVN_HDIVN_4_8:

168 hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;

169 break;

170

171 case S3C2440_CLKDIVN_HDIVN_3_6:

172 hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;

173 break;

174 }

175

176 return get_FCLK() / hdiv / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);

177 }

178 }

179

現(xiàn)在重新執(zhí)行“make 100ask24x0_config”和“make?
all”生成的u-boot.bin文件既可以運(yùn)行于S3C2410開發(fā)板,也可以運(yùn)行于S3C2440開發(fā)板。將它燒入NOR?
Flash后啟動(dòng),就可以在串口工具(設(shè)置為115200,8N1)中看到提示信息,可以輸入各種命令操作U-Boot了。

(4)選擇NOR Flash的型號。

但是,現(xiàn)在還無法通過U-Boot命令燒寫NOR Flash。本書所用開發(fā)板中的NOR Flash型號為AM29LV800,而配置文件include/configs/100ask24x0.h中的默認(rèn)型號為AM29LV400。修改如下:

#define CONFIG_AMD_LV4001/* uncomment this if you have a LV400 flash */

#if 0

#define CONFIG_AMD_LV8001/* uncomment this if you have a LV800 flash */

#endif

改為:

#if 0

#define CONFIG_AMD_LV4001/* uncomment this if you have a LV400 flash */

#endif

#define CONFIG_AMD_LV8001/* uncomment this if you have a LV800 flash */

本例中NOR?
Flash的操作函數(shù)在board/100ask24x0/flash.c中實(shí)現(xiàn),它支持AM29LV400y和AM29LV800。對于其他型號的?
NOR?
Flash,如果符合CFI接口標(biāo)準(zhǔn),則可以在使用drivers/cfi_flash.c中的接口函數(shù);否則,只好自己編寫了。如果要使用?
cfi_flash.c,如下修改兩個(gè)文件:

在include/configs/100ask24x0.h中增加以下一行:

#define CFG_FLASH_CFI_DRIVER 1

在board/100ask24x0/Makefile中去掉flash.o:

COBJS:= 100ask24x0.o flash.o

改為:

COBJS:= 100ask24x0.o

修改好對NOR Flash的支持后,重新編譯U-Boot:make clean、make all。運(yùn)行后可以在串口中看到如下字樣:

Flash: 1 MB

現(xiàn)在可以使用loadb、loady等命令通過串口下載文件,然后使用erase、cp命令分別擦除、燒寫NOR Flash了,它們的效率比JTAG快上好幾倍。

2. 支持串口xmodem協(xié)議

上面的loadb命令需要配合Linux下的kermit工具來使用,loady命令通過串?
口ymodem協(xié)議來傳輸文件。Windows下的超級終端雖然支持ymodem,但是它的使用界面實(shí)在不友好。而本書推薦使用的Windows工具?
SecureCRT只支持xmodem和zmodem。為了方便在Windows下開發(fā),現(xiàn)在修改代碼增加對xmodem的支持,即增加一個(gè)命令?
loadx。

依照loady的實(shí)現(xiàn)來編寫代碼,首先使用U_BOOT_CMD宏來增加loadx命令:

/* 支持xmodem, www.100ask.net */

U_BOOT_CMD(

loadx, 3, 0,do_load_serial_bin,

"loadx - load binary file over serial line (xmodem mode)\n",

"[ off ] [ baud ]\n"

" - load binary file over serial line"

" with offset 'off' and baudrate 'baud'\n"

);

其次,在do_load_serial_bin函數(shù)中增加對loadx命令的處理分支。也是依照loady來實(shí)現(xiàn):

481 /* 支持xmodem, www.100ask.net */

482 if (strcmp(argv[0],"loadx")==0) {

483 printf ("## Ready for binary (xmodem) download "

484 "to 0x%08lX at %d bps...\n",

485 offset,

486 load_baudrate);

487

488 addr = load_serial_xmodem (offset);

489

490 } else if (strcmp(argv[0],"loady")==0) {

491 printf ("## Ready for binary (ymodem) download "

492 "to 0x%08lX at %d bps...\n",

……

第481~490行就是為loadx命令增加的代碼。

在第288行調(diào)用load_serial_xmodem函數(shù),它是依照load_serial_ymodem實(shí)現(xiàn)的一個(gè)新函數(shù):

36 #if (CONFIG_COMMANDS & CFG_CMD_LOADB)

37 /* 支持xmodem, www.100ask.net */

38 static ulong load_serial_xmodem (ulong offset);

39 static ulong load_serial_ymodem (ulong offset);

40 #endif

……

995 /* 支持xmodem, www.100ask.net */

996 static ulong load_serial_xmodem (ulong offset)

997 {

……

1003 char xmodemBuf[1024];/* 原來是ymodemBuf,這只是為了與函數(shù)名稱一致 */

……

1008 info.mode = xyzModem_xmodem;/* 原來是xyzModem_ymodem,對應(yīng)ymodem */

……

首先在文件開頭增加load_serial_xmodem函數(shù)的聲明,然后復(fù)制load_serial_ymodem函數(shù)為load_serial_xmodem,稍作修改:

① 將局部數(shù)組ymodemBuf改名為xmodemBuf,并在后面使用到的地方統(tǒng)一修改。這只是為了與函數(shù)名稱一致。

② info.mode的值從xyzModem_ymodem改為xyzModem_xmodem。

重新編譯、燒寫u-boot.bin后,就可以使用loadx命令下載文件了。

3. 支持網(wǎng)卡芯片CS8900

使用串口來傳輸文件的速率太低,現(xiàn)在增加對網(wǎng)卡芯片CS8900的支持。

本書使用開發(fā)板的網(wǎng)卡芯片CS8900的連接方式與smdk2410完全一樣,所以現(xiàn)在的?
U-Boot中已經(jīng)支持CS8900了,它的驅(qū)動(dòng)程序?yàn)閐rivers/cs8900.c。只要在U-Boot控制界面中稍加配置就可以使用網(wǎng)絡(luò)功能。使?
用網(wǎng)絡(luò)之前,先設(shè)置開發(fā)板IP地址、MAC地址,服務(wù)器IP地址,比如可以在U-Boot中執(zhí)行以下命令:

setenv ipaddr 192.168.1.17

setenv ethaddr 08:00:3e:26:0a:5b

setenv serverip 192.168.1.11

saveenv

然后就可以使用tftp或nfs命令下載文件了,注意:服務(wù)器上要開啟tftp或nfs服務(wù)。比如可以使用如下命令將u-boot.bin文件下載到內(nèi)存0x30000000中:

tftp 0x30000000 u-boot.bin

nfs 0x30000000 192.168.1.57:/work/nfs_root/u-boot.bin

可以修改配置文件,讓網(wǎng)卡的各個(gè)默認(rèn)值就是上面設(shè)置的值。在此之前,先了解網(wǎng)卡的相關(guān)文件,這有助于移植代碼以支持其他連接方式的CS8900。

首先,CS8900接在S3C2410、S3C2440的BANK3,位寬為16,使用WAIT、nBE信號。在設(shè)置存儲控制器時(shí)要設(shè)置好BANK3。代碼在board/100ask24x0/lowlevel_init.S中:

#define B3_BWSCON (DW16 + WAIT + UBLB)

……

/* 時(shí)序參數(shù) */

#define B3_Tacs 0x0/* 0clk */

#define B3_Tcos 0x3/* 4clk */

#define B3_Tacc 0x7/* 14clk */

#define B3_Tcoh 0x1/* 1clk */

#define B3_Tah 0x0/* 0clk */

#define B3_Tacp 0x3 /* 6clk */

#define B3_PMC 0x0/* normal */

接下來,還要確定CS8900的基地址。這在配置文件include/configs/100ask24x0.h中定義:

#define CONFIG_DRIVER_CS89001/* 使用CS8900 */

#define CS8900_BASE0x19000300/* 基地址 */

#define CS8900_BUS161 /* 位寬為16 */

從第6章可以知道網(wǎng)卡CS8900的訪問基址為0x19000000,之所以再偏移0x300是由它的特性決定的。

最后,還是在配置文件include/configs/100ask24x0.h中定義CS8900的各個(gè)默認(rèn)地址:

#define CONFIG_ETHADDR08:00:3e:26:0a:5b

#define CONFIG_NETMASK 255.255.255.0

#define CONFIG_IPADDR192.168.1.17

#define CONFIG_SERVERIP192.168.1.11

額外的,如果要增加ping命令,還可以在配置文件include/configs/100ask24x0.h的宏CONFIG_COMMANDS中增加CFG_CMD_PING,如下:

#define CONFIG_COMMANDS \

(CONFIG_CMD_DFL | \

CFG_CMD_CACHE | \

CFG_CMD_PING | \

……

4. 支持NAND Flash

U-Boot 1.1.6中對NAND?
Flash的支持有新舊兩套代碼,新代碼在drivers/nand目錄下,舊代碼在drivers/nand_legacy目錄下。文檔doc?
/README.nand對這兩套代碼有所說明:使用舊代碼需要定義更多的宏,而新代碼移植自Linux內(nèi)核2.6.12,它更加智能,可以自動(dòng)識別更多?
型號的NAND?
Flash。目前之所以還保留舊的代碼,是因?yàn)閮蓚€(gè)目標(biāo)板NETTA、NETTA_ISDN使用JFFS文件系統(tǒng),它們還依賴于舊代碼。當(dāng)相關(guān)功能移植到?
新代碼之后,舊的代碼將從U-Boot中去除。

要讓U-Boot支持NAND Flash,首先在配置文件include/configs/100ask24x0.h的宏CONFIG_COMMANDS中增加CFG_CMD_NAND,如下:

#define CONFIG_COMMANDS \

(CONFIG_CMD_DFL | \

CFG_CMD_CACHE | \

CFG_CMD_PING | \

CFG_CMD_NAND| \

……

然后選擇使用哪套代碼:在配置文件中定義宏CFG_NAND_LEGACY則使用舊代碼,否則使用新代碼。

使用舊代碼時(shí),需要實(shí)現(xiàn)drivers/nand_legacy/nand_legacy.c中使用到的各種宏,比如:

#define NAND_WAIT_READY(nand)/* 等待Nand Flash的狀態(tài)為“就緒”,代碼依賴于具體的開發(fā)板 */

#define WRITE_NAND_COMMAND(d, adr)/* 寫NAND Flash命令,代碼依賴于具體的開發(fā)板 */

本書使用新代碼,下面講述移植過程。

代碼的移植沒有現(xiàn)成的文檔,可以在配置文件include/configs/100ask24x0.h的宏CONFIG_COMMANDS中增加CFG_CMD_NAND后,就編譯代碼,然后一個(gè)一個(gè)地解決出現(xiàn)的錯(cuò)誤。編譯結(jié)果中出現(xiàn)的錯(cuò)誤和警告如下:

nand.h:412: error: `NAND_MAX_CHIPS' undeclared here (not in a function)

nand.c:35: error: `CFG_MAX_NAND_DEVICE' undeclared here (not in a function)

nand.c:38: error: `CFG_NAND_BASE' undeclared here (not in a function)

nand.c:35: error: storage size of `nand_info' isn't known

nand.c:37: error: storage size of `nand_chip' isn't known

nand.c:38: error: storage size of `base_address' isn't known

nand.c:37: warning: 'nand_chip' defined but not used

nand.c:38: warning: 'base_address' defined but not used

在配置文件include/configs/100ask24x0.h中增加如下3個(gè)宏就可?
以解決上述錯(cuò)誤。在Flash的驅(qū)動(dòng)程序中,設(shè)備是邏輯上的概念,表示一組相同結(jié)構(gòu)、訪問函數(shù)相同的Flash芯片。在本書所用開發(fā)板中,只有一個(gè)?
NAND Flash芯片,所以設(shè)備數(shù)為1,芯片數(shù)也為1。

#define CFG_NAND_BASE 0/* 無實(shí)際意義:基地址,這在board_nand_init中重新指定 */

#define CFG_MAX_NAND_DEVICE 1/* NAND Flash“設(shè)備”的數(shù)目為1 */

#define NAND_MAX_CHIPS 1/* 每個(gè)NAND Flash“設(shè)備”由1個(gè)NAND Flash“芯片”組成 */

修改配置文件后再次編譯,現(xiàn)在只有一個(gè)錯(cuò)誤了,“board_nand_init函數(shù)未定義”:

nand.c:50: undefined reference to `board_nand_init'

調(diào)用board_nand_init函數(shù)的過程為:NAND?
Flash的初始化入口函數(shù)是nand_init,它在lib_arm/board.c的start_armboot函數(shù)中被調(diào)用;nand_init函?
數(shù)在drivers/nand/nand.c中實(shí)現(xiàn),它調(diào)用相同文件中的nand_init_chip函數(shù);nand_init_chip函數(shù)首先調(diào)用?
board_nand_init函數(shù)來初始化NAND Flash設(shè)備,最后才是統(tǒng)一的識別過程。

從board_nand_init函數(shù)的名稱就可以知道它是平臺/開發(fā)板相關(guān)的函數(shù),需要自?
己編寫。本書在cpu/arm920t/s3c24x0目錄下新建一個(gè)文件nand_flash.c,在里面針對S3C2410、S3C2440實(shí)現(xiàn)了統(tǒng)?
一的board_nand_init函數(shù)。

在編寫board_nand_init函數(shù)的之前,需要針對S3C2410、S3C2440 NAND Flash控制器的不同定義一些數(shù)據(jù)結(jié)構(gòu)和函數(shù):

(1)在include/s3c24x0.h文件中增加S3C2440_NAND數(shù)據(jù)結(jié)構(gòu)。

/* NAND FLASH (see S3C2440 manual chapter 6, www.100ask.net) */

typedef struct {

S3C24X0_REG32 NFCONF;

S3C24X0_REG32 NFCONT;

S3C24X0_REG32 NFCMD;

S3C24X0_REG32 NFADDR;

S3C24X0_REG32 NFDATA;

S3C24X0_REG32 NFMECCD0;

S3C24X0_REG32 NFMECCD1;

S3C24X0_REG32 NFSECCD;

S3C24X0_REG32 NFSTAT;

S3C24X0_REG32 NFESTAT0;

S3C24X0_REG32 NFESTAT1;

S3C24X0_REG32 NFMECC0;

S3C24X0_REG32 NFMECC1;

S3C24X0_REG32 NFSECC;

S3C24X0_REG32 NFSBLK;

S3C24X0_REG32 NFEBLK;

} /*__attribute__((__packed__))*/ S3C2440_NAND;

(2)在include/s3c2410.h文件中仿照S3C2410_GetBase_NAND函數(shù)定義S3C2440_GetBase_NAND函數(shù)。

/* for s3c2440, www.100ask.net */

static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)

{

return (S3C2440_NAND * const)S3C2410_NAND_BASE;

}

既然新的NAND?
Flash代碼是從Linux內(nèi)核2.6.12中移植來的,那么cpu/arm920t/s3c24x0/nand_flash.c文件也可以仿照內(nèi)核?
中,對S3C2410、S3C2440的NAND?
Flash進(jìn)行初始化的drivers/mtd/nand/s3c2410.c文件來編寫。為了方便閱讀,先把cpu/arm920t/s3c24x0?
/nand_flash.c文件的代碼全部列出來,再講解:

01 /*

02 * s3c2410/s3c2440的NAND Flash控制器接口, www.100ask.net

03 * 修改自Linux內(nèi)核2.6.13文件drivers/mtd/nand/s3c2410.c

04 */

05

06 #include <common.h>

07

08 #if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)

09 #include <s3c2410.h>

10 #include <nand.h>

11

12 DECLARE_GLOBAL_DATA_PTR;

13

14 #define S3C2410_NFSTAT_READY (1<<0)

15 #define S3C2410_NFCONF_nFCE (1<<11)

16

17 #define S3C2440_NFSTAT_READY (1<<0)

18 #define S3C2440_NFCONT_nFCE (1<<1)

19

20

21 /* S3C2410:NAND Flash的片選函數(shù) */

22 static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)

23 {

24 S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

25

26 if (chip == -1) {

27 s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;/* 禁止片選信號 */

28 } else {

29 s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;/* 使能片選信號 */

30 }

31 }

32

33 /* S3C2410:命令和控制函數(shù)

34 *

35 * 注意,這個(gè)函數(shù)僅僅根據(jù)各種命令來修改“寫地址”IO_ADDR_W 的值(這稱為tglx方法),

36 * 這種方法使得平臺/開發(fā)板相關(guān)的代碼很簡單。

37 * 真正發(fā)出命令是在上一層NAND Flash的統(tǒng)一的驅(qū)動(dòng)中實(shí)現(xiàn),

38 * 它首先調(diào)用這個(gè)函數(shù)修改“寫地址”,然后才分別發(fā)出控制、地址、數(shù)據(jù)序列。

39 */

40 static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)

41 {

42 S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

43 struct nand_chip *chip = mtd->priv;

44

45 switch (cmd) {

46 case NAND_CTL_SETNCE:

47 case NAND_CTL_CLRNCE:

48 printf("%s: called for NCE\n", __FUNCTION__);

49 break;

50

51 case NAND_CTL_SETCLE:

52 chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;

53 break;

54

55 case NAND_CTL_SETALE:

56 chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;

57 break;

58

59 /* NAND_CTL_CLRCLE: */

60 /* NAND_CTL_CLRALE: */

61 default:

62 chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;

63 break;

64 }

65 }

66

67 /* S3C2410:查詢NAND Flash狀態(tài)

68 *

69 * 返回值:0 – 忙, 1 – 就緒

70 */

71 static int s3c2410_nand_devready(struct mtd_info *mtd)

72 {

73 S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

74

75 return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);

76 }

77

78

79 /* S3C2440:NAND Flash的片選函數(shù) */

80 static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip)

81 {

82 S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

83

84 if (chip == -1) {

85 s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;/* 禁止片選信號 */

86 } else {

87 s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;/* 使能片選信號 */

88 }

89 }

90

91 /* S3C2440:命令和控制函數(shù),與s3c2410_nand_hwcontrol函數(shù)類似 */

92 static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)

93 {

94 S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

95 struct nand_chip *chip = mtd->priv;

96

97 switch (cmd) {

98 case NAND_CTL_SETNCE:

99 case NAND_CTL_CLRNCE:

100 printf("%s: called for NCE\n", __FUNCTION__);

101 break;

102

103 case NAND_CTL_SETCLE:

104 chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;

105 break;

106

107 case NAND_CTL_SETALE:

108 chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;

109 break;

110

111 /* NAND_CTL_CLRCLE: */

112 /* NAND_CTL_CLRALE: */

113 default:

114 chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;

115 break;

116 }

117 }

118

119 /* S3C2440:查詢NAND Flash狀態(tài)

120 *

121 * 返回值:0 – 忙, 1 – 就緒

122 */

123 static int s3c2440_nand_devready(struct mtd_info *mtd)

124 {

125 S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

126

127 return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);

128 }

129

130 /*

131 * Nand flash硬件初始化:

132 * 設(shè)置NAND Flash的時(shí)序, 使能NAND Flash控制器

133 */

134 static void s3c24x0_nand_inithw(void)

135 {

136 S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

137 S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

138

139 #define TACLS 0

140 #define TWRPH0 4

141 #define TWRPH1 2

142

143 if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)

144 {

145 /* 使能NAND Flash控制器,初始化ECC,使能片選信號,設(shè)置時(shí)序 */

146 s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

147 }

148 else

149 {

150 /* 設(shè)置時(shí)序 */

151 s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);

152 /* 初始化ECC,使能NAND Flash控制器,使能片選信號 */

153 s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);

154 }

155 }

156

157 /*

158 * 被drivers/nand/nand.c調(diào)用, 初始化NAND Flash硬件,初始化訪問接口函數(shù)

159 */

160 void board_nand_init(struct nand_chip *chip)

161 {

162 S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

163 S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

164

165 s3c24x0_nand_inithw();/* Nand flash硬件初始化 */

166

167 if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410) {

168 chip->IO_ADDR_R = (void *)&s3c2410nand->NFDATA;

169 chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;

170 chip->hwcontrol = s3c2410_nand_hwcontrol;

171 chip->dev_ready = s3c2410_nand_devready;

172 chip->select_chip = s3c2410_nand_select_chip;

173 chip->options = 0;/* 設(shè)置位寬等,位寬為8 */

174 } else {

175 chip->IO_ADDR_R = (void *)&s3c2440nand->NFDATA;

176 chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;

177 chip->hwcontrol = s3c2440_nand_hwcontrol;

178 chip->dev_ready = s3c2440_nand_devready;

179 chip->select_chip = s3c2440_nand_select_chip;

180 chip->options = 0;/* 設(shè)置位寬等,位寬為8 */

181 }

182

183 chip->eccmode = NAND_ECC_SOFT;/* ECC較驗(yàn)方式:軟件ECC */

184 }

185

186 #endif

文件中分別針對S3C2410、S3C2440實(shí)現(xiàn)了NAND?
Flash最底層訪問函數(shù),并進(jìn)行了一些硬件的設(shè)置(比如時(shí)序、使能NAND Flash控制器等)。新的代碼對NAND?
Flash的封裝做得很好,只要向上提供底層初始化函數(shù)board_nand_init來設(shè)置好平臺/開發(fā)板相關(guān)的初始化、提供底層接口即可。

最后,只要將新建的nand_flash.c文件編入U(xiǎn)-Boot中就可以擦除、讀寫NAND Flash了。如下修改cpu/arm920t/s3c24x0/Makefile文件即可:

COBJS = i2c.o interrupts.o serial.o speed.o \

usb_ohci.o

改為:

COBJS = i2c.o interrupts.o serial.o speed.o \

usb_ohci.o nand_flash.o

現(xiàn)在,可以使用新編譯的u-boot.bin燒寫內(nèi)核映像到NAND Flash去了,請參考15.2.6。

5. 支持燒寫yaffs文件系統(tǒng)映像

在實(shí)際生產(chǎn)中,可以通過燒片器等手段將內(nèi)核、文件系統(tǒng)映像燒入固態(tài)存儲設(shè)備中,Bootloader不需要具備燒寫功能。但為了方便開發(fā),通常在Bootloader中增加燒寫內(nèi)核、文件系統(tǒng)映像文件的功能。

增加了NAND Flash功能的U-Boot 1.1.6已經(jīng)可以通過“nand?
write ……”、“nand write.jffs2 ……”等命令來燒寫內(nèi)核,cramfs、jffs2文件系統(tǒng)映像文件。但是在NAND?
Flash上,yaffs文件系統(tǒng)的性能更佳,下面增加“nand write.yaffs ……”命令以燒寫yaffs文件系統(tǒng)映像文件。

“nand write.yaffs ……”字樣的命令中,“nand”是具體命令,“write.yaffs ……”是參數(shù)。nand命令在common/cmd_nand.c中實(shí)現(xiàn):

U_BOOT_CMD(nand, 5, 1, do_nand,

"nand - NAND sub-system\n",

"info - show available NAND devices\n"

"nand device [dev] - show or set current device\n"

"nand read[.jffs2] - addr off|partition size\n"

"nand write[.jffs2] - addr off|partiton size - read/write `size' bytes starting\n"

" at offset `off' to/from memory address `addr'\n"

……

先在其中增加“nand write.yaffs ……”的使用說明:

U_BOOT_CMD(nand, 5, 1, do_nand,

"nand - NAND sub-system\n",

"info - show available NAND devices\n"

"nand device [dev] - show or set current device\n"

"nand read[.jffs2] - addr off|partition size\n"

"nand write[.jffs2] - addr off|partiton size - read/write `size' bytes starting\n"

" at offset `off' to/from memory address `addr'\n"

"nand read.yaffs addr off size - read the `size' byte yaffs image starting\n"

" at offset `off' to memory address `addr'\n"

"nand write.yaffs addr off size - write the `size' byte yaffs image starting\n"

" at offset `off' from memory address `addr'\n"

……

然后,在nand命令的處理函數(shù)do_nand中增加對“write.yaffs ……”的支持。do_nand函數(shù)仍在common/cmd_nand.c中實(shí)現(xiàn),代碼修改如下:

331 (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) {

……

354 }else if ( s != NULL && !strcmp(s, ".yaffs")){

355 if (read) {

356 /* read */

357 nand_read_options_t opts;

358 memset(&opts, 0, sizeof(opts));

359 opts.buffer = (u_char*) addr;

360 opts.length = size;

361 opts.offset = off;

362 opts.readoob = 1;

363 opts.quiet = quiet;

364 ret = nand_read_opts(nand, &opts);

365 } else {

366 /* write */

367 nand_write_options_t opts;

368 memset(&opts, 0, sizeof(opts));

369 opts.buffer = (u_char*) addr;/* yaffs文件系統(tǒng)映像存放的地址 */

370 opts.length = size;/* 長度 */

371 opts.offset = off;/* 要燒寫到的NAND Flash的偏移地址 */

372 /* opts.forceyaffs = 1; *//* 計(jì)算ECC碼的方法,沒有使用 */

373 opts.noecc = 1; /* 不需要計(jì)算ECC,yaffs映像中有OOB數(shù)據(jù) */

374 opts.writeoob = 1;/* 寫OOB區(qū) */

375 opts.blockalign = 1;/* 每個(gè)“邏輯上的塊”大小為1個(gè)“物理塊” */

376 opts.quiet = quiet;/* 是否打印提示信息 */

377 opts.skipfirstblk = 1;/* 跳過第一個(gè)可用塊 */

378 ret = nand_write_opts(nand, &opts);

379 }

380 } else {

……

385 }

386

第354~379行就是針對命令“nand read.yaffs ……”、“nand?
write.yaffs ……”增加的代碼。有興趣的讀者可以自己分析“if (read)”分支的代碼,下面只講解“else”分支,即“nand?
write.yaffs ……”命令的實(shí)現(xiàn)。

NAND Flash每一頁大小為(512+16)字節(jié)(還有其他格式的NAND?
Flash,比如每頁大小為(256+8)、(2048+64)等),其中的512字節(jié)就是一般存儲數(shù)據(jù)的區(qū)域,16字節(jié)稱為OOB(Out Of?
Band)區(qū)。通常在OOB區(qū)存放壞塊標(biāo)記、前面512字節(jié)的ECC較驗(yàn)碼等。

cramfs、jffs2文件系統(tǒng)映像文件中并沒有OOB區(qū)的內(nèi)容,如果將它們燒入NOR?
Flash中,則是簡單的“平鋪”關(guān)系;如果將它們燒入NAND Flash中,則NAND?
Flash的驅(qū)動(dòng)程序首先根據(jù)OOB的標(biāo)記略過壞塊,然后將一頁數(shù)據(jù)(512字節(jié))寫入后,還會(huì)計(jì)算這512字節(jié)的ECC較驗(yàn)碼,最后將它寫入OOB區(qū),?
如此循環(huán)。cramfs、jffs2文件系統(tǒng)映像文件的大小通常是512的整數(shù)倍。

而yaffs文件系統(tǒng)映像文件的格式則跟它們不同,文件本身就包含了OOB區(qū)的數(shù)據(jù)(里面有?
壞塊標(biāo)記、ECC較驗(yàn)碼、其他yaffs相關(guān)的信息)。所以燒寫時(shí),不需要再計(jì)算ECC值,首先檢查是否壞塊(是則跳過),然后寫入512字節(jié)的數(shù)據(jù),最?
后寫入16字節(jié)的OOB數(shù)據(jù),如此循環(huán)。yaffs文件系統(tǒng)映像文件的大小是(512+16)的整數(shù)倍。

注意:燒寫yaffs文件系統(tǒng)映像時(shí),分區(qū)上第一個(gè)可用的(不是壞塊)塊也要跳過。

下面分析上面的代碼。

第369~371行設(shè)置源地址、目的地址、長度。燒寫yaffs文件系統(tǒng)映像前,一般通過網(wǎng)?
絡(luò)將它下載到內(nèi)存某個(gè)地址處(比如0x30000000),然后通過類似“nand write.yaffs 0x30000000?
0x00A00000 $(filesize)”的命令燒到NAND?
Flash的偏移地址0x00A00000處。對于這個(gè)命令,第369行中opts.buffer等于0x30000000,第370行中?
opts.length等于$(filesize)的值,就是前面下載的文件的大小,第371行中的opts.offset等于0x00A00000。

這里列出不使用的第372行,是因?yàn)閛pts.forceyaffs這個(gè)名字很有欺騙性,它其實(shí)是指計(jì)算ECC較驗(yàn)碼的一種方法。燒寫yaffs文件系統(tǒng)映像時(shí),不需要計(jì)算ECC較驗(yàn)碼。

第373、374行指定燒寫數(shù)據(jù)時(shí)不計(jì)算ECC較驗(yàn)碼、而是燒入文件中的OOB數(shù)據(jù)。

第375行指定“邏輯塊”的大小,“邏輯塊”可以由多個(gè)“物理塊”組成,在yaffs文件系統(tǒng)映像中,它們是1:1的關(guān)系。

第377行的opts.skipfirstblk是新加的項(xiàng),nand_write_options_t結(jié)構(gòu)中沒有skipfirstblk成員。它表示燒寫時(shí)跳過第一個(gè)可用的邏輯塊──這是由yaffs文件系統(tǒng)的特性決定的。

既然skipfirstblk是在nand_write_options_t結(jié)構(gòu)中新加的項(xiàng),那么就要重新定義nand_write_options_t結(jié)構(gòu),并在下面調(diào)用的nand_write_opts函數(shù)中對它進(jìn)行處理。

首先在include/nand.h中如下修改,增加skipfirstblk成員:

struct nand_write_options {

u_char *buffer;/* memory block containing image to write */

ulong length;/* number of bytes to write */

ulong offset;/* start address in NAND */

int quiet;/* don't display progress messages */

int autoplace;/* if true use auto oob layout */

int forcejffs2;/* force jffs2 oob layout */

int forceyaffs;/* force yaffs oob layout */

int noecc;/* write without ecc */

int writeoob;/* image contains oob data */

int pad;/* pad to page size */

int blockalign;/* 1|2|4 set multiple of eraseblocks to align to */

int skipfirstblk; /* 新加,燒寫時(shí)跳過第一個(gè)可用的邏輯塊 */

};

typedef struct nand_write_options nand_write_options_t;

然后,修改nand_write_opts函數(shù)增加對skipfirstblk成員的支持。它在drivers/nand/nand_util.c文件中,下面的第301、第430~435行是新加的:

285 int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)

286 {

……

300 int result;

301 int skipfirstblk = opts->skipfirstblk;

……

430 /* skip the first good block when wirte yaffs image, by www.100ask.net */

431 if (skipfirstblk) {

432 mtdoffset += erasesize_blockalign;

433 skipfirstblk = 0;

434 continue;

435 }

……

進(jìn)行了上面的移植后,U-Boot已經(jīng)可以燒yaffs文件系統(tǒng)映像了。由于前面設(shè)置“opts.noecc = 1”不使用ECC較驗(yàn)碼,在燒寫過程中會(huì)出現(xiàn)很多的提示信息:

Writing data without ECC to NAND-FLASH is not recommended

可以修改drivers/nand/nand_base.c文件的nand_write_page函數(shù)將它去掉:

917 case NAND_ECC_NONE:

918 printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");

改為:

917 case NAND_ECC_NONE:

918 //printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");

6. 修改默認(rèn)配置參數(shù)以方便使用

前面移植網(wǎng)卡芯片CS8900時(shí),已經(jīng)設(shè)置過默認(rèn)IP地址等。為了使用U-Boot時(shí)減少一些設(shè)置,現(xiàn)在修改配置文件include/configs/100ask24x0.h增加默認(rèn)配置參數(shù),其中一些在移植過程中已經(jīng)增加的選項(xiàng)這里也再次說明。

(1)Linux啟動(dòng)參數(shù)。

增加如下3個(gè)宏:

#define CONFIG_SETUP_MEMORY_TAGS 1/* 向內(nèi)核傳遞內(nèi)存分布信息 */

#define CONFIG_CMDLINE_TAG 1/* 向內(nèi)核傳遞命令行參數(shù) */

/* 默認(rèn)命令行參數(shù) */

#define CONFIG_BOOTARGS "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0"

(2)自動(dòng)啟動(dòng)命令。

增加如下2個(gè)宏:

/* 自動(dòng)啟動(dòng)前延時(shí)3秒 */

#define CONFIG_BOOTDELAY3

/* 自動(dòng)啟動(dòng)的命令 */

#define CONFIG_BOOTCOMMAND “nboot 0x32000000 0 0; bootm 0x32000000”

自動(dòng)啟動(dòng)時(shí)(開機(jī)3秒內(nèi)無輸入),首先執(zhí)行“nboot 0x32000000 0 0”命令將第0個(gè)NAND Flash偏移地址0上的映像文件復(fù)制到內(nèi)存0x32000000中;然后執(zhí)行“bootm 0x32000000”命令啟動(dòng)內(nèi)存中的映像。

(3)默認(rèn)網(wǎng)絡(luò)設(shè)置。

根據(jù)具體網(wǎng)絡(luò)環(huán)境增加、修改下面4個(gè)宏:

#define CONFIG_ETHADDR08:00:3e:26:0a:5b

#define CONFIG_NETMASK 255.255.255.0

#define CONFIG_IPADDR192.168.1.17

#define CONFIG_SERVERIP192.168.1.11

2.6 U-Boot的常用命令

1. U-Boot的常用命令的用法

進(jìn)入U(xiǎn)-Boot控制界面后,可以運(yùn)行各種命令,比如下載文件到內(nèi)存,擦除、讀寫Flash,運(yùn)行內(nèi)存、NOR Flash、NAND Flash中的程序,查看、修改、比較內(nèi)存中的數(shù)據(jù)等。

使用各種命令時(shí),可以使用其開頭的若干個(gè)字母代替它。比如tftpboot命令,可以使用t、tf、tft、tftp等字母代替,只要其他命令不以這些字母開頭即可。

當(dāng)運(yùn)行一個(gè)命令之后,如果它是可重復(fù)執(zhí)行的(代碼中使用U_BOOT_CMD定義這個(gè)命令時(shí),第3個(gè)參數(shù)是1),若想再次運(yùn)行可以直接輸入回車。

U-Boot接受的數(shù)據(jù)都是16進(jìn)制,輸入時(shí)可以省略前綴0x、0X。

下面介紹常用的命令:

(1)幫助命令help。

運(yùn)行help命令可以看到U-Boot中所有命令的作用,如果要查看某個(gè)命令的使用方法,運(yùn)行“help 命令名”,比如“help bootm”。

可以使用“?”來代替“help”,比如直接輸入“?”、“? bootm”。

(2)下載命令。

U-Boot支持串口下載、網(wǎng)絡(luò)下載,相關(guān)命令有:loadb、loads、loadx、loady和tftpboot、nfs。

前幾個(gè)串口下載命令使用方法相似,以loadx命令為例,它的用法為“l(fā)oadx [?
off ] [ baud?
]”。中括號“[]”表示里面的參數(shù)可以省略,off表示文件下載后存放的內(nèi)存地址,baud表示使用的波特率。如果baud參數(shù)省略,則使用當(dāng)前的波特?
率;如果off參數(shù)省略,存放的地址為配置文件中定義的宏CFG_LOAD_ADDR。

tftpboot命令使用TFTP協(xié)議從服務(wù)器下載文件,服務(wù)器的IP地址為環(huán)境變量?
serverip。用法為“tftpboot [loadAddress]?
[bootfilename]”,loadAddress表示文件下載后存放的內(nèi)存地址,bootfilename表示要下載的文件的名稱。如果?
loadAddress省略,存放的地址為配置文件中定義的宏CFG_LOAD_ADDR;如果bootfilename省略,則使用單板的IP地址構(gòu)造?
一個(gè)文件名,比如單板IP為192.168.1.17,則缺省的文件名為C0A80711.img。

nfs命令使用NFS協(xié)議下載文件,用法為“nfs [loadAddress]?
[host ip?
addr:bootfilename]”。loadAddress、bootfilename的意義與tftpboot命令一樣,host ip?
addr表示服務(wù)器的IP地址,默認(rèn)為環(huán)境變量serverip。

下載文件成功后,U-Boot會(huì)自動(dòng)創(chuàng)建或更新環(huán)境變量filesize,它表示下載的文件的長度,可以在后續(xù)命令中使用“$(filesize)”來引用它。

(3)內(nèi)存操作命令。

常用的命令有:查看內(nèi)存命令md、修改內(nèi)存命令md、填充內(nèi)存命令mw、拷貝命令cp。這些?
命令都可以帶上后綴“.b”、“.w”或“.l”,表示以字節(jié)、字(2個(gè)字節(jié))、雙字(4個(gè)字節(jié))為單位進(jìn)行操作。比如“cp.l 30000000?
31000000 2”將從開始地址0x30000000處,拷貝2個(gè)雙字到開始地址為0x31000000的地方。

md命令用法為“md[.b, .w, .l] address [count]”,表示以字節(jié)、字或雙字(默認(rèn)為雙字)為單位,顯示從地址address開始的內(nèi)存數(shù)據(jù),顯示的數(shù)據(jù)個(gè)數(shù)為count。

mm命令用法為“mm[.b, .w, .l] address”,表示以字節(jié)、字或雙字(默認(rèn)為雙字)為單位,從地址address開始修改內(nèi)存數(shù)據(jù)。執(zhí)行mm命令后,輸入新數(shù)據(jù)后回車,地址會(huì)自動(dòng)增加,Ctrl+C退出。

mw命令用法為“mw[.b, .w, .l] address value [count]”,表示以字節(jié)、字或雙字(默認(rèn)為雙字)為單位,往開始地址為address的內(nèi)存中填充count個(gè)數(shù)據(jù),數(shù)據(jù)值為value。

cp命令用法為“cp[.b, .w, .l] source target count”,表示以字節(jié)、字或雙字(默認(rèn)為雙字)為單位,從源地址source的內(nèi)存拷貝count個(gè)數(shù)據(jù)到目的地址的內(nèi)存。

(4)NOR Flash操作命令。

常用的命令有查看Flash信息的flinfo命令、加/解寫保護(hù)命令protect、擦除?
命令erase。由于NOR Flash的接口與一般內(nèi)存相似,所以一些內(nèi)存命令可以在NOR Flash上使用,比如讀NOR?
Flash時(shí)可以使用md、cp命令,寫NOR Flash時(shí)可以使用cp命令(cp根據(jù)地址分辨出是NOR Flash,從而調(diào)用NOR?
Flash驅(qū)動(dòng)完成寫操作)。

直接運(yùn)行“flinfo”即可看到NOR Flash的信息,有NOR Flash的型號、容量、各扇區(qū)的開始地址、是否只讀等信息。比如對于本書基于的開發(fā)板,flinfo命令的結(jié)果如下:

Bank # 1: AMD: 1x Amd29LV800BB (8Mbit)

Size: 1 MB in 19 Sectors

Sector Start Addresses:

00000000 (RO) 00004000 (RO) 00006000 (RO) 00008000 (RO) 00010000 (RO)

00020000 (RO) 00030000 00040000 00050000 00060000

00070000 00080000 00090000 000A0000 000B0000

000C0000 000D0000 000E0000 000F0000 (RO)

其中的RO表示該扇區(qū)處于寫保護(hù)狀態(tài),只讀。

對于只讀的扇區(qū),在擦除、燒寫它之前,要先解除寫保護(hù)。最簡單的命令為“protect off all”,解除所有NOR Flash的寫保護(hù)。

erase命令常用的格式為“erase start?
end”──擦除的地址范圍為start至end、“erase start +len”──擦除的地址范圍為start至(start + len?
– 1),“erase all”──表示擦除所有NOR Flash。

注意:其中的地址范圍,剛好是一個(gè)扇區(qū)的開始地址到另一個(gè)(或同一個(gè))扇區(qū)的結(jié)束地址。比如要擦除Amd29LV800BB的前5個(gè)扇區(qū),執(zhí)行的命令為“erase 0 0x2ffff”,而非“erase 0 0x30000”。

(5)NAND Flash操作命令。

NAND Flash操作命令只有一個(gè):nand,它根據(jù)不同的參數(shù)進(jìn)行不同操作,比如擦除、讀取、燒寫等。

“nand info”查看NAND Flash信息。

“nand erase [clean] [off size]”擦除NAND?
Flash。加上“clean”時(shí),表示在每個(gè)塊的第一個(gè)扇區(qū)的OOB區(qū)加寫入清除標(biāo)記;off、size表示要擦除的開始偏移地址和長度,如果省略?
off和size,表示要擦除整個(gè)NAND Flash。

“nand read[.jffs2] addr off size”從NAND Flash偏移地址off處讀出size個(gè)字節(jié)的數(shù)據(jù),存放到開始地址為addr的內(nèi)存中。是否加后綴“.jffs”的差別只是讀操作時(shí)的ECC較驗(yàn)方法不同。

“nand write[.jffs2] addr off size”把開始地址為addr的內(nèi)存中的size個(gè)字節(jié)數(shù)據(jù),寫到NAND Flash的偏移地址off處。是否加后綴“.jffs”的差別只是寫操作時(shí)的ECC較驗(yàn)方法不同。

“nand read.yaffs addr off size”從NAND Flash偏移地址off處讀出size個(gè)字節(jié)的數(shù)據(jù)(包括OOB區(qū)域),存放到開始地址為addr的內(nèi)存中。

“nand write.yaffs addr off size”把開始地址為addr的內(nèi)存中的size個(gè)字節(jié)數(shù)據(jù)(其中有要寫入OOB區(qū)域的數(shù)據(jù)),寫到NAND Flash的偏移地址off處。

“nand dump off”,將NAND Flash偏移地址off的一個(gè)扇區(qū)的數(shù)據(jù)打印出來,包括OOB數(shù)據(jù)。

(6)環(huán)境變量命令。

“printenv”命令打印全部環(huán)境變量,“printenv name1 name2 ...”打印名字為name1、name2、……”的環(huán)境變量。

“setenv name value”設(shè)置名字為name的環(huán)境變量的值為value。

“setenv name”刪除名字為name的環(huán)境變量。

上面的設(shè)置、刪除操作只是在內(nèi)存中進(jìn)行,“saveenv”將更改后的所有環(huán)境變量寫入NOR Flash中。

(7)啟動(dòng)命令。

不帶參數(shù)的“boot”、“bootm”命令都是執(zhí)行環(huán)境變量bootcmd所指定的命令。

“bootm [addr [arg?
...]]”命令啟動(dòng)存放在地址addr處的U-Boot格式的映像文件(使用U-Boot目錄tools下的mkimage工具制作得到),[arg?
...]表示參數(shù)。如果addr參數(shù)省略,映像文件所在地址為配置文件中定義的宏CFG_LOAD_ADDR。

“go addr [arg ...]”與bootm命令類似,啟動(dòng)存放在地址addr處的二進(jìn)制文件, [arg ...]表示參數(shù)。

“nboot [[[loadAddr] dev] offset]”命令將NAND?
Flash設(shè)備dev上偏移地址off處的映像文件復(fù)制到內(nèi)存loadAddr處,然后,如果環(huán)境變量autostart的值為“yes”,就啟動(dòng)這個(gè)映?
像。如果loadAddr參數(shù)省略,存放地址為配置文件中定義的宏CFG_LOAD_ADDR;如果dev參數(shù)省略,則它的取值為環(huán)境變量?
bootdevice的值;如果offset參數(shù)省略,則默認(rèn)為0。

2. U-Boot命令使用實(shí)例

下面通過一個(gè)例子來演示如何使用各種命令燒寫內(nèi)核映像文件、yaffs映像文件,并啟動(dòng)系統(tǒng)。

(1)制作內(nèi)核映像文件。

對于本書使用的Linux 2.6.22.6版本,編譯內(nèi)核時(shí)可以直接生成U-Boot格式的映像文件uImage。

對于不能直接生成uImage的內(nèi)核,制作方法在U-Boot根目錄下的README文件中?
有說明,假設(shè)已經(jīng)編譯好的內(nèi)核文件為vmlinux,它是ELF格式的。mkimage是U-Boot目錄tools下的工具,它在編譯U-Boot時(shí)自?
動(dòng)生成。執(zhí)行以下3個(gè)命令將內(nèi)核文件vmlinux制作為U-Boot格式的映像文件uImage,它們首先將vmlinux轉(zhuǎn)換為二進(jìn)制格式,然后壓?
縮,最后構(gòu)造頭部信息(里面包含有文件名稱、大小、類型、CRC較驗(yàn)碼等):

① arm-linux-objcopy -O binary -R .note -R .comment -S vmlinux linux.bin

② gzip -9 linux.bin

③ mkimage -A arm -O linux -T kernel -C gzip -a 0x30008000 -e 0x30008000 -n "Linux Kernel Image" -d linux.bin.gz uImage

(2)燒寫內(nèi)核映像文件uImage。

首先將uImage放在主機(jī)上的tftp或nfs目錄下,確保已經(jīng)開啟tftp或nfs服務(wù)。

然后運(yùn)行如下命令下載文件,擦除、燒寫NAND Flash:

① tftp 0x30000000 uImage 或 nfs 0x30000000 192.168.1.57:/work/nfs_root/uImage

② nand erase 0x0 0x00200000

③ nand write.jffs2 0x30000000 0x0 $(filesize)

第3條命令之所以使用“nand write.jffs2”而不是“nand?
write”,是因?yàn)榍罢卟灰笪募拈L度是頁對齊的(512字節(jié)對齊)。也可以使用“nand?
write”,但是需要將命令中的長度參數(shù)改為$(filesize)向上進(jìn)行512取整后的值。比如uImage的大小為1540883,向上進(jìn)行?
512取整后為1541120(即0x178400),可以使用命令“nand write 0x30000000 0x0?
0x178400”進(jìn)行燒寫。

(3)燒寫yaffs文件系統(tǒng)映像。

假設(shè)yaffs文件系統(tǒng)映像的文件名為yaffs.img,首先將它放在主機(jī)上的tftp或nfs目錄下,確保已經(jīng)開啟tftp或nfs服務(wù);然后執(zhí)行如下命令下載、擦除、燒寫:

① tftp 0x30000000 yaffs.img 或 nfs 0x30000000 192.168.1.57:/work/nfs_root/yaffs.img

② nand erase 0xA00000 0x3600000

③ nand write.yaffs 0x30000000 0xA00000 $(filesize)

這時(shí),重啟系統(tǒng),在U-Boot倒數(shù)3秒之后,就會(huì)自動(dòng)啟動(dòng)Linux系統(tǒng)。

(4)燒寫jffs2文件系統(tǒng)映像。

假設(shè)jffs2文件系統(tǒng)映像的文件名為jffs2.img,首先將它放在主機(jī)上的tftp或nfs目錄下,確保已經(jīng)開啟tftp或nfs服務(wù);然后執(zhí)行如下命令下載、擦除、燒寫:

① tftp 0x30000000 jffs2.img 或 nfs 0x30000000 192.168.1.57:/work/nfs_root/jffs2.img

② nand erase 0x200000 0x800000

③ nand write.jffs2 0x30000000 0x200000 $(filesize)

系統(tǒng)啟動(dòng)后,就可以使用“mount -t jffs2 /dev/mtdblock1 /mnt”掛接jffs2文件系統(tǒng)。

2.7 使用U-Boot來執(zhí)行程序

在前面的硬件實(shí)驗(yàn)中使用JTAG燒寫程序到NAND?
Flash,燒寫過程十分緩慢。如果使用U-Boot來燒寫NAND Flash,效率會(huì)高很多。燒寫二進(jìn)制文件到NAND?
Flash中所使用的命令與上面燒寫內(nèi)核映像文件uImage的過程類似,只是不需要將二進(jìn)制文件制作成U-Boot格式。

另外,可以將程序下載到內(nèi)存中,然后使用go命令執(zhí)行它。假設(shè)有一個(gè)程序的二進(jìn)制可執(zhí)行文件?
test.bin,連接地址為0x30000000。首先將它放在主機(jī)上的tftp或nfs目錄下,確保已經(jīng)開啟tftp或nfs服務(wù);然后將它下載到內(nèi)?
存0x30000000處,最后使用go命令執(zhí)行它:

① tftp 0x30000000 test.bin 或 nfs 0x30000000 192.168.1.57:/work/nfs_root/test.bin

② go 0x30000000

轉(zhuǎn)載于:https://www.cnblogs.com/zhugeanran/p/8427736.html

總結(jié)

以上是生活随笔為你收集整理的Bootloader之uBoot简介(转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

中文字幕乱码人妻无码久久 | 97人妻精品一区二区三区 | 男女下面进入的视频免费午夜 | 四虎永久在线精品免费网址 | 人妻夜夜爽天天爽三区 | 丰满人妻被黑人猛烈进入 | 国产激情艳情在线看视频 | 一本久久伊人热热精品中文字幕 | 欧美野外疯狂做受xxxx高潮 | 蜜桃无码一区二区三区 | 无码人中文字幕 | 午夜理论片yy44880影院 | 国产精品人人爽人人做我的可爱 | 强开小婷嫩苞又嫩又紧视频 | 免费视频欧美无人区码 | 久久久婷婷五月亚洲97号色 | 国产99久久精品一区二区 | 成人免费视频在线观看 | 色一情一乱一伦一区二区三欧美 | 国产精品无码一区二区三区不卡 | 1000部夫妻午夜免费 | 熟女俱乐部五十路六十路av | 国产又爽又黄又刺激的视频 | 精品国产精品久久一区免费式 | 麻豆果冻传媒2021精品传媒一区下载 | 青草视频在线播放 | 日本熟妇人妻xxxxx人hd | 国产疯狂伦交大片 | 久久久久亚洲精品中文字幕 | 99er热精品视频 | 熟女俱乐部五十路六十路av | 欧美人妻一区二区三区 | 4hu四虎永久在线观看 | av人摸人人人澡人人超碰下载 | 骚片av蜜桃精品一区 | 大乳丰满人妻中文字幕日本 | 内射后入在线观看一区 | 大屁股大乳丰满人妻 | 中文字幕无码av波多野吉衣 | 中文无码成人免费视频在线观看 | 国精产品一区二区三区 | 国产成人一区二区三区在线观看 | 一个人看的视频www在线 | 久久精品99久久香蕉国产色戒 | 亚洲综合无码久久精品综合 | 人妻无码久久精品人妻 | 亚洲国产精品毛片av不卡在线 | 国产乡下妇女做爰 | 久久久久久久久蜜桃 | 国产精品人妻一区二区三区四 | 国产成人一区二区三区在线观看 | 麻豆国产97在线 | 欧洲 | 久久综合九色综合97网 | 欧美性黑人极品hd | 亚洲国产av美女网站 | 午夜精品久久久内射近拍高清 | 成人aaa片一区国产精品 | 少女韩国电视剧在线观看完整 | 无码吃奶揉捏奶头高潮视频 | 免费无码肉片在线观看 | 97精品国产97久久久久久免费 | 天堂а√在线地址中文在线 | 国产两女互慰高潮视频在线观看 | 亚洲人成网站免费播放 | 正在播放老肥熟妇露脸 | 伦伦影院午夜理论片 | 久久精品中文闷骚内射 | 亚洲精品国偷拍自产在线观看蜜桃 | 丰满岳乱妇在线观看中字无码 | 日本丰满护士爆乳xxxx | 亚洲精品国产精品乱码不卡 | 天天躁夜夜躁狠狠是什么心态 | 中文字幕 亚洲精品 第1页 | 欧洲熟妇精品视频 | 亚洲aⅴ无码成人网站国产app | aa片在线观看视频在线播放 | 国产午夜亚洲精品不卡下载 | 玩弄少妇高潮ⅹxxxyw | 国内丰满熟女出轨videos | 久久无码专区国产精品s | 夫妻免费无码v看片 | 亚洲精品成人福利网站 | 97久久精品无码一区二区 | 久久久精品成人免费观看 | 日韩av激情在线观看 | 亚洲精品一区二区三区四区五区 | 成人无码精品1区2区3区免费看 | 欧美野外疯狂做受xxxx高潮 | 无码国产乱人伦偷精品视频 | 精品成在人线av无码免费看 | 国产偷自视频区视频 | 东北女人啪啪对白 | 伊人久久大香线焦av综合影院 | 国产人妻精品午夜福利免费 | 精品国产青草久久久久福利 | 欧美人与禽猛交狂配 | 国产片av国语在线观看 | 最新国产麻豆aⅴ精品无码 | 中文无码伦av中文字幕 | 水蜜桃亚洲一二三四在线 | 亚洲综合色区中文字幕 | 精品国产国产综合精品 | 伊人久久婷婷五月综合97色 | 亚洲日韩av一区二区三区四区 | 久久久久亚洲精品男人的天堂 | 久久久久久a亚洲欧洲av冫 | 麻豆成人精品国产免费 | 国产无遮挡又黄又爽免费视频 | 99久久精品国产一区二区蜜芽 | 精品无码一区二区三区爱欲 | 精品一区二区三区无码免费视频 | 国产真实乱对白精彩久久 | 国产人妻久久精品二区三区老狼 | 俺去俺来也www色官网 | 午夜嘿嘿嘿影院 | 亚洲精品国产精品乱码视色 | 国精产品一品二品国精品69xx | 极品尤物被啪到呻吟喷水 | 又色又爽又黄的美女裸体网站 | 无码国产乱人伦偷精品视频 | 欧美性色19p | 99久久人妻精品免费二区 | 狠狠亚洲超碰狼人久久 | 久久精品女人天堂av免费观看 | 伊人色综合久久天天小片 | 国产亚洲美女精品久久久2020 | 国内精品一区二区三区不卡 | 成 人 网 站国产免费观看 | 国产 精品 自在自线 | 伊人久久大香线焦av综合影院 | 俄罗斯老熟妇色xxxx | 少妇一晚三次一区二区三区 | 欧美国产日韩久久mv | 日韩精品无码一区二区中文字幕 | 日韩成人一区二区三区在线观看 | 亚洲va中文字幕无码久久不卡 | 少妇愉情理伦片bd | 无码人妻精品一区二区三区下载 | 沈阳熟女露脸对白视频 | 欧美猛少妇色xxxxx | 欧美老人巨大xxxx做受 | 国产精品福利视频导航 | 亚洲精品久久久久avwww潮水 | 99精品视频在线观看免费 | 内射爽无广熟女亚洲 | 中文字幕中文有码在线 | 色情久久久av熟女人妻网站 | 精品亚洲成av人在线观看 | 香港三级日本三级妇三级 | 成人精品视频一区二区三区尤物 | 一本久久伊人热热精品中文字幕 | 无码人妻av免费一区二区三区 | 中文字幕无线码免费人妻 | 国产精品毛片一区二区 | 无码人妻久久一区二区三区不卡 | 久久无码专区国产精品s | v一区无码内射国产 | 性开放的女人aaa片 | 精品久久久久久亚洲精品 | 一本色道婷婷久久欧美 | 久久综合网欧美色妞网 | 色情久久久av熟女人妻网站 | 嫩b人妻精品一区二区三区 | 国产人妻人伦精品 | 日韩 欧美 动漫 国产 制服 | a国产一区二区免费入口 | 娇妻被黑人粗大高潮白浆 | 国产一区二区三区四区五区加勒比 | 国产精品亚洲а∨无码播放麻豆 | 18精品久久久无码午夜福利 | 日本www一道久久久免费榴莲 | 无码任你躁久久久久久久 | 精品无码成人片一区二区98 | 久久国产劲爆∧v内射 | 久久成人a毛片免费观看网站 | 久久97精品久久久久久久不卡 | 人人澡人人妻人人爽人人蜜桃 | 4hu四虎永久在线观看 | 人人妻人人澡人人爽精品欧美 | 色噜噜亚洲男人的天堂 | 国产午夜无码精品免费看 | 无码午夜成人1000部免费视频 | 国产午夜福利亚洲第一 | 2020久久超碰国产精品最新 | 特黄特色大片免费播放器图片 | 精品人妻中文字幕有码在线 | 精品人妻中文字幕有码在线 | 夫妻免费无码v看片 | 国产美女极度色诱视频www | 国产人妖乱国产精品人妖 | 国产激情无码一区二区app | 玩弄中年熟妇正在播放 | 两性色午夜免费视频 | 无码人妻少妇伦在线电影 | 国产亚洲人成a在线v网站 | 精品乱子伦一区二区三区 | 欧美国产日韩亚洲中文 | 人妻aⅴ无码一区二区三区 | 无码人妻丰满熟妇区毛片18 | 欧美放荡的少妇 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 久久久久亚洲精品男人的天堂 | 亚洲色大成网站www国产 | 亚洲人成影院在线无码按摩店 | 天天爽夜夜爽夜夜爽 | 中文字幕人妻丝袜二区 | 国产综合久久久久鬼色 | 1000部夫妻午夜免费 | 性做久久久久久久久 | 国产精品毛多多水多 | 动漫av一区二区在线观看 | 亚洲爆乳精品无码一区二区三区 | 天下第一社区视频www日本 | 国产精品久久久久久亚洲影视内衣 | 一二三四在线观看免费视频 | 欧美日韩人成综合在线播放 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 超碰97人人做人人爱少妇 | 国内精品九九久久久精品 | 无码人妻av免费一区二区三区 | 精品国产精品久久一区免费式 | 亚洲熟妇自偷自拍另类 | 亚洲色偷偷男人的天堂 | 免费无码肉片在线观看 | 久久精品中文字幕一区 | 色狠狠av一区二区三区 | 天天摸天天碰天天添 | 98国产精品综合一区二区三区 | 精品一区二区不卡无码av | 精品水蜜桃久久久久久久 | 99精品久久毛片a片 | 中文字幕日产无线码一区 | 四虎国产精品免费久久 | 日日躁夜夜躁狠狠躁 | 免费观看的无遮挡av | 久9re热视频这里只有精品 | 特级做a爰片毛片免费69 | 无码人妻少妇伦在线电影 | 3d动漫精品啪啪一区二区中 | 亚洲人成网站色7799 | 狠狠综合久久久久综合网 | 在线观看国产午夜福利片 | 国产黑色丝袜在线播放 | 亚洲色大成网站www国产 | 国语自产偷拍精品视频偷 | 欧美丰满老熟妇xxxxx性 | 男女性色大片免费网站 | 丰腴饱满的极品熟妇 | 色窝窝无码一区二区三区色欲 | 成人无码精品1区2区3区免费看 | 午夜丰满少妇性开放视频 | 亚洲日本一区二区三区在线 | 欧美亚洲日韩国产人成在线播放 | 无码精品国产va在线观看dvd | 国产成人av免费观看 | 日本一本二本三区免费 | 亚洲а∨天堂久久精品2021 | 久久久av男人的天堂 | 日韩人妻少妇一区二区三区 | 亚洲精品www久久久 | 亚洲色无码一区二区三区 | 漂亮人妻洗澡被公强 日日躁 | 国产成人精品三级麻豆 | 一个人免费观看的www视频 | 色婷婷av一区二区三区之红樱桃 | 久久国产精品_国产精品 | 欧美三级不卡在线观看 | 少女韩国电视剧在线观看完整 | 红桃av一区二区三区在线无码av | 亚洲自偷自偷在线制服 | 人妻aⅴ无码一区二区三区 | 国产精品人人妻人人爽 | 精品无码一区二区三区爱欲 | 成熟女人特级毛片www免费 | 亚洲精品一区三区三区在线观看 | 扒开双腿疯狂进出爽爽爽视频 | √8天堂资源地址中文在线 | 最近免费中文字幕中文高清百度 | 色五月五月丁香亚洲综合网 | 国产精品怡红院永久免费 | 国产激情综合五月久久 | 亚洲伊人久久精品影院 | 伊人久久大香线焦av综合影院 | 亚洲精品国偷拍自产在线麻豆 | 国产内射爽爽大片视频社区在线 | 国产午夜视频在线观看 | 亚洲一区av无码专区在线观看 | 老子影院午夜伦不卡 | 男女作爱免费网站 | 性开放的女人aaa片 | 欧美阿v高清资源不卡在线播放 | 国产精品99爱免费视频 | 爽爽影院免费观看 | 国产精品亚洲五月天高清 | 久久人人爽人人爽人人片av高清 | 亚洲最大成人网站 | 久久久婷婷五月亚洲97号色 | 性生交大片免费看女人按摩摩 | 无码人妻黑人中文字幕 | 波多野结衣乳巨码无在线观看 | 成人免费无码大片a毛片 | 亚洲自偷精品视频自拍 | 一本一道久久综合久久 | 色窝窝无码一区二区三区色欲 | 丝袜人妻一区二区三区 | 97人妻精品一区二区三区 | 成熟女人特级毛片www免费 | 欧美变态另类xxxx | 无码国内精品人妻少妇 | 性色欲网站人妻丰满中文久久不卡 | 中文无码成人免费视频在线观看 | 日本丰满护士爆乳xxxx | 国产成人人人97超碰超爽8 | 日韩精品成人一区二区三区 | 午夜时刻免费入口 | 人人澡人人透人人爽 | 国产成人人人97超碰超爽8 | 久久午夜无码鲁丝片午夜精品 | 亚洲中文字幕久久无码 | 成人无码精品一区二区三区 | 波多野结衣av一区二区全免费观看 | 免费观看激色视频网站 | 成人片黄网站色大片免费观看 | 国产精品亚洲专区无码不卡 | 麻豆人妻少妇精品无码专区 | 欧美午夜特黄aaaaaa片 | 亚洲性无码av中文字幕 | 亚洲综合无码久久精品综合 | 思思久久99热只有频精品66 | 2019nv天堂香蕉在线观看 | 7777奇米四色成人眼影 | 无码人妻av免费一区二区三区 | 久久人妻内射无码一区三区 | 日韩人妻无码一区二区三区久久99 | 免费人成在线视频无码 | 精品国产乱码久久久久乱码 | 国产无遮挡又黄又爽又色 | 国产另类ts人妖一区二区 | 国产九九九九九九九a片 | 7777奇米四色成人眼影 | 性生交大片免费看女人按摩摩 | 人妻体内射精一区二区三四 | 精品人妻中文字幕有码在线 | 99精品无人区乱码1区2区3区 | 色一情一乱一伦一视频免费看 | 久久精品国产精品国产精品污 | 国产一区二区三区影院 | 波多野42部无码喷潮在线 | 国模大胆一区二区三区 | 伊人久久大香线蕉av一区二区 | 成人三级无码视频在线观看 | 曰韩无码二三区中文字幕 | 欧美喷潮久久久xxxxx | 1000部夫妻午夜免费 | 亚洲国产精品久久人人爱 | 久久久久久久人妻无码中文字幕爆 | 麻豆蜜桃av蜜臀av色欲av | 成年美女黄网站色大免费视频 | 日韩人妻无码一区二区三区久久99 | 国产 精品 自在自线 | 超碰97人人做人人爱少妇 | 一个人看的视频www在线 | 波多野结衣aⅴ在线 | 桃花色综合影院 | 黑人巨大精品欧美一区二区 | 秋霞特色aa大片 | 久久精品国产大片免费观看 | 鲁鲁鲁爽爽爽在线视频观看 | 又湿又紧又大又爽a视频国产 | av无码电影一区二区三区 | 我要看www免费看插插视频 | 极品尤物被啪到呻吟喷水 | 亚洲国产精品久久久久久 | 中文毛片无遮挡高清免费 | а√资源新版在线天堂 | 久久午夜无码鲁丝片午夜精品 | 国产三级久久久精品麻豆三级 | 四虎国产精品一区二区 | 又大又紧又粉嫩18p少妇 | 色一情一乱一伦一区二区三欧美 | 亚洲色偷偷男人的天堂 | 亚洲国产精品久久久久久 | 日韩av无码一区二区三区不卡 | 欧美激情内射喷水高潮 | 18禁止看的免费污网站 | 欧美黑人巨大xxxxx | 国产精品亚洲专区无码不卡 | 亚洲日本一区二区三区在线 | 香蕉久久久久久av成人 | 无码人妻精品一区二区三区下载 | 无遮无挡爽爽免费视频 | 暴力强奷在线播放无码 | 俄罗斯老熟妇色xxxx | 久久精品中文闷骚内射 | 曰韩无码二三区中文字幕 | 亚洲精品午夜无码电影网 | 97夜夜澡人人双人人人喊 | 亚洲国产精品美女久久久久 | 大胆欧美熟妇xx | 亚洲无人区午夜福利码高清完整版 | 一区二区三区乱码在线 | 欧洲 | 欧美熟妇另类久久久久久多毛 | 日日摸天天摸爽爽狠狠97 | 丰满人妻被黑人猛烈进入 | 国产农村乱对白刺激视频 | 亚洲人亚洲人成电影网站色 | 亚洲人亚洲人成电影网站色 | 亚洲国产av美女网站 | 国产热a欧美热a在线视频 | 久久久婷婷五月亚洲97号色 | 色一情一乱一伦 | 久久久久亚洲精品中文字幕 | 四虎4hu永久免费 | 欧美野外疯狂做受xxxx高潮 | 久久久久免费精品国产 | 亚洲国产精品无码久久久久高潮 | 日韩精品久久久肉伦网站 | 少妇性l交大片 | 日本精品久久久久中文字幕 | 欧美性猛交xxxx富婆 | 午夜熟女插插xx免费视频 | 精品少妇爆乳无码av无码专区 | 亚洲精品中文字幕乱码 | 性欧美videos高清精品 | 青青久在线视频免费观看 | 99久久精品无码一区二区毛片 | 欧美怡红院免费全部视频 | 久久久久久a亚洲欧洲av冫 | 无码国内精品人妻少妇 | 精品人妻人人做人人爽 | 少妇被黑人到高潮喷出白浆 | 2019nv天堂香蕉在线观看 | 久久综合给合久久狠狠狠97色 | 男人扒开女人内裤强吻桶进去 | 国产精品久久精品三级 | 中文字幕无码乱人伦 | 精品 日韩 国产 欧美 视频 | 最近的中文字幕在线看视频 | 久久99精品国产麻豆 | 亚洲色成人中文字幕网站 | 熟妇人妻中文av无码 | 极品嫩模高潮叫床 | 国产亚洲人成a在线v网站 | 国产国语老龄妇女a片 | 亚洲精品无码人妻无码 | 综合人妻久久一区二区精品 | 国产精品鲁鲁鲁 | 色老头在线一区二区三区 | 成人欧美一区二区三区黑人免费 | 国产精品久久国产精品99 | 55夜色66夜色国产精品视频 | 女人被爽到呻吟gif动态图视看 | 国产免费无码一区二区视频 | 美女极度色诱视频国产 | 亚洲精品一区二区三区在线观看 | 麻豆国产人妻欲求不满 | 久久久久久av无码免费看大片 | 亚洲国产精品成人久久蜜臀 | 国产国语老龄妇女a片 | 久久综合色之久久综合 | 夜先锋av资源网站 | 丝袜 中出 制服 人妻 美腿 | 亚洲码国产精品高潮在线 | 午夜免费福利小电影 | 丝袜 中出 制服 人妻 美腿 | 国产精品久久久 | 午夜无码人妻av大片色欲 | 国产午夜福利亚洲第一 | 精品 日韩 国产 欧美 视频 | 日本精品人妻无码77777 天堂一区人妻无码 | 精品欧洲av无码一区二区三区 | 丰满人妻一区二区三区免费视频 | 丰满人妻被黑人猛烈进入 | 无码av免费一区二区三区试看 | 久久99热只有频精品8 | 全黄性性激高免费视频 | 色诱久久久久综合网ywww | 成人无码精品1区2区3区免费看 | 久久久中文字幕日本无吗 | 亚洲人成网站免费播放 | 亚洲精品www久久久 | 欧美老妇交乱视频在线观看 | 亚洲乱码国产乱码精品精 | 日产精品高潮呻吟av久久 | 精品厕所偷拍各类美女tp嘘嘘 | 久久久久亚洲精品中文字幕 | 中国女人内谢69xxxx | 在线精品国产一区二区三区 | 亚洲国产精品久久久久久 | www一区二区www免费 | 国产精品久久久久影院嫩草 | 麻豆精品国产精华精华液好用吗 | 国产精品亚洲一区二区三区喷水 | 亚洲熟妇色xxxxx欧美老妇y | 亚洲欧美综合区丁香五月小说 | 亚洲熟女一区二区三区 | 国产麻豆精品一区二区三区v视界 | 欧美 亚洲 国产 另类 | 18禁止看的免费污网站 | 夫妻免费无码v看片 | 在线a亚洲视频播放在线观看 | 国产精品高潮呻吟av久久4虎 | 亚洲色大成网站www | 午夜精品一区二区三区在线观看 | 99久久人妻精品免费二区 | 乱人伦人妻中文字幕无码久久网 | 亚洲日韩乱码中文无码蜜桃臀网站 | 久久精品99久久香蕉国产色戒 | 乱人伦人妻中文字幕无码久久网 | 荫蒂添的好舒服视频囗交 | 中文字幕乱码中文乱码51精品 | 丰满少妇高潮惨叫视频 | 激情综合激情五月俺也去 | 亚洲综合久久一区二区 | 波多野结衣乳巨码无在线观看 | 蜜桃无码一区二区三区 | 无遮挡国产高潮视频免费观看 | 日日天日日夜日日摸 | 成人女人看片免费视频放人 | 丰满人妻精品国产99aⅴ | 国产成人无码午夜视频在线观看 | 亚洲成a人一区二区三区 | 国产内射老熟女aaaa | 人人超人人超碰超国产 | 亚洲中文字幕成人无码 | 风流少妇按摩来高潮 | www国产亚洲精品久久网站 | 欧美大屁股xxxxhd黑色 | 欧美野外疯狂做受xxxx高潮 | 国产一区二区不卡老阿姨 | 成人综合网亚洲伊人 | 国内精品久久久久久中文字幕 | 丰满少妇弄高潮了www | 欧美亚洲国产一区二区三区 | 动漫av一区二区在线观看 | 免费无码午夜福利片69 | 日韩av无码中文无码电影 | 欧美亚洲日韩国产人成在线播放 | 成人精品视频一区二区三区尤物 | 老子影院午夜伦不卡 | 男女性色大片免费网站 | 少妇人妻偷人精品无码视频 | 99视频精品全部免费免费观看 | 色一情一乱一伦一区二区三欧美 | 少妇高潮一区二区三区99 | 亚洲国产精品无码久久久久高潮 | 国内揄拍国内精品人妻 | 女高中生第一次破苞av | 精品一二三区久久aaa片 | 亚洲一区二区观看播放 | 亚洲欧美国产精品专区久久 | 激情综合激情五月俺也去 | 久久久久久久久888 | 国产无套粉嫩白浆在线 | 午夜无码人妻av大片色欲 | 中文字幕无码乱人伦 | 中文字幕亚洲情99在线 | 中文字幕av无码一区二区三区电影 | 国产成人综合在线女婷五月99播放 | 7777奇米四色成人眼影 | 欧美丰满老熟妇xxxxx性 | 亚洲成a人一区二区三区 | 日韩精品成人一区二区三区 | 日韩精品无码一本二本三本色 | 亚洲人成影院在线观看 | 国产明星裸体无码xxxx视频 | 亚洲精品午夜国产va久久成人 | 中文字幕乱码亚洲无线三区 | 超碰97人人做人人爱少妇 | 午夜精品久久久久久久 | 久久婷婷五月综合色国产香蕉 | 欧美成人午夜精品久久久 | 国产精品二区一区二区aⅴ污介绍 | 亚洲日韩精品欧美一区二区 | 中文字幕无码乱人伦 | 无码国内精品人妻少妇 | 粗大的内捧猛烈进出视频 | 大乳丰满人妻中文字幕日本 | 久久精品国产一区二区三区肥胖 | 亚洲一区二区三区在线观看网站 | 日韩精品无码免费一区二区三区 | 女高中生第一次破苞av | 亚洲精品国偷拍自产在线观看蜜桃 | 日韩无套无码精品 | 蜜臀aⅴ国产精品久久久国产老师 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 国产日产欧产精品精品app | 国产亲子乱弄免费视频 | 国产亚洲美女精品久久久2020 | 少妇性俱乐部纵欲狂欢电影 | 国内精品九九久久久精品 | 日韩av无码一区二区三区 | 在线观看欧美一区二区三区 | 国产口爆吞精在线视频 | 妺妺窝人体色www婷婷 | 亚洲国产午夜精品理论片 | 久青草影院在线观看国产 | 内射后入在线观看一区 | 亚洲日本一区二区三区在线 | 国产无遮挡又黄又爽又色 | 中国女人内谢69xxxx | 国内精品一区二区三区不卡 | 久久无码专区国产精品s | 成人无码精品一区二区三区 | 女人高潮内射99精品 | 久久久久国色av免费观看性色 | 日日噜噜噜噜夜夜爽亚洲精品 | 久久久www成人免费毛片 | 国产免费无码一区二区视频 | 亚洲国产精品久久久久久 | 亚洲人成网站免费播放 | 国产成人无码区免费内射一片色欲 | 久久无码中文字幕免费影院蜜桃 | 亚洲成熟女人毛毛耸耸多 | 亚洲成色在线综合网站 | 欧美人妻一区二区三区 | 一本无码人妻在中文字幕免费 | 人人爽人人爽人人片av亚洲 | 亚洲国产综合无码一区 | 欧美丰满老熟妇xxxxx性 | 一本大道伊人av久久综合 | 久久久久亚洲精品男人的天堂 | 麻豆蜜桃av蜜臀av色欲av | 国语精品一区二区三区 | 东京热男人av天堂 | 久久天天躁夜夜躁狠狠 | 欧美性黑人极品hd | 国产亲子乱弄免费视频 | 国内少妇偷人精品视频免费 | 成人影院yy111111在线观看 | 亚洲人成影院在线观看 | 中文无码成人免费视频在线观看 | 国产精品成人av在线观看 | 2019nv天堂香蕉在线观看 | 欧美性猛交xxxx富婆 | 性啪啪chinese东北女人 | 久久久久亚洲精品男人的天堂 | 窝窝午夜理论片影院 | 国产成人久久精品流白浆 | 乱码av麻豆丝袜熟女系列 | 亚洲日韩av片在线观看 | 青春草在线视频免费观看 | 夜精品a片一区二区三区无码白浆 | 婷婷综合久久中文字幕蜜桃三电影 | 成人性做爰aaa片免费看不忠 | 宝宝好涨水快流出来免费视频 | 国产精品二区一区二区aⅴ污介绍 | 国产香蕉尹人综合在线观看 | 色情久久久av熟女人妻网站 | 国产黑色丝袜在线播放 | 男人的天堂2018无码 | 日韩av无码一区二区三区不卡 | 中文字幕无码av波多野吉衣 | 成人综合网亚洲伊人 | 亚洲精品一区二区三区在线观看 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 爱做久久久久久 | 国产精品亚洲一区二区三区喷水 | 国产熟妇高潮叫床视频播放 | 亚洲区欧美区综合区自拍区 | 狠狠色噜噜狠狠狠狠7777米奇 | 亚洲欧美国产精品久久 | 老熟妇仑乱视频一区二区 | 内射白嫩少妇超碰 | 亚洲精品国产精品乱码视色 | 欧美第一黄网免费网站 | 国产精品99久久精品爆乳 | 午夜无码区在线观看 | 国产在线精品一区二区三区直播 | 67194成是人免费无码 | 男女猛烈xx00免费视频试看 | 国产成人无码a区在线观看视频app | 清纯唯美经典一区二区 | 亚洲高清偷拍一区二区三区 | 欧美精品免费观看二区 | 在线 国产 欧美 亚洲 天堂 | 亚洲中文字幕在线无码一区二区 | 伊人久久大香线焦av综合影院 | 中文字幕av伊人av无码av | 妺妺窝人体色www婷婷 | 欧美日本精品一区二区三区 | 人妻人人添人妻人人爱 | 精品久久久久香蕉网 | 国产成人一区二区三区在线观看 | 丁香花在线影院观看在线播放 | 少妇性l交大片欧洲热妇乱xxx | 午夜精品久久久久久久久 | 国产人妖乱国产精品人妖 | 亚洲综合精品香蕉久久网 | 成 人 网 站国产免费观看 | 欧美阿v高清资源不卡在线播放 | 欧美freesex黑人又粗又大 | √8天堂资源地址中文在线 | 午夜精品久久久久久久久 | 国产又爽又黄又刺激的视频 | 自拍偷自拍亚洲精品10p | 国产午夜亚洲精品不卡下载 | 奇米影视7777久久精品人人爽 | 人妻尝试又大又粗久久 | 亚洲高清偷拍一区二区三区 | 女人和拘做爰正片视频 | 久久无码人妻影院 | 99久久精品日本一区二区免费 | 亚洲一区二区三区在线观看网站 | 少女韩国电视剧在线观看完整 | 四虎4hu永久免费 | 天天综合网天天综合色 | 67194成是人免费无码 | 国产人妻精品一区二区三区不卡 | 久9re热视频这里只有精品 | 国产综合在线观看 | 精品久久久久香蕉网 | 97久久国产亚洲精品超碰热 | 桃花色综合影院 | 久久国产精品萌白酱免费 | 久久久久亚洲精品中文字幕 | 国产精品va在线观看无码 | 欧美 丝袜 自拍 制服 另类 | 欧美亚洲国产一区二区三区 | 免费乱码人妻系列无码专区 | 日日碰狠狠丁香久燥 | 无码国产乱人伦偷精品视频 | 日韩精品一区二区av在线 | 日韩少妇白浆无码系列 | 国产无遮挡又黄又爽免费视频 | 成人精品视频一区二区三区尤物 | 波多野结衣高清一区二区三区 | 中文字幕无码av激情不卡 | 日本熟妇大屁股人妻 | 日本护士xxxxhd少妇 | 国产精品18久久久久久麻辣 | 欧美性生交xxxxx久久久 | 亚洲男人av香蕉爽爽爽爽 | 一本久久a久久精品亚洲 | 国产亚洲精品久久久久久久 | 欧美日韩一区二区三区自拍 | 国内精品人妻无码久久久影院蜜桃 | 黑人巨大精品欧美黑寡妇 | 久久综合狠狠综合久久综合88 | 人妻人人添人妻人人爱 | av无码久久久久不卡免费网站 | 狠狠色欧美亚洲狠狠色www | 亚洲综合色区中文字幕 | 九九综合va免费看 | 精品偷拍一区二区三区在线看 | 久久99精品国产.久久久久 | 伊人久久婷婷五月综合97色 | 日韩精品a片一区二区三区妖精 | 欧美精品无码一区二区三区 | 狂野欧美性猛xxxx乱大交 | 中文字幕日韩精品一区二区三区 | 亚洲午夜久久久影院 | 欧美日本精品一区二区三区 | 日本护士毛茸茸高潮 | 自拍偷自拍亚洲精品10p | 亚拍精品一区二区三区探花 | 99久久精品日本一区二区免费 | 欧美激情内射喷水高潮 | 福利一区二区三区视频在线观看 | 国产精品亚洲lv粉色 | 国产又爽又猛又粗的视频a片 | 7777奇米四色成人眼影 | 国产精品久久久 | 又粗又大又硬又长又爽 | 午夜福利一区二区三区在线观看 | 国产av人人夜夜澡人人爽麻豆 | 亚洲热妇无码av在线播放 | 76少妇精品导航 | 成人无码视频免费播放 | 狂野欧美性猛交免费视频 | 久久五月精品中文字幕 | 国产av无码专区亚洲awww | 狠狠cao日日穞夜夜穞av | 国产亚洲视频中文字幕97精品 | 色婷婷av一区二区三区之红樱桃 | 学生妹亚洲一区二区 | 麻豆成人精品国产免费 | 亚洲精品中文字幕 | 粉嫩少妇内射浓精videos | 日韩 欧美 动漫 国产 制服 | 97人妻精品一区二区三区 | 久久精品99久久香蕉国产色戒 | 沈阳熟女露脸对白视频 | 亚洲va欧美va天堂v国产综合 | 成人性做爰aaa片免费看不忠 | 97资源共享在线视频 | 欧美成人午夜精品久久久 | 亚洲伊人久久精品影院 | 国产suv精品一区二区五 | 国产电影无码午夜在线播放 | 高清国产亚洲精品自在久久 | 中文字幕av无码一区二区三区电影 | 国产午夜无码视频在线观看 | 国产乱人偷精品人妻a片 | 精品国产aⅴ无码一区二区 | 无码毛片视频一区二区本码 | 粉嫩少妇内射浓精videos | 最近中文2019字幕第二页 | 丰满岳乱妇在线观看中字无码 | 午夜熟女插插xx免费视频 | 麻豆国产丝袜白领秘书在线观看 | 久久久精品欧美一区二区免费 | 狂野欧美激情性xxxx | 激情五月综合色婷婷一区二区 | 国产亚洲精品久久久久久大师 | 国产熟妇高潮叫床视频播放 | 国产激情一区二区三区 | av小次郎收藏 | 日日摸天天摸爽爽狠狠97 | 国内揄拍国内精品少妇国语 | 久久精品99久久香蕉国产色戒 | а√天堂www在线天堂小说 | 无码毛片视频一区二区本码 | 国产xxx69麻豆国语对白 | 丁香花在线影院观看在线播放 | 国产亚洲精品久久久久久久久动漫 | 人人澡人人透人人爽 | 国产熟妇另类久久久久 | 国产三级久久久精品麻豆三级 | 欧美成人免费全部网站 | 丰腴饱满的极品熟妇 | 无码人妻精品一区二区三区下载 | 久久国产精品偷任你爽任你 | 内射后入在线观看一区 | 妺妺窝人体色www在线小说 | 亚洲精品国偷拍自产在线观看蜜桃 | 男女性色大片免费网站 | 亚洲精品久久久久久一区二区 | 国产成人无码a区在线观看视频app | av小次郎收藏 | 亚洲一区二区三区在线观看网站 | 亚洲中文字幕在线观看 | 伊人久久大香线蕉亚洲 | 国产特级毛片aaaaaa高潮流水 | 国产精品内射视频免费 | 97无码免费人妻超级碰碰夜夜 | 人人爽人人澡人人人妻 | 国产亚洲日韩欧美另类第八页 | 三上悠亚人妻中文字幕在线 | 国模大胆一区二区三区 | 少妇无套内谢久久久久 | 国内丰满熟女出轨videos | 7777奇米四色成人眼影 | 人妻互换免费中文字幕 | 国产性生交xxxxx无码 | 曰本女人与公拘交酡免费视频 | 国产精品久免费的黄网站 | 亚洲一区二区三区播放 | 国产亚洲人成a在线v网站 | 日韩亚洲欧美中文高清在线 | 久久无码中文字幕免费影院蜜桃 | 欧美丰满熟妇xxxx | 国产人成高清在线视频99最全资源 | 国产无av码在线观看 | 亚洲人成影院在线无码按摩店 | 国产精品久久久久久无码 | 一本色道婷婷久久欧美 | 夫妻免费无码v看片 | 欧美怡红院免费全部视频 | 色综合天天综合狠狠爱 | 国产 精品 自在自线 | 久久 国产 尿 小便 嘘嘘 | 成人无码精品一区二区三区 | 99精品无人区乱码1区2区3区 | 国产xxx69麻豆国语对白 | 中文字幕中文有码在线 | 一本久道久久综合狠狠爱 | 国产无套粉嫩白浆在线 | 午夜肉伦伦影院 | 麻豆国产人妻欲求不满 | 国产婷婷色一区二区三区在线 | 国产精品久久久 | 永久黄网站色视频免费直播 | 欧美 日韩 亚洲 在线 | 国产在线无码精品电影网 | 在线观看国产午夜福利片 | 丰腴饱满的极品熟妇 | 国产农村乱对白刺激视频 | 九月婷婷人人澡人人添人人爽 | 精品国产一区二区三区四区 | 伊人色综合久久天天小片 | 国产激情无码一区二区app | 综合激情五月综合激情五月激情1 | 夜夜影院未满十八勿进 | 国产午夜无码视频在线观看 | 捆绑白丝粉色jk震动捧喷白浆 | 大色综合色综合网站 | 久久99精品久久久久久动态图 | 精品久久久无码人妻字幂 | 天天躁日日躁狠狠躁免费麻豆 | 国产人妻人伦精品 | 国产av无码专区亚洲awww | 久久亚洲日韩精品一区二区三区 | 欧美成人午夜精品久久久 | 久久午夜无码鲁丝片 | 国产精品美女久久久久av爽李琼 | 全球成人中文在线 | 欧美一区二区三区视频在线观看 | 自拍偷自拍亚洲精品10p | 欧美大屁股xxxxhd黑色 | 午夜理论片yy44880影院 | 无码中文字幕色专区 | 成人女人看片免费视频放人 | 国产成人无码av片在线观看不卡 | 亚洲色大成网站www | 国产乱人偷精品人妻a片 | 欧美性猛交xxxx富婆 | 欧美激情综合亚洲一二区 | 99久久人妻精品免费一区 | 欧美人与物videos另类 | 亚洲精品无码人妻无码 | 中文字幕日韩精品一区二区三区 | 亚洲伊人久久精品影院 | 夜精品a片一区二区三区无码白浆 | 国产成人综合在线女婷五月99播放 | 成人精品视频一区二区三区尤物 | 99在线 | 亚洲 | 久久久久久亚洲精品a片成人 | 午夜肉伦伦影院 | 国产成人一区二区三区别 | 中文字幕乱妇无码av在线 | 色婷婷欧美在线播放内射 | 国产午夜视频在线观看 | 免费国产成人高清在线观看网站 | 亚洲第一网站男人都懂 | 精品国偷自产在线视频 | 青草青草久热国产精品 | 无码免费一区二区三区 | 精品国产麻豆免费人成网站 | 又大又硬又黄的免费视频 | 久久久久久亚洲精品a片成人 | 久久综合久久自在自线精品自 | 国产成人综合美国十次 | 中文字幕无码热在线视频 | 亚洲日韩av片在线观看 | 中文亚洲成a人片在线观看 | 亚洲无人区午夜福利码高清完整版 | 午夜无码区在线观看 | 国产艳妇av在线观看果冻传媒 | 亚洲精品国产第一综合99久久 | 欧美35页视频在线观看 | 亚洲精品国产a久久久久久 | 欧美阿v高清资源不卡在线播放 | 国产精品久久久一区二区三区 | 少妇性l交大片 | 激情内射亚州一区二区三区爱妻 | 国产人妻精品一区二区三区不卡 | 熟妇人妻中文av无码 | 强伦人妻一区二区三区视频18 | 婷婷五月综合缴情在线视频 | 欧美人与禽zoz0性伦交 | 亚洲国产一区二区三区在线观看 | 未满成年国产在线观看 | 国模大胆一区二区三区 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 四虎4hu永久免费 | 国产精品久久久久无码av色戒 | 无遮无挡爽爽免费视频 | 一本久道久久综合狠狠爱 | 国产无遮挡又黄又爽免费视频 | 夜夜高潮次次欢爽av女 | 又大又硬又黄的免费视频 | 久久久久久九九精品久 | 男人的天堂av网站 | 亲嘴扒胸摸屁股激烈网站 | 日韩精品无码免费一区二区三区 | 国产精品自产拍在线观看 | 国产真实夫妇视频 | 中文字幕人妻无码一区二区三区 | 亚洲国产精品一区二区第一页 | 欧美老妇与禽交 | 无码一区二区三区在线观看 | 国产精品亚洲专区无码不卡 | 妺妺窝人体色www在线小说 | 精品人妻人人做人人爽夜夜爽 | 久久99精品久久久久久动态图 | 美女扒开屁股让男人桶 | 一个人看的视频www在线 | 国产精品成人av在线观看 | 欧美怡红院免费全部视频 | 蜜臀aⅴ国产精品久久久国产老师 | 丰满少妇弄高潮了www | 国产午夜手机精彩视频 | 三上悠亚人妻中文字幕在线 | 熟妇女人妻丰满少妇中文字幕 | 亚洲狠狠婷婷综合久久 | 欧美日韩色另类综合 | 东京热男人av天堂 | 激情五月综合色婷婷一区二区 | 麻豆人妻少妇精品无码专区 | 狠狠色丁香久久婷婷综合五月 | 7777奇米四色成人眼影 | 国产午夜亚洲精品不卡下载 | 精品无码国产自产拍在线观看蜜 | 水蜜桃亚洲一二三四在线 | 亚洲自偷自拍另类第1页 | 久久午夜无码鲁丝片 | 少妇性l交大片 | 高潮毛片无遮挡高清免费视频 | 成人无码视频免费播放 | 无码纯肉视频在线观看 | 欧美成人免费全部网站 | 岛国片人妻三上悠亚 | 日日摸天天摸爽爽狠狠97 | 国产精品久免费的黄网站 | 国产网红无码精品视频 | 欧美精品无码一区二区三区 | 丰满少妇弄高潮了www | 国产麻豆精品一区二区三区v视界 | 日韩精品a片一区二区三区妖精 | 亚洲国产成人av在线观看 | 麻豆精品国产精华精华液好用吗 | 久久久久久av无码免费看大片 | 丰腴饱满的极品熟妇 | 亚洲s色大片在线观看 | 无码人妻精品一区二区三区下载 | 狠狠色噜噜狠狠狠7777奇米 | 一个人看的视频www在线 | 亚洲国产精品成人久久蜜臀 | 国产熟妇另类久久久久 | www成人国产高清内射 | 老司机亚洲精品影院 | 久久久久国色av免费观看性色 | 色婷婷欧美在线播放内射 | 久久综合狠狠综合久久综合88 | 国产成人无码专区 | 少女韩国电视剧在线观看完整 | 国产人成高清在线视频99最全资源 | 国产人妻精品一区二区三区 | 纯爱无遮挡h肉动漫在线播放 | 亚洲精品综合一区二区三区在线 | 无码国模国产在线观看 | 精品熟女少妇av免费观看 | 精品国产福利一区二区 | 国产精品亚洲lv粉色 | 永久黄网站色视频免费直播 | 成人影院yy111111在线观看 | 国产av无码专区亚洲awww | 任你躁在线精品免费 | 国产亚洲精品久久久久久国模美 | 黑人巨大精品欧美一区二区 | 国产熟女一区二区三区四区五区 | 香蕉久久久久久av成人 | 日韩无套无码精品 | 蜜桃无码一区二区三区 | 欧美性生交xxxxx久久久 | 人妻插b视频一区二区三区 | 少妇高潮喷潮久久久影院 | 性欧美牲交xxxxx视频 | 精品乱子伦一区二区三区 | 久久人人爽人人爽人人片ⅴ | 亚洲 欧美 激情 小说 另类 | 欧美35页视频在线观看 | 美女扒开屁股让男人桶 | 久久久中文字幕日本无吗 | 中文字幕人妻无码一区二区三区 | 国产精品久久久 | 日本饥渴人妻欲求不满 | 亚洲精品综合一区二区三区在线 | 中文字幕无码日韩专区 | 伊人久久大香线蕉av一区二区 | 午夜福利电影 | 亚洲码国产精品高潮在线 | 国产精品毛片一区二区 | 免费人成在线视频无码 | 国产精品igao视频网 | 正在播放老肥熟妇露脸 | 欧美xxxxx精品 | 久久亚洲a片com人成 | 国产9 9在线 | 中文 | 97人妻精品一区二区三区 | 男人的天堂2018无码 | 久久亚洲中文字幕无码 | 九月婷婷人人澡人人添人人爽 | 人妻与老人中文字幕 | 久久国产36精品色熟妇 | 搡女人真爽免费视频大全 | 婷婷五月综合缴情在线视频 | 亚洲精品午夜国产va久久成人 | 日本一卡二卡不卡视频查询 | 无码帝国www无码专区色综合 | 俄罗斯老熟妇色xxxx | 双乳奶水饱满少妇呻吟 | 1000部夫妻午夜免费 | 亚洲精品成人福利网站 | 久热国产vs视频在线观看 | 99精品视频在线观看免费 | 高潮毛片无遮挡高清免费 | 久久综合香蕉国产蜜臀av | 国产偷国产偷精品高清尤物 | 樱花草在线播放免费中文 | 内射爽无广熟女亚洲 | 国产午夜无码视频在线观看 | 四虎永久在线精品免费网址 | 亚洲日本va中文字幕 | 中文字幕无码免费久久99 | 亚洲精品国偷拍自产在线观看蜜桃 | 婷婷丁香六月激情综合啪 | 久久99精品久久久久久动态图 | 国产精品嫩草久久久久 | 国产成人无码一二三区视频 | 伊人久久大香线蕉午夜 | 97无码免费人妻超级碰碰夜夜 | 未满成年国产在线观看 | 亚洲精品国产第一综合99久久 | 久久人人爽人人爽人人片av高清 | 狠狠噜狠狠狠狠丁香五月 | 国产一区二区不卡老阿姨 | 人妻少妇精品视频专区 | 少妇久久久久久人妻无码 | 久久午夜无码鲁丝片午夜精品 | 日日天干夜夜狠狠爱 | 色婷婷香蕉在线一区二区 | 亚洲男人av天堂午夜在 | 国产乱子伦视频在线播放 | 中文字幕无线码 | 国产精品人人爽人人做我的可爱 | 国产成人午夜福利在线播放 | 国产成人久久精品流白浆 | 亚洲色www成人永久网址 | а天堂中文在线官网 | 中文精品无码中文字幕无码专区 | 狠狠综合久久久久综合网 | 俺去俺来也在线www色官网 | 中文字幕无码日韩专区 | 午夜福利不卡在线视频 | 欧美性生交xxxxx久久久 | 亚洲精品一区二区三区在线 | 无码人妻少妇伦在线电影 | 成熟女人特级毛片www免费 | 久久 国产 尿 小便 嘘嘘 | 丰满人妻翻云覆雨呻吟视频 | 精品无码av一区二区三区 | 99久久99久久免费精品蜜桃 | 少妇激情av一区二区 | 国产一精品一av一免费 | 日韩精品无码一本二本三本色 | 嫩b人妻精品一区二区三区 | 一个人看的www免费视频在线观看 | 国产午夜福利亚洲第一 | 国内综合精品午夜久久资源 | 一区二区三区乱码在线 | 欧洲 | 伊人色综合久久天天小片 | 中文字幕乱码人妻二区三区 | 性开放的女人aaa片 | 久久国产劲爆∧v内射 | 亚洲gv猛男gv无码男同 | 国产又粗又硬又大爽黄老大爷视 | www国产亚洲精品久久网站 | 强辱丰满人妻hd中文字幕 | 久久精品一区二区三区四区 | 亚洲国产精品成人久久蜜臀 | 久久久av男人的天堂 | 久久国产精品二国产精品 | 亚洲呦女专区 | 国产成人精品一区二区在线小狼 | 国产午夜福利100集发布 | 国产另类ts人妖一区二区 | 天堂а√在线中文在线 | 中文字幕日产无线码一区 | 久久无码专区国产精品s | 自拍偷自拍亚洲精品被多人伦好爽 | 久久午夜无码鲁丝片午夜精品 | 精品久久久无码人妻字幂 | 又大又硬又爽免费视频 | 波多野结衣乳巨码无在线观看 | 国产热a欧美热a在线视频 | 欧美日韩精品 | 国产精品二区一区二区aⅴ污介绍 | 无码播放一区二区三区 | 精品国产乱码久久久久乱码 | 欧美阿v高清资源不卡在线播放 | 国产乱子伦视频在线播放 | 人人妻人人澡人人爽欧美精品 | 青青青爽视频在线观看 | 波多野结衣 黑人 | 色情久久久av熟女人妻网站 | 欧美人与动性行为视频 | 国产又爽又黄又刺激的视频 | 一本大道伊人av久久综合 | 欧美熟妇另类久久久久久不卡 | 中文字幕无码人妻少妇免费 | 日日摸天天摸爽爽狠狠97 | 久久久久av无码免费网 | 久久精品国产一区二区三区 | 青青草原综合久久大伊人精品 | 欧美乱妇无乱码大黄a片 | 免费网站看v片在线18禁无码 | 色情久久久av熟女人妻网站 | 无码人妻少妇伦在线电影 | 亚洲一区av无码专区在线观看 | 日本高清一区免费中文视频 | 婷婷丁香五月天综合东京热 | 暴力强奷在线播放无码 | 国产三级精品三级男人的天堂 | 沈阳熟女露脸对白视频 | 波多野结衣av在线观看 | 欧美日韩久久久精品a片 | 国产无av码在线观看 | 乌克兰少妇xxxx做受 | 国产精品自产拍在线观看 | 日韩精品无码一区二区中文字幕 | 18黄暴禁片在线观看 | 久青草影院在线观看国产 | 国产一区二区三区四区五区加勒比 | 久久久久成人片免费观看蜜芽 | 亚洲欧洲中文日韩av乱码 | 国产精品资源一区二区 | 熟妇女人妻丰满少妇中文字幕 | 日日摸天天摸爽爽狠狠97 | 蜜臀aⅴ国产精品久久久国产老师 | 成人无码影片精品久久久 | 日日碰狠狠丁香久燥 | 欧美日韩在线亚洲综合国产人 | 亚洲 a v无 码免 费 成 人 a v | 亚洲中文字幕va福利 | 欧美三级a做爰在线观看 | 久久久久人妻一区精品色欧美 | 成 人影片 免费观看 | 中文精品无码中文字幕无码专区 | 一本精品99久久精品77 | 成人影院yy111111在线观看 | 99久久精品国产一区二区蜜芽 | 性啪啪chinese东北女人 | 天海翼激烈高潮到腰振不止 | 少妇被粗大的猛进出69影院 | 噜噜噜亚洲色成人网站 | 中文亚洲成a人片在线观看 | 偷窥村妇洗澡毛毛多 | 熟妇人妻无乱码中文字幕 | 色 综合 欧美 亚洲 国产 | 2019nv天堂香蕉在线观看 | 纯爱无遮挡h肉动漫在线播放 | 国内丰满熟女出轨videos | 人妻少妇精品久久 | 激情国产av做激情国产爱 | 在线а√天堂中文官网 | 亚洲а∨天堂久久精品2021 | 欧美熟妇另类久久久久久不卡 | 中文字幕乱码人妻无码久久 | 国产精品自产拍在线观看 | 国产午夜视频在线观看 | ass日本丰满熟妇pics | 国产成人综合在线女婷五月99播放 | 国产精品无套呻吟在线 | 国产欧美亚洲精品a | 亚洲精品中文字幕 | 99re在线播放 | 国产女主播喷水视频在线观看 | 黑人大群体交免费视频 | 18禁止看的免费污网站 | 久久久久av无码免费网 | 三上悠亚人妻中文字幕在线 | 中文字幕av日韩精品一区二区 | 未满成年国产在线观看 | 一个人看的www免费视频在线观看 | 伊在人天堂亚洲香蕉精品区 | 日本丰满熟妇videos | 99视频精品全部免费免费观看 | 日韩欧美中文字幕公布 | 亚洲男女内射在线播放 | 国产激情无码一区二区app | 88国产精品欧美一区二区三区 | 久久人人爽人人爽人人片av高清 | 丰满岳乱妇在线观看中字无码 | 亚洲欧洲日本无在线码 | 无码精品国产va在线观看dvd | 88国产精品欧美一区二区三区 | 色婷婷久久一区二区三区麻豆 | 亚洲精品中文字幕乱码 | 亚洲欧洲日本综合aⅴ在线 | 日韩人妻无码中文字幕视频 | 婷婷丁香六月激情综合啪 | 欧美黑人巨大xxxxx | 亚洲а∨天堂久久精品2021 | 久久久久99精品成人片 | 天天综合网天天综合色 | 最近免费中文字幕中文高清百度 | 乱中年女人伦av三区 | 99久久人妻精品免费一区 | 无码中文字幕色专区 | 清纯唯美经典一区二区 | 中文字幕乱码人妻无码久久 | 一本大道伊人av久久综合 | 日本高清一区免费中文视频 | 国产情侣作爱视频免费观看 | 国产超碰人人爽人人做人人添 | 东京一本一道一二三区 | 国产成人一区二区三区在线观看 | 亚洲精品国偷拍自产在线观看蜜桃 | 老头边吃奶边弄进去呻吟 | 国产精品丝袜黑色高跟鞋 | 国产人妻精品一区二区三区不卡 | 宝宝好涨水快流出来免费视频 | 十八禁真人啪啪免费网站 | 中文字幕无线码免费人妻 | 在线亚洲高清揄拍自拍一品区 | www国产精品内射老师 | 亚洲国产精品无码一区二区三区 | 久久久久久a亚洲欧洲av冫 | 麻豆国产人妻欲求不满 | 天天摸天天碰天天添 | 十八禁视频网站在线观看 | 中文字幕无码视频专区 | 少妇久久久久久人妻无码 | 国产三级久久久精品麻豆三级 | 国产香蕉尹人综合在线观看 | 夜夜高潮次次欢爽av女 | 欧美国产亚洲日韩在线二区 | 精品乱码久久久久久久 | 撕开奶罩揉吮奶头视频 | 国产成人综合在线女婷五月99播放 | 久久久精品人妻久久影视 | 国产精品久久久久久亚洲毛片 | 国产精品美女久久久网av | 精品久久久无码中文字幕 | 中文无码伦av中文字幕 | 亚洲 激情 小说 另类 欧美 | 少妇人妻大乳在线视频 | 国产av一区二区三区最新精品 | 亚洲精品国产精品乱码不卡 | 老熟女重囗味hdxx69 | 精品无码一区二区三区爱欲 | 久久精品人人做人人综合试看 | 沈阳熟女露脸对白视频 | 久久久亚洲欧洲日产国码αv | 国产精品亚洲五月天高清 | 成人一区二区免费视频 | 国色天香社区在线视频 | 亚洲人成影院在线无码按摩店 | 亚洲精品国偷拍自产在线麻豆 | 高潮毛片无遮挡高清免费视频 | 中文字幕无码免费久久99 | 精品日本一区二区三区在线观看 | 无码人妻黑人中文字幕 | 丰满人妻一区二区三区免费视频 | 黑人巨大精品欧美黑寡妇 | 日本爽爽爽爽爽爽在线观看免 | 无码av免费一区二区三区试看 | 天天综合网天天综合色 | 97久久国产亚洲精品超碰热 | 小sao货水好多真紧h无码视频 | 狂野欧美性猛xxxx乱大交 | 亚洲日本va午夜在线电影 | 狠狠色色综合网站 | 国产亚洲欧美日韩亚洲中文色 | 乱人伦中文视频在线观看 | 亚洲国产精品无码久久久久高潮 | 国产亚洲精品久久久久久久久动漫 | 亚洲经典千人经典日产 | 免费观看的无遮挡av | 熟妇人妻激情偷爽文 | 欧美日韩色另类综合 | 亚洲日韩av一区二区三区中文 | 成人一在线视频日韩国产 | 日韩av无码一区二区三区 | 日韩av无码一区二区三区不卡 | 久久人人爽人人爽人人片av高清 | 久久久www成人免费毛片 | 国产成人无码区免费内射一片色欲 | 天堂无码人妻精品一区二区三区 | 国产av剧情md精品麻豆 | 性欧美大战久久久久久久 | 国产成人精品必看 | 亚洲欧美色中文字幕在线 | 成人一在线视频日韩国产 | 日日天日日夜日日摸 | 少妇激情av一区二区 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 亚洲日韩av一区二区三区中文 | 无码人妻少妇伦在线电影 | 亚洲 欧美 激情 小说 另类 | 国产肉丝袜在线观看 | 天海翼激烈高潮到腰振不止 | 亚洲精品美女久久久久久久 | 人妻少妇精品无码专区二区 | 久久久国产精品无码免费专区 | 成熟人妻av无码专区 | 老司机亚洲精品影院无码 | 精品国产一区二区三区av 性色 | 久久成人a毛片免费观看网站 | 88国产精品欧美一区二区三区 | 性欧美大战久久久久久久 | 国产精品无码永久免费888 | 国产免费观看黄av片 | 无码一区二区三区在线观看 | 成人免费视频视频在线观看 免费 | 亚洲小说春色综合另类 | 欧美国产日韩亚洲中文 | 免费无码的av片在线观看 | 国产精品.xx视频.xxtv | 99精品国产综合久久久久五月天 | 亚洲中文无码av永久不收费 | 成人无码影片精品久久久 | 大色综合色综合网站 | 99久久亚洲精品无码毛片 | 55夜色66夜色国产精品视频 | 成年美女黄网站色大免费全看 | 四虎4hu永久免费 | 国产精品亚洲а∨无码播放麻豆 | 任你躁在线精品免费 | 精品国产青草久久久久福利 | 九九久久精品国产免费看小说 | 在线视频网站www色 | 女人被男人爽到呻吟的视频 | 国产精品亚洲综合色区韩国 | 国产精品igao视频网 | 男女爱爱好爽视频免费看 | 伊人色综合久久天天小片 | 在线视频网站www色 | а√资源新版在线天堂 | 牛和人交xxxx欧美 | 色诱久久久久综合网ywww | 熟女俱乐部五十路六十路av | 久久综合久久自在自线精品自 | 激情内射日本一区二区三区 | 免费无码的av片在线观看 | 台湾无码一区二区 | 男女性色大片免费网站 | 樱花草在线社区www | 亚洲色欲久久久综合网东京热 | 国产香蕉尹人视频在线 | 激情国产av做激情国产爱 | 亚洲码国产精品高潮在线 | 精品国偷自产在线 | 无遮挡国产高潮视频免费观看 | 久久视频在线观看精品 | 曰韩少妇内射免费播放 | 黑人粗大猛烈进出高潮视频 | 国产精品久久国产精品99 | v一区无码内射国产 | 1000部夫妻午夜免费 | 对白脏话肉麻粗话av | 俺去俺来也在线www色官网 | 国产精品第一区揄拍无码 | 性欧美videos高清精品 | 成人精品视频一区二区三区尤物 | 国产成人无码一二三区视频 | 草草网站影院白丝内射 | 亚洲大尺度无码无码专区 | 色综合久久88色综合天天 | 日本一卡二卡不卡视频查询 | 精品熟女少妇av免费观看 | 亚洲精品国产精品乱码视色 | 精品成人av一区二区三区 | 国产一区二区三区四区五区加勒比 | 色综合久久久久综合一本到桃花网 | 日本高清一区免费中文视频 | 亚洲一区av无码专区在线观看 | 亚洲自偷自拍另类第1页 | 国产成人精品视频ⅴa片软件竹菊 | 日本护士毛茸茸高潮 | 四虎国产精品一区二区 | 日韩欧美中文字幕在线三区 | 国产香蕉尹人综合在线观看 | 蜜桃视频韩日免费播放 | 亚洲午夜无码久久 | 亚欧洲精品在线视频免费观看 | 中文字幕无码人妻少妇免费 | 中文字幕无码日韩专区 | 亚洲精品国产精品乱码视色 | 荡女精品导航 | 久久www免费人成人片 | 日日摸天天摸爽爽狠狠97 | 国产成人综合在线女婷五月99播放 | 99精品国产综合久久久久五月天 | 美女极度色诱视频国产 | 一区二区传媒有限公司 | 免费无码午夜福利片69 | 2020久久香蕉国产线看观看 | 国产人妖乱国产精品人妖 | 夜夜夜高潮夜夜爽夜夜爰爰 | 日本欧美一区二区三区乱码 | 永久黄网站色视频免费直播 | 欧美人与动性行为视频 | 日本xxxx色视频在线观看免费 | 国产av一区二区精品久久凹凸 | 性史性农村dvd毛片 | 玩弄人妻少妇500系列视频 | 国产av久久久久精东av | 精品一二三区久久aaa片 | 亚洲精品www久久久 | 午夜免费福利小电影 | 图片区 小说区 区 亚洲五月 | 亚洲人成影院在线观看 | 成熟女人特级毛片www免费 | 久久久久久久女国产乱让韩 | 日日噜噜噜噜夜夜爽亚洲精品 | 婷婷五月综合缴情在线视频 | 亚洲小说图区综合在线 | 粗大的内捧猛烈进出视频 | 国产片av国语在线观看 | 精品乱子伦一区二区三区 | 国产97色在线 | 免 | 55夜色66夜色国产精品视频 | 麻豆国产人妻欲求不满谁演的 | 欧美精品免费观看二区 | 亚洲国产成人a精品不卡在线 | 亚洲精品国偷拍自产在线观看蜜桃 | 大地资源中文第3页 | 欧美日本免费一区二区三区 | 扒开双腿吃奶呻吟做受视频 | 婷婷五月综合缴情在线视频 | 国产一精品一av一免费 | 天天爽夜夜爽夜夜爽 | 日日躁夜夜躁狠狠躁 | 国产激情无码一区二区app | 四虎影视成人永久免费观看视频 | 日本成熟视频免费视频 | 国产精品久久久久影院嫩草 | 国产凸凹视频一区二区 | 国产精品无码一区二区桃花视频 | 动漫av网站免费观看 | 99久久无码一区人妻 | 亚洲精品国产品国语在线观看 | 亚洲热妇无码av在线播放 | 女高中生第一次破苞av | 国产成人精品优优av | 2019午夜福利不卡片在线 | 精品乱码久久久久久久 | 欧美放荡的少妇 | 国产精华av午夜在线观看 | 纯爱无遮挡h肉动漫在线播放 | 国产精品二区一区二区aⅴ污介绍 | 中文字幕无码免费久久9一区9 | 十八禁真人啪啪免费网站 | 久久久www成人免费毛片 | 国产乱人偷精品人妻a片 | www国产精品内射老师 | 99麻豆久久久国产精品免费 | 高潮喷水的毛片 | 色五月五月丁香亚洲综合网 | 亚洲日韩av一区二区三区四区 | 亚洲精品国产a久久久久久 | 精品无码成人片一区二区98 | 中文字幕无码av激情不卡 | 成人免费视频一区二区 | 免费观看黄网站 | 国产在线精品一区二区高清不卡 | 久久精品99久久香蕉国产色戒 | 久久久国产精品无码免费专区 | 在线天堂新版最新版在线8 | 日韩无套无码精品 | 在线 国产 欧美 亚洲 天堂 | 精品久久久无码中文字幕 | 亚洲中文字幕无码一久久区 | 国产精品无码永久免费888 | 九月婷婷人人澡人人添人人爽 | 国产午夜精品一区二区三区嫩草 | 国产午夜手机精彩视频 | 中文无码成人免费视频在线观看 | 欧美 日韩 人妻 高清 中文 | 欧美性猛交内射兽交老熟妇 | 乱码午夜-极国产极内射 | 丰满护士巨好爽好大乳 | 乱人伦人妻中文字幕无码久久网 | 福利一区二区三区视频在线观看 | 亚洲毛片av日韩av无码 | 熟女少妇人妻中文字幕 | 18精品久久久无码午夜福利 | 亚洲无人区一区二区三区 | 国产网红无码精品视频 | 亚洲呦女专区 | 无码国产色欲xxxxx视频 | 亚洲日本va午夜在线电影 | 国产无av码在线观看 | 亚洲综合在线一区二区三区 | 青草青草久热国产精品 | 色婷婷香蕉在线一区二区 | 亚洲中文字幕无码一久久区 | 国产麻豆精品精东影业av网站 | 亚洲国产欧美国产综合一区 | 免费国产成人高清在线观看网站 | 狂野欧美性猛交免费视频 | 内射老妇bbwx0c0ck | 国产女主播喷水视频在线观看 | 妺妺窝人体色www在线小说 | 国产农村乱对白刺激视频 | 免费人成在线视频无码 | 中文字幕av伊人av无码av | 国产精品多人p群无码 | 精品人人妻人人澡人人爽人人 | 久久亚洲精品成人无码 | 国产成人无码av片在线观看不卡 | 无码人妻精品一区二区三区下载 | 国内精品人妻无码久久久影院 | 国产97色在线 | 免 | 成年美女黄网站色大免费全看 | 99久久亚洲精品无码毛片 | 亚洲色www成人永久网址 | 东北女人啪啪对白 | 欧美性猛交内射兽交老熟妇 | 精品人妻人人做人人爽 | 丝袜足控一区二区三区 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 激情五月综合色婷婷一区二区 | 天堂а√在线地址中文在线 | 国产成人精品久久亚洲高清不卡 | 中文毛片无遮挡高清免费 | 亚洲伊人久久精品影院 | 亚洲一区av无码专区在线观看 | 国产黄在线观看免费观看不卡 | 欧美三级不卡在线观看 | 亚洲国产精品无码一区二区三区 | 偷窥日本少妇撒尿chinese | 波多野结衣aⅴ在线 | 精品亚洲韩国一区二区三区 | 国内少妇偷人精品视频免费 | 久久亚洲日韩精品一区二区三区 | 老熟妇乱子伦牲交视频 | 国产精品爱久久久久久久 | 国产av人人夜夜澡人人爽麻豆 | 性欧美videos高清精品 | 正在播放东北夫妻内射 | 欧美人与牲动交xxxx | 99久久久国产精品无码免费 | 天天躁夜夜躁狠狠是什么心态 | 四虎影视成人永久免费观看视频 | 欧美精品国产综合久久 | 无码人妻av免费一区二区三区 | 国产免费观看黄av片 | 亚洲欧美综合区丁香五月小说 | 久久久久国色av免费观看性色 | 久久www免费人成人片 | 亚洲欧美日韩成人高清在线一区 | 国产午夜视频在线观看 | 少妇高潮一区二区三区99 | 久久久av男人的天堂 | 日本精品久久久久中文字幕 | 亚洲a无码综合a国产av中文 | 7777奇米四色成人眼影 | 99久久精品国产一区二区蜜芽 | 99久久人妻精品免费一区 | 无码纯肉视频在线观看 | 国内精品久久久久久中文字幕 | 免费看少妇作爱视频 | 国产香蕉97碰碰久久人人 | 久久久久久av无码免费看大片 | 久久综合九色综合欧美狠狠 | 青青草原综合久久大伊人精品 | 国产午夜视频在线观看 | 欧美人与禽zoz0性伦交 | 波多野42部无码喷潮在线 | 色综合久久久无码网中文 | 国产人妻久久精品二区三区老狼 | 久久精品国产亚洲精品 | 国产凸凹视频一区二区 | 一本久久a久久精品亚洲 | 又大又黄又粗又爽的免费视频 | 精品亚洲成av人在线观看 | 国产精品对白交换视频 | 亚洲欧洲无卡二区视頻 | 欧美老人巨大xxxx做受 | 日本精品高清一区二区 | 国产成人无码专区 | 帮老师解开蕾丝奶罩吸乳网站 | 国产绳艺sm调教室论坛 | 精品久久久久久人妻无码中文字幕 | 国产超碰人人爽人人做人人添 | 欧美三级不卡在线观看 | 任你躁在线精品免费 | 成人女人看片免费视频放人 | 午夜时刻免费入口 | 丰满护士巨好爽好大乳 | 免费无码一区二区三区蜜桃大 | 亚洲天堂2017无码 | 玩弄中年熟妇正在播放 | 小sao货水好多真紧h无码视频 | 国产精品igao视频网 | 久久婷婷五月综合色国产香蕉 | 欧美精品无码一区二区三区 | 国产精品沙发午睡系列 | 国产69精品久久久久app下载 | 婷婷丁香五月天综合东京热 | 国精品人妻无码一区二区三区蜜柚 | 国产精品人人爽人人做我的可爱 |