在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

ucos-II移植到51單片機的解決辦法

ss ? 作者:工程師譚軍 ? 2018-09-11 09:30 ? 次閱讀

本文主要是關于ucos-II的相關介紹,并著重對ucos-II移植到51單片機進行了詳盡的闡述。

ucos-II

μC/OS-II由Micrium公司提供,是一個可移植、可固化的、可裁剪的、占先式多任務實時內核,它適用于多種微處理器微控制器和數字處理芯片(已經移植到超過100種以上的微處理器應用中)。同時,該系統源代碼開放、整潔、一致,注釋詳盡,適合系統開發。 μC/OS-II已經通過聯邦航空局(FAA)商用航行器認證,符合航空無線電技術委員會(RTCA)DO-178B標準。

μC/OS-II被廣泛應用于微處理器、微控制器和數字信號處理器。

μC/OS-II 的前身是μC/OS,最早出自于1992 年美國嵌入式系統專家Jean J.Labrosse 在《嵌入式系統編程》雜志的5 月和6 月刊上刊登的文章連載,并把μC/OS 的源碼發布在該雜志的B B S 上。

μC/OS 和μC/OS-II 是專門為計算機的嵌入式應用設計的, 絕大部分代碼是用C語言編寫的。CPU 硬件相關部分是用匯編語言編寫的、總量約200行的匯編語言部分被壓縮到最低限度,為的是便于移植到任何一種其它的CPU 上。用戶只要有標準的ANSI 的C交叉編譯器,有匯編器、連接器等軟件工具,就可以將μC/OS-II嵌入到開發的產品中。μC/OS-II 具有執行效率高、占用空間小、實時性能優良和可擴展性強等特點, 最小內核可編譯至 2KB 。μC/OS-II 已經移植到了幾乎所有知名的CPU 上。

嚴格地說uC/OS-II只是一個實時操作系統內核,它僅僅包含了任務調度,任務管理,時間管理,內存管理和任務間的通信和同步等基本功能。沒有提供輸入輸出管理,文件系統,網絡等額外的服務。但由于uC/OS-II良好的可擴展性和源碼開放,這些非必須的功能完全可以由用戶自己根據需要分別實現。

uC/OS-II目標是實現一個基于優先級調度的搶占式的實時內核,并在這個內核之上提供最基本的系統服務,如信號量,郵箱,消息隊列,內存管理,中斷管理等。

uC/OS-II以源代碼的形式發布,是開源軟件, 但并不意味著它是免費軟件。你可以將其用于教學和私下研究(peaceful research);但是如果你將其用于商業用途,那么你必須通過Micrium獲得商用許可。

uCOSII移植的一點心得

uCOS-II是一種十分優秀實時操作系統,其在NASA的認證通過直接說明了其優秀及穩健的性能,同時由于其完全open,所以受到廣大開源愛好者的喜愛。uCOS-II簡單明了,同時絕大部分代碼都采用ANSI C編寫(除了與CPU相關代碼外),所以學習起來十分容易,是嵌入式學習乃至操作系統學習最好的入門OS之一。

我主要想講一下自己最近移植uCOS-II的心得,因為最近也在學習操作系統,所以這段日子對于uCOS-II的學習的確也讓我對于操作系統有了一個實際深刻的認識。

uCOS-II移植其實十分簡單。對于一個處理器,需要做的工作只有:修改三個文件――os_cpu_c.c、os_cpu.h、os_cpu_a.asm(ASM文件根據編譯器不同而又有一些不同)。

用另一種方式說,需要做的工作就是修改五個函數:

1、os_cpu_c.c:OSTaskStkInit;

2、os_cpu_a.asm:OSStartHighRdy、OSCtxSw、OSIntCtxSw、OSTickISR;

OSTaskStkInit函數是針對CPU壓棧的函數,需要模仿出CPU初始化后的寄存器狀況。也使需要修改的唯一一個C語言函數。其他的都是匯編函數。

如果我們可以從uCOS-II官方網站上找到相同CPU或是相似的同一家族的CPU移植代碼,那么我們的移植工作將會簡單得多。因為至少我們可以只用了解這個處理器的內部結構,而不用細致的了解其匯編指令等很多繁瑣而沒有意義的事情(有的處理器你可能一輩子不再用它,了解得太細致只是在浪費時間)。

譬如,此次我要做的是將uCOS-II移植到瑞薩M16C/62A上,而官方網站上只有其62P的移植代碼,于是乎我就將二者的datasheet在CPU的寄存器、中斷部分仔細比對,發現二者區別很小。最大的區別恐怕就在CPU內部寄存器中的INTBL和PC寄存器二者順序相反吧,這只要在相關部分注意就可以了,所以很容易就搞定了CPU相關代碼部分。

總結一下移植中浪費我時間的幾個小錯誤吧,這完全是個人粗心導致的失誤:

1、在os_cpu.h文件中需要用宏定義將OS_TASK_SW指向OSCtxSw函數,而我開始像以前一樣直接將OSCtxSw函數與0號軟終端鏈接起來,結果發現函數調用不成功。后來直接用宏定義將OS_TASK_SW define為OSCtxSw函數,初步調試通過,即驗證OSCtxSw函數正確,但是到后來調用任務的時候卻發現任務切換不正常,不得不重新將函數與中斷結合起來,當然就不能還是0號中斷了,而是改為一個比較保險的軟終端,這個問題糾結了很長時間。

2、在看書的時候不仔細直接導致我犯了一個大錯誤。起初以為task只要是能夠達到功能的死循環即可。所以每個task函數都是while(1)或者for(;;;),但是我沒有注意到一點就是每個task里面都應該有OSTimeDly()函數,否則將導致任務之間不能跳轉。所以最初的實驗現象是永遠只有一個任務在運行,但是任務不能切換……

3、未注意到版本之間的區別。我們知道在新版本的uCOS-II中,添加了一個文件os_tmr.c,主要是在timer上面做了很大的調整,但是我沒有注意到這一點,仍舊按照老版本的方法調試,導致函數調用讓我完全不知所措。最后注意到os的源代碼的不同,仔細閱讀源代碼之后知道了其用法,其實如果不需要timer太強大的功能,只要在os_cfg.h文件中將OS_TMR_EN設置為0即可。這在習慣老版本調試方法的同學而言是很好的方法。

ucos-II移植到51單片機的解決辦法

先來了解和51移植相關的三個概念:

第一,移植UCOS必須要了解編譯器,我們一般使用的51編譯器都是KEIL。值得一提的是KEIL對可重入函數的處理。由于51單片機的堆棧指針是8位的,所以硬件堆棧只能設置在內部RAM的DATA區和IDATA區(DATA、IDATA、PDATA、XDATA、CODE這些概念相關資料很多,我不想在此處滋述),所以51的堆棧是很緊張的。于是,KEIL將函數內的動態變量和函數傳遞的參數(當然有一部分參數是用寄存器直接傳送的),放在分配的固定數據段中,函數執行時在固定的數據段中去取得相關的數據,而不是像傳統的CPU都用堆棧來處理,這就導致了函數不可重入,因為當一個函數沒執行完成時再次執行會把數據段里的內容覆蓋掉。為了使函數可重入KEIL引入了仿真堆棧的概念(重入函數需在函數定義后面加上reentrant關鍵字),用仿真堆棧來傳遞參數及分配動態變量,就好像傳統堆棧的入棧、出棧操作一般,如此函數第二次進入執行時,就不會覆蓋掉上一次的變量和參數,仿真堆棧實現原理詳見http://hi.baidu.com/lyb1900/blog/item/99b6313defc2b40abaa167fe.html 。但是,KEIL的這一機制會給我們移植造成了麻煩,任務切換時不僅要保存好硬件堆棧內容,還要保存好仿真堆棧的內容。(建議先理解仿真堆棧的概念)

第二,其他類型的CPU可以在任務切換時先將SP指針保存到被中斷任務的OSTCBCur-》OSTCBStkPtr中,再將高優先級任務的OSTCBCur-》OSTCBStkPtr恢復到SP中就可以了,各個任務使用各自的堆棧空間,互不干擾,切換也很方便。而51的堆棧指針是8位的,SP只能指向內部RAM空間,但是內部RAM很小,根本不可能將所有任務堆棧都設置在內部RAM中(DATA和IDATA區)。所以,51只能設置一個固定的硬件堆棧,每個任務可以在外部RAM中設置各自的任務堆棧,任務切換時,將本任務所使用到的硬件堆棧的長度和內容保存到任務堆棧中,然后將高優先級任務的用戶堆棧里的內容恢復到硬件堆棧中。所以51切換任務會比較慢。

第三,在KEIL的工程配置Target選項中會有一個Memory Model選項。用鼠標點擊Memory Model的下拉箭頭,會有3個選項。

Small:變量存儲在內部ram里。

Compact:變量存儲在外部ram里,使用頁8位間接尋址

Large:變量存儲在外部Ram里,使用16位間接尋址。

這三個變量決定了定義的變量在不加存儲類型關鍵字時,變量存放的位置。這一點很多網站、資料都說的很明白。但是其實還有一點很多資料都是沒說的。它還默認決定了上述仿真堆棧的位置。這一點在51的啟動代碼STARTUP.asm中能體現出來。其中有一段如下:

; Stack Space for reentrant functions in the SMALL model.

IBPSTACK EQU 1 ; set to 1 if small reentrant is used.

IBPSTACKTOP EQU 0FFH+1 ; set top of stack to highest location+1.

;

; Stack Space for reentrant functions in the LARGE model.

XBPSTACK EQU 0 ; set to 1 if large reentrant is used.

XBPSTACKTOP EQU 7FFFH+1; set top of stack to highest location+1.

;

; Stack Space for reentrant functions in the COMPACT model.

PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.

PBPSTACKTOP EQU 7FFFH+1; set top of stack to highest location+1.

IF IBPSTACK 《》 0

EXTRN DATA (?C_IBP)

MOV ?C_IBP,#LOW IBPSTACKTOP

ENDIF

IF XBPSTACK 《》 0

EXTRN DATA (?C_XBP)

MOV ?C_XBP,#HIGH XBPSTACKTOP

MOV ?C_XBP+1,#LOW XBPSTACKTOP

ENDIF

IF PBPSTACK 《》 0

EXTRN DATA (?C_PBP)

MOV ?C_PBP,#LOW PBPSTACKTOP

ENDIF

注釋講的很清楚,根據所選模式,編譯器會將IBPSTACK、PBPSTACK或者XBPSTACK設置為1,就決定了仿真堆棧在IDATA區、PDAIA區還是XDATA區。對應的,KEIL會自動分配一個仿真堆棧指針,分別是?C_IBP、?C_PBP和(?C_XBP、?C_XBP+1),由于尋址XDATA區需要16位地址,所以需要兩個字節。這三個指針是KEIL根據選擇的Memory Model選項自動分配的。

注意:不要試圖在選擇好模式后將仿真堆棧設置在另一模式的空間中。比如,我用的小模式編譯,仿真堆棧在IDATA區,用的仿真堆棧指針是?C_IBP,但是我現在在啟動代碼中將IBPSTACK定義為0,將XBPSTACK設置為1,看起來我們先把仿真堆棧設置在XDATA區了,但實際上其它代碼段中使用的仿真堆棧指針任然是?C_IBP。有趣的是,KEIL還為我們的啟動代碼做了一個很友好的列表框選擇界面。但實際上選擇好編譯模式后,仿真堆棧使用空間是不能更改的,不知道KEIL為什么這么做?但是我們有時候要根據單片機的型號選擇仿真堆棧的起始地址。

講了那么多,應該來看看關于堆棧的組織了,首先是不知道哪位前輩移植的,用的小模式編譯的堆棧結構:

ucos-II移植到51單片機的解決辦法

每個任務分都需要配一個任務堆棧,OSTCBCur-》OSTCBStkPtr指向任務堆棧的棧底,任務堆棧的首字節是仿真堆棧指針?C_IBP(由于是小模式編譯,所以使用的仿真堆棧設置在IDAIA區)。用戶堆棧中緊接著存放的是該任務的仿真堆棧中的內容。再接著是系統堆棧(就是SP指針所指的堆棧)的長度,最后是系統堆棧的內容。

任務在切換時,首先將當前的?C_IBP的值保存到本任務堆棧的首地址中,然后將仿真堆棧的全部內容復制到任務堆棧中(仿真堆棧棧底固定在IDATA區的最高字節0xff,可以根據(0xff-?C_IBP+1)的值來確定所使用的仿真堆棧的長度),接著保存系統堆棧的長度(系統堆棧設置在DATA或IDATA區中,系統堆棧的棧底的地址我們可以在啟動代碼中設置,長度可以用(SP-Stack+1)來計算得到)最后將所用的系統堆棧中的內容復制到任務堆棧中。

然后得到高優先級的任務堆棧,首先恢復高優先級任務的?C_IBP,然后計算出高優先級任務所用仿真堆棧的長度,將保存的仿真堆棧的內容一一恢復到仿真堆棧中,然后得到系統棧的長度,再將保存的系統堆棧的內容恢復到系統堆棧中,最后恢復SP指針并執行RETI返回指令,便實現了任務切換。

任務被打斷時將仿真堆棧和系統堆棧的內容全都備份到任務堆棧中,在恢復運行時將相應的內容還原到系統堆棧和仿真堆棧中。

這種方法的缺點是,任務切換將會變的很慢,因為要分別拷貝和恢復仿真堆棧和系統堆棧的全部內容。完全可以將仿真堆棧設置在XDATA區中,任務切換時,只需保存和恢復?C_XBP指針就行了,而不必每次都拷貝和恢復仿真堆棧的全部內容。由于SP指針只有8位,系統堆棧只能設置在內部RAM中。

再來看看楊屹大俠大模式編譯下的堆棧結構:

ucos-II移植到51單片機的解決辦法

同樣,每個任務分配一個任務堆棧,OSTCBCur-》OSTCBStkPtr指向任務堆棧的棧底,任務堆棧的首字節是系統堆棧的長度,接著是系統堆棧的全部內容。再接著是仿真堆棧指針?C_XBP的高低字節(因為是大模式編譯,所以仿真堆棧在XDATA區),任務堆棧再高的字節是作為仿真堆棧用的,用戶堆棧的棧頂就是仿真堆棧的棧底。

任務切換時,首先計算任務使用的系統堆棧的長度,將長度保存在任務堆棧棧底,然后將使用的系統堆棧的內容全部復制到任務堆棧中,最后保存當前的?C_XBP仿真堆棧指針的高低字節。

接著恢復高優先級任務的信息,先得到堆棧長度,將備份的堆棧內容恢復到系統堆棧中,并恢復SP指針(根據長度和系統堆棧的棧底可以計算出SP指針的值)。最后恢復?C_XBP的高低字節。便實現了任務的切換。

任務切換時將系統堆棧的內容和仿真堆棧指針保存起來,再將高優先級任務的仿真堆棧指針和系統堆棧的內容恢復。

和上述的小模式下的切換過程相比,仿真堆棧的內容在任務切換時不需要保存和恢復了,任務切換速度會提高不少。但是讀過楊屹大俠代碼的朋友肯定知道,每個任務堆棧的大小都要設置成相同。這對于有些堆棧使用很少的任務來說是很浪費的,而且51的RAM本來就那么緊張?仿真堆棧被設置在任務堆棧的最高地址處,細心的朋友會發現,堆棧檢測函數肯定是無法運行了。

正是意識到這些缺陷,我對楊屹大俠移植的代碼進行了一些改動,堆棧結構也有較大改變,使用的也是大模式編譯:

ucos-II移植到51單片機的解決辦法

先來了解和51移植相關的三個概念:

第一,移植UCOS必須要了解編譯器,我們一般使用的51編譯器都是KEIL。值得一提的是KEIL對可重入函數的處理。由于51單片機的堆棧指針是8位的,所以硬件堆棧只能設置在內部RAM的DATA區和IDATA區(DATA、IDATA、PDATA、XDATA、CODE這些概念相關資料很多,我不想在此處滋述),所以51的堆棧是很緊張的。于是,KEIL將函數內的動態變量和函數傳遞的參數(當然有一部分參數是用寄存器直接傳送的),放在分配的固定數據段中,函數執行時在固定的數據段中去取得相關的數據,而不是像傳統的CPU都用堆棧來處理,這就導致了函數不可重入,因為當一個函數沒執行完成時再次執行會把數據段里的內容覆蓋掉。為了使函數可重入KEIL引入了仿真堆棧的概念(重入函數需在函數定義后面加上reentrant關鍵字),用仿真堆棧來傳遞參數及分配動態變量,就好像傳統堆棧的入棧、出棧操作一般,如此函數第二次進入執行時,就不會覆蓋掉上一次的變量和參數,仿真堆棧實現原理詳見http://hi.baidu.com/lyb1900/blog/item/99b6313defc2b40abaa167fe.html 。但是,KEIL的這一機制會給我們移植造成了麻煩,任務切換時不僅要保存好硬件堆棧內容,還要保存好仿真堆棧的內容。(建議先理解仿真堆棧的概念)

第二,其他類型的CPU可以在任務切換時先將SP指針保存到被中斷任務的OSTCBCur-》OSTCBStkPtr中,再將高優先級任務的OSTCBCur-》OSTCBStkPtr恢復到SP中就可以了,各個任務使用各自的堆棧空間,互不干擾,切換也很方便。而51的堆棧指針是8位的,SP只能指向內部RAM空間,但是內部RAM很小,根本不可能將所有任務堆棧都設置在內部RAM中(DATA和IDATA區)。所以,51只能設置一個固定的硬件堆棧,每個任務可以在外部RAM中設置各自的任務堆棧,任務切換時,將本任務所使用到的硬件堆棧的長度和內容保存到任務堆棧中,然后將高優先級任務的用戶堆棧里的內容恢復到硬件堆棧中。所以51切換任務會比較慢。

第三,在KEIL的工程配置Target選項中會有一個Memory Model選項。用鼠標點擊Memory Model的下拉箭頭,會有3個選項。

Small:變量存儲在內部ram里。

Compact:變量存儲在外部ram里,使用頁8位間接尋址

Large:變量存儲在外部Ram里,使用16位間接尋址。

這三個變量決定了定義的變量在不加存儲類型關鍵字時,變量存放的位置。這一點很多網站、資料都說的很明白。但是其實還有一點很多資料都是沒說的。它還默認決定了上述仿真堆棧的位置。這一點在51的啟動代碼STARTUP.asm中能體現出來。其中有一段如下:

; Stack Space for reentrant functions in the SMALL model.

IBPSTACK EQU 1 ; set to 1 if small reentrant is used.

IBPSTACKTOP EQU 0FFH+1 ; set top of stack to highest location+1.

;

; Stack Space for reentrant functions in the LARGE model.

XBPSTACK EQU 0 ; set to 1 if large reentrant is used.

XBPSTACKTOP EQU 7FFFH+1; set top of stack to highest location+1.

;

; Stack Space for reentrant functions in the COMPACT model.

PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.

PBPSTACKTOP EQU 7FFFH+1; set top of stack to highest location+1.

IF IBPSTACK 《》 0

EXTRN DATA (?C_IBP)

MOV ?C_IBP,#LOW IBPSTACKTOP

ENDIF

IF XBPSTACK 《》 0

EXTRN DATA (?C_XBP)

MOV ?C_XBP,#HIGH XBPSTACKTOP

MOV ?C_XBP+1,#LOW XBPSTACKTOP

ENDIF

IF PBPSTACK 《》 0

EXTRN DATA (?C_PBP)

MOV ?C_PBP,#LOW PBPSTACKTOP

ENDIF

注釋講的很清楚,根據所選模式,編譯器會將IBPSTACK、PBPSTACK或者XBPSTACK設置為1,就決定了仿真堆棧在IDATA區、PDAIA區還是XDATA區。對應的,KEIL會自動分配一個仿真堆棧指針,分別是?C_IBP、?C_PBP和(?C_XBP、?C_XBP+1),由于尋址XDATA區需要16位地址,所以需要兩個字節。這三個指針是KEIL根據選擇的Memory Model選項自動分配的。

注意:不要試圖在選擇好模式后將仿真堆棧設置在另一模式的空間中。比如,我用的小模式編譯,仿真堆棧在IDATA區,用的仿真堆棧指針是?C_IBP,但是我現在在啟動代碼中將IBPSTACK定義為0,將XBPSTACK設置為1,看起來我們先把仿真堆棧設置在XDATA區了,但實際上其它代碼段中使用的仿真堆棧指針任然是?C_IBP。有趣的是,KEIL還為我們的啟動代碼做了一個很友好的列表框選擇界面。但實際上選擇好編譯模式后,仿真堆棧使用空間是不能更改的,不知道KEIL為什么這么做?但是我們有時候要根據單片機的型號選擇仿真堆棧的起始地址。

結語

關于ucos-II的相關介紹就到這了,如有不足之處歡迎指正。

相關閱讀推薦:UCOS-II操作系統在ZEVIO1020上移植過程的主要步驟詳解

相關閱讀推薦:uCOSii的移植過程詳解

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 處理器
    +關注

    關注

    68

    文章

    19825

    瀏覽量

    233776
  • 單片機
    +關注

    關注

    6065

    文章

    44934

    瀏覽量

    647653
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    快速實現STM32移植ucos-ii

    快速實現STM32移植ucos-ii,歡迎大家一起學習[groupid=618]單片機項目開發設計群[/groupid]
    發表于 08-08 16:28

    ucos_II51單片機上的移植源代碼

    求各位大神幫忙發一個51單片機ucos-II移植好的源代碼
    發表于 04-26 23:33

    51系列單片機移植uCOS-II

    本文詳細系統地介紹了uC/OS-II51單片機上的移植、重入實現方法、硬件仿真、固化、人機界面等關鍵內容。關鍵詞:嵌入式實時多任務操作系統、uC/OS-
    發表于 06-16 11:22 ?4798次閱讀
    在<b class='flag-5'>51</b>系列<b class='flag-5'>單片機</b>上<b class='flag-5'>移植</b><b class='flag-5'>uCOS-II</b>

    ucOS-II入門經典教程

    ucOS-II入門經典教程,ucOS-II入門經典教程
    發表于 11-06 10:07 ?0次下載

    盤古STM32F103開發板移植uCOS-II詳細說明

    盤古STM32F103開發板移植uCOS-II詳細說明
    發表于 03-02 17:29 ?13次下載

    STM32平臺移植uCOS-II詳細說明-2012.11.13

    STM32平臺移植uCOS-II詳細說明-2012.11.13
    發表于 03-04 15:31 ?12次下載

    uCOS-ii中文書

    學習uCOS-ii的最好中文教材,uCOS-ii中文書(邵貝貝)
    發表于 08-24 18:31 ?0次下載

    uCOS-II原理1

    原理uCOS-II
    發表于 12-20 22:58 ?5次下載

    uCOS-II原理2

    uCOS-II原理2
    發表于 12-20 22:53 ?0次下載

    uCOS-II原理3

    uCOS-II原理3
    發表于 12-20 22:52 ?0次下載

    在W78E58處理器上移植uCOS-II

    在W78E58處理器上移植uCOS-II
    發表于 01-08 14:27 ?12次下載

    uCOS-II在MSP430移植

    uCOS-II在MSP430移植
    發表于 10-12 17:24 ?9次下載
    <b class='flag-5'>uCOS-II</b>在MSP430<b class='flag-5'>移植</b>

    手把手盤古STM32開發板移植uCOS-II教程

    手把手盤古STM32開發板移植uCOS-II教程
    發表于 10-16 09:38 ?22次下載

    如何在系列51單片機移植uCOS-II

    本文詳細系統地介紹了uC/OS-II51單片機上的移植、重入實現方法、硬件仿真、固化、人機界面等關鍵內容。
    發表于 08-02 17:34 ?2次下載
    如何在系列<b class='flag-5'>51</b><b class='flag-5'>單片機</b>上<b class='flag-5'>移植</b><b class='flag-5'>uCOS-II</b>

    基于51單片機uCOS_ii仿真源碼下載

    基于51單片機uCOS_ii仿真源碼下載
    發表于 04-09 14:30 ?20次下載
    主站蜘蛛池模板: 久久99精品福利久久久 | 天天插在线视频 | 爱爱免费网址 | 国产在线精品香蕉综合网一区 | 四虎永久免费网站入口2020 | 国产精品黄页网站在线播放免费 | h在线观看视频 | 一区二区三区免费在线 | 色拍拍综合网 | 亚洲国产成人久久一区www | 色婷婷五 | www.色天使| 午夜精品久久久久久久第一页 | 成片免费的禁v影片 | 亚洲高清一区二区三区 | 1024国产欧美日韩精品 | 天天看天天摸色天天综合网 | 亚洲一区免费在线 | 极品美女洗澡后露粉嫩木耳视频 | 亚洲永久网站 | 久久人人干 | 欧洲性freefree大白屁股 | wwwxxx亚洲| 色噜噜狠狠色综合中文字幕 | 自拍偷拍福利 | 2017av在线| 国产黄色在线网站 | 亚洲男人精品 | 手机免费看大片 | 久久综合久久久 | 手机看片福利1024 | 最新午夜宅男 | 亚洲欧美成人在线 | 免费精品美女久久久久久久久 | 国模私拍视频 | 黄色福利网 | 美女拍拍拍免费视频观看 | 欧美又黄又嫩大片a级 | 久久视频精品线视频在线网站 | 清纯唯美亚洲综合欧美色 | 狠狠噜天天噜日日噜 |