色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

3天內不再提示

什么是cola_os?

汽車電子技術 ? 來源:嵌入式大雜燴 ? 作者: ZhengNL ? 2023-02-09 17:00 ? 次閱讀

大家好,我是ZhengN。

嵌入式大雜燴周記主要是一些實用項目學習分享,每周一篇,每篇一個主題。

內容主要來源于我們之前收集的資料

https://gitee.com/zhengnianli/EmbedSummary

本期主角:cola_os

cola_os是一個300多行代碼實現的多任務管理的OS,在很多MCU開發中,功能很簡單,實時性要求不強,任務多了管理不當又很亂。

如果使用RTOS顯得太浪費,這時候可以嘗試使用使用cola_os這類基于軟件定時器實現的時間片輪詢框架。

倉庫鏈接:

https://gitee.com/schuck/cola_os

license:MulanPSL-1.0(木蘭寬松許可證, 第1版)。

cola_os是一份簡潔明了的代碼,包含很多有用的編程思想,值得通讀。下面我們一起來學習一下:

cola_os的分析及使用

其實關于cola_os其實我們前幾天的推文中也有做介紹。今天我們再一起來完整地梳理一遍。

cola_os目前的內容如:

圖片

圖片

1、cola_os

cola_os就是cola_os的任務管理模塊。任務使用鏈表進行管理,其數據結構如:

typedef void (*cbFunc)(uint32_t event);

typedef struct task_s
{
    uint8_t     timerNum;    //定時編號
    uint32_t    period;      //定時周期
    bool        oneShot;     //true只執行一次
    bool        start;       //開始啟動
    uint32_t    timerTick;   //定時計數
    bool        run;         //任務運行標志 
    bool        taskFlag;    //任務標志是主任務還是定時任務
    uint32_t    event;       //驅動事件  
    cbFunc      func;        //回調函數
    struct task_s *next;
}task_t;

每創建一個任務嗎,就是往任務鏈表中插入一個任務節點。

其創建任務的方法有兩種:

  • 創建主循環任務
  • 創建定時任務

兩種方式創建,都是會在while(1)循環中調度執行任務函數。

我們可以看看cola_task_loop任務遍歷函數,這個函數最終是要放在主函數while(1)中調用的。其內容如:

void cola_task_loop(void)
{
    uint32_t events;
    task_t *cur  = task_list;
    OS_CPU_SR cpu_sr;
    
    while( cur != NULL )
    {
        if(cur->run)
        {
            if(NULL !=cur->func)
            {
                events = cur->event;
                if(events)
                {
                    enter_critical();
                    cur->event = 0;
                    exit_critical();
                }
                cur->func(events);                
            }
            if(TASK_TIMER == cur->taskFlag)
            {
                enter_critical();
                cur->run = false;
                exit_critical();
            }
            if((cur->oneShot)&&(TASK_TIMER == cur->taskFlag))
            {
               cur->start = false; 
            }
        }
        cur = cur->next;
    }
}

兩種方式創建的任務都會在cur->func(events);被調用。不同的就是:遍歷執行到定時任務時,需要清掉定時相關標志。

其中,events作為任務函數的參數傳入。從cola_task_loop可以看到,事件并未使用到,events無論真還是假,在執行任務函數前,都被清零了。events的功能應該是作者預留的。

創建任務很簡單,比如創建一個定時任務:

static task_t timer_500ms;

//每500ms執行一次
static void timer_500ms_cb(uint32_t event)
{
    printf("task0 running...\\n");
}

cola_timer_create(&timer_500ms, timer_500ms_cb);
cola_timer_start(&timer_500ms, TIMER_ALWAYS, 500);

cola_os是基于軟件定時器來進行任務調度管理的,需要一個硬件定時器提供時基。比如使用系統滴答定時器,配置為1ms中斷一次。

在1ms中斷中不斷輪詢判斷定時計數是否到達定時時間:

void SysTick_Handler(void)
{
  cola_timer_ticker();
}

void cola_timer_ticker(void)
{
    task_t *cur  = task_list;
    OS_CPU_SR cpu_sr;
    while( cur != NULL )
    {
        if((TASK_TIMER == cur->taskFlag)&& cur->start)
        {
            if(++cur->timerTick >= cur->period)
            {
                cur->timerTick = 0;
                if(cur->func != NULL)
                {
                    enter_critical();                   
                    cur->run = true;
                    exit_critical();
                }
            }
        }
        cur = cur->next;
    }
}

如果到了則將標志cur->run置位,在while大循環中的cola_task_loop函數中如果檢測到該標志就執行該任務函數。

2、cola_device

cola_device是硬件抽象層,使用鏈表來管理各個設備。其借鑒了RT-ThreadLinux相關驅動框架思想。大致內容如:

數據結構如:

typedef struct cola_device  cola_device_t;

struct cola_device_ops
{
    int  (*init)   (cola_device_t *dev);
    int  (*open)   (cola_device_t *dev, int oflag);
    int  (*close)  (cola_device_t *dev);
    int  (*read)   (cola_device_t *dev, int pos, void *buffer, int size);
    int  (*write)  (cola_device_t *dev, int pos, const void *buffer, int size);
    int  (*control)(cola_device_t *dev, int cmd, void *args);

};

struct cola_device
{
    const char * name;
    struct cola_device_ops *dops;
    struct cola_device *next;
};

硬件抽象層的接口如:

/*
    驅動注冊
*/
int cola_device_register(cola_device_t *dev);
/*
    驅動查找
*/
cola_device_t *cola_device_find(const char *name);
/*
    驅動讀
*/
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
/*
    驅動寫
*/
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
/*
    驅動控制
*/
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);

首先,在驅動層注冊好設備,把操作設備的函數指針及設備名稱插入到設備鏈表中:

static cola_device_t led_dev;

static void led_gpio_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;                            
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                     
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                  
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                     
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;                  
    GPIO_Init(PORT_GREEN_LED, &GPIO_InitStructure);
    LED_GREEN_OFF;
}

static int led_ctrl(cola_device_t *dev, int cmd, void *args)
{
    if(LED_TOGGLE == cmd)
    {
        LED_GREEN_TOGGLE;
    }
    else 
    {
        
    }
    return 1;
}


static struct cola_device_ops ops =
{
    .control = led_ctrl,
};

static void led_register(void)
{
    led_gpio_init();
    led_dev.dops = &ops;
    led_dev.name = "led";
    cola_device_register(&led_dev);
}

cola_device_register函數如:

int cola_device_register(cola_device_t *dev)
{
    if((NULL == dev) || (cola_device_is_exists(dev)))
    {
        return 0;
    }

    if((NULL == dev->name) ||  (NULL == dev->dops))
    {
        return 0;
    }
    return device_list_inster(dev);
}

驅動注冊好設備之后,應用層就可以根據設備名稱來查找設備是否被注冊,如果已經注冊則可以調用設備操作接口操控設備。比如創建一個定時任務定時反轉led:

void app_init(void)
{
    app_led_dev = cola_device_find("led");
    assert(app_led_dev);
    cola_timer_create(&timer_500ms,timer_500ms_cb);
    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
}

static void timer_500ms_cb(uint32_t event)
{
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
}

3、cola_init

cola_init是一個自動初始化模塊,模仿Linux的initcall機制。RT-Thread也有實現這個功能:

圖片

一般的,我們的初始化在主函數中調用,如:

圖片

有了自動初始化模塊,可以不在主函數中調用,例如:

void SystemClock_Config(void)
{
}
pure_initcall(SystemClock_Config);

這樣也可以調用SystemClock_Config。pure_initcall如:

#define  __used  __attribute__((__used__))

typedef void (*initcall_t)(void);

#define __define_initcall(fn, id) \\
    static const initcall_t __initcall_##fn##id __used \\
    __attribute__((__section__("initcall" #id "init"))) = fn; 

#define pure_initcall(fn)       __define_initcall(fn, 0) //可用作系統時鐘初始化  
#define fs_initcall(fn)         __define_initcall(fn, 1) //tick和調試接口初始化
#define device_initcall(fn)     __define_initcall(fn, 2) //驅動初始化
#define late_initcall(fn)       __define_initcall(fn, 3) //其他初始化

在cola_init中,首先是調用不同順序級別的__define_initcall宏來把函數指針fn放入到自定義的指定的段中。各個需要自動初始化的函數放到指定的段中,形成一張初始化函數表。

__ attribute __ (( __ section __)) 關鍵字就是用來指定數據存放段。

do_init_call函數在我們程序起始時調用,比如在bsp_init中調用:

void bsp_init(void)
{
    do_init_call();
}

do_init_call里做的事情就是遍歷初始化函數表里的函數:

void do_init_call(void)
{
    extern initcall_t initcall0init$$Base[];
    extern initcall_t initcall0init$$Limit[];
    extern initcall_t initcall1init$$Base[];
    extern initcall_t initcall1init$$Limit[];
    extern initcall_t initcall2init$$Base[];
    extern initcall_t initcall2init$$Limit[];
    extern initcall_t initcall3init$$Base[];
    extern initcall_t initcall3init$$Limit[];
    
    initcall_t *fn;
    
    for (fn = initcall0init$$Base;
            fn < initcall0init$$Limit;
            fn++)
    {
        if(fn)
            (*fn)();
    }
    
    for (fn = initcall1init$$Base;
            fn < initcall1init$$Limit;
            fn++)
    {
        if(fn)
            (*fn)();
    }
    
    for (fn = initcall2init$$Base;
            fn < initcall2init$$Limit;
            fn++)
    {
        if(fn)
            (*fn)();
    }
    
    for (fn = initcall3init$$Base;
            fn < initcall3init$$Limit;
            fn++)
    {
        if(fn)
            (*fn)();
    }
}

這里有 initcall0init $$ Baseinitcall0init Limit這幾個initcall_t類型的函數指針數組的聲明。它們事先是調用__define_initcall把函數指針fn放入到自定義的指定的段.initcall0init、.initcall1init、.initcall2init、.initcall3init。

**initcall0init$$

Baseinitcall0init

Limit**按照我的理解就是各個初始化函數表的開始及結束地址。從而實現遍歷:

for (fn = initcall0init$$Base;
            fn < initcall0init$$Limit;
            fn++)
    {
        if(fn)
            (*fn)();
    }

例如RT-Thread里的實現也是類似的:

volatile const init_fn_t *fn_ptr;

    for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
    {
        (*fn_ptr)();
    }

關于init自動初始化機制大致就分析這些。

cola_os包含有cola_os任務管理、cola_device硬件抽象層及cola_init自動初始化三大塊,這三塊內容其實可以單獨抽出來學習、使用。

4、cola_os的使用

下面我們基于小熊派IOT開發板來簡單實踐實踐。

圖片

我們創建兩個定時任務:

  • task0任務:定時500ms打印一次。
  • task1任務:定時1000ms打印一次。

main.c:

/* Private variables ---------------------------------------------------------*/
static task_t timer_500ms;
static task_t timer_1000ms;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

//每500ms執行一次
static void timer_500ms_cb(uint32_t event)
{
    printf("task0 running...\\n");
}

//每1000ms執行一次
static void timer_1000ms_cb(uint32_t event)
{
    printf("task1 running...\\n");
}

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
//  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  printf("微信公眾號:嵌入式大雜燴\\r\\n");
  printf("cola_os test!\\r\\n");
  
  cola_timer_create(&timer_500ms,timer_500ms_cb);
  cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
  cola_timer_create(&timer_1000ms,timer_1000ms_cb);
  cola_timer_start(&timer_1000ms,TIMER_ALWAYS,1000);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
    cola_task_loop();
  }
  /* USER CODE END 3 */

}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInit;

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = 0;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
  RCC_OscInitStruct.PLL.PLLM = 1;
  RCC_OscInitStruct.PLL.PLLN = 40;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the main internal regulator output voltage 
    */
  if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time 
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
pure_initcall(SystemClock_Config);

SysTick_Handler:

void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  cola_timer_ticker();
  HAL_IncTick();
  HAL_SYSTICK_IRQHandler();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

編譯、下載、運行:

圖片

從運行結果可以看到,task1的定時周期是task0的兩倍,符合預期。

本文代碼工程可在本公眾號后臺回復關鍵詞:cola_os測試 ,即可獲取。

以上就是本次的分享,文章如有錯誤,歡迎指出,謝謝!

咱們下期見~

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

    關注

    146

    文章

    17316

    瀏覽量

    352254
  • OS
    OS
    +關注

    關注

    0

    文章

    92

    瀏覽量

    34785
  • 代碼
    +關注

    關注

    30

    文章

    4823

    瀏覽量

    68901
收藏 人收藏

    評論

    相關推薦

    IOT OS比較,分析IOT OS的發展方向

    摘要:根據IOT設備的需求,以及IOT OS需要滿足的技術特征、現有IOT OS的來源,分別概述FreeRTOS、AliOS-Things、RT-Thread、Lite OS、Zephyr、Mbed
    的頭像 發表于 08-16 17:12 ?4708次閱讀

    使用cola_os軟件定時器實現時間片輪詢框架

    如果使用RTOS顯得太浪費,這時候可以嘗試使用使用cola_os這類基于軟件定時器實現的時間片輪詢框架。
    的頭像 發表于 09-22 09:03 ?1469次閱讀
    使用<b class='flag-5'>cola_os</b>軟件定時器實現時間片輪詢框架

    cola os程序框架介紹

    系列文章目錄嵌入式開發|嵌入式軟件框架《一》常用的軟件框架介紹與選擇文章目錄系列文章目錄前言一、cola os程序框架1.cola_init2.cola_device3.cola_os task任務
    發表于 11-08 08:17

    什么是uC/OS

    什么是uC/OS uC/OS是源碼公開的實時嵌入式操作系統。uC/OS-Ⅱ的主要特點如下:公開源代碼,系統透明,很容易就能把操作系統移植到各個不同
    發表于 06-17 00:37 ?4207次閱讀

    Palm OS

    Palm OS              Palm OS是Palm公司的是一種32位的嵌入式操作系統,它的操作界面采用觸控式,差不多所有的控制選
    發表于 12-19 11:33 ?1704次閱讀

    操作系統(OS),什么是操作系統(OS)

    操作系統(OS),什么是操作系統(OS) 操作系統(Operating System,簡稱 OS)的出現、使用和發展是近四十余年來計算機軟件的一個重大進展。
    發表于 03-26 15:21 ?2834次閱讀

    鴻蒙OS系統詳解

    華為的鴻蒙OS是一款“面向未來”的操作系統,是基于微內核的全場景分布式OS,可按需擴展,實現更廣泛的系統安全。目前主要用于智能物聯網,今年將擴展到智能手機上鴻蒙OS擁有分布架構、內核安全、生態共享、運行流暢四大優勢,鴻蒙
    的頭像 發表于 11-12 11:24 ?1.4w次閱讀

    鴻蒙OS與Lite OS的區別是什么

    鴻蒙OS鴻蒙OS面向未來、面向全場景、分布式。在單設備系統能力基礎上,鴻蒙OS提出了基于同一套系統能力、適配多種終端形態的分布式理念,支持多種終端設備。鴻蒙的特點:1)分布式軟總線2)分布式設備虛擬化
    的頭像 發表于 12-24 12:40 ?5072次閱讀

    No-OS Drivers

    No-OS Drivers
    發表于 02-20 13:02 ?0次下載
    No-<b class='flag-5'>OS</b> Drivers

    鴻蒙os怎么升級

    6月2日,華為正式發布了鴻蒙armonyOS 2系統,那么鴻蒙os如何升級?現將鴻蒙os升級方式告知如下。
    的頭像 發表于 06-08 16:26 ?2777次閱讀

    嵌入式開發|嵌入式軟件框架《二》前后臺任務框架-cola os系統

    系列文章目錄嵌入式開發|嵌入式軟件框架《一》常用的軟件框架介紹與選擇文章目錄系列文章目錄前言一、cola os程序框架1.cola_init2.cola_device3.cola_os task任務
    發表于 11-03 13:51 ?18次下載
    嵌入式開發|嵌入式軟件框架《二》前后臺任務框架-<b class='flag-5'>cola</b> <b class='flag-5'>os</b>系統

    COLA Architecture整潔面向對象分層架構

    ./oschina_soft/COLA.zip
    發表于 06-14 09:41 ?0次下載
    <b class='flag-5'>COLA</b> Architecture整潔面向對象分層架構

    cola_os的分析及使用

    cola_os是一個300多行代碼實現的多任務管理的OS,在很多MCU開發中,功能很簡單,實時性要求不強,任務多了管理不當又很亂。
    的頭像 發表于 08-12 09:37 ?1362次閱讀

    慢下來&amp;快起來,看Coca-Cola高效轉型路徑

    事半功倍 | 聚沙成塔, 打造 Coca-Cola 速度! 企業的數字化轉型并非“一蹴而就”,而是一個持續迭代的過程,從初期確認需求、匯集資源到有效利用資源再到具體實踐,其中的每一個環節對于最終效果
    的頭像 發表于 01-06 06:50 ?484次閱讀

    STM32 模擬Linux kernel自動初始化流程

    Linux中有很多編程思想可以學習,很多大佬把這些思想、機制運用到單片機的編程上。 比如: 嵌入式大雜燴周記 | 第 4 期 中介紹的cola_os、大家熟知的RT-Thread。 還有屋脊雀的代碼
    的頭像 發表于 06-22 10:03 ?655次閱讀
    STM32 模擬Linux kernel自動初始化流程
    主站蜘蛛池模板: jk制服啪啪网站 | 甜宠溺H宝贝嗯撞PLAY啊 | 精品区2区3区4区产品乱码9 | 色多多污污在线播放免费 | 在线精品视频免费观看 | 国产伦精品一区二区三区 | 精品久久伦理中文字幕 | 中文字幕在线永久 | 97免费在线视频 | 精品香蕉99久久久久网站 | 秋霞特色大片18岁入口 | 国产成人精品自拍 | 10分钟免费观看视频 | 日本亚洲欧洲免费旡码 | 国产精品国产三级国产AV麻豆 | 色综合久久88色综合天天提莫 | 插曲的痛30分钟视频最新章节 | 国产亚洲精品久久无亚洲 | 2019午夜福利757视频第12集 | 国产人妻XXXX精品HD电影 | 国产人妻XXXX精品HD电影 | 狠狠综合久久综合88亚洲 | 亚洲妈妈精品一区二区三区 | 午夜福利电影网站鲁片大全 | 国产三区在线成人AV | 亚洲日本香蕉视频观看视频 | 欧美顶级情欲片免费看 | 亚洲永久精品AV在线观看 | 96.8在线收听 | 99国产精品人妻无码免费 | SM脚奴调教丨踩踏贱奴 | 成人无码在线超碰视频 | 亚洲AV蜜桃永久无码精品无码网 | 香蕉eeww99国产精品 | 美女穿丝袜被狂躁动态图 | 在线观看国产精选免费 | 亚洲精品国产专区91在线 | 最新无码国产在线视频9299 | 色婷婷亚洲精品天天综合影院 | 中文字幕在线播放 | 韩国伦理片2018在线播放免费观看 |