《電子技術應用》
您所在的位置:首頁 > 模擬設計 > 設計應用 > ucos ii嵌入式操作系統的分析和移植
ucos ii嵌入式操作系統的分析和移植
摘要: ucosii是由Labrosse先生編寫的一個開放式內核,最主要的特點就是源碼公開。這一點對于用戶來說可謂利弊各半,好處在于,一方面它是免費的,另一方面用戶可以根據自己的需要對它進行修改。缺點在于它缺乏必要的支持...
Abstract:
Key words :

  ucos ii的特點

  1.ucos ii是由Labrosse先生編寫的一個開放式內核,最主要的特點就是源碼公開。這一點對于用戶來說可謂利弊各半,好處在于,一方面它是免費的,另一方面用戶可以根據自己的需要對它進行修改。缺點在于它缺乏必要的支持,沒有功能強大的軟件包,用戶通常需要自己編寫驅動程序,特別是如果用戶使用的是不太常用的單片機,還必須自己編寫移植程序。

  2.ucos ii是一個占先式的內核,即已經準備就緒的高優先級任務可以剝奪正在運行的低優先級任務的CPU使用權。這個特點使得它的實時性比非占先式的內核要好。通常我們都是在中斷服務程序中使高優先級任務進入就緒態(例如發信號),這樣退出中斷服務程序后,將進行任務切換,高優先級任務將被執行。拿51單片機為例,比較一下就可以發現這樣做的好處。假如需要用中斷方式采集一批數據并進行處理,在傳統的編程方法中不能在中斷服務程序中進行復雜的數據處理,因為這會使得關中斷時間過長。所以經常采用的方法是置一標志位,然后退出中斷。由于主程序是循環執行的,所以它總有機會檢測到這一標志并轉到數據處理程序中去。但是因為無法確定發生中斷時程序到底執行到了什么地方,也就無法判斷要經過多長時間數據處理程序才會執行,中斷響應時間無法確定,系統的實時性不強。如果使用μC/OS-II的話,只要把數據處理程序的優先級設定得高一些,并在中斷服務程序中使它進入就緒態,中斷結束后數據處理程序就會被立即執行。這樣可以把中斷響應時間限制在一定的范圍內。對于一些對中斷響應時間有嚴格要求的系統,這是必不可少的。但應該指出的是如果數據處理程序簡單,這樣做就未必合適。因為ucos ii要求在中斷服務程序末尾使用OSINTEXIT函數以判斷是否進行任務切換,這需要花費一定的時間。

  3.ucos ii和大家所熟知的Linux等分時操作系統不同,它不支持時間片輪轉法。ucos ii是一個基于優先級的實時操作系統,每個任務的優先級必須不同,分析它的源碼會發現,ucos ii把任務的優先級當做任務的標識來使用,如果優先級相同,任務將無法區分。進入就緒態的優先級最高的任務首先得到CPU的使用權,只有等它交出CPU的使用權后,其他任務才可以被執行。所以它只能說是多任務,不能說是多進程,至少不是我們所熟悉的那種多進程。顯而易見,如果只考慮實時性,它當然比分時系統好,它可以保證重要任務總是優先占有CPU。但是在系統中,重要任務畢竟是有限的,這就使得劃分其他任務的優先權變成了一個讓人費神的問題。另外,有些任務交替執行反而對用戶更有利。例如,用單片機控制兩小塊顯示屏時,無論是編程者還是使用者肯定希望它們同時工作,而不是顯示完一塊顯示屏的信息以后再顯示另一塊顯示屏的信息。這時候,要是ucos ii即支持優先級法又支持時間片輪轉法就更合適了。

  4.ucos ii對共享資源提供了保護機制。正如上文所提到的,ucos ii是一個支持多任務的操作系統。一個完整的程序可以劃分成幾個任務,不同的任務執行不同的功能。這樣,一個任務就相當于模塊化設計中的一個子模塊。在任務中添加代碼時,只要不是共享資源就不必擔心互相之間有影響。而對于共享資源(比如串口),ucos ii也提供了很好的解決辦法。一般情況下使用的是信號量的方法。簡單地說,先創建一個信號量并對它進行初始化。當一個任務需要使用一個共享資源時,它必須先申請得到這個信號量,而一旦得到了此信號量,那就只有等使用完了該資源,信號量才會被釋放。在這個過程中即使有優先權更高的任務進入了就緒態,因為無法得到此信號量,也不能使用該資源。這個特點的好處顯而易見,例如當顯示屏正在顯示信息的時候,外部產生了一個中斷,而在中斷服務程序中需要顯示屏顯示其他信息。這樣,退出中斷服務程序后,原有的信息就可能被破壞了。而在μC/OS-II中采用信號量的方法時,只有顯示屏把原有信息顯示完畢后才可以顯示新信息,從而可以避免這個現象。不過,采用這種方法是以犧牲系統的實時性為代價的。如果顯示原有信息需要耗費大量時間,系統只好等待。從結果上看,等于延長了中斷響應時間,這對于未顯示信息是報警信息的情況,無疑是致命的。發生這種情況,在μC/OS-II中稱為優先級反轉,就是高優先級任務必須等待低優先級任務的完成。在上述情況下,在兩個任務之間發生優先級反轉是無法避免的。所以在使用ucos ii時,必須對所開發的系統了解清楚,才能決定對于某種共享資源是否使用信號量。

  ucos ii在單片機使用中的一些特點

  1.在單片機系統中嵌入ucos ii將增強系統的可靠性,并使得調試程序變得簡單。以往傳統的單片機開發工作中經常遇到程序跑飛或是陷入死循環。可以用看門狗解決程序跑飛問題,而對于后一種情況,尤其是其中牽扯到復雜數學計算的話,只有設置斷點,耗費大量時間來慢慢分析。如果在系統中嵌入 ucos ii的話,事情就簡單多了。可以把整個程序分成許多任務,每個任務相對獨立,然后在每個任務中設置超時函數,時間用完以后,任務必須交出 CPU的使用權。即使一個任務發生問題,也不會影響其他任務的運行。這樣既提高了系統的可靠性,同時也使得調試程序變得容易。

  2.在單片機系統中嵌入ucos ii將增加系統的開銷。現在所使用的51單片機,一般是指87C51或者89C51,其片內都帶有一定的RAM和 ROM。對于一些簡單的程序,如果采用傳統的編程方法,已經不需要外擴存儲器了。如果在其中嵌入ucos ii的話,在只需要使用任務調度、任務切換、信號量處理、延時或超時服務的情況下,也不需要外擴ROM了,但是外擴RAM是必須的。由于ucos ii是可裁減的操作系統,其所需要的RAM大小就取決于操作系統功能的多少。舉例來說,μC/OS-II允許用戶定義最大任務數。由于每建立一個任務,都要產生一個與之相對應的數據結構TCB,該數據結構要占用很大一部分內存空間。所以在定義最大任務數時,一定要考慮實際情況的需要。如果定得過大,勢必會造成不必要的浪費。嵌入ucos ii以后,總的RAM需求可以由如下表達式得出:

  RAM總需求=應用程序的RAM需求+內核數據區的RAM需求+(任務棧需求+最大中斷嵌套棧需求)·任務數

  所幸的是,μC/OS-II可以對每個任務分別定義堆棧空間的大小,開發人員可根據任務的實際需求來進行棧空間的分配。但在RAM容量有限的情況下,還是應該注意一下對大型數組、數據結構和函數的使用,別忘了,函數的形參也是要推入堆棧的。

  3.ucos ii的移植也是一件需要值得注意的工作。如果沒有現成的移植實例的話,就必須自己來編寫移植代碼。雖然只需要改動兩個文件,但仍需要對相應的微處理器比較熟悉才行,最好參照已有的移植實例。另外,即使有移植實例,在編程前最好也要閱讀一下,因為里面牽扯到堆棧操作。在編寫中斷服務程序時,把寄存器推入堆棧的順序必須與移植代碼中的順序相對應。

  4.和其他一些著名的嵌入式操作系統不同,ucos ii在單片機系統中的啟動過程比較簡單,不像有些操作系統那樣,需要把內核編譯成一個映像文件寫入ROM中,上電復位后,再從ROM中把文件加載到RAM中去,然后再運行應用程序。ucos ii的內核是和應用程序放在一起編譯成一個文件的,使用者只需要把這個文件轉換成HEX格式,寫入ROM中就可以了,上電后,會像普通的單片機程序一樣運行。

  結語

  由以上介紹可以看出,ucos ii具有免費、使用簡單、可靠性高、實時性好等優點,但也有移植困難、缺乏必要的技術支持等缺點,尤其不像商用嵌入式系統那樣得到廣泛使用和持續的研究更新。但開放性又使得開發人員可以自行裁減和添加所需的功能,在許多應用領域發揮著獨特的作用。當然,是否在單片機系統中嵌入ucos ii應視所開發的項目而定,對于一些簡單的、低成本的項目來說,就沒必要使用嵌入式操作系統了。

  --摘自INTERNET

  44B0下ucos-ii的移植

  要保證ucos Ⅱ移植到微處理器后能正確運行;處理器需具備如下特性:

  1) 處理器的c編譯器支持可重入函數

  可重入的代碼指的是一段代碼(如一個函數)可以被多個任務同時調用,而不必擔心會破壞數據。也就是說,可重入型函數在任何時候都可以被中斷執行,過一段時間以后又可以繼續運行,而不會因為在函數中斷的時候被其他的任務重新調用,影響函數中的數據。下面的兩個例子可以比較可重入型函數和非可重入型函數:

  程序1:可重入型函數

  void swap(int *x, int *y)

  int temp;

  temp=*x;

  *x=*y;

  *y=temp;

  程序2:非可重入型函數

  int temp;

  void swap(int *x, int *y)

  temp=*x;

  *x=*y;

  *y=temp;

  程序1 中使用的是局部變量temp 作為變量。通常的C 編譯器,把局部變量分配在棧中。

  所以,多次調用同一個函數,可以保證每次的temp 互不受影響。而程序2 中temp 定義的是全局變量,多次調用函數的時候,必然受到影響。代碼的可重入性是保證完成多任務的基礎,除了在C 程序中使用局部變量以外,還需要C 編譯器的支持。筆者使用的是ARM SDT 以及ADS 的集成開發環境,均可以生成可重入的代碼。

  2)在程序中可以打開和關閉中斷

  在ucos Ⅱ中,可以通過OS_ENTER_CRITICAL()或者OS_EXIT_CRITICAL()宏來控制

  系統關閉或者打開中斷。這需要處理器的支持,在ARM7TDMI 的處理器上,可以設置相應的寄存器來關閉或者打開系統的所有中斷。

  3)處理器支持中斷,并且能產生定時器中斷(ucos Ⅱ是通過定時器中斷來實現多任務的調度,即時間片的產生 )ucos Ⅱ 是通過處理器產生的定時器的中斷來實現多任務之間的調度的。在ARM7TDMI 的處理器上可以產生定時器中斷。

  4)處理器要具有一定的硬件堆棧數量

  5)處理器要有將堆棧指針和其他cpu寄存器存儲和讀出堆棧(或者內存)的指令(如51的pop,push指令)。

  ucos Ⅱ進行任務調度的時候,會把當前任務的CPU 寄存器存放到此任務的堆棧中,然后,再從另一個任務的堆棧中恢復原來的工作寄存器,繼續運行另一個任務。所以,寄存器的入棧和出棧是ucos Ⅱ多任務調度的基礎。

  ARM7TDMI 處理器完全滿足上述要求。

 

  ucos ii的特點

  1.ucos ii是由Labrosse先生編寫的一個開放式內核,最主要的特點就是源碼公開。這一點對于用戶來說可謂利弊各半,好處在于,一方面它是免費的,另一方面用戶可以根據自己的需要對它進行修改。缺點在于它缺乏必要的支持,沒有功能強大的軟件包,用戶通常需要自己編寫驅動程序,特別是如果用戶使用的是不太常用的單片機,還必須自己編寫移植程序。

  2.ucos ii是一個占先式的內核,即已經準備就緒的高優先級任務可以剝奪正在運行的低優先級任務的CPU使用權。這個特點使得它的實時性比非占先式的內核要好。通常我們都是在中斷服務程序中使高優先級任務進入就緒態(例如發信號),這樣退出中斷服務程序后,將進行任務切換,高優先級任務將被執行。拿51單片機為例,比較一下就可以發現這樣做的好處。假如需要用中斷方式采集一批數據并進行處理,在傳統的編程方法中不能在中斷服務程序中進行復雜的數據處理,因為這會使得關中斷時間過長。所以經常采用的方法是置一標志位,然后退出中斷。由于主程序是循環執行的,所以它總有機會檢測到這一標志并轉到數據處理程序中去。但是因為無法確定發生中斷時程序到底執行到了什么地方,也就無法判斷要經過多長時間數據處理程序才會執行,中斷響應時間無法確定,系統的實時性不強。如果使用μC/OS-II的話,只要把數據處理程序的優先級設定得高一些,并在中斷服務程序中使它進入就緒態,中斷結束后數據處理程序就會被立即執行。這樣可以把中斷響應時間限制在一定的范圍內。對于一些對中斷響應時間有嚴格要求的系統,這是必不可少的。但應該指出的是如果數據處理程序簡單,這樣做就未必合適。因為ucos ii要求在中斷服務程序末尾使用OSINTEXIT函數以判斷是否進行任務切換,這需要花費一定的時間。

  3.ucos ii和大家所熟知的Linux等分時操作系統不同,它不支持時間片輪轉法。ucos ii是一個基于優先級的實時操作系統,每個任務的優先級必須不同,分析它的源碼會發現,ucos ii把任務的優先級當做任務的標識來使用,如果優先級相同,任務將無法區分。進入就緒態的優先級最高的任務首先得到CPU的使用權,只有等它交出CPU的使用權后,其他任務才可以被執行。所以它只能說是多任務,不能說是多進程,至少不是我們所熟悉的那種多進程。顯而易見,如果只考慮實時性,它當然比分時系統好,它可以保證重要任務總是優先占有CPU。但是在系統中,重要任務畢竟是有限的,這就使得劃分其他任務的優先權變成了一個讓人費神的問題。另外,有些任務交替執行反而對用戶更有利。例如,用單片機控制兩小塊顯示屏時,無論是編程者還是使用者肯定希望它們同時工作,而不是顯示完一塊顯示屏的信息以后再顯示另一塊顯示屏的信息。這時候,要是ucos ii即支持優先級法又支持時間片輪轉法就更合適了。

  4.ucos ii對共享資源提供了保護機制。正如上文所提到的,ucos ii是一個支持多任務的操作系統。一個完整的程序可以劃分成幾個任務,不同的任務執行不同的功能。這樣,一個任務就相當于模塊化設計中的一個子模塊。在任務中添加代碼時,只要不是共享資源就不必擔心互相之間有影響。而對于共享資源(比如串口),ucos ii也提供了很好的解決辦法。一般情況下使用的是信號量的方法。簡單地說,先創建一個信號量并對它進行初始化。當一個任務需要使用一個共享資源時,它必須先申請得到這個信號量,而一旦得到了此信號量,那就只有等使用完了該資源,信號量才會被釋放。在這個過程中即使有優先權更高的任務進入了就緒態,因為無法得到此信號量,也不能使用該資源。這個特點的好處顯而易見,例如當顯示屏正在顯示信息的時候,外部產生了一個中斷,而在中斷服務程序中需要顯示屏顯示其他信息。這樣,退出中斷服務程序后,原有的信息就可能被破壞了。而在μC/OS-II中采用信號量的方法時,只有顯示屏把原有信息顯示完畢后才可以顯示新信息,從而可以避免這個現象。不過,采用這種方法是以犧牲系統的實時性為代價的。如果顯示原有信息需要耗費大量時間,系統只好等待。從結果上看,等于延長了中斷響應時間,這對于未顯示信息是報警信息的情況,無疑是致命的。發生這種情況,在μC/OS-II中稱為優先級反轉,就是高優先級任務必須等待低優先級任務的完成。在上述情況下,在兩個任務之間發生優先級反轉是無法避免的。所以在使用ucos ii時,必須對所開發的系統了解清楚,才能決定對于某種共享資源是否使用信號量。

  ucos ii在單片機使用中的一些特點

  1.在單片機系統中嵌入ucos ii將增強系統的可靠性,并使得調試程序變得簡單。以往傳統的單片機開發工作中經常遇到程序跑飛或是陷入死循環。可以用看門狗解決程序跑飛問題,而對于后一種情況,尤其是其中牽扯到復雜數學計算的話,只有設置斷點,耗費大量時間來慢慢分析。如果在系統中嵌入 ucos ii的話,事情就簡單多了。可以把整個程序分成許多任務,每個任務相對獨立,然后在每個任務中設置超時函數,時間用完以后,任務必須交出 CPU的使用權。即使一個任務發生問題,也不會影響其他任務的運行。這樣既提高了系統的可靠性,同時也使得調試程序變得容易。

  2.在單片機系統中嵌入ucos ii將增加系統的開銷。現在所使用的51單片機,一般是指87C51或者89C51,其片內都帶有一定的RAM和 ROM。對于一些簡單的程序,如果采用傳統的編程方法,已經不需要外擴存儲器了。如果在其中嵌入ucos ii的話,在只需要使用任務調度、任務切換、信號量處理、延時或超時服務的情況下,也不需要外擴ROM了,但是外擴RAM是必須的。由于ucos ii是可裁減的操作系統,其所需要的RAM大小就取決于操作系統功能的多少。舉例來說,μC/OS-II允許用戶定義最大任務數。由于每建立一個任務,都要產生一個與之相對應的數據結構TCB,該數據結構要占用很大一部分內存空間。所以在定義最大任務數時,一定要考慮實際情況的需要。如果定得過大,勢必會造成不必要的浪費。嵌入ucos ii以后,總的RAM需求可以由如下表達式得出:

  RAM總需求=應用程序的RAM需求+內核數據區的RAM需求+(任務棧需求+最大中斷嵌套棧需求)·任務數

  所幸的是,μC/OS-II可以對每個任務分別定義堆棧空間的大小,開發人員可根據任務的實際需求來進行棧空間的分配。但在RAM容量有限的情況下,還是應該注意一下對大型數組、數據結構和函數的使用,別忘了,函數的形參也是要推入堆棧的。

  3.ucos ii的移植也是一件需要值得注意的工作。如果沒有現成的移植實例的話,就必須自己來編寫移植代碼。雖然只需要改動兩個文件,但仍需要對相應的微處理器比較熟悉才行,最好參照已有的移植實例。另外,即使有移植實例,在編程前最好也要閱讀一下,因為里面牽扯到堆棧操作。在編寫中斷服務程序時,把寄存器推入堆棧的順序必須與移植代碼中的順序相對應。

  4.和其他一些著名的嵌入式操作系統不同,ucos ii在單片機系統中的啟動過程比較簡單,不像有些操作系統那樣,需要把內核編譯成一個映像文件寫入ROM中,上電復位后,再從ROM中把文件加載到RAM中去,然后再運行應用程序。ucos ii的內核是和應用程序放在一起編譯成一個文件的,使用者只需要把這個文件轉換成HEX格式,寫入ROM中就可以了,上電后,會像普通的單片機程序一樣運行。

  結語

  由以上介紹可以看出,ucos ii具有免費、使用簡單、可靠性高、實時性好等優點,但也有移植困難、缺乏必要的技術支持等缺點,尤其不像商用嵌入式系統那樣得到廣泛使用和持續的研究更新。但開放性又使得開發人員可以自行裁減和添加所需的功能,在許多應用領域發揮著獨特的作用。當然,是否在單片機系統中嵌入ucos ii應視所開發的項目而定,對于一些簡單的、低成本的項目來說,就沒必要使用嵌入式操作系統了。

  --摘自INTERNET

  44B0下ucos-ii的移植

  要保證ucos Ⅱ移植到微處理器后能正確運行;處理器需具備如下特性:

  1) 處理器的c編譯器支持可重入函數

  可重入的代碼指的是一段代碼(如一個函數)可以被多個任務同時調用,而不必擔心會破壞數據。也就是說,可重入型函數在任何時候都可以被中斷執行,過一段時間以后又可以繼續運行,而不會因為在函數中斷的時候被其他的任務重新調用,影響函數中的數據。下面的兩個例子可以比較可重入型函數和非可重入型函數:

  程序1:可重入型函數

  void swap(int *x, int *y)

  int temp;

  temp=*x;

  *x=*y;

  *y=temp;

  程序2:非可重入型函數

  int temp;

  void swap(int *x, int *y)

  temp=*x;

  *x=*y;

  *y=temp;

  程序1 中使用的是局部變量temp 作為變量。通常的C 編譯器,把局部變量分配在棧中。

  所以,多次調用同一個函數,可以保證每次的temp 互不受影響。而程序2 中temp 定義的是全局變量,多次調用函數的時候,必然受到影響。代碼的可重入性是保證完成多任務的基礎,除了在C 程序中使用局部變量以外,還需要C 編譯器的支持。筆者使用的是ARM SDT 以及ADS 的集成開發環境,均可以生成可重入的代碼。

  2)在程序中可以打開和關閉中斷

  在ucos Ⅱ中,可以通過OS_ENTER_CRITICAL()或者OS_EXIT_CRITICAL()宏來控制

  系統關閉或者打開中斷。這需要處理器的支持,在ARM7TDMI 的處理器上,可以設置相應的寄存器來關閉或者打開系統的所有中斷。

  3)處理器支持中斷,并且能產生定時器中斷(ucos Ⅱ是通過定時器中斷來實現多任務的調度,即時間片的產生 )ucos Ⅱ 是通過處理器產生的定時器的中斷來實現多任務之間的調度的。在ARM7TDMI 的處理器上可以產生定時器中斷。

  4)處理器要具有一定的硬件堆棧數量

  5)處理器要有將堆棧指針和其他cpu寄存器存儲和讀出堆棧(或者內存)的指令(如51的pop,push指令)。

  ucos Ⅱ進行任務調度的時候,會把當前任務的CPU 寄存器存放到此任務的堆棧中,然后,再從另一個任務的堆棧中恢復原來的工作寄存器,繼續運行另一個任務。所以,寄存器的入棧和出棧是ucos Ⅱ多任務調度的基礎。

  ARM7TDMI 處理器完全滿足上述要求。

 

  接下來將介紹如何把ucos Ⅱ移植到Samsung公司的一款ARM7TDMI 的嵌入式處理器——S3C44B0X 上。

  ucos Ⅱ中與處理器有關的代碼:os_cpu.h os_cpu_a.asm os_cpu_c.c

  ucos Ⅱ的設置 : os_cfg.h inludes.h

  ucos Ⅱ在44b0上的移植

  1)設置inludes.h中與處理器及編譯器有關的代碼

  FORADS

  #include “os_cpu.h”

  #include “os_cfg.h”

  #include “ucos_ii.h”

  這里未做處理 取默認的數據類型。

  FOR SDT

  #include 》stdio.h《

  #include 》stdlib.h《

  #include 》string.h《

  #include “os_cpu.h”

  #include “os_cfg.h”

  #include “ucos_ii.h”

  #ifdef EX3_GLOBALS

  #define EX3_EXT

  #else

  #define EX3_EXT extern

  #endif

  typedef struct {

  char TaskName[30];

  INT16U TaskCtr;

  INT16U TaskExecTime;

  INT32U TaskTotExecTime;

  } TASK_USER_DATA;

  EX3_EXT TASK_USER_DATA TaskUserData[10];

  void DispTaskStat(INT8U id);

  ********************************************************************************

  其他人的應用修改事例:

  #define INT8U unsigned char

  #define INT16U unsigned short

  #define INT32U unsigned long

  #define OS_STK unsigned long

  #define BOOLEAN int

  #define OS_CPU_SR unsigned long

  #define INT8S char

  extern int INTS_OFF(void);

  extern void INTS_ON(void);

  #define OS_ENTER_CRITICAL() { cpu_sr = INTS_OFF(); }

  #define OS_EXIT_CRITICAL() { if(cpu_sr == 0) INTS_ON(); }

  #define OS_STK_GROWTH 1

  #define STACKSIZE 256

  因為不同的微處理器有不同的字長,所以ucos Ⅱ的移植包括了一系列的類型定義以確

  保其可移植性。尤其是ucos Ⅱ代碼從不使用C 的short,int 和long 等數據類型,因為它們是與編譯器相關的,不可移植。相反的,我們定義的整形數據結構既是可移植的又是直觀的。為了方便,雖然ucos Ⅱ不是用浮點數據,但我們還是定義了浮點數據類型。

  例如,INT16U 數據類型總是代表16 位的無符號整數。現在,ucos Ⅱ和用戶的應用程序就可以估計出聲明為該數據類型的變量的取值范圍是0~65535。將ucos Ⅱ移植到32 位的處理器上也就意味著INT16U 實際被聲明為無符號短整形數據結構而不是無符號整數數據結構。但是,μC/OS-Ⅱ所處理的仍然是INT16U。用戶必須將任務堆棧的數據類型告訴給μC/OS-Ⅱ。這個過程是通過為OS_STK 聲明正確的C 數據類型來完成的。我們的處理器上的堆棧成員是16 位的,所以將OS_TSK 聲明為無符號整形數據類型。所有的任務堆棧都必須用OS_TSK 聲明數據類型。

  2)OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()

  與所有的實時內核一樣,μC/OS-Ⅱ需要先禁止中斷再訪問代碼的臨界區,并且在訪問完

  畢后重新允許中斷。這就使得μC/OS-Ⅱ能夠保護臨界區代碼免受多任務或中斷服務例程

  (ISR)的破壞。在S3C44B0X 上是通過兩個函數(OS_CPU_A.S)實現開關中斷的。

  INTS_OFF

  mrs r0, cpsr ; 當前CSR

  mov r1, r0 ; 復制屏蔽

  orr r1, r1, #0xC0 ; 屏蔽中斷位

  msr CPSR, r1 ; 關中斷(IRQ and FIQ)

  and r0, r0, #0x80 ; 從初始CSR 返回FIQ 位

  mov pc,lr ; 返回

  INTS_ON

  mrs r0, cpsr ; 當前CSR

  bic r0, r0, #0xC0 ; 屏蔽中斷

  msr CPSR, r0 ; 開中斷(IRQ and FIQ)

  mov pc,lr ; 返回

  3)OS_STK_GROWTH

  絕大多數的微處理器和微控制器的堆棧是從上往下長的。但是某些處理器是用另外一種方式工作的。μC/OS-Ⅱ被設計成兩種情況都可以處理,只要在結構常量OS_STK_GROWTH中指定堆棧的生長方式就可以了。

  置OS_STK_GROWTH 為0 表示堆棧從下往上長。

  置OS_STK_GROWTH 為1 表示堆棧從上往下長。

  用c語言編寫6個與操作系統相關的函數(OS_CPU_C.C)

  1. OsTaskStKInit()

  OSTaskCreate()和OSTaskCreateExt()通過調用OSTaskStkInit()來初始化任務的堆

  棧結構。因此,堆棧看起來就像剛發生過中斷并將所有的寄存器保存到堆棧中的情形一樣。

  圖12-2 顯示了OSTaskStkInt()放到正被建立的任務堆棧中的東西。這里我們定義了堆棧是

  從上往下長的。

  在用戶建立任務的時候,用戶傳遞任務的地址,pdata 指針,任務的堆棧棧頂和任務的

  優先級給OSTaskCreate()和OSTaskCreateExt()。一旦用戶初始化了堆棧,OSTaskStkInit

  ()就需要返回堆棧指針所指的地址。OSTaskCreate()和OSTaskCreateExt()會獲得該地

  址并將它保存到任務控制塊(OS_TCB)中。

  OS_STK * OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)

  {

  unsigned int * stk;

  stk = (unsigned int *)ptos;

  opt++;

  *--stk = (unsigned int) task;

  *--stk = (unsigned int) task;

  *--stk = 12;

  *--stk = 11;

  *--stk = 10;

  *--stk = 9;

  *--stk = 8;

  *--stk = 7;

  *--stk = 6;

  *--stk = 5;

  *--stk = 4;

  *--stk = 3;

  *--stk = 2;

  *--stk = 1;

  *--stk = (unsigned int) pdata;

  *--stk = (SUPMODE);

  *--stk = (SUPMODE);

  return ((OS_STK *)stk);

  }

  2).OSTaskCreateHook

  當用OSTaskCreate()和OSTaskCreateExt ()建立任務的時候就會調用OSTaskCreateHook

  ()。該函數允許用戶或使用移植實例的用戶擴展μC/OS-Ⅱ功能。當μC/OS-Ⅱ設置完了自己的內部結構后,會在調用任務調度程序之前調用OSTaskCreateHook()。該函數被調用的時候中斷是禁止的。因此用戶應盡量減少該函數中的代碼以縮短中斷的響應時間。當OSTaskCreateHook()被調用的時候,它會收到指向已建立任務的OS_TCB 的指針,這樣它就可以訪問所有的結構成員了。

  函數原型:

  void OSTaskCreateHook (OS_TCB *ptcb)

  3).OsTaskDelHook()

  當任務被刪除的時候就會調用OSTaskDelHook()。該函數在把任務從μC/OS-Ⅱ的內部

  任務鏈表中解開之前被調用。當OSTaskDelHook()被調用的時候,它會收到指向正被刪除任務的OS_TCB 的指針,這樣它就可以訪問所有的結構成員了。OSTaskDelHook()可以來檢驗TCB 擴展是否被建立(一個非空指針)并進行一些清除操作。

  函數原型:

  void OSTaskDelHook (OS_TCB *ptcb)

  4.OsTaskSwHook()

  當發生任務切換的時候就會調用OSTaskSwHook()。OSTaskSwHook()可以直接訪問

  OSTCBCur 和OSTCBHighRdy,因為它們是全局變量。OSTCBCur 指向被切換出去的任務OS_TCB,而OSTCBHighRdy 指向新任務OS_TCB。注意在調用OSTaskSwHook()期間中斷一直是被禁止的。因此用戶應盡量減少該函數中的代碼以縮短中斷的響應時間。

  函數原型:

  void OSTaskSwHook (void)

  5.OsTaskStatHook()

  OSTaskStatHook()每秒鐘都會被OSTaskStat()調用一次。用戶可以用OSTaskStatHook

  ()來擴展統計功能。例如,用戶可以保持并顯示每個任務的執行時間,每個任務所用的CPU 份額,以及每個任務執行的頻率等。

  函數原型:

  void OSTaskStatHook (void)

  6.OsTimeTickHook()

  OSTimeTickHook()在每個時鐘節拍都會被OSTaskTick()調用。實際上,OSTimeTickHook

  ()是在節拍被μC/OS-Ⅱ真正處理,并通知用戶的移植實例或應用程序之前被調用的。

 

  函數原型:

  void OSTimeTickHook (void)

  后5 個函數為鉤子函數,可以不加代碼。只有當OS_CFG.H 中的OS_CPU_HOOKS_EN

  被置為1 時才會產生這些函數的代碼。

  用匯編語言編寫4個與處理器相關的函數(OS_CPU_a.asm)

  (1)OsStartHighRdy();運行優先級最高的就緒任務

  OSStartHighRdy

  LDR r4, addr_OSTCBCur ; 得到當前任務TCB 地址

  LDR r5, addr_OSTCBHighRdy ; 得到最高優先級任務TCB 地址

  LDR r5, [r5] ; 獲得堆棧指針

  LDR sp, [r5] ; 轉移到新的堆棧中

  STR r5, [r4] ; 設置新的當前任務TCB 地址

  LDMFD sp!, {r4} ;

  MSR SPSR, r4

  LDMFD sp!, {r4} ; 從棧頂獲得新的狀態

  MSR CPSR, r4 ; CPSR 處于SVC32Mode 摸式

  LDMFD sp!, {r0-r12, lr, pc } ; 運行新的任務

  (2)OS_TaSK_SW();任務級的任務切換函數

  OS_TASK_SW

  STMFD sp!, {lr} ; 保存pc

  STMFD sp!, {lr} ; 保存lr

  STMFD sp!, {r0-r12} ; 保存寄存器和返回地址

  MRS r4, CPSR

  STMFD sp!, {r4} ; 保存當前的PSR

  MRS r4, SPSR

  STMFD sp!, {r4} ; 保存SPSR

  ; OSPrioCur = OSPrioHighRdy

  LDR r4, addr_OSPrioCur

  LDR r5, addr_OSPrioHighRdy

  LDRB r6, [r5]

  STRB r6, [r4]

  ; 得到當前任務TCB 地址

  LDR r4, addr_OSTCBCur

  LDR r5, [r4]

  STR sp, [r5] ; 保存sp 在被占先的任務的TCB

  ; 得到最高優先級任務TCB 地址

  LDR r6, addr_OSTCBHighRdy

  LDR r6, [r6]

  LDR sp, [r6] ; 得到新任務堆棧指針

  ; OSTCBCur = OSTCBHighRdy

  STR r6, [r4] ; 設置新的當前任務的TCB 地址

  ;保存任務方式寄存器

  LDMFD sp!, {r4}

  MSR SPSR, r4

  LDMFD sp!, {r4}

  MSR CPSR, r4

  ; 返回到新任務的上下文

  LDMFD sp!, {r0-r12, lr, pc}

  (3)OSINTCTXSW();中斷級的任務切換函數

  OSIntCtxSw

  add r7, sp, #16 ; 保存寄存器指針

  LDR sp, =IRQStack ;FIQ_STACK

  mrs r1, SPSR ; 得到暫停的PSR

  orr r1, r1, #0xC0 ; 關閉IRQ, FIQ.

  msr CPSR_cxsf, r1 ; 轉換模式(應該是SVC_MODE)

  ldr r0, [r7, #52] ; 從IRQ 堆棧中得到IRQ‘s LR (任務PC)

  sub r0, r0, #4 ; 當前PC 地址是(saved_LR - 4)

  STMFD sp!, {r0} ; 保存任務PC

  STMFD sp!, {lr} ; 保存LR

  mov lr, r7 ; 保存FIQ 堆棧ptr in LR (轉到nuke r7)

  ldmfd lr!, {r0-r12} ; 從FIQ 堆棧中得到保存的寄存器

  STMFD sp!, {r0-r12} ;在任務堆棧中保存寄存器

  ;在任務堆棧上保存PSR 和任務PSR

  MRS r4, CPSR

  bic r4, r4, #0xC0 ; 使中斷位處于使能態

  STMFD sp!, {r4} ; 保存任務當前PSR

  MRS r4, SPSR

  STMFD sp!, {r4} ; SPSR

  ; OSPrioCur = OSPrioHighRdy // 改變當前程序

  LDR r4, addr_OSPrioCur

  LDR r5, addr_OSPrioHighRdy

  LDRB r6, [r5]

  STRB r6, [r4]

  ; 得到被占先的任務TCB

  LDR r4, addr_OSTCBCur

  LDR r5, [r4]

  STR sp, [r5] ; 保存sp 在被占先的任務的TCB

  ; 得到新任務TCB 地址

  LDR r6, addr_OSTCBHighRdy

  LDR r6, [r6]

  LDR sp, [r6] ; 得到新任務堆棧指針

  ; OSTCBCur = OSTCBHighRdy

  STR r6, [r4] ; 設置新的當前任務的TCB 地址

  LDMFD sp!, {r4}

  MSR SPSR, r4

  LDMFD sp!, {r4}

  BIC r4, r4, #0xC0 ; 必須退出新任務通過允許中斷

  MSR CPSR, r4

  LDMFD sp!, {r0-r12, lr, pc}

  完成了上述工作以后,μC/OS-Ⅱ就可以正常運行在ARM 處理器上了。

  我們的板子上已經有移植成功的簡單應用,移植部分不須多大改動就可以直接復制到您的應用中去。

  文件系統的建立:

  文件系統相關的API函數功能解釋:

  void initosfile();

  功能:初始化文件管理,為文件結構分配空間,在系統初始化時調用

  FILE* OPENOSFILE(char filename[],u32 open mode);

  功能:以讀取方式或寫入方式指定打開的文件,并創建FILE結構,為文件讀取分配緩沖區,返回當前指向文件結構的指針。

  參數說明:

  filename 打開的文件名

  openmode 打開文件的方式:FILEMODE_READ 1

  FILEMODE_WRITE 2

  U32 Readosfile(FILE* pfile,u8* readbuffer,u32 nreadbyte);

  功能: 讀取已經打開的文件到制定的緩沖區,成功則返回讀取的字節數

  參數說明:

  pfile : 指向打開文件的指針

  readbuffer :讀文件的目的緩沖區。

  Nreadbyte: 讀文件的字節數

  U32 linereadosfile(FILE* pfile,char str[]);

  功能:讀取之定文件的一行,返回讀取文件的字節數。

  參數說明:

  Pfile: 指向打開文件的指針

  Str: 讀取的字符竄數組

  U8 writeosfile(FILE* pfile,u8* writebuffer,u32 nreadbyte);

  功能:把緩沖區寫入指定的文件,如果成功就返回true 否則false.

  參數說明:

  pfile: 指向打開文件的指針

  writebuffer :寫入文件的目的緩沖區。

  Nreadbyte: 寫入文件的字節數

  Void closeosfile()

  功能:關閉打開的文件,釋放文件緩沖區

  參數說明:

  pfile: 指向打開文件的指針

  u8 getnextfilename(u32 *filepos,char filename[]);

  功能:得到文件目錄分配表中的指定位置的文件名(包括擴展名),文件位置自動下移。

  若文件有效則返回true ,否則flase

  filepos: 文件的位置,范圍從0~511;

  filename: 返回的文件名

  u8 listnextfilename(u32 *filepos,char fileexname[],char filename[]);

  功能:列出當前位置開始第一個制定擴展名的文件,如果沒有,返回flase

  參數說明:

  filepos: 文件的位置,范圍從0~511;

  fileexname:指定的文件擴展名

  filename:返回的文件名

  外設計驅動程序

  1) 串口接口函數

  void Uart_Init(int uartnum,int mclk,int baud);

  功能:初始化串口,設置通訊的波特率

  參數說明:

  uartnum :所設定的串行口號

  mclk: 系統的主時鐘頻率,如果為0則為默認值 60

  baud:所設定的串口通訊波特率

  void uart_printf(char *fmt,…)

  功能:輸出字符到串口0

  參數說明:

  fmt:輸出到串口的字符串

  char uart_getch(char *revdatq,int uartnum,int timeout);

  功能:接收指定的串口的數據,收到數據是返回true 否則flase

  參數說明:

  revdatq: 輸入緩沖區

  uartnum:所設定得串口號

  timeout: 等待超時時間

  void uart_sendbyte(int uartnum,u8 data);

  功能:向指定串口發送數據

  參數說明:

  uart_num : 所設定得串口號

  data: 發送的數據

  例子:

  當操作系統啟動時,將自動初始化各串行口,所以應用程序調用串行口資源將變得非常

  容易。值的注意的是,應用程序往往是多任務系統,為了實時監測串行口信息,在本操作環

  境中必須單開一個串行口掃描任務,保證信息不丟失。

  ⑴ 打開一個已有的工程文件,在其中的主函數MAIN 中添加串行口的寄存器初始化

  代碼,并添加串行口和鍵盤掃描任務,串行口掃描任務的代碼如下:

  void Uart_Scan_Task1(void *Id)

  {

  char c1;

  POSMSG pmsg1;

  for (;;){

  if(Uart_Getch(&c1,0,1))

  {

  pmsg1=OSCreateMessage(NULL,OSM_SERIAL,0,c1);

  if(pmsg1)

  SendMessage(pmsg1);

  }

  }

  }//Uart_Scan_Task

 

  (2)當系統收到串行口信息時,將會自動向主任務發送一個串行口消息。主任務接收

  到該消息,將會調用響應函數,響應該消息。添加消息響應函數的代碼如下:

  void onSerial(int portn, char c)

  {

  Uart_SendByte(0,c);

  ⑶ 添加主任務

  void Main_Task(void *Id) //Main_Test_Task

  {

  POSMSG pMsg=0;

  ClearScreen();

  //消息循環

  for(;;){

  pMsg=WaitMessage(0); //等待消息

  switch(pMsg-{

  case OSM_SERIAL:

  onSerial(pMsg-break;

  }

  DeleteMessage(pMsg);//刪除消息,釋放資源

  }

  }

  2) 鍵盤掃描驅動4*4

  u32 GetKey();

  功能:1 有效。此函數位死鎖函數,調用以后,除非有鍵按下 否則不返回

  void setfunctionkey();

  功能:設定功能鍵掃描碼,1 有效。類似計算機的ctrl/alt ,可以提供復合鍵

  u32 getnotaskkey();

  功能:1 有效。此函數位死鎖函數,調用以后,除非有鍵按下 否則不返回, 與u32 GetKey()的區別詩詞函數不會釋放此任務的控制權,除非有更高級的任務運行

  例子

  1)在主函數中定義鍵盤映射表,定義鍵盤掃描函數,定義鍵盤驅動函數。

  (2)定義鍵盤響應函數,將得到的鍵值在液晶屏上顯示。

  void onKey(int nkey, int fnkey)//鍵盤響應函數

  {

  char temp[3];//轉換成ASC-II 的鍵值數組

  if(nkey《9)

  {

  temp[0]=0x31;

  temp[1]=(nkey-10)|0x30;

  temp[2]=0;

  }

  else

  {

  temp[0]=nkey+0x30;

  temp[1]=0;

  }

  LCD_printf(temp);//在液晶平上顯示鍵值

  LCD_printf(“\n”);

  }

  (3)定義鍵盤掃描任務。

  OS_STK My_Key_Scan_Stack[STACKSIZE]={0, }; //定義鍵盤掃描任務的堆棧大小

  void My_Key_Scan_Task(void *Id); //定義鍵盤掃描任務

  #define MyKey_Scan_Task_Prio 58 //定義鍵盤掃描任務的優先級

  OSTaskCreate(My_Key_Scan_Task,(void*)0,(OS_STK*)&My_Key_Scan_Stack[STACKSIZE-1],

  MyKey_Scan_Task_Prio );//在主函數中創建鍵盤掃描任務

  void My_Key_Scan_Task(void *Id)//鍵盤掃描任務

  {

  U32 key;

  u32 tempkey=0;

  POSMSG pmsg;//創建消息

  Uart_Printf(“begin key task \n”);

  for (;;)

  {

  key=MyGetKey();

  key&=0x000f;

  if(key《9)

  {

  Uart_SendByte(0,0x31);

  32

  tempkey=key-10;

  Uart_SendByte(0,tempkey|=0x0030);

  }

  else

  Uart_SendByte(0,key|0x0030);

  Uart_Printf(“,”);

  pmsg=OSCreateMessage(NULL, OSM_KEY,key,key);//創建鍵盤消息

  if(pmsg)

  SendMessage(pmsg);//發送鍵盤消息

  }

  }

  (4)定義主任務。

  OS_STK Main_Stack[STACKSIZE*8]={0, };//定義主任務的堆棧大小

  void Main_Task(void *Id); //定義主任務

  #define Main_Task_Prio 12 //定義主任務的優先級

  OSTaskCreate(Main_Task,(void*)0,(OS_STK*)&Main_Stack[STACKSIZE*8-1],

  Main_Task_Prio);//在主函數重創建主任務

  void Main_Task(void *Id) //主任務

  {

  POSMSG pMsg=0;//創建消息

  LCD_ChangeMode(DspTxtMode);//將液晶屏設為文本顯示摸式

  LCD_Cls();//清屏

  for(;;)

  {

  pMsg=WaitMessage(0); //等待消息

  switch(pMsg-{

  case OSM_KEY:

  onKey(pMsg-break;

  Delay(200);

  }

  DeleteMessage(pMsg);//刪除消息,釋放資源

  } }

  注意:以上API接口函數只是原型 ;例子只作為參考

此內容為AET網站原創,未經授權禁止轉載。
主站蜘蛛池模板: 欧美疯狂做受xxxx富婆 | 奶罩不戴乳罩邻居hd播放 | 日韩精品一区二区三区四区 | 无码东京热一区二区三区 | 91在线网| 亚洲精品午睡沙发系列 | 男人晚上看的网址 | 免费人成视频在线观看不卡 | 国产免费人做人爱午夜视频 | 久久99精品久久久水蜜桃 | 欧美不卡 | 性残虐av片在线播放 | 一级持黄录像免费观看 | 日韩欧美国产成人 | 日韩在线视频不卡 | 日韩黄色一区 | 女同三级在线观看bd | 探花视频免费观看高清视频 | 国产精品久久久久久久久久免费看 | 日本丰满大乳mm | 一二三四日本高清社区5 | av在线免费播放网站 | 强行糟蹋人妻hd中文 | 亚洲综合av网 | 色牛影院| 国产亚洲性欧美日韩在线观看软件 | youporn免费视频成人软件 | 久久97精品国产96久久小草 | ga∨成人网 | 国产一级午夜一级在线观看 | www.超碰在线.com | 操碰在线观看 | 欧美一本乱大交性xxxⅹ | 欧美黄色大片视频 | 日本一级爽快片野花 | 第一章婶婶的性事 | 婷婷丁香综合网 | 91麻豆精品国产理伦片在线观看 | 三级毛片在线播放 | 国产一区视频网站 | 国产欧美日韩一区二区三区 | 不卡精品视频 | 天堂中文字幕av | 日韩精品――中文字幕 | 中文精品久久久久人妻不卡 | 美女少妇一区二区 | 欧美xxxx非洲 | 3344国产永久在线观看视频 | 台湾swag在线播放 | 精品成人一区二区三区四区 | 真人真事免费毛片 | 黄色成人在线网站 | 亚洲国产一区二区精品 | 国产一二三区在线 | 青草草在线视频 | 五月激情五月婷婷 | 激情五月色综合国产精品 | 亚洲综合射 | 午夜在线视频观看 | 国产精品久久久久久影院8一贰佰 | 国内国内在线自偷第68页 | 少妇高潮一区二区三区99 | 青青视频网 | 丰满少妇高潮叫久久国产 | 日韩精品在线播放 | 香蕉一区二区 | 久久久久久久久99精品情浪 | 久久成人毛片 | 国产一级淫片a免费播放口欧美 | 综合图区亚洲欧美另类图片 | 特级毛片a | а中文在线天堂 | 张柏芝hd一区二区 | av不卡网| 久久亚洲国产成人影院 | 麻豆福利视频 | 国产做国产爱免费视频 | 影音先锋男人av橹橹色 | 沦为黑人姓奴的少妇 | 婷婷久久综合九色综合 | 中文字幕精品三区 | 青青成人在线 | 国产精品免费看久久久无码 | 国产经典一区二区三区 | 未满十八18禁止午夜免费网站 | 国产欧美日韩中文字幕 | 中午日产幕无线码1区 | 怡红院亚洲 | 欧美一级爆毛片 | 精品国产乱码久久久久久口爆网站 | 岛国大片在线免费观看 | 久久精品久久久久久噜噜老黄 | 国产成人精品亚洲日本在线观看 | 欧洲性网站| 久久夜色av| 中文字幕在线观看一区二区 | 黄色片欧美| 亚洲国产精品女人久久久 | 97精品国产手机 | 成人免费毛片网站 | 一个人看的日本hd免费 | 少妇激情av一区二区 | 亚洲欧美另类综合 | 波多野结衣激情视频 | 国产日韩在线一区 | 国产高潮又爽又刺激的视频免费 | 精品久久久噜噜噜久久久 | 国产色妞影院wwwxxx | 亚洲无毛 | 成人久久av | 在线观看福利网站 | 国产高清在线一区 | 国产3页| 国产黄a三级三级三级av在线看 | 免费国产黄线在线观看 | 国产果冻豆传媒麻婆 | 中文字字幕 | 亚洲最大av网站在线观看 | av福利在线 | 亚洲综合二区 | 欧美jizzhd精品欧美性24 | 欧美日韩一区二区在线观看 | av天堂午夜精品一区 | 亚洲最大的熟女水蜜桃av网站 | 夜色毛片永久免费 | 国产毛片乡下农村妇女bd | 国产真实乱人偷精品视频 | 少妇被躁爽到高潮无码人狍大战 | 亚洲天堂二区 | 日本一级淫片免费放 | 久久av一区二区三区亚洲 | 久久精品国产亚洲沈樵 | 日韩精品在线观看一区 | 天天狠狠色综合图片区 | 欧美日韩成人免费 | 一本色道久久综合狠狠躁邻居 | 综合在线播放 | 亚洲精品网站在线观看你懂的 | 国产日产精品一区二区三区四区介绍 | 国产免费麻豆 | 亚洲精品免费在线视频 | 国产精品视频h | 国产日韩精品一区二区 | 国产精选91 | 精品一区二区三区在线视频 | www.蜜臀| 性一交一乱一伦一色一情孩交 | av三级毛片 | 成人免费无码大片a毛片抽搐色欲 | 激情伊人五月天久久综合 | 国产日产精品一区二区三区四区的观看方式 | 亚洲精品视频播放 | 国产精品无码一区二区三区不卡 | 久久视频这里有久久精品视频11 | 少妇一级片| 国内av在线 | 精品久久久久久无码免费 | 久久精品日本啪啪涩涩 | 少妇人妻真实偷人精品视频 | 黄色九九| 国产精品久久久久无码人妻 | 热久久精品免费视频 | 成人黄色免费在线观看 | 国产精品久久久久久亚洲色 | 亚洲国产精久久久久久久 | 成人网在线免费观看 | 日韩色婷婷 | 欧美福利网| 国产交换配乱婬视频 | 影音先锋女人aa鲁色资源 | 国产呻吟久久久久久久92 | 在线观看成人动漫 | 亚洲福利一区二区三区 | 激情啪啪网站 | 在线国产精品视频 | 国产成a人亚洲精品无码樱花 | 亚洲污片| 国产成人精品无码免费看夜聊软件 | 少妇av一区二区三区无码 | 无码人妻精品一区二区三区东京热 | 三上悠亚久久精品 | 一级一片免播放 | 四虎wwwaa884成人精品视频 | 偷窥欧美wc经典tv | 亚洲中文字幕乱码av波多ji | 国产成人无码免费看片软件 | 欧美久久视频 | 中文字幕第一页永久有效 | 伊人免费网 | 成人免费无码大片a毛片抽搐 | 天天摸天天做天天爽水多 | 成人含羞草tv免费入口 | 韩国美女视频黄是免费 | 久久性色| 久久卡一卡二 | 成人在线视频在线观看 | 欧美日韩亚洲国产精品 | 欧美亚洲一区 | 国产一级特黄毛片在线毛片 | 大肉大捧一进一出好爽视频mba | 最近免费中文字幕中文高清百度 | 天美乌鸦星空mv | 一区二区三区四区国产 | 成人亚洲一区二区 | 日批在线 | www成人免费 | 伦理一国产a级 | 国产乱人视频 | 2022天天躁狠狠燥 | 天堂аⅴ在线地址8 | 精精国产xxxx视频在线播放 | 精品视频不卡 | 欧美性猛交xxxⅹ乱大交小说 | 色婷婷亚洲一区二区三区 | 一区二区视频在线观看免费 | 九九re6热在线视频精品66 | 99国内精品久久久久久久夜夜嗨 | 97伊人久久 | 午夜av在线免费观看 | 中文字幕第四页 | 国产又粗又猛又大爽又黄老大爷 | a级毛片网 | 国产伦精品视频一区二区三区 | 青青草色视频 | 中文字幕日韩国产 | 黄色精品一区 | 国产午夜夜伦鲁鲁片 | 国产69精品久久久久999天美 | 日韩欧美a级片 | 久久久无码一区二区三区 | 日本大尺度吃奶做爰过程 | 欧美色图亚洲视频 | 国产寡妇亲子伦一区二区三区四区 | 精品一区二区三区四区五区六区 | 男女下面进入的视频 | 91九色视频在线观看 | 最新色网址 | 欧美精品色视频 | 日韩在线观看av | 国产亚洲精久久久久久叶玉卿 | 超碰人人草 | 中文在线а√在线 | 久久久久女教师免费一区 | 国产中文区二幕区2021 | a级毛片在线免费看 | 欧美乱色伦图片区 | 伊人免费在线 | 精精国产xxxx在线观看主放器 | 国产色综合天天综合网 | 97av麻豆蜜桃一区二区 | 最近中文字幕第一页 | 国产精品国产精品国产专区不卡 | 俄罗斯黄色录像 | 亚洲第一网站男人都懂 | 99久久久成人国产精品 | 国产资源精品 | 欧美成人高清ww | 综合五月天 | 国产麻豆剧果冻传媒白晶晶 | 成人av影院 | 日韩黄色成人 | 91插插影院| 一级片成人 | 强伦人妻一区二区三区视频18 | 欧美性受极品xxxx喷水 | 欧美福利在线 | 在线观看av大片 | 91精品国产综合婷婷香蕉 | 美女的mm免费视频 | 99在线免费观看视频 | a免费在线观看 | 亚洲自拍三区 | www.久久久精品 | 国产1区2区3区中文字幕 | 欧洲亚洲一区二区 | 在线日韩一区 | 丰满熟妇乱又伦 | 亚洲精品乱码久久久久久蜜桃不爽 | 乱色熟女综合一区二区三区 | 蜜臀av性久久久久蜜臀aⅴ四虎 | 久久99热这里只频精品6学生 | 国内精品偷拍视频 | 日韩成人高清视频 | 日韩美女做爰高潮免费 | 国产在线精品一区二区三区不卡 | 粉嫩av四季av绯色av | 狼人综合网 | 国产精品日本一区二区在线播放 | 2021中文字幕在线观看 | 天天干天天爽 | 欧美日本国产欧美日本韩国99 | 国产精品视频1区 | 国产精品久久久久久久久久ktv | 真实的国产乱xxxx在线 | 91精品国产91综合久久蜜臀 | 噜噜视频 | 青青草欧美 | 高潮毛片无遮挡高清免费视频 | 国内自拍视频一区二区三区 | 在线a天堂 | 日韩欧美一区二区视频 | 国产在线观看码高清视频 | 亚洲国产av高清无码 | 18禁无遮挡羞羞污污污污免费 | 国产婷婷vvvv激情久 | 裸体美女无遮挡免费网站 | 天天色图片 | 国产第5页| 久久久精品久久久久久96 | 欧美乱大交xxxxx潮喷l头像 | 插插操操 | 日日碰狠狠躁久久躁综合小说 | 草草浮力地址线路①屁屁影院 | 亚洲免费综合色在线视频 | 国产免费女女脚奴视频网 | 久久久久久婷 | 日本三级韩国三级三级a级按摩 | 成人影院免费 | 狠狠色噜噜狠狠狠888777米奇 | 成人性生交大片免费看r老牛网站 | 2021狠狠天天天 | 精品一卡二卡三卡 | 久操久操久操 | 九九热免费视频 | 久久无码中文字幕免费影院蜜桃 | 久久久久久久久久久99 | 国产精品久久久久久av福利软件 | 免费观看又色又爽又黄6699 | 日韩a片无码毛片免费看 | 丰满熟妇人妻中文字幕 | 亚洲a成人 | 水蜜桃av导航 | 在线天堂中文在线资源网 | 国产在线精品一区二区高清不卡 | 国产激情自拍视频 | 一本色道无码道在线观看 | 日产精品久久久一区二区福利 | 热99re6久精品国产首页青柠 | 日韩高清在线播放 | 女女百合av大片一区二区三区九县 | 国产无遮挡裸体免费视频 | 亚洲深夜 | 在线看片人成视频免费无遮挡 | 亚洲精品aaaa乱码 | 男男一级淫片免费播放 | 成年人免费av | 久草免费看 | 成人av国产| 8050午夜二级无码中文字幕 | 天堂中文在线观看 | 亚洲午夜在线 | 久久久久久久久久久中文字幕 | 日本视频色| 99啪啪| 国模小黎自慰gogo人体 | 欧美极品少妇xxxxⅹ喷水 | 欧美成年人在线观看 | 91精品国产综合久久精品性色 | 国产精品第十页 | 欧美性xxxx顶级按摩 | 久综合| 亚洲色图二区 | 成人做爰www看视频软件 | 狠狠色丁香婷婷综合潮喷 | 无遮挡国产高潮视频免费观看 | 国产看黄网站又黄又爽又色 | 亚洲国产精久久久久久久 | 亚洲精品久久久久久久久 | 四虎影视免费观看 | 成人18视频| 老色鬼av| 亚洲精品国产91 | 婷婷激情偷拍在线 | 国产精品亚洲一区二区三区 | 成人在线短视频 | 国产真实乱对白精彩久久老熟妇女 | 免费国精产品自偷自偷免费看 | 成人免费视 | 爱情岛论坛亚洲品质自拍 | 男女啪啪十八 | 99香蕉视频| 久久99国产视频 | 亚洲成人黄色片 | 午夜视频污 | 亚洲精品国产第一综合99久久 | 欧美激情视频免费 | 久久97精品国产96久久小草 | 精品一区二区三区在线视频 | 欧美一区二区激情 | www欧美亚洲 | 亚洲国产视频网站 | 国产免费视频一区二区裸体 | 偷看美女洗澡一二三四区 | 在线精品国产成人综合 | 亚洲啪啪网 | 美国性生活大片 | 久久久www影院人成_免费 | 日韩精品一二三四区 | 国产精品高潮呻吟久久aⅴ码 | 天堂网在线最新版www | 欧美高清视频一区二区三区 | 尤物视频在线观看免费 | jyzz中国jizz十八岁免费 | 成人欧美一区二区三区的电影 | 一区二区三区四区五区视频 | 老妇高潮潮喷到猛进猛出 | 91丝袜超薄交口足 | 亚洲精品69| 天天操天天操天天操天天操天天操 | 超碰人人爱人人 | 中国妇女做爰视频 | 中文字幕乱码免费 | 精品亚洲国产成av人片传媒 | 26uuu国产精品视频 | 中文字母av| 日韩精品一区二区三区色欲av | 色噜噜狠狠色综合中国 | 狠狠躁天天躁中文字幕无码 | 国产精品免费看久久久 | 日韩亚洲精品视频 | 精品国产户外野外 | 亚洲一区二区三区av无码 | 黑人狂躁日本妞一区二区三区 | 中文字幕av伊人av无码av | 亚洲精品无码久久久久久 | 91尤物视频在线观看 | 理论片午午伦夜理片久久 | 欧美大胆a视频 | 高潮白浆女日韩av免费看 | 99精品热 | av在线观看地址 | 国产在线观看码高清视频 | 久久久人成影片免费观看 | 小鲜肉自慰网站 | 亚洲国产成人综合精品 | 2018天天干天天操 | 高潮毛片又色又爽免费 | av涩涩| 少妇艹逼 | 天天躁日日躁xxxxaaaa | 亚洲国产成人丁香五月激情 | 伊朗做爰xxxⅹ性视频 | 香蕉国产片一级一级一级一级 | 天天爽网站 | 青青草官网 | 伊人成年综合网 | 风韵丰满熟妇啪啪区老老熟妇 | 国产成人精品免高潮在线观看 | 石原莉奈一区二区三区在线观看 | 超薄肉色丝袜一区二区 | 欧美在线观看一区二区 | 亚洲欧美高清在线 | 一级激情片 | 黄色在线免费观看视频 | 成熟的女同志hd | 高清黄色一级片 | 粉嫩av免费一区二区三区 | 国产亚洲欧美日韩在线一区二区三区 | 欧美国产一区二区 | 日韩狠狠| 国产激情久久久久久熟女老人av | 日韩精品一区二区三区 | 日本少妇呻吟高潮免费看 | 久草福利在线视频 | 国产夫妻性爱视频 | 五月色吧 | 婷婷丁香社区 | 亚洲精品久久久久 | 黄色录像毛片 | 精品久久蜜桃 | 成人三级做爰视频在线看 | 四色永久访问网站 | 少妇边打电话边呻吟在线91 | 男女下面进入的视频 | 日韩av午夜在线观看 | 欧美人妖ⅹxxx极品另类 | 久久人人干| 国产青草视频在线观看 | 欧洲精品久久 | 亚洲精品国产精品久久99热 | 夜夜夜网站 | 国内毛片毛片毛片毛片毛片毛片 | 国产黄色大片免费看 | 色乱码一区二区三区 | 国产精品自在在线午夜出白浆 | 啪啪网视频 | 亚洲国产综合精品2020 | 春色校园综合人妻av | 日本一道高清一区二区三区 | 免费福利av | 在线日本中文字幕 | 欧美性猛交xx乱大交 | 熟妇高潮一区二区三区 | 国产精品国产三级国产专播品爱网 | 97久人人做人人妻人人玩精品 | 狠狠色丁香婷婷综合欧美 | 老太脱裤让老头玩ⅹxxxx | 成av人片在线观看www | 日韩精品一区二区三区中文在线 | 国产91在线播放9色不卡 | 精品成人乱色一区二区 | 天天操天天干天天舔 | 五月视频 | 可以免费看的av | 日韩免费看 | 一区二区观看 | 91精品国产99久久久久久久 | 天堂视频免费 | 97人妻精品一区二区三区 | 国产精品久久高潮呻吟粉嫩av | 综合色吧| 无遮挡边吃摸边吃奶边做 | 欧美一级在线观看 | 九一精品视频 | 亚洲成av人片在线观看无码 | 欧美熟妇毛茸茸 | 小明看平台日韩综合45页 | 国产露脸91国语对白 | 黄色精品一区二区三区 | 久久久黄色片 | 5级黄色片 | 日日躁夜夜摸月月添添添 | 精品国产污污免费网站 | 国产娇小性色xxxxx视频 | 欧美另类极品videosbest最新版本 | 性猛色xxxxx富婆 | 日本爽快片毛片 | 免费国产黄色 | 国产性生交xxxxx免费 | 福利一区在线 | 91亚洲精品国偷拍自产在线观看 | 18禁真人抽搐一进一出免费 | 久热超碰| 国内精品久久久久影院中文字幕 | 亚洲婷婷在线 | 久久久久久9| 一本一本久久a久久精品牛牛影视 | 亚洲午夜久久 | 强制中出し~大桥未久在线播放 | 少妇露脸大战黑人视频 | 亚洲一区二区在线视频观看 | 精品久久久久久亚洲精品 | 国产一区二区三区四区五区加勒比 | 4438x成人免费 | 精品国产美女福到在线不卡 | 欧美日韩在线高清 | 日本日皮视频 | 亚洲天堂91 | 国产日产欧产精品精品app | 裸露双乳挤奶无遮掩裸体网站 | 另类亚洲小说图片综合区 | 欧美中文字幕第一页 | 欧美日韩免费 | 偷窥少妇高潮呻吟av久久免费 | 午夜影院免费观看 | 欧美午夜精品一区二区蜜桃 | 国产精品偷窥熟女精品视频 | 亚洲永久精品视频 | 国产伦精品一区二区三区四区视频 | 射进来av影视| 国产综合色在线精品 | 性生av免费播放 | 欧美大浪妇猛交饥渴大叫 | 女神呻吟娇喘高潮毛片 | av亚洲午夜网站福利天堂 | 性欧美在线视频 | 亚洲精品国产剧情久久9191 | 99国产精品国产免费观看 | 山东熟女啪啪哦哦叫 | 亚洲深深色噜噜狠狠爱网站 | 麻豆视频软件 | 久久亚洲少妇 | 国产精品久久久爽爽爽麻豆色哟哟 | 一级黄色免费 | 日本中文字幕在线观看 | 少妇又紧又色又爽又刺激的视频 | 五月婷婷激情第四季 | 亚洲色大成网站www 中文字幕色婷婷在线视频 麻豆人妻少妇精品无码专区 | 久久精品九九精av | 亚洲av毛片成人精品 | 利智三级露全乳 | 成人免费视频国产免费麻豆 | 国产中文字幕在线观看 | 人人爽人人爽人人片av | 欧美国产在线一区 | 欧美午夜性春猛交xxxx明星 | 中文字幕人成乱码在线观看 | 日韩在线观看视频一区二区三区 | 欧美色亚洲色 | 超碰97在线播放 | 久草色香蕉| 久久久综合香蕉尹人综合网 | 少妇搡bbbb搡bbb搡澳门 | 国产欧美综合一区二区三区 | 又粗又黄又硬又爽的免费视频 | 绿色地狱在线观看 | 青草精品在线 | 香蕉视频ww| 亚洲免费网站观看视频 | 国产精品成人免费 | 精品成人69xx.xyz | 在线成人免费 | 久久五月激情 | 一级大毛片 | 成人影片麻豆国产影片免费观看 | 精品视频一区在线观看 | 少妇天天干 | 国产精品久久无码一区二区三区网 | 综合久久伊人 | 亚洲久久色 | 国产真实伦在线观看视频 | 少妇露脸大战黑人视频 | 亚洲精品日韩激情欧美 | 亚洲欧美在线人成最新 | 欧美裸体xxxx极品少妇 |