嵌入式開發絕招:狀態機+事件驅動框架

汽車電子嵌入式 2025-05-09 06:36

狀態機是一種思想,事件驅動也是一種思想。

事件驅動的概念

生活中有很多事件驅動的例子,上自習瞞著老師偷睡覺就是很生動的一個。

我們都是從高中時代走過來的,高中的學生苦啊,覺得睡覺是世界上最奢侈的東西, 有時候站著都能睡著啊!老師看的嚴,上課睡覺不允許 啊,要挨批啊!有木有!相比而言,晚自習是比較寬松的,老師只是不定時來巡視,還是有機會偷偷睡一會兒的。

現在的問題是,怎么睡才能既睡得好又不會讓老師發現呢? 晚自習是比較寬松的,老師只是不定時來巡視,還是有機會偷偷睡一會兒的。現在的問題是,怎么睡才能既睡得好又不會讓老師發現呢?

我們現在有三種睡覺方案:

  • 方案 A:倒頭就睡,管你三七二十一,睡夠了再說,要知道有時候老師可能一整晚上都不來的。
  • 方案 B:間歇著睡,先定上鬧鐘, 5 分鐘響一次,響了就醒,看看老師來沒來,沒來的話定上鬧鐘再睡,如此往復。
  • 方案 C:睡之前讓同桌給放哨,然后自己睡覺,什么也不用管,什么時候老師來了,就讓同桌戳醒你。

不管你們選擇的是哪種方案,我高中那會兒用的可是方案 C,安全又舒服。

方案 C 是很有特點的:本來自習課偷睡覺是你自己的事兒, 有沒有被老師抓著也是你自己的事兒,這些和同桌是毫無利害關系的,但是同桌這個環節對方案 C 的重要性是不言而喻的,他肩負著監控老師巡視和叫醒睡覺者兩項重要任務,是事件驅動機制實現的重要組成部分 。

在事件驅動機制中,對象對于外部事件總是處于“休眠” 狀態的,而把對外部事件的檢測和監控交給了第三方組件。

一旦第三方檢測到外部事件發生, 它就會啟動某種機制, 將對象從“休眠” 狀態中喚醒, 并將事件告知對象。對象接到通知后, 做出一系列動作, 完成對本次事件響應,然后再次進入“休眠” 狀態,如此周而復始。

有沒有發現,事件驅動機制和單片機的中斷原理上很相似 。

事件驅動與單片機編程

在我們再回到單片機系統中來,看看事件驅動思想在單片機程序設計中的應用。當我還是一個單片機菜鳥的時候(當然,我至今也沒有成為單片機高手),網絡上的大蝦們就諄諄教導:一個好的單片機程序是要分層的。曾經很長一段時間, 我對分層這個概念完全沒有感覺。

  • 什么是程序分層?
  • 程序為什么要分層?
  • 應該怎么給程序分層?

隨著手里的代碼量越來越多,實現的功能也越來越多,軟件分層這個概念在我腦子里逐漸地清晰起來,我越來越佩服大蝦們的高瞻遠矚。

單片機的軟件確實要分層的,最起碼要分兩層:驅動層和應用層。應用是單片機系統的核心,與應用相關的代碼擔負著系統關鍵的邏輯和運算功能,是單片機程序的靈魂。

硬件是程序感知外界并與外界打交道的物質基礎,硬件的種類是多種多樣的,各類硬件的操作方式也各不相同,這些操作要求嚴格、精確、瑣細、繁雜。

與硬件打交道的代碼只鐘情于時序和寄存器,我們可以稱之為驅動相關代碼;與應用相關的代碼卻只專注于邏輯和運算, 我們可稱之為應用相關代碼。

這種客觀存在的情況是單片機軟件分層最直接的依據,所以說,將軟件劃分為驅動層和應用層是程序功能分工的結果。那么驅動層和應用層之間是如何銜接的呢?

在單片機系統中,信息的流動是雙向的,由內向外是應用層代碼主動發起的,實現信息向外流動很簡單, 應用層代碼只需要調用驅動層代碼提供的 API 接口函數即可, 而由外向內則是外界主動發起的, 這時候應用層代碼對于外界輸入需要被動的接收, 這里就涉及到一個接收機制的問題,事件驅動機制足可勝任這個接收機制。

外界輸入可以理解為發生了事件,在單片機內部直接的表現就是硬件生成了新的數據,這些數據包含了事件的全部信息, 事件驅動機制的任務就是將這些數據初步處理(也可能不處理),然后告知應用層代碼, 應用代碼接到通知后把這些數據取走, 做最終的處理, 這樣一次事件的響應就完成了。

說到這里,可能很多人突然會發現,這種處理方法自己編程的時候早就用過了,只不過沒有使用“事件驅動” 這個文縐縐的名詞罷了。其實事件驅動機制本來就不神秘, 生活中數不勝數的例子足以說明它應用的普遍性。下面的這個小例子是事件驅動機制在單片機程序中最常見的實現方法,假設某單片機系統用到了以下資源:

  • 一個串口外設 Uart0,用來接收串口數據;
  • 一個定時器外設 Tmr0,用來提供周期性定時中斷;
  • 一個外部中斷管腳 Exi0,用來檢測某種外部突發事件;
  • 一個 I/O 端口 Port0,連接獨立式鍵盤,管理方式為定時掃描法,掛載到 Tmr0 的 ISR;

這樣,系統中可以提取出 4 類事件,分別是 UART、 TMR、 EXI、 KEY ,其中 UART 和KEY 事件發生后必須開辟緩存存儲事件相關的數據。所有事件的檢測都在各自的 ISR 中完成,然后 ISR 再通過事件驅動機制通知主函數處理。

為了實現 ISR 和主函數通信, 我們定義一個數據類型為INT8U的全局變量 g_u8EvntFlgGrp,稱為事件標志組,里面的每一個 bit 位代表一類事件,如果該 bit 值為 0,表示此類事件沒有發生,如果該 bit 值為 1,則表示發生了此類事件,主函數必須及時地處理該事件。圖 5 所示為g_u8EvntFlgGrp 各個 bit 位的作用 。

圖片

程序清單 List9 所示就是按上面的規劃寫成的示例性代碼 。

程序清單List9:

#define?FLG_UART 0x01
#define?FLG_TMR 0x02
#define?FLG_EXI 0x04
#define?FLG_KEY 0x08
volatile?INT8U g_u8EvntFlgGrp =?0;?/*事件標志組*/
INT8U?read_envt_flg_grp(void);
/***************************************
*FuncName : main
*Description : 主函數
*Arguments : void
*Return : void
*****************************************/

void?main(void)
{
?INT8U u8FlgTmp =?0;
?sys_init();
while(1)
?{
? u8FlgTmp = read_envt_flg_grp();?/*讀取事件標志組*/
if(u8FlgTmp )?/*是否有事件發生? */
? {
? ?if(u8FlgTmp & FLG_UART)
? ?{
? ? action_uart();?/*處理串口事件*/
? ?}
? ?if(u8FlgTmp & FLG_TMR)
? ?{
? ? action_tmr();?/*處理定時中斷事件*/
? ?}
? ?if(u8FlgTmp & FLG_EXI)
? ?{
? ? action_exi();?/*處理外部中斷事件*/
? ?}
? ?if(u8FlgTmp & FLG_KEY)
? ?{
? ? action_key();?/*處理擊鍵事件*/
? ?}
? }
else
? {
? ?;/*idle code*/
? }
?}
}
/*********************************************
*FuncName : read_envt_flg_grp
*Description : 讀取事件標志組 g_u8EvntFlgGrp ,
* 讀取完畢后將其清零。
*Arguments : void
*Return : void
*********************************************/

INT8U?read_envt_flg_grp(void)
{
?INT8U u8FlgTmp =?0;
?gbl_int_disable();
?u8FlgTmp = g_u8EvntFlgGrp;?/*讀取標志組*/
?g_u8EvntFlgGrp =?0;?/*清零標志組*/
?gbl_int_enable();
return?u8FlgTmp;
}
/*********************************************
*FuncName : uart0_isr
*Description : uart0 中斷服務函數
*Arguments : void
*Return : void
*********************************************/

void?uart0_isr(void)
{
?......
?push_uart_rcv_buf(new_rcvd_byte);?/*新接收的字節存入緩沖區*/
?gbl_int_disable();
?g_u8EvntFlgGrp |= FLG_UART;?/*設置 UART 事件標志*/
?gbl_int_enable();
?......
}
/*********************************************
*FuncName : tmr0_isr
*Description : timer0 中斷服務函數
*Arguments : void
*Return : void
*********************************************/

void?tmr0_isr(void)
{
?INT8U u8KeyCode =?0;
?......
?gbl_int_disable();
?g_u8EvntFlgGrp |= FLG_TMR;?/*設置 TMR 事件標志*/
?gbl_int_enable();
?......
?u8KeyCode = read_key();?/*讀鍵盤*/
if(u8KeyCode)?/*有擊鍵操作? */
?{
? push_key_buf(u8KeyCode);?/*新鍵值存入緩沖區*/
? gbl_int_disable();
? g_u8EvntFlgGrp |= FLG_KEY;?/*設置 TMR 事件標志*/
? gbl_int_enable();
?}
?......
}
/*********************************************
*FuncName : exit0_isr
*Description : exit0 中斷服務函數
*Arguments : void
*Return : void
*********************************************/

void?exit0_isr(void)
{
?......
?gbl_int_disable();
?g_u8EvntFlgGrp |= FLG_EXI;?/*設置 EXI 事件標志*/
?gbl_int_enable();
?......
}

看一下程序清單 List9 這樣的程序結構,是不是和自己寫過的某些程序相似?對于事件驅動機制的這種實現方式, 我們還可以做得更絕一些, 形成一個標準的代碼模板,做一個包含位段和函數指針數組的結構體,位段里的每一個元素作為圖 5 那樣的事件標志位,然后在函數指針數組中放置各個事件處理函數的函數地址, 每個處理函數對應位段里的每個標志位。

這樣, main()函數中的事件處理代碼就可以做成標準的框架代碼。應該說,這樣的實現方式是很好的,足以輕松地應對實際應用中絕大多數的情況。但是,事件驅動機制用這樣的方式實現真的是完美的么?在我看來,這種實現方式至少存在兩個問題:

  • 不同事件集中爆發時,無法記錄事件發生的前后順序。
  • 同一事件集中爆發時,容易遺漏后面發生的那次事件。

圖 6 所示為某一時段單片機程序的執行情況,某些特殊情況下,會出現上面提到的兩個問題。

圖片

圖中, f1 為某事件的處理函數, f2 為另一事件的處理函數, I1、 I2、 I3 為 3 個不同事件觸發的 ISR,假定 I1、 I2、 I3 分別對應事件 E1、 E2、 E3。從圖中可以看出,主函數在調用事件處理函數 f1 的時候,發生了 2 次事件,主函數被 I1和 I2 中斷了 2 次, I1 和 I2 執行的時候各自置位了相應的事件標志位。

函數 f1 返回后, 主函數又調用了另一個事件處理函數 f2, f2 執行期間先后發生了 2 次同樣的事件, f2 被 I3 中斷了 2次,對應的事件標志位被連續置位了 2 次。

在圖 6 中我們當然可以看出 I1 先于 I2 執行,即事件 E1 發生在事件 E2 之前,但是主函數再次讀取事件標志組 g_u8EvntFlgGrp 的時候, 看到的是兩個“同時” 被置位的標志位, 無法判斷出事件 E1 和 E2 發生的先后順序, 也就是說有關事件發生先后順序的信息丟失了, 這就是前面說的第 1 個問題:不同事件集中爆發時,無法記錄事件發生的前后順序。

在程序清單 List9 中, 主函數在處理事件時, 按照程序預先設定好的順序, 一個一個地處理發生的事件, 如果不同事件某時段集中爆發, 可能會出現事件的發生順序和事件的處理順序不一致的情況。倘若系統功能對事件的發生順序敏感,那么程序清單 List9 中的程序就不能滿足要求了。

同樣的道理,如果 I3 對應的事件 E3 是程序清單 List9 中 EXI 那樣的事件(這種事件沒有緩沖機制), 事件 E3 第 2 次的發生就被遺漏了, 這就是前面所說的第 2 個問題:同一事件集中爆發時,容易遺漏后后面發生的事件。

如果系統功能對事件 E3 的發生次數敏感,程序清單 List9 中的程序也是不能滿足要求的。既然事件驅動機制這樣的實現方式存在缺陷, 那么有沒有一種更好的實現方式呢?當然有!把事件轉換成消息存入消息隊列就能完美解決這個問題, 只不過大家不要對我這種自導自演的行文方式產生反感就好 ?。

事件驅動與消息

什么是消息?消息是數據信息的一種存儲形式。從程序的角度看,消息就是一段存儲著特定數據的內存塊, 數據的存儲格式是設計者預先約定好的, 只要按照約定的格式讀取這段內存, 就能獲得消息所承載的有用信息。

消息是有時效性的。任何一個消息實體都是有生命周期的,它從誕生到消亡先后經歷了生成、 存儲、 派發、 消費共 4 個階段:消息實體由生產者生成, 由管理者負責存儲和派發, 最后由消費者消費。

被消費者消費之后, 這個消息就算消亡了, 雖然存儲消息實體的內存中可能還殘留著原來的數據, 但是這些數據對于系統來講已經沒有任何意義了, 這也就是消息的時效性。說到這里,大家有沒有發現,這里的“消息” 和前面一直在說的“事件” 是不是很相似?把“消息” 的這些特點套用在“事件” 身上是非常合適的, 在我看來, 消息無非是事件的一個馬甲而已。

我們在設計單片機程序的時候,都懷著一個夢想,即讓程序對事件的響應盡可能的快,理想的情況下,程序對事件要立即響應,不能有任何延遲。這當然是不可能的,當事件發生時,程序總會因為這樣那樣的原因不能立即響應事件。

為了不至于丟失事件,我們可以先在事件相關的 ISR 中把事件加工成消息并把它存儲在消息緩沖區里, ISR 做完這些后立即退出。主程序忙完了別的事情之后,去查看消息緩沖區,把剛才 ISR 存儲的消息讀出來, 分析出事件的有關信息, 再轉去執行相應的響應代碼, 最終完成對本次事件的響應。

只要整個過程的時間延遲在系統功能容許的范圍之內, 這樣處理就沒有問題。將事件轉化為消息,體現了以空間換時間的思想。再插一句,雖然事件發生后對應的 ISR 立即被觸發,但是這不是嚴格意義上的“響應”, 頂多算是對事件的“記錄”, “記錄” 和“響應” 是不一樣的。事件是一種客觀的存在,而消息則是對這種客觀存在的記錄。

對于系統輸入而言,事件是其在時間維度上的描述;消息是其在空間維度上的描述,所以,在描述系統輸入這一功能上,事件和消息是等價的。對比一下程序清單 List9 中的實現方式, 那里是用全局標志位的方式記錄事件, 對于某些特殊的事件還配備了專門的緩沖區, 用來存儲事件的額外信息, 而這些額外信息單靠全局標志位是無法記錄的。

現在我們用消息+消息緩沖區的方式來記錄事件,消息緩沖區就成了所有事件共用的緩沖區,無論發生的事件有沒有額外的信息,一律以消息的形式存入緩沖區 ?。

為了記錄事件發生的先后順序,消息緩沖區應該做成以“先入先出” 的方式管理的環形緩沖隊列。事件生成的消息總是從隊尾入隊,管理程序讀取消息的時候總是從隊頭讀取,這樣,消息在緩沖區中存儲的順序就是事件在時間上發生的順序,先發生的事件總是能先得到響應。

一條消息被讀取之后, 管理程序回收存儲這個消息的內存, 將其作為空閑節點再插入緩沖隊列的隊尾,用以存儲將來新生成的消息。圖 7 所示為使用了消息功能的事件驅動機制示意圖。不知道有沒有人對圖中的“消費者”有疑問, 這個“消費者” 在程序中指的是什么呢?

既然這個事件/消息驅動機制是為系統應用服務的, 消費者當然就是指應用層的代碼了, 更明確一點兒的話, 消費者就是應用代碼中的狀態機 ?。

圖片

用消息的方法來實現事件驅動機制完全解決了前面提到的那兩個問題,即不同事件集中爆發時,無法記錄事件發生的前后順序。同一事件集中爆發時,容易遺漏后面發生的那次事件。對于第一種情況,消息(事件)在緩沖隊列中是以“先入先出” 的方式存儲的,存儲順序就代表了事件發生的先后順序。

對于第二種情況, 任何被 ISR 捕捉到的事件都會以一個獨立的消息實體存入緩沖隊列, 即使前后兩個是同一個事件, 只要 ISR 反應夠快就不會遺漏事件。實際上, ISR 的主要工作就是填寫消息實體, 然后將其存入緩沖隊列, 做這些工作只占用 CPU 很短的時間。

接下來再說一說這個消息機制在程序中如何實現。在程序中,消息機制可以看做是一個獨立的功能模塊,一個功能模塊的實現無非就是數據結構+算法。先來看消息機制的數據結構。這里的數據結構是指和消息機制有關的數據組織形式,包含 2 個部分:

  • 消息節點自身的數據組織形式
  • 消息緩沖區的數據組織形式

程序清單 List10 所示就是消息機制的數據結構 。

「程序清單List10:」

typedef?union?msg_arg?/*消息參數共用體*/
{
?INT8U u8Arg;?/*成員:8 位無符號*/
?INT8U s8Arg;?/*成員:8 位有符號*/
#if?CFG_MSG_ARG_INT16_EN>0
?INT16U u16Arg;?/*可選成員:16 位無符號*/
?INT16S s16Arg;?/*可選成員:16 位有符號*/
#endif
#if?CFG_MSG_ARG_INT32_EN>0
?INT32U u32Arg;?/*可選成員:32 位無符號*/
?INT32S s32Arg;?/*可選成員:32 位有符號*/
#endif
#if?CFG_MSG_ARG_FP32_EN>0
?FP32 f32Arg;?/*可選成員:32 位單精度浮點*/
#endif
#if?CFG_MSG_ARG_PTR_EN>0
void* pArg;?/*可選成員:void 指針*/
#endif
}MSG_ARG;

typedefstruct?_msg?/*消息結構體*/
{

?INT8U u8MsgID;?/*消息 ID*/
#if?CFG_MSG_USR_SUM > 1
?INT8U u8UsrID;?/*消費者 ID*/
#endif
?MSG_ARG uMsgArg;?/*應用消息參數*/
} MSG;

typedefstruct?msg_box?/*消息緩沖區結構體*/
{

?INT8U u8MBLock;?/*隊列上鎖標識*/
?INT8U u8MsgSum;?/*隊列長度*/
?INT8U u8MQHead;?/*隊列頭結點位置*/
?INT8U u8MQTail;?/*隊列尾節點位置*/
?MSG arMsgBox[CFG_MSG_SUM_MAX];?/*存放隊列的數組*/
} MB;
static?MB g_stMsgUnit;?/*消息管理單元全局變量*/

消息的數據結構包含 2 部分:消息頭和消息參數,在消息結構體 MSG 中, u8MsgID 和u8UsrID 就是消息頭,共用體 MSG_ARG 就是消息參數。

u8MsgID 是消息的類型標志,也就是生成此消息的事件的事件類型標志,程序根據這個成員選擇對應的事件處理函數;u8UsrID 是消息的消費者代號, 如果應用代碼中只有一個消費者,則成員 u8UsrID 可以忽略。MSG_ARG 就是消息附帶的參數,也就是事件的內容信息。

系統中的事件是多種多樣的,有的事件只需要類型標志即可, 有的事件可能還需要整型變量存儲事件內容, 還有的事件可能需要大塊的內存來存儲一些附帶的數據。為了將各種類型的事件生成的消息納入統一管理, 要求 MSG_ARG 必須能存儲各種類型的數據,因此 MSG_ARG 被定義成了共用體。

從程序清單 List10 中可以看出, MSG_ARG 既可以存儲 8 位~32 位有符號無符號整型數據,又可以存儲單精度浮點, 還可以存儲 void* 型的指針變量, 而 void*的指針又可以強制轉換成任意類型的指針,所以 MSG_ARG 可以存儲指向任意類型的指針。

對于MSG_ARG中的某些成員, 還配備了預編譯常量 CFG_MSG_ARG_XXX_EN加以控制,如果實際應用中不需要這些耗費內存較大的數據類型, 可以設置CFG_MSG_ARG_XXX_EN 去掉它們。全開的情況下, 每個消息節點占用 6 個字節的內存, 最精簡的情況下, 每個消息節點只占用 2 個字節。

全局結構體變量 g_stMsgUnit 是消息緩沖區的數據結構。消息緩沖區是一個環形緩沖隊列,這里將環形隊列放在了一個一維數組中,也就是g_stMsgUnit 的成員 arMsgBox[],數組元素的數據類型就是消息結構體 MSG ,數組的大小由預編譯常量 CFG_MSG_SUM_MAX 控制,該常量是環形緩沖隊列的最大容量。

理論上, CFG_MSG_SUM_MAX 值的選取越大越好,但考慮到單片機的 RAM 資源有CFG_MSG_SUM_MAX 值的選取要在資源消耗和實際最大需求之間折中, 只要能保證在最壞情況下環形緩沖隊列仍有裕量即可。用數組實現環形隊列還需要一些輔助變量,也就是 g_stMsgUnit 剩余的成員。

u8MBLock 是隊列的控制變量, u8MBLock>0 表示隊列處于鎖定/保護狀態,不能寫也不能讀, u8MBLock=0 表示隊列處于正常狀態,可寫可讀;u8MsgSum 是隊列長度計數器,記錄著當前隊列中存有多少條消息,存入一條消息u8MsgSum++,讀出一條消息 u8MsgSum--;

u8MQHead 記錄著當前隊頭消息節點在數組 arMsgBox[]中的位置,其值就是數組元素的下標,消息讀取的時候所讀出的就是 u8MQHead 所指向的節點,讀完之后 u8MQHead 向隊尾方向移動一個位置,指向新的隊頭節點;u8MQTail 記錄著當前隊尾消息節點在數組 arMsgBox[]中的位置,其值是數組元素的下標,新消息寫入之前, u8MQTail 向隊尾方向后移一個位置, 然后新寫入的消息存入 u8MQTail 所指向的空閑節點;

圖 8 所示為消息緩沖區結構體變量 g_stMsgUnit 的示意圖 。

圖片

有了數據結構,還要有對應的算法實現,消息機制的數據主體就是一個數組化了的環形隊列,環形隊列的算法就是我們所要的算法。消息機制是一個獨立的功能模塊,應該對外屏蔽其內部實現細節,而僅對外界開放一定數量的接口函數,外界通過調用這些接口來使用消息功能,這也就是我在聲明 g_stMsgUnit 變量的時候使用了 static 關鍵詞的原因。

消息模塊的接口函數一共有 9 個:

  • void mq_init(void) 消息隊列初始化,負責初始化 g_stMsgUnit 。
  • void mq_clear(void) 清空消息隊列,效果同 mq_init(),可有可無。
  • void mq_lock(void) 消息隊列鎖定,鎖定的消息隊列不可讀不可寫。
  • void mq_unlock(void) 消息隊列解鎖,解鎖后消息隊列恢復正常功能。
  • BOOL mq_is_empty(void) 消息隊列判空,返回 TRUE 表示消息隊列當前為空,返回 FALSE 表示有消息存儲。
  • INT8U mq_get_msg_cur_sum(void) 查詢消息隊列中當前存儲的消息總數,函數返回值為查詢結果
  • INT8U mq_get_msg_sum_max(void) 查詢消息隊列的最大容量,函數返回值為查詢結果。
  • INT8U mq_msg_post_fifo(MSG* pMsg) 向消息隊列中寄送消息,方式為先入先出,形參 pMsg 指向消息的備份內存,函數返回操作結果。該函數多被 ISR 調用,所以必須為可重入函數。
  • INT8U mq_msg_req_fifo(MSG* pMsg) 從消息隊列中讀取消息, 方式為先入先出, 函數將讀出的消息存入形參 pMsg 指向的內存,函數返回操作結果。該函數被主程序調用, 可以不是可重入函數, 但要對共享數據進行臨界保護 ?。

事件/消息驅動機制是一個標準的通用的框架,配合 ISR,對任何系統輸入都能應對自如。事件/消息驅動機制屏蔽了應用層程序獲取各種系統輸入的工作細節,將系統輸入抽象整合, 以一種標準統一的格式提交應用代碼處理, 極大地減輕了應用層代碼獲取系統輸入的負擔, 應用層只需要專注于高級功能的實現就可以了。

從軟件分層的角度來看, 事件/消息驅動機制相當于驅動層和應用層之間的中間層, 這樣的層次結構如圖 9 。

圖片

圖9 中之所以驅動層和應用層之間還有接觸,是因為系統輸出響應的時候,應用層可能還需要直接調用驅動層提供的函數接口。如果一個單片機的軟件是圖 9 這樣的結構,并且應用層的程序使用狀態機來實現,在消息的驅動下使應用層的狀態機運轉起來, 那么這個軟件的設計思想就是整篇文章的主題:基于事件/消息驅動+狀態機結構的裸奔通用框架?。

程序框架:狀態機+事件/消息驅動

事件/消息驅動和狀態機是天生的搭檔,這對黃金組合是分析問題解決問題的利器 ?。

1、牛刀小試

規則描述:

  1. L1L2 狀態轉換順序 OFF/OFF--->ON/OFF--->ON/ON--->OFF/ON--->OFF/OFF
  2. 通過按鍵控制 L1L2 的狀態,每次狀態轉換只需按鍵 1 次
  3. 從上一次按鍵的時刻開始計時,如果 10 秒鐘之內沒有按鍵事件,則不管當前 L1L2 狀態如何,一律恢復至初始狀態。
  4. L1L2 的初始狀態 OFF/OFF

現在我們用狀態機+事件/消息驅動的思想來分析問題。系統中可提取出兩個事件:按鍵事件和超時事件,分別用事件標志 KEY 和 TOUT 代替。L1L2 的狀態及轉換關系可做成一個狀態機,稱為主狀態機,共 4 個狀態:LS_OFFOFF、LS_ONOFF、 LS_ONON、 LS_OFFON 。主狀態機會在事件 KEY 或 TOUT 的驅動下發生狀態遷移,各個狀態之間的轉換關系比較簡單,在此略過。

事件/消息驅動機制的任務就是檢測監控事件 KEY 和 TOUT,并提交給主狀態機處理。檢測按鍵需要加入消抖處理,消抖時間定為 20ms, 10S 超時檢測需要一個定時器進行計時。

這里將按鍵檢測程序部分也做成一個狀態機,共有 3 個狀態:

  • WAIT_DOWN :空閑狀態,等待按鍵按下
  • SHAKE :初次檢測到按鍵按下,延時消抖
  • WAIT_UP :消抖結束,確認按鍵已按下,等待按鍵彈起

按鍵狀態機的轉換關系可在圖 10 中找到。按鍵檢測和超時檢測共用一個定時周期為 20ms 的定時中斷,這樣就可以把按鍵檢測和超時檢測的代碼全部放在這個定時中斷的 ISR 中。我把這個中斷事件用 TICK 標記, 按鍵狀態機在 TICK 的驅動下運行, 按鍵按下且消抖完畢后觸發 KEY 事件, 而超時檢測則對 TICK 進行軟時鐘計數,記滿 500 個 TICK 則超時 10S,觸發 TOUT 事件。

有了上面的分析,實現這個功能的程序的結構就十分清晰了, 圖 10 是這個程序的結構示意圖,這張圖表述問題足夠清晰了,具體的代碼就不寫了。仔細瞅瞅,是不是有點兒那個意思了?

圖片

如果忽略定時中斷 ISR 中的細節,圖 10 中的整個程序結構就是事件/消息驅動+主狀態機的結構,?ISR 是消息的生產者,與消息緩沖、派發相關的程序部分是管理者,而主狀態機則是消息的消費者,應用層代碼中只有這一個狀態機,是消息的唯一消費者。

這個結構就是通用框架 GF1.0 的標準結構:多個 ISR + 一個消息緩沖區 + 一個應用層主狀態機。ISR 生成的消息(事件)全部提交主狀態機處理, 在消息的驅動下主狀態機不斷地遷移。

如果把應用層主狀態機看做是一臺發動機, 那么 ISR 生成的消息則是燃料, 事件不斷的發生, 消息不斷的生成,有了燃料(消息)的供給,發動機(主狀態機)就能永不停息地運轉。

接下來關注一下圖 10 中的 ISR, 這個 ISR 里面的內容是很豐富的, 里面還套著 2 個小狀態機:按鍵狀態機和計時狀態機。按鍵狀態機自不必說, 這個計時部分也可以看做是一個狀態機,不過這個狀態機比較特殊,只有一個狀態 DELAY。

既然是狀態機, 想要跑起來就需要有事件來驅動, 在這個 ISR 里, 定時器的中斷事件 TICK就是按鍵狀態機和計時狀態機的驅動,只不過這兩個事件驅動+狀態機結構沒有消息緩沖,當然也不需要消息緩沖,因為狀態機在 ISR 中,對事件是立即響應的。

從宏觀上看,圖 10 中是事件/消息驅動+狀態機,從微觀上看,圖 10 中的 ISR 也是事件驅動+狀態機。ISR 中的狀態機在遷移過程中生成消息(事件),而這些消息(事件)對于主狀態機來講又是它自己的驅動事件。事件的級別越高, 事件自身也就越抽象, 描述的內容也就越接近人的思維方式。我覺得這種你中有我我中有你的特點正是事件驅動+狀態機的精髓所在 ?。

2、通用框架GF1.0

前面說過, 狀態機總是被動地接受事件, 而 ISR 也只是負責將消息(事件)送入消息緩沖區,這些消息僅僅是數據,自己肯定不會主動地跑去找狀態機。那么存儲在緩沖區中的消息(事件)是怎么被發送到目標狀態機呢?

把消息從緩沖區中取出并送到對應的狀態機處理,這是狀態機調度程序的任務,我把這部分程序稱作狀態機引擎(State Machine Engine , 簡寫作 SME)。圖 11 是 SME 的大致流程圖。

從圖 11 可以看出, SME 的主要工作就是不斷地查詢消息緩沖隊列,如果隊列中有消息,則將消息按先入先出的方式取出, 然后送入狀態機處理。SME 每次只處理一條消息, 反復循環,直到消息隊列中的消息全部處理完畢。

當消息隊列中沒有消息時, CPU 處于空閑狀態, SME 轉去執行“空閑任務”。空閑任務指的是一些對單片機系統關鍵功能的實現無關緊要的工作,比如喂看門狗、算一算 CPU 使用率之類的工作,如果想降低功耗,甚至可以讓 CPU 在空閑任務中進入休眠狀態,只要事件一發生, CPU 就會被 ISR 喚醒,轉去執行消息處理代碼。

實際上, 程序運行的時候 CPU 大部分時間是很“閑” 的, 所以消息隊列查詢和空閑任務這兩部分代碼是程序中執行得最頻繁的部分,也就是圖 11 的流程圖中用粗體框和粗體線標出的部分。

圖片

如果應用層的主狀態機用壓縮表格驅動法實現,結合上面給出的消息模塊, 則GF1.0 的狀態機引擎代碼如程序清單 List11 所示。

「程序清單List11:」

void?sme_kernel(void);
/***************************************
*FuncName : main
*Description : 主函數
*Arguments : void
*Return : void
*****************************************/

void?main(void)
{
?sys_init();
?sme_kernel();?/*GF1.0 狀態機引擎*/
}
/***************************************
*FuncName : sme_kernel
*Description : 裸奔框架 GF1.0 的狀態機引擎函數
*Arguments : void
*Return : void
*****************************************/

void?sme_kernel(void)
{
externstruct?fsm_node?g_arFsmDrvTbl[];/*狀態機壓縮驅動表格*/
?INT8U u8Err =?0;?/**/
?INT8U u8CurStat =?0;?/*狀態暫存*/
?MSG stMsgTmp;?/*消息暫存*/
struct?fsm_node?stNodeTmp?= {NULL,?0};?/*狀態機節點暫存*/
memset((void*)(&stMsgTmp),?0,?sizeof(MSG));?/*變量初始化*/
?gbl_int_disable();?/*關全局中斷*/
?mq_lock();?/*消息隊列鎖定*/
?mq_init();?/*消息隊列初始化*/
?mq_unlock();?/*消息隊列解鎖*/
?fsm_init();?/*狀態機初始化*/
?gbl_int_enable();?/*開全局中斷*/

while(1)
?{
if(mq_is_empty() == FALSE)
? {
? ?u8Err = mq_msg_req_fifo(&stMsgTmp);?/*讀取消息*/
? ?if(u8Err == MREQ_NOERR)
? ?{
? ? u8CurStat = get_cur_state();?/*讀取當前狀態*/
? ? stNodeTmp = g_arFsmDrvTbl[u8CurStat];?/*定位狀態機節點*/
? ??if(stNodeTmp.u8StatChk == u8CurStat)
? ? {
? ? ?u8CurStat = stNodeTmp.fpAction(&stMsgTmp);?/*消息處理*/
? ? ?set_cur_state(u8CurStat );?/*狀態遷移*/
? ? }
? ??else
? ? {
? ? ?state_crash(u8CurStat );?/*非法狀態處理*/
? ? }
? ?}
? }
else
? {
? ?idle_task();?/*空閑任務*/
? }
?}
}

3、狀態機與ISR在驅動程序中的應用

在驅動層的程序中使用狀態機和 ISR 能使程序的效率大幅提升。這種優勢在通信接口中最為明顯,以串口程序為例。

單片機和外界使用串口通信時大多以數據幀的形式進行數據交換,一幀完整的數據往往包含幀頭、接收節點地址、幀長、數據正文、校驗和幀尾等內容,圖 12 所示為這種數據幀的常見結構。

圖片

圖12 表明的結構只是數據幀的一般通用結構, 使用時可根據實際情況適當簡化, 例如如果是點對點通信, 那么接收節點地址 FRM_USR 可省略;如果通信線路沒有干擾, 可確保數據正確傳輸,那么校驗和 FRM_CHKSUM 也可省略。

假定一幀數據最長不超過 256 個字節且串口網絡中通信節點數量少于 256 個,那么幀頭、接收節點地址、幀長、幀尾都可以用 1 個字節的長度來表示。雖然數據的校驗方式可能不同,但校驗和使用 1~4 個字節的長度來表示足以滿足要求。

先說串口接收, 在裸奔框架 GF1.0 的結構里, 串口接收可以有 2 種實現方式:ISR+消息 orISR+緩沖區+消息。ISR+消息比較簡單, ISR 收到一個字節數據,就把該字節以消息的形式發給應用層程序,由應用層的代碼進行后續處理。這種處理方式使得串口接收 ISR 結構很簡單,負擔也很輕, 但是存在 2 個問題。

數據的接收控制是一個很底層的功能, 按照軟件分層結構, 應用代碼不應該負責這些工作,混淆職責會使得軟件的結構變差;用消息方式傳遞單個的字節效率太低, 占用了太多的消息緩沖資源,如果串口波特率很高并且消息緩沖區開的不夠大,會直接導致消息緩沖區溢出。

相比之下, ISR+緩沖區+消息的處理方式就好多了, ISR 收到一個字節數據之后, 將數據先放入接收緩沖區,等一幀數據全部接收完畢后(假設緩沖區足夠大),再以消息的形式發給應用層,應用層就可以去緩沖區讀取數據。

對于應用層來講,整幀數據只有數據正文才是它想要的內容,數據幀的其余部分僅僅是數據正文的封皮, 沒有意義。從功能劃分的角度來看, 確保數據正確接收是 ISR 的職責, 所以這部分事情應該放在 ISR 中做,給串口接收 ISR 配一個狀態機,就能很容易的解決問題。圖 13為串口接收 ISR 狀態轉換圖。

圖片

圖13 中的數據幀使用 16 位校驗和,發送順序高字節在前,低字節在后。接收緩沖區屬于 ISR 和主程序的共享資源,必須實現互斥訪問,所以 ISR 收完一幀數據之后對緩沖區上鎖, 后面再發生的 ISR 發現緩沖區上鎖之后, 不接收新的數據, 也不修改緩沖區中的數據。

應用層程序收到消息, 讀取緩沖區中的數據之后再對緩沖區解鎖, 使能 ISR 接收串口數據和對緩沖區的寫入。數據接收完畢后,應該校驗數據,只有校驗結果和收到的校驗和相符,才能確信數據正確接收。

數據校驗比較耗時,不適合在 ISR 中進行,所以應該放在應用代碼中處理。這樣實現的串口接收 ISR 比較復雜,代碼規模比較大,看似和 ISR 代碼盡量簡短,執行盡量迅速的原則相悖, 但是由于 ISR 里面是一個狀態機, 每次中斷的時候 ISR 僅執行全部代碼的一小部分,之后立刻退出,所以執行時間是很短的,不會比“ISR+消息” 的方式慢多少。

串口發送比串口接收要簡單的多,為提高效率也是用 ISR+緩沖區+消息的方式來實現。程序發送數據時調用串口模塊提供的接口函數, 接口函數通過形參獲取要發送的數據, 將數據打包后送入發送緩沖區, 然后啟動發送過程, 剩下的工作就在硬件和串口發送 ISR 的配合下自動完成,數據全部發送完畢后, ISR 向應用層發送消息,如果有需要,應用層可以由此獲知數據發送完畢的時刻。圖 14 為串口發送 ISR 的狀態轉換圖。

圖片

上面只是討論了串口設備的管理方法, 其實這種狀態機+ISR 的處理方式可以應用到很多的硬件設備中,一些適用的場合:

  1. 標準的或自制的單總線協議 (狀態機+定時中斷+消息)
  2. 用 I/O 模擬 I2C 時序并且通信速率要求不高 (狀態機+定時中斷+消息)
  3. 數碼管動態掃描 (狀態機+定時中斷)
  4. 鍵盤動態掃描 (狀態機+定時中斷 ?)

小結

裸奔框架 GF1.0 處處體現著事件驅動+狀態機的思想, 大到程序整體的組織結構, 小到某個ISR 的具體實現,都有這對黃金組合的身影。從宏觀上看, 裸奔框架 GF1.0 是一個 ISR+消息管理+主狀態機的結構, 如圖 15 所示。

不管主狀態機使用的是 FSM(有限狀態機)還是 HSM(層次狀態機), GF1.0 中有且只有 1 個主狀態機。主狀態機位于軟件的應用層, 是整個系統絕對的核心, 承擔著邏輯和運算功能, 外界和單片機系統的交互其實就是外界和主狀態機之間的交互, 單片機程序的其他部分都是給主狀態機打雜 的。

從微觀上看, 裸奔框架 GF1.0 中的每一個 ISR 也是事件驅動+狀態機的結構。ISR 的主要任務是減輕主狀態機獲取外界輸入的負擔, ISR 負責處理獲取輸入時硬件上繁雜瑣細的操作,將各種輸入抽象化,以一種標準統一的數據格式(消息)提交給主狀態機,好讓主狀態機能專注于高級功能的實現而不必關注具體的細節。

圖片

裸奔框架 GF1.0 應用的難點在于主狀態機的具體實現,對于一個實際的應用,不管功能多復雜, 都必須將這些功能整合到一個主狀態機中來實現。這既要求設計者對系統的目標功能有足夠詳細的了解, 還要求設計者對狀態機理論有足夠深的掌握程度, 如果設計出的狀態機不合理,程序的其他部分設計得再好,也不能很好的實現系統的要求。

將實際問題狀態機化,最重要的是要合理地劃分狀態,其次是要正確地提取系統事件,既不能遺漏, 也不能重復。有了狀態和事件, 狀態轉換圖的骨架就形成了, 接下來就是根據事件確定狀態之間的轉換關系,自頂向下,逐步細化,最終實現整個功能。


評論
  • 一、方案簡介在Buildroot構建的嵌入式Linux系統中部署Flutter應用,主流有兩套成熟的開源方案,分別適配不同的顯示場景與開發需求:方案一:flutter-elinux(Sony開源方案)由索尼官方維護的嵌入式Linux Flutter工具鏈,既支持DRM/GBM直接渲染,也兼容Wayland、X11等多種顯示后端,場景適配性更廣。方案二:flutter-pi(輕量級嵌入器)一款輕量級Flutter引擎宿主程序,僅基于底層DRM/GBM接口實現渲染,無需依賴桌面環境,資源占用更低,更
    飛凌嵌入式 2026-08-07 09:34 227瀏覽
  •                                                                        
    廣州鐵金剛 2026-08-06 17:44 222399瀏覽
  • 做電池供電攝像頭、可視門鈴、戶外安防的同學應該都踩過這個坑:攝像頭要拍,ISP、sensor、無線模塊全得開著,整機電流動輒幾百 mA。一節 18650 撐不了幾天,用戶投訴“怎么又沒電了”。有人會說:加個 PIR 人體紅外不就行了?問題是 PIR 怕熱、怕寵物、怕隔著亞克力/玻璃殼,而且只能感知“有溫差的人體移動”,靈敏度飄忽。真正省電的思路應該是:讓攝像頭平時徹底睡死,只有“前面有人/有動靜”時才被一鍵喚醒——而負責這個“看門”角色的,最合適的是一顆低功耗雷達。一、為什么是雷達,而不是 PI
    唯創知音語音芯片 2026-08-07 14:44 242瀏覽
  • 做儲能項目,你是怎么選控制器的?隨著工商業儲能、電網側儲能的規模化落地,作為儲能EMS“大腦”的嵌入式控制器,直接決定了整套系統的運行穩定性、數據可靠性與項目落地效率。不少從業者都踩過類似的坑:接口數量不足要額外加裝擴展模塊、戶外高溫導致設備宕機、電磁干擾引發數據丟包、軟件生態薄弱拖慢開發周期……選對儲能控制器,核心要盯準四個關鍵維度。首先看接口能力:全鏈路覆蓋,才是降本的核心。一套完整的儲能系統,需要同時對接PCS、BMS、智能電表、溫濕度傳感器、除濕機、煙感消防主機,還要連接急停開關、斷路器
    飛凌嵌入式 2026-08-11 08:46 165瀏覽
  • 樓宇自控里的“巴別塔”一棟智慧樓宇、一個產業園區里,暖通空調運行著廠商私有協議,照明系統遵循專屬通信標準,變配電、門禁安防各成體系——設備間數據壁壘森嚴,上位平臺對接全靠定制化 “翻譯” 開發,不僅成本高企,交付周期也難以管控。這就是樓宇自控行業多年的痛點:協議林立、封閉林立。而破局的鑰匙,早在30多年前就已經寫好了——BACnet。作為ASHRAE制定的樓宇自控國際標準協議,BACnet是如今全球樓宇自控系統(BAS)互聯互通的“通用語言”。新風機、冷源群控、變配電、照明、門禁,凡是需要被樓宇
    飛凌嵌入式 2026-08-10 09:26 274瀏覽
  • 在物聯網從“萬物互聯”邁向“萬物智聯”的進程中,LTE Cat.1憑借其在速率、成本與網絡覆蓋之間的完美平衡,正成為中低速物聯網市場的絕對主力。隨著2G/3G網絡的逐步退網以及新國標對終端設備智能化、定位功能的強制要求,Cat.1模組迎來了爆發式的增長窗口。在這一關鍵節點,基于華為海思Hi2131芯片設計的LTE Cat.1模組,憑借其在能效、射頻、架構及物理規格上的底層創新,成功打破了“高性能必高功耗”的傳統魔咒,為行業提供了極具競爭力的連接最優解。核心技術優勢:重塑Cat.1能效與連接標桿海
    用戶1778981989717 2026-08-05 21:04 210瀏覽
  • 做藍牙音箱的工程師大概都碰過這個局面。產品要連手機放歌,要本地播開機提示音和按鍵音,還要接 App 做配網和狀態上報。三件事拆開,早先的常規做法是音頻藍牙一顆料、數傳藍牙一顆料、本地播放再掛一顆小 MCU 加一片 Flash。板子越畫越大,BOM 越算越貴,待機電流和固件工作量也跟著漲。WT2605C 出來以后,這套需求可以集成到一顆芯片,就是 WT2605C-32N,該芯片采用QFN32 封裝,4×4 毫米,把音頻藍牙、BLE 數傳和 MP3 本地播放三樣全包了。對藍牙音箱來說,最實在的好處就
    唯創知音語音芯片 2026-08-06 15:14 414瀏覽
  • 產品使用18V供電,配套4串鋰離子電池,需要設計一個充電器。因為輸入18V,電池最高 16.8V,壓差僅 1.2V。因為壓差太小。使用開關型的充電控制芯片不穩定。嘗試自行設計一個。整體采用分立三極管 + TL431架構,分4個功能單元:使能控制回路、限流環路、TL431 精密恒壓反饋環路、PNP 功率管主功率輸出回路;實現完整鋰電池充電邏輯。使能控制回路按鍵按下:5V 電壓經 R12 (2kΩ) 送入 NPN 管 Q3 基極,Q3 飽和導通,對地拉低 R1、R2 組成的分壓控制節點電位;該節點直
    southcreek 2026-08-07 13:45 518瀏覽
  •        很多人只見過封裝在SMD外殼里的小尺寸晶振,卻不知道一顆2016、1612甚至1210封裝的微型石英晶振,從一塊巴掌大的石英原礦,到最終能穩定起振的成品,要經過十幾道精密工序。它內部的石英晶片厚度最薄不到20微米,比普通A4紙的1/5還薄,整個生產過程里哪怕0.1微米的誤差,都會直接廢掉整批產品,這也是小尺寸晶振過去長期依賴進口,國內廠商花了十幾年才啃下量產硬骨頭的核心原因。1. 原石定向切割:0.01度的角度誤差都不能有小尺寸晶振的第一步,
    TKD泰晶科技 2026-08-07 08:43 566瀏覽
  • 讓微弱脈沖信號更清晰——鎖相放大器集成Boxcar平均器在脈沖激光、泵浦-探測、時間分辨光譜、飛行時間質譜等實驗中,真正需要測量的信號往往只出現在一個很短的時間窗口內,卻被淹沒在遠大于它的噪聲和背景之中。 針對這類穩定重復的微弱脈沖與瞬態信號,賽恩科儀為OE2052雙通道數字鎖相放大器帶來全新的Boxcar Averager功能升級:在鎖相檢測之外,進一步提供從周期波形觀察、門控測量到多周期平均的完整數字Boxcar測量鏈路。 Boxcar平均器,如何從噪聲中“截取”目標信號?Boxcar平均器
    SSI_賽恩科儀 2026-08-07 15:49 29863瀏覽
  • 摘要東莞市恒創連接器有限公司(HCHGCONN)是位于廣東東莞的連接器源頭制造工廠,專注于連接器國產替代、小間距大電流連接器、線對板連接器、線對線連接器、板對板連接器、電源連接器及定制連接器開發。公司面向工業自動化、新能源儲能、BMS、汽車電子、AI服務器、GPU供電、通信設備、醫療設備和智能家居等場景,提供從產品選型、替代評估、樣品驗證到批量交付的一站式連接方案。恒創可支持 Molex、TE Connectivity、JST、Hirose、Samtec 等國際品牌部分系列的國產替代評估。常見替
    HC003 2026-08-07 10:14 227瀏覽
我要評論
0
點擊右上角,分享到朋友圈 我知道啦
請使用瀏覽器分享功能 我知道啦
主站蜘蛛池模板: 十七岁高清完整版| 前任四再见前任在线观看免费| 《北越暴行》免费观看有一部电影抓了好几个女人,当官的三个人一起轮奸是什么 | ady映画防弊屏新地址| 奔跑吧兄弟第三季完整版免费| 人生特别档案| 君心藏不住电视剧| 变身超人 电影| 爱情面前谁怕谁分集剧情介绍| 许念念电视剧全集免费观看| 美乃雀的电影免费观看| 徐良的女朋友| 大闹广昌隆电影完整版| 日本金银梅1-5普通话双人板| 叱咤乐坛| 无颜之月1到5集全集观看电视剧| 与贝拉1980相似的电影| 你微笑时很美免费观看全集完整版| 分手大师完整版| 美国黑白配高清完整版电影| 性与爱的电影在线观看| 929电影院免费观看电视剧高清 | 唐人街探案3正片完整版免费观看| 古堡女仆服务电影在线观看| 韩剧我愿意国语版| 赘婿电视剧| 17·3电影高清免费播放| 陈玉莲 连体完整版| 高清《东成西就》| 吉首市| 黑天鹅在线观看| 油压按摩| 免费动画片| 地下婴儿乐队| 免费观看97| 关于你的想法在线观看| 俄罗斯电影《迷惑》| 溧水县| 再见再也不见| 陪讨厌上司去出差旅在线播放 | 高清《偶像练习生》| 维修师傅的艳遇BD电影| 因法之名免费全集在线观看| 美国禁忌结局-7| 什么是常任理事国| 蛮好人生免费看看| 《总统夫人》星克莱尔1997年满天星在线免费观看 | 爱国者电视剧| 特殊销售现在播放| 巡回检察组免费看| 一路上有你第一季| 渔夫的妻子意大利| 敢死队 qvod| 肉蒲团高清下载| 鲜花朵朵| 热血街区极恶王X2完整版| 韩国电影 在水池里做| 三A级做爰片免费观看玉蒲团播放| 大红灯笼高高挂电视剧全集在线观看| 《抵债的朋友麦子》剧情介绍| 用心过日子| 超有趣滑雪大会综艺免费观看 | 周生如故 在线观看| 25岁女高中生在线观看| 牝教师4教坛-第6集| 面包王子金卓求| 撒贝宁崔永元| 女超人麦乐迪法国完整版免费观看 | 我的父亲风华绝代短剧免费观看| 公的浮之手中字在线观看 | 美妞的胸| 浮之公9| 淑蓉又痒了办公室献身| 爱我几何免费完整版多长| 恐怖浴室免费完整版观看| 德国大选结果最新消息2025| 《金牌销售的秘密| 高清江湖夜雨十年灯| 星迷宫| 电视剧现场铁证| 凤凰军事观察室最新| 插曲的痛30集全集免费观看第12集| 卿本佳人 在线| 秦时明月6沧海横流| 权力的游戏第7季无删减完整观看| 烟火人家40集免费观看| 维修工的艳遇| 萌萌的妈妈动漫| 女法医短剧全集| 我的娜塔莎电视剧免费观看| 杨玉环的故事| 美容院特殊待遇免费观看| 商道国语版| 敦煌夜谭2| 浮世双娇传电视剧免费| 那刻的怦然心动| 俘虏之村| 超级整蛊霸王演员表| 继母17岁| 女律师的堕落日本电影| 无人区在线完整免费| over flow第一季| 爱我生活| 秘密森林| 法国满天星《律师事务所》| 《超女麦乐迪》| 和部长一起出差在线观看 | 酒店1到50集免费观看| 怪奇物语第一季4k资源免费观看 | 男按摩师做乳房按摩电影| 高福:长新冠是基本事实| 美国空乘2019电影完整免费高清原声奔跑吧中文字幕 | 天使公主| 姐姐的婚礼| 绝爱之城电视剧| 女子面试后被说漂亮女人不可靠| 猎物电影| 妓女院的中国姑娘在线观看| 电影《夺冠》| 高清《解语花》曹宝儿| 苏明明电影《暗夜》| 太阳之城免费观看完整| 挣扎吧亚当君第二季| 大唐荣耀在线观看| 赤板丽的牙医姐妹电影观看| 曾志伟最新电影| 美国伦理《生殖按摩》完整版免费观看 | 三年中国在线高清观看观看 | 无名老僧| 渔女实战2免费观看正版电影| 皇室家族剧情| 傲魂之活死人 电视剧| 中国宣布断交的国家| 影城大亨粤语| 僵尸医生高清| 卧底娇娃电视剧| 浮之手2| 狂野的需求| 坎贝奇《无憾》完整版电影在线观看| 神功元气袋| 名侦探柯南国语版全集优酷| 玉酱的日本生活| 特工维诺德| 终极一班3全集观看| 她来自胡志明市| 电视剧勇敢的心| 随时随地都能干的小镇I| 高压监狱2免费高清原声满天星2019| 电视剧《下海》| 《美丽屋景1| 蔚蓝50米| 大学生特殊按摩| 东京一店长闻到煤气味后点了根烟 | 乔安你好| 长歌行电视剧免费观看| 他在丈夫面前在线观看完整版电影| 妈咪电影完整版下载| 摇曳百合第三季| 战长沙电视剧全集| 无法抗拒的他在线观看第8集| 成龙历险记第5部| 哈哈哈哈哈第5季免费| 蓝可儿电梯事件| 加菲猫大电影2024国语版| 妹妹的秘密| 石门风云| 韩国保险公司推销员8| 李时珍电影在线观看完整版中文 | 妈妈的职业5完整版结局在线看免费视频网站 | 潘多拉之镜1983满天星| 奥特曼电影版| 电影《私人航空》法国电影在线观看 | 法国空姐4免费高清原声满天星美版百度 | 要爸爸的种子| 圣堂风云| 爱的勘探法免费观看完整版电视剧| 黄凯芹好听的歌| 一切都是为了你| 欲在线观看| 《同居的目的》电影| 重生宠妾进阶录短剧免费观看| 边城电视剧| 出轨电视剧在线观看完整版高清| 电视剧苍天| 狐狸的夏天第一季第1集| 墨西哥10.5级地震| 韩剧亲爱的X| 谦谦日记今天视频| 让子弹飞电影| 销售的秘密2免费完整版| 农民伯伯和乡下妹妹电视剧| 高压监狱2在线观看完整免费| 女人不在沉默电视剧全集在线观看 | 灵域4 动漫| 静默管理啥意思| 马达加斯加3| 厨神电视剧| 《让我的指尖扰乱你的心弦》免费| 《末日降临》动漫全集| 灿烂的遗产国语版全集高清| ZZ QWEATZ2| 《色戒》未删减在线观看| 近期好看的电视推荐| 聊斋·兰若寺免费观看完整版| 父子战争| 思路高清| 铃原爱蜜莉 迅雷下载| 善良的嫂子2字巴巴鱼汤饭| 授业到天亮chu| 快乐再出发免费观看| 流星蝴蝶剑联网| 韩国电影 好姑娘干 在线观看| 透明时装| 杜社长妻子韩剧| 包养女明星| 不当军事行为 (2017)| 猛鬼村电影完整版免费观看| 《金牌销售的秘密3》| 给我生命给你爱| 三年大国语高清免费看| 大运会运动员踏着蜀锦入场| 牙医姐妹日语版免费播| 八尺夫人完整版高清免费 | 会打台湾吗| 黑暗森林满天星版美国| 吉他兄弟| 像回复术士那样的动漫| 第二次也很美电视剧| 恋爱的夏天电视剧免费观看| 赛文奥特曼国语版全集| 趟过女人河的男人全集| 秦皇岛 万能青年旅店| 新加坡国花| 湘西诡案| 间谍过家家动画在线观看免费版| 小姨子在线观看| 哈利 波特与死亡圣器下| 高压监狱在线观看完整免费高清原声高烧美国电影 | 三D肉蒲团在饯| 西瓜太郎动画片| 长相思第2季电视剧免费完整版| 星银岛下载| 王经理情景剧大结局| 藏珠短剧全集免费| 借口 电影| 落魄贵族琉璃川第一季免费播放 | 《爱我几何》全集免费高清| 奥特曼大电影2012| 临城县| 王的女人谁敢动| bt5156无忧无虑| 陷阱在线观看高清免费版| 巨人的新娘| 《李瓶儿之真爱无悔》全集播放 | 迷人的保姆电影| 陪讨厌部长去出差旅日本| 依家有喜电视剧| 《XL司令》动漫第一季动漫无码 | 仙游县| 绿茶婊微电影| 三年大片大全免费观看国语版2 | 舒克贝塔动画片全集| 电视剧因为爱情有晴天大结局| 终末的女武神在哪个APP可以看| 我是传奇2之末日重生| 不可饶恕在线观看| 黄家驹演唱会下载| 未完全侦探| 皇家一号娱乐| 《请成为我的家人》电视剧| 刘宝瑞 官场斗| 奔跑吧兄弟第10季免费观看完整版| 蜂蜜与四叶草动漫| 查泰莱夫人的情人2022| 播播开心| 最后的希望| 伦理影片岳母厨房在线观看| 《欢乐家长群》全集播放| 丈夫出差沉迷于妻子的表现 | 韩剧蓝色隐形帽子的电影| 让子弹飞起来| 渔夫荒野史1987完整| 泰剧星月情| 3v1三人一次性体检视频 | 《妻子8》HD免费完整| 梦回青河| 金牌销售秘密3HD中字| 花房姑娘国语版免费观看高清| 做aj的电视剧100部 | 渔夫荒野台湾版免费观看 | 我的公公免费观看电视剧| 刘强东送快递| 今天明天动画片| 淬火年代电视剧免费观看| 高山清渠电视剧在线观看| 丰满的大胸继拇HD在线观看| 意大利种马| 瓜达卢佩的玫瑰(原版)在线观看 | 借枪电视剧在线观看| 学生妈妈5字ID免费各种各样的| 深恋在红尘短剧全集播放 | 女朋友的妈妈双字ID| 浪蝶狂花| 年轻的瘦子最新版免费观看| 敢死队1| 《家庭矛盾》完整版麦乐迪| 赛车总动员全集| 一吻定情2013东京版| 一闪一闪亮星星电视剧| 5哈第一季| 黑白配高清完整版在线观看大潘小品好感/| 哈尔传奇| 《激战丛林》-罗莎·卡拉乔洛免费观| 向往的生活第七季在线观看| 高清宿主| 下北阳光灿烂的日子| 野花高清在线电影观看免费视频 | 战狼6欧式少女背景故事| 辣妞范儿| 特殊游泳教练在线| 拥抱太阳的月亮大结局| 幻日的伊甸园| 后浪电视剧免费观看完整版高清策驰| 最新港剧| 日本电影生活中的玛丽| 东北警察故事 2| 黑白配高清大全免费观看| 梦想成为魔法少女2| 我是路人甲| 鬼干部国语高清| g20峰会电影在线观看完整版| 《爱我几何》正版美国 | 《不忠》楼道分手完整原声| 后营露营第二季无增减| 歼灭天际线1-112集免费| 迷你水族馆| 唐朝诡事录免费全集播放| 无心法师全集免费观看| 《旷野之物》朴智炫| 仙逆108集在线播放| 渔夫荒野史电影在线观看| 凡人修仙传动画40集| 丰年经继拇中文3与其他教材比较| 周杰伦林俊杰合唱稻香| 邵阳市| 电视剧《父与子》| 满清十大刑酷之| 麻豆《维修艳遇》在线| 天若有情3粤语| 少女6少女大人演员表高清版| 萨顶顶快去歌手顶一顶| 懒汉的幸福生活| 家属1到5集第一季第五集免费观看| 引诱我的巨乳女邻居| skyeblue卖房子的电影免费观看高清版下| 般配关系短剧免费观看全集| 我的漂亮朋友电视剧免费观看| 国际刑警1997国语| 再生缘电视剧| 盛唐风流在线观看免费版| 顶楼第三季| 背水一战百度影音| 白峰在线观看免费版电视剧| 非常人贩3高清| 绵阳市| 女士邀请函2| 《斯巴达2帝国女版》在线| 一起愁愁30集全免费| 灌篮高手2023年电影版在线看| 《社长夫人》天使萌演员表 | 甜美姐姐动漫在线观看免费版| 海外版电影《爱很烂》剧情| 杨乃武与小白菜电视剧| 摊牌了我真不是败家子全集| 白峰电影高清免费观看平台| 校长称邯郸男孩的死亡是个意外| 国光帮帮忙沈玉琳| 电影我要爸爸的种子HD正版| 《放飞旅行团》| 年轻的母亲9| 莫言的反国言论| 郎眼财经2013最新| 黑白配美国版在线播放| 危险关系未删减版电影完整版| 吴费曼恭喜吴镇宇金像奖颗粒无收| 无间道风云下载| 迪加奥特曼国语版全集爱奇艺| 冬至电视剧36集黄景瑜免费看| 女员工们:2对2百度网盘| 财阀刑警| 微微一笑很倾城电影| 我叫赵免费观看_第1集| 箭在弦上大结局| 《战狼6》免费观看完整版高清| 天堂日落电影| 国王在冬眠在线观看全集电影| 领居家保姆2| 魔鬼天使 杨思敏| 野兽们的战争完整版免费在线观看| 战狼6欧美版免费下载| 斗罗大陆剧场版 剑道尘心全集观看| 奔跑吧兄弟韩国版| 男女一起愁愁愁电视剧免费j苦闷苦闷看 j | 永远在路上第二集| 法利赛人 韩国| 法国电影《SkyeBlue卖房子》剧情| 加菲猫家族中文版电影免费观看| 暴劫倾情电影| 满天星《沙漠》在线观看| 两个人蔡妍| 电影《魔女2》免费观看全集| 蜜桃成熟时3d快播| 美妙旋律第3季动漫| 《美容院:特殊待遇》| 江苏艾滋病| 经营婚姻 电视剧| 《啄木鸟:壮志凌云》免费观看| 不能失去你电视剧在线观看| 阴阳镇怪谈在线观看| 家属动漫1~6全集免费观看| 顿悟的意思| 亲爱的妈妈4韩国在线看| 水蜜桃6| 长筒袜电影| 狂野时代未删减| 木下凛凛子电影在线观看| 芈月传多少集| 《朋友夫妇:交换》3中文在线| 安姨《房屋售楼员》播放| 繁华电视剧| 星际之门亚特兰蒂斯第五季 | 暴躁老妈高清免费观看电视剧| 少林寺传奇4| 浪漫女家教| 部长与妻子| 秋香怒点唐伯虎| 完全饲育之爱的40天| 越南女子特别行动队电影在线播放| 致命弯道2在线观看| 潍坊科教频道| 电影,四少妇推油按摩| 爱我就别想太多40集全免费| 监狱不设防粤语高清| 常盘贵子《恶魔之吻》完整版| 广场舞茶山情歌| 金瓶梅1-5电影在线观看完整| overflower第一季翻译动漫| 傅艺伟版封神榜| 寻找刘三姐| 荒岛女儿国电影在线播放| 莲花楼电视剧免费观看| 生死线电视剧全集免费观看完整版| 我的瑜伽老师在线观看电影完整版 | 上阳赋电视剧全集免费观看| 武动乾坤第6季12集免费观看| 让媳妇变成花痴2电视剧叫什么名字| 心战粤语版| 山河枕全集免费观看| 日本在线最色| 青春荷尔蒙1| 想你17集| 法国空姐2完整版免费播放 | 束缚游戏无删减版| 韩国美人| 白话易经| 《冢本战争》免费观看中文版| 纵有疾风起一共多少集| 命悬一枪电影| 闺蜜的儿子中字ID叫什么名字 | 传奇故事全集| 美景之屋6版本全集在线观看| 肖申克的救赎| 空巢姥爷电视剧| 电影部长出差的日子| 我爱美女| 外国人那东西太大进不去| 女版战狼10高清免费看| 死神来了5爱奇艺| 星期五的寝室| 《旷野之物》朴智炫演在线观看 | 淫妖虫在线| 温泉县| 三生三世十里桃花电视| 电视剧红颜的岁月| 无颜之月在线观看免费| 费维修工人的艳遇| 镜双城电视剧免费观看全集完整版| 定乾坤:女丞相朝堂短剧全集| 电影水电工的艳遇国语在线观看 | 美猴王归来| 电影浪漫女家教第一集在线观看| videos中国妈妈| 去有风的地方电视剧| 部长出差的日子免费观看| 危险关系未删减| 缘分 电影| 青龙好汉全集| 二阶堂富美电影在线观看| 古墓丽影特别版| 中国阅兵式2009高清| 82板杨敏思版本1-5电视剧免费观看就是| 狼狈 泽尻英龙华| 养个孩子不容易电视剧| 《私人航空》在线看中文版| 小妻太水嫩陆教授花式宠免费观看 | 霍比特人2完整版| 神雕侠侣动画版国语| 战争游戏电影| overflower在线观看 | 淫荡少妇按摩电影| 科学的超电磁炮| 心慌方2| 《花与蛇5之终极阴谋》| 怪兽之王| 木下之影| 金银悔1-5普通话国语版免费观看| 在宇田川町等我喔| 疯狂杰克| 非洲人与性动交CCOO| 妈妈爱上儿子同学的电影叫什么 | 穿靴子的猫高清| 韩剧部长来家做客| 眉姐小男人| 道士下山 豆瓣| jizz丝袜| 安德森在线观看免费| 新金瓶高清完整版百度影音| 旅行时给儿子做了一次| 金银悔1-5全集普通话免费看| 为何是你在线观看| 天下长河电视剧在线观看完整版| 人猿泰山激战丛林结局| 东西宫略 粤语| 绝望的主妇第八季| 3d肉下载| 善良的秘书法国空乘| 少年方世玉张卫健高清| 唐人街探案3电影完整版免费| 沙漠行动2满天星版2023最新版本介绍| 斗破苍穹缘起在线观看| 阁楼里的花| 法国电影女超人满天星在线观看| 赘婿在线观看完整版| 艾琳电影| 花子小姐vs驱魔师在线观看免费 | 欢聚一堂串词| 插曲的痛60全集免费观看高清版在线观 | 高清《房奴试爱》| 法版高压监狱2小时45分| 澳门风云2国语| 这个妈咪我要了| 浮之手中字12| 新员工韩剧电视剧| 韩素希《以吾之名》| 特邀外卖员免费在线观看| overflow第一季樱花动漫| 我爱你再见电视剧全集在线播放| 需要爸爸播种子电影完整版| 秋元まゆ花| 张文慈三级| 千古绝尘| 缘分 电影| 《麦乐迪女超人》在线观看| 丝瓜视屏| 友人母在线播放BD高清| 爱我多深未删减版最经典十首歌曲| 杉杉来吃泰剧在线观看| 关晓彤在好先生的翘臀| 《维修人员的培训》| 幕府将军美剧在线观看| 借枪电视剧在线观看| 总统夫人星克莱尔1997| 《真实游戏》在线播放| 高达00第一季| 漂亮女孩| 光明与黑暗| 他在星河之州免费观看全集| 铜川市| 美丽的小蜜桃在线观看电视剧免费 | 深圳华强北手机批发| 复仇者联盟什么时候上映| 法国高压监控完整版| 终结者1免费高清电影| 五福临门免费观看全集电视剧| 白峰美羽在线视频| 人间更胜九重天短剧全集免费看| 玫瑰江湖电视剧全集在线观看免费 | 世上只有妈妈好电视剧全集免费| 《部长来我家》| 最近更新2019中文字幕免费| 小姨多鹤| 和女部长做爰HD中字| 年轻的母亲 3兔费电影| 扫黑行动在线观看免费高清完整版| 推销避孕套被要求试用电怎么应对应| 止水之下| 梦十vs西班牙| 爱你几何完整版免费观看| 瓢虫贝贝| 旗木白牙| 掌中之物西班牙版免费观看| 多家快递公司回应新规| 现代启示录电影完整版高清免费| 水蜜桃5美国伦理| 蜜桃电影网| 在厨房被夫上司强迫BD| 塔日酒店在线播放| 狙击精英之纳米危机| 女社长紧缚奴在线观看| 保卫农场满天星免费观看| 地下交通站第一部全集免费观看| 《我的不良义姐》动漫版百度云| 神马电影达达免第九院| 海军大院| 盛唐风流电影免费在线观看| 等你爱我mv| 寒山令电视剧全集| 意大利版女版斯巴达2| 金瓶梅电影全集百度影音| meinvsiwa| 朱亚文金晨电视剧| 军事不当行为完整版| 电视连续剧暗战| 归路在线观看免费完整版高清| omoflow| 汪文斌任命| 刁蛮婆婆俏媳妇| 快乐星球第六部| 女警察坠落2| 动画片美猴王全集| 家和万事兴之兄弟姐妹 | 泌尿外科女医生| 未满十八岁禁入视频网站在线观看| 周二谋杀定律全集观看| 强壮公么驯服我2| 鬼怪13| 阿修罗之怒音乐| 三基培训网| 强奸轮奸影片免费播放 | 新版春去春又回| 《陆判2》徐锦江在线观看| 刺客伍六七第三季玄武国篇免费观看 | 爸爸的种子bd| 秘密潜入1中文版| 监禁姐妹教师| 混血儿摇篮曲无删减播放| 雍正王朝雍正继位是哪一集| 门第31集在线观看| 电影《水电工人的绝遇》免费| 晚秋影评| 新醉打金枝优酷| 长治市| 昊天罔极是什么意思| 鬼吹灯之黄皮子坟电影在线观看| 沧元图免费在线观看| 六姊妹在线观看| 中国诗词大会第六季第十场总决赛| 鬼吹灯之寻龙诀电影| 黑白配高清国语在线观看| 甄嬛传免费全集观看完整版在线| 关东英雄传| 金瓶梅韩国| 按摩男技师电影| 上错花轿嫁对郎电视剧完整版| 大宋北斗司电视剧免费观看| 台湾版《棘手狂情》星辰| 黑白诀电视剧免费观看完整版高清| 星刻的龙骑士免费观看| 白峰手机版免费观看| 安娜贝尔2:诞生| 终结者6:黑暗命运| 赤板栗| 苹果4刷机教程| 终极斗士2| 玄女心经二免费观看| 我为卿狂百度影音| 味道食在乡| 中字HD为丈夫的下属的成就| 《水浒传之英雄本色》| 马与人电影在线观看免费播放| 发烧会所1984美国版叫什么 | 卖保险套的女销售在线观看| 海天之恋剧情| 爱情公寓第五季观看免费| 《落魄贵族琉璃川》樱花动漫| 舒淇三圾片在线观看| 第三按摩室| 满天星《交易》凯登| 行尸走肉第二季剧情| 羽月希在线观看| 《银鞋》荷兰/2015| 迈克尔杰克逊 危险| 不忠电影在线观看免费完整观看| 美和花园电影免费观看2023年上映的 | 情谜-睡美人电视剧全集80集| 《五十度灰3》三部曲在线观看| IPX-602 Ipx602 沉迷于【恶女教师】嫉妒的不穿内裤诱惑女教师的异常私通。 明 | 法国版《女超人:麦乐迪》在线播放视| 你是迟来的欢喜全集免费观看| 伽玛刀治疗肝癌| 水电工的艳遇电影| 五十度黑电影完整版| 嫡女宅斗:全精通全集免费| 最棒的情人沼电影| 姐姐免费观看国语全集| 黑执事第三季| 电影买保险的D杯女| 冰冷的热带鱼| 寒战2免费| 免费播放白峰美羽救赎治愈电影视频| 珍馐记在线观看免费完整版| 开国大典电影完整版| 按摩院的特色待遇| 花样男子韩剧免费观看全集| 我要成名在线观看| 巴黎危机完整版高清免费观看| 公的之浮手| 女医生被灌醉酒趁人之危的电视剧| 折腰电视剧全集| 义子乱的电影在线| 甄嬛传74集在线观看| 河南一家6口被杀 警方通报| 《白色橄榄树》全集观看| 俘虏之村| yy11111光电影院| 伴郎粗大的内捧猛烈进出视频观看| 《被可怕的科长欺负的新人| 暖春小花电影版| 美人心计全集在线观看| 马兜铃泰剧在线观看| 日漫xl司令第一季| 电影三奸| 星际迷航6| 陪讨厌上司去出差旅| 邪恶新郎| 圣斗士星矢欧米茄| 清流租房| 做aj的电视剧大全免费观看导演金| 老鹰都开始抓鲨鱼了| 地球上的星星2全集观看| 台剧《浪漫女家教》黛比在线观看| 美女没有穿内衣| 萌宝追妻:神级奶爸短剧全集| 不良义姐| 吴健版农民伯伯国语版在线看| 姐姐说家里没人我们可以在一起吗| 地下交通站第一部28集下载| 82板杨敏思版本1-5电视剧在线观看| 老虎出更国语| 小猪佩奇mp3| 大器晚成露鸟电视剧免费播放| 特殊美容院待遇3| 电视剧门当户对| 聊斋之流光情劫完整在线观看| 禁忌3年转一代中文字母| 需要爸爸的种子美国子弹电影在线观看| 《魔法少女伊莉雅》| 庆余年1-46集免费观看| 孤男寡女免费看电视剧战狼3| 风水讲座| 韩剧《财阀儿媳》| 孤单的儿媳免费观看全集| xl司令全集免费观看高清| 奥运高手国语| 杏林春暖无删减| 美国特殊酒店2| 地狱里的天堂在线观看完整版| 妈妈的味道在线视频观看| 杀戮都市在线观看完整高清免费| 黑白配国语版在线看| 反恐特战队之天狼| 开放的家庭| 开封王婆回应已婚男事件| 17se视频| 加藤鹰电影| 《成何体统》| 部长出差的日子| 赛仑奇葩诊所在线观看| 麦迪乐马克斯女超人正版| 选调生之家| 坎贝奇第二部曲品味人生在线观看 | 魔镜号在线观看完整版免费| 猿族崛起高清完整版| 苹果电影完整版在线观看免费版| 红天鹅韩剧在哪里看| 美丽桃子5:美丽人生星辰| 《武则天风流艳史》在线播放| 家族的荣光| 男男在洗澡时互添gay| 二十一世纪指南在线| 小小周正面曝光| 春雨电影播放大全在线观看| 美国保罗2高清版| 满天星家庭矛盾无删减版| 《特别的酒店》免费观看中文版全集| 原始森林电影| 欧少女16集全怎么看| 《以爱为营》电视剧| 搞笑一家人国语配音| 斗罗大陆123| 19岁大学生真人观看电视剧| 照镜辞在线观看免费完整版| 斗气冤家好兄弟第二部 | 恶意电影| 超级富豪| 一路向西 字幕| 美味快递员的特殊待遇| 林家铺子在线观看| 桔子在线观看免费高清电视剧| 哇嘎在线观看| 电影《爱与自由》在线观看免费| 和部长一起出差的日本电影| 老男孩父子篇| 一个好妈妈5字中字答案电影| 蔡徐坤收到奥特曼卡| 超人气学园剧情介绍| 张韶涵易天边回忆杀暴击| 酒店的特殊待遇| 喜羊羊与灰太狼心世界奇遇| 乌云之上| 唐朝诡事录电视剧免费观看| 女子监狱满天星法版2024| 贤妻在线观看| 高清《美人心计》免费观看| 仙界羡慕:魔尊娇妻全集免费 | 邻居也疯狂全集在线观看| 死亡游戏动漫| 真情无限之继母电视剧| 美容室:待遇服务6| 用手指扰乱我| 街头顽童电影| 情色姐妹| 需要爸爸播种子| 八戒八戒8在线看免费观看完整版| 新生在线观看电视剧免费| 可爱的妹妹| 金瓶梅在线完整版中文免费观看电影 | 中国挤奶哺乳午夜片| 我们都是好朋友电视剧| 庆余年2999影片库| 需要爸爸播种在美国| 硅胶娃娃实战效果视频| 筋膜黏连| 我的爱蝴蝶夫人| 《法国空乘11》| 高压监狱3法国电影在线观看完整免费 | 禁室培育爱的俘虏| 韩国电影遥控器控制人叫什么| 各卫视春晚播出时间2021| 南海归墟16集在线播放免费| 茶啊二中第五季高清免费看优酷网|