wwwxxx国产_337p日本欧洲亚洲大胆张筱雨_免费在线看成人av_日本黄色不卡视频_国产精品成熟老女人_99视频一区_亚洲精品97久久中文字幕_免费精品视频在线_亚洲色图欧美视频_欧美一区二三区

專注電子技術學習與研究
當前位置:單片機教程網 >> STM32 >> 瀏覽文章

STM32F10x片上Flash 模擬 EEPROM程序

作者:JASoN   來源:會員上傳   點擊數:  更新時間:2014年05月18日   【字體:

本程序還要用到一個頭文件,完整源碼的下載地址是: http://m.izizhuan.cn/f/STM32F10x_EEPROM_Emulation.zip

STM32F10x芯片沒有自帶eeprom我們可以用Flash來模擬 EEPROM程序,本程序原理詳見: http://m.izizhuan.cn/stm32/3581.html

 /**

 *******************************************************************************
 * @file    eeprom.c
 * @author  JASoN
 * @version V1.0
 * @date    2014-03-20
 * @since   2014-03-20
 * @ref     STM32F10x_AN2594_FW_V3.1.0 - MCD Application Team
 * @brief   This file provides all the EEPROM emulation firmware functions.
 *
 * Page map
 * +---------+-------------+----------------------------+
 * | byte    | length      | description                |
 * +---------+-------------+----------------------------+ <- PAGE_BASE_ADDRESS
 * | [0: 1]  | 16 bits     | page status:               |
 * |         |             |   0xFFFF: ERASED           |
 * |         |             |   0xEEEE: RECEIVE_DATA     |
 * |         |             |   0x0000: VALID_PAGE       |
 * +---------+-------------+----------------------------+
 * | [2: 7]  | 48 bits     | reserved                   |
 * +---------+-------------+----------------------------+
 * | [8: 15] | 64 bits     | block 1                    |
 * +---------+-------------+----------------------------+
 * |         |             | ...                        |  鈫揵lock grows
 * +---------+-------------+----------------------------+
 * |         | 64 bits     | block n                    | ------+
 * +---------+-------------+----------------------------+       |
 * |                                                    |       | data offset
 * +---------+-------------+----------------------------+       | (16 bits)
 * |         | 16 bits     | 0xCCCC                     |       |
 * +---------+-------------+----------------------------+ <-----+
 * |         | data length | data n (2 bytes alignment) |
 * +---------+-------------+----------------------------+
 * |         |             | ...                        |  鈫慸ata grows
 * +---------+-------------+----------------------------+
 * |         | 16 bits     | 0xCCCC                     |
 * +---------+-------------+----------------------------+
 * |         | data length | data 1 (2 bytes alignment) |
 * +---------+-------------+----------------------------+  <- PAGE_END_ADDRESS
 *
 * Block map (64 bits)
 * +----------+---------+-----------------------------------------+
 * | bits     | length  | description                             |
 * +----------+---------+-----------------------------------------+
 * | [0: 15]  | 16 bits | block status:                           |
 * |          |         |   0xAAAA: VALID_BLOCK                   |
 * |          |         |   0x0000: EXPIRED_BLOCK                 |
 * +----------+---------+-----------------------------------------+
 * | [16: 23] | 8 bits  | data key                                |
 * +----------+---------+-----------------------------------------+
 * | [24: 31] | 8 bits  | data checksum                           |
 * +----------+---------+-----------------------------------------+
 * | [32: 47] | 16 bits | data offset (base on PAGE_BASE_ADDRESS) |
 * +----------+---------+-----------------------------------------+
 * | [48: 63] | 16 bits | data length (bytes)                     |
 * +----------+---------+-----------------------------------------+
 *
 *******************************************************************************
 */
 
#include "eeprom.h"
 
 
/**
 * Private functions
 */
static uint16_t EE_Format(void);
static uint16_t EE_FindValidPage(uint8_t operation);
static uint16_t EE_WriteByVerify(uint8_t key, const uint8_t *pdata, uint16_t size);
static uint16_t EE_PageTransfer(uint16_t page);
static uint16_t EE_CheckData(void);
 
 
/**
 * Function EE_Init
 * Restore the pages to a known good state in case of page's status corruption
 * after a power loss.
 * Page status combinations and actions to be taken as follows:
 * +--------------+-----------------------------------------------------------------------------------+
 * |              |                                     PAGE_0                                        |
 * |    PAGE_1    +-------------------------+----------------------------+----------------------------+
 * |              | ERASED                  | RECEIVE_DATA               | VALID_PAGE                 |
 * +--------------+-------------------------+----------------------------+----------------------------+
 * |              | First EEPROM access or  | Erase PAGE_1 and mark      | OK                         |
 * | ERASED       | invalid state.          | PAGE_0 as valid.           | Run check data routine.    |
 * |              | Erase both pages and    | Run check data routine.    |                            |
 * |              | mark PAGE_0 as valid.   |                            |                            |
 * |--------------+-------------------------+----------------------------+----------------------------+
 * |              | Erase PAGE_0 and mark   | Invalid state.             | Transfer the last updated  |
 * |              | PAGE_1 as valid.        | Erase both pages and       | data from PAGE_0 to PAGE_1 |
 * | RECEIVE_DATA | Run check data routine. | format PAGE_0.             | and mark PAGE_1 as valid   |
 * |              |                         |                            | and erase PAGE_0.          |
 * |              |                         |                            | Run check data routine.    |
 * +--------------+-------------------------+----------------------------+----------------------------+
 * |              | OK                      | Transfer the last updated  | Invalid state.             |
 * |              | Run check data routine. | data from PAGE_1 to PAGE_0 | Erase both pages and mark  |
 * | VALID_PAGE   |                         | and mark PAGE_0 as valid   | PAGE_0 as valid.           |
 * |              |                         | and erase PAGE_1.          |                            |
 * |              |                         | Run check data routine.    |                            |
 * +--------------+-------------------------+----------------------------+----------------------------+
 *
 * @param  none
 * @return success or error status
 *         - FLASH_COMPLETE: on success
 *         - error code:     on error
 */
uint16_t EE_Init(void) {
  uint16_t status = FLASH_COMPLETE;
  uint16_t ps0 = 0; // PAGE_0 status
  uint16_t ps1 = 0; // PAGE_1 status
 
  ps0 = (*(__IO uint16_t*)PAGE_0_BASE_ADDRESS);
  ps1 = (*(__IO uint16_t*)PAGE_1_BASE_ADDRESS);
 
//  printf("PAGE_0 status: %x, PAGE_1 status: %x\n", ps0, ps1);
 
  switch(ps0) {
    /* --------------------------- PAGE_0 erased ---------------------------- */
    case ERASED:
      if(ps1 == VALID_PAGE) {                                    // PAGE_1 valid
        return EE_CheckData();
      }
      else if(ps1 == RECEIVE_DATA) {                           // PAGE_1 receive
        /* erase PAGE_0 */
        status = FLASH_ErasePage(PAGE_0_BASE_ADDRESS);
        if(status != FLASH_COMPLETE) return status;
 
        /* mark PAGE_1 as valid */
        status = FLASH_ProgramHalfWord(PAGE_1_BASE_ADDRESS, VALID_PAGE);
        if(status != FLASH_COMPLETE) return status;
      }
      else {                                                    // invalid state
        /* erase both pages and mark PAGE_0 as valid */
        return EE_Format();
      }
      break;
 
    /* --------------------------- PAGE_0 receive --------------------------- */
    case RECEIVE_DATA:
      if(ps1 == VALID_PAGE) {                                    // PAGE_1 valid
        /* transfer the last updated data from PAGE_1 to PAGE_0
           and mark PAGE_0 as valid and erase PAGE_1
         */
        status = EE_PageTransfer(PAGE_1);
        if(status != FLASH_COMPLETE) return status;
      }
      else if(ps1 == ERASED) {                                  // PAGE_1 erased
        /* erase PAGE_1 */
        status = FLASH_ErasePage(PAGE_1_BASE_ADDRESS);
        if(status != FLASH_COMPLETE) return status;
 
        /* mark PAGE_0 as valid */
        status = FLASH_ProgramHalfWord(PAGE_0_BASE_ADDRESS, VALID_PAGE);
        if(status != FLASH_COMPLETE) return status;
      }
      else {                                                    // invalid state
        /* erase both pages and mark PAGE_0 as valid */
        return EE_Format();
      }
      break;
 
    /* --------------------------- PAGE_0 valid ----------------------------- */
    case VALID_PAGE:
      if(ps1 == VALID_PAGE) {                                   // invalid state
        /* erase both pages and mark PAGE_0 as valid */
        return EE_Format();
      }
      else if(ps1 == ERASED) {                                  // PAGE_1 erased
        return EE_CheckData();
      }
      else {                                                   // PAGE_1 receive
        /* transfer the last updated data from PAGE_0 to PAGE_1
           and mark PAGE_1 as valid and erase PAGE_0
         */
        status = EE_PageTransfer(PAGE_0);
        if(status != FLASH_COMPLETE) return status;
      }
      break;
 
    /* ------------------------------ default ------------------------------- */
    default:
      /* erase both pages and set PAGE_0 as valid */
      return EE_Format();
  }
 
  return EE_CheckData();
}
 
/**
 * Function EE_ReadData
 * Get the last stored data correspond to the passed data key.
 * @param  key:   8 bits key of the stored data
 * @param  pdata: pointer to the variable that will contain the read value
 * @param  size:  data size in bytes
 * @return success or error status
 *         - 0: if data found
 *         - 1: if data not found
 *         - EE_NO_VALID_PAGE:       if no valid page found
 *         - EE_DATA_SIZE_ERROR:     if the passed size not equal to data length
 *         - EE_DATA_CHECKSUM_ERROR: if data checksum error
 */
uint16_t EE_ReadData(uint8_t key, uint8_t* pdata, uint16_t size) {
  uint16_t page = PAGE_0;
  uint32_t base = EEPROM_START_ADDRESS;
  uint32_t address = EEPROM_START_ADDRESS;
  uint16_t value = 0;
  uint16_t dataOffset = 0;
  uint16_t dataLength = 0;
  uint8_t dataChecksum = 0;
  uint8_t checksum = 0;
  uint16_t flag = 1; // data not found
 
  /* get valid page for read operation */
  page = EE_FindValidPage(READ_FROM_VALID_PAGE);
  if(page == EE_NO_VALID_PAGE) return page;
 
  /* page base address */
  base = EEPROM_START_ADDRESS + (uint32_t)(page * PAGE_SIZE);
 
  /* block address */
  address = base + 8;
 
  /* check each valid block starting from begining */
  while(address < base + PAGE_SIZE) {
    value = (*(__IO uint16_t*)address); // block status
 
    /* in case the valid block found */
    if(value == VALID_BLOCK) {
      value = (*(__IO uint16_t*)(address + 2)); // key & checksum
 
      /* in case the key matched (valid data found) */
      if((value & 0x00FF) == key) {
        dataChecksum = (uint8_t)(value >> 8);
        dataOffset = (*(__IO uint16_t*)(address + 4));
        dataLength = (*(__IO uint16_t*)(address + 6));
 
        /* check data size */
        if(dataLength != size || (base + dataOffset + size) > (base + PAGE_SIZE)) {
          return EE_DATA_SIZE_ERROR;
        }
 
//        printf("read data from: %x\n", base + dataOffset);
 
        /* read data */
        for(; size > 0; size--) {
          value = (*(__IO uint8_t*)(base + dataOffset));
          checksum = (checksum << 1) || (checksum >> 7);
          checksum += value;
          *(pdata++) = value;
          dataOffset++;
        }
 
        /* verify the checksum */
        if(checksum != dataChecksum) {
          return EE_DATA_CHECKSUM_ERROR;
        }
 
        flag = 0;
        break;
      }
    }
    else if(value != EXPIRED_BLOCK) { // end of block area
      break;
    }
    address += 8; // next block
  }
 
  return flag;
}
 
/**
 * Function EE_WriteData
 * Writes/upadtes data in EEPROM.
 * @param  key:   8 bits key of the data
 * @param  pdata: pointer to the data that will be written
 * @param  size:  data size in bytes
 * @return success or error status
 *         - FLASH_COMPLETE: on success
 *         - error code:     on error
 */
uint16_t EE_WriteData(uint8_t key, const uint8_t *pdata, uint16_t size) {
  uint16_t status = FLASH_COMPLETE;
 
  status = EE_WriteByVerify(key, pdata, size);
 
  /* in case the valid page is full, then perform page transfer */
  if(status == EE_PAGE_FULL) {
    status = EE_PageTransfer(EE_FindValidPage(WRITE_IN_VALID_PAGE));
    if(status != FLASH_COMPLETE) return status;
 
    /* write again */
    status = EE_WriteByVerify(key, pdata, size);
  }
 
  return status;
}
 
/**
 * Function EE_Format
 * Erase both pages and mark PAGE_0 as valid.
 * @param  none
 * @return status of the last operation
 */
static uint16_t EE_Format(void) {
  FLASH_Status status = FLASH_COMPLETE;
 
//  printf("format page.\n");
 
  /* erase PAGE_0 */
  status = FLASH_ErasePage(PAGE_0_BASE_ADDRESS);
  if(status != FLASH_COMPLETE) return status;
 
  /* mark PAGE_0 as valid */
  status = FLASH_ProgramHalfWord(PAGE_0_BASE_ADDRESS, VALID_PAGE);
  if(status != FLASH_COMPLETE) return status;
 
  /* erase PAGE_1 */
  status = FLASH_ErasePage(PAGE_1_BASE_ADDRESS);
  return status;
}
 
/**
 * Function EE_FindValidPage
 * Find valid page for write or read operation.
 * @param  operation: operation to achieve on the valid page
 *         @arg READ_FROM_VALID_PAGE: read operation from valid page
 *         @arg WRITE_IN_VALID_PAGE:  write operation to valid page
 * @return valid page number (PAGE_0 or PAGE_1) or EE_NO_VALID_PAGE
 */
static uint16_t EE_FindValidPage(uint8_t operation) {
  uint16_t ps0 = 0; // PAGE_0 status
  uint16_t ps1 = 0; // PAGE_1 status
 
  ps0 = (*(__IO uint16_t*)PAGE_0_BASE_ADDRESS);
  ps1 = (*(__IO uint16_t*)PAGE_1_BASE_ADDRESS);
 
  switch(operation) {
    /* write operation */
    case WRITE_IN_VALID_PAGE:
      if(ps1 == VALID_PAGE) {
        if(ps0 == RECEIVE_DATA) { // transfer PAGE_1 -> PAGE_0
          return PAGE_0;
        }
        else {
          return PAGE_1;
        }
      }
      else if(ps0 == VALID_PAGE) {
        if(ps1 == RECEIVE_DATA) { // transfer PAGE_0 -> PAGE_1
          return PAGE_1;
        }
        else {
          return PAGE_0;
        }
      }
      else {
        return EE_NO_VALID_PAGE;
      }
 
    /* read operation */
    case READ_FROM_VALID_PAGE:
      if(ps0 == VALID_PAGE) {
        return PAGE_0;
      }
      else if(ps1 == VALID_PAGE) {
        return PAGE_1;
      }
      else {
        return EE_NO_VALID_PAGE;
      }
 
    default:
      return PAGE_0;
  }
}
 
/**
 * Function EE_WriteByVerify
 * Verify if valid page is full and write data to EEPROM.
 * @param  key:   8 bits key of the data
 * @param  pdata: pointer to the data that will be written
 * @param  size:  data size in bytes
 * @return success or error status
 *         - FLASH_COMPLETE:     on success
 *         - EE_NO_VALID_PAGE:   if no valid page was found
 *         - EE_PAGE_FULL:       if valid page is full
 *         - EE_DATA_SIZE_ERROR: if passed data size is zero
 *         - error code:         on write flash error
 */
static uint16_t EE_WriteByVerify(uint8_t key, const uint8_t *pdata, uint16_t size) {
  uint16_t status = FLASH_COMPLETE;
  uint16_t page = PAGE_0;
  uint32_t base = EEPROM_START_ADDRESS;
  uint32_t address = EEPROM_START_ADDRESS;
  uint32_t dataAddress = EEPROM_START_ADDRESS;
  uint16_t value = 0;
  uint8_t checksum = 0;
  uint16_t i = 0;
 
  if(size == 0) return EE_DATA_SIZE_ERROR;
 
  /* get valid page for write operation */
  page = EE_FindValidPage(WRITE_IN_VALID_PAGE);
  if(page == EE_NO_VALID_PAGE) return page;
 
  /* page base address */
  base = EEPROM_START_ADDRESS + (uint32_t)(page * PAGE_SIZE);
 
  /* block address */
  address = base + 8;
 
  /* check each valid block starting from begining */
  while(address < base + PAGE_SIZE) {
    value = (*(__IO uint16_t*)address); // block head
 
    /* in case the valid block found */
    if(value == VALID_BLOCK) {
      value = (*(__IO uint16_t*)(address + 2)); // key & checksum
 
      /* in case the key matched, then set the block expired */
      if((value & 0x00FF) == key) {
        status = FLASH_ProgramHalfWord(address, EXPIRED_BLOCK);
        if(status != FLASH_COMPLETE) return status;
      }
    }
    else if(value != EXPIRED_BLOCK) { // end of block area
      break;
    }
    address += 8; // next block
  }
 
  /* get the last empty data address (2 bytes alignment) */
  if(address == (base + 8)) {
    dataAddress = base + PAGE_SIZE - 2;
  }
  else {
    value = (*(__IO uint16_t*)(address - 4)); // data offset
    if(value >= PAGE_SIZE) {
      return EE_PAGE_FULL; // trigger the page transfering action
    }
    dataAddress = base + value - 4;
  }
 
  /* check if has enough space for the new block and data */
  if((address + 8 + 2 + size) > dataAddress) { // accurate: dataAddress + 2
    return EE_PAGE_FULL;
  }
 
  /* check empty space for new block */
  for(i = 0; i < 4; i++) {
    value = (*(__IO uint16_t*)(address + i * 2));
    if(value != 0xFFFF) return EE_PAGE_FULL;
  }
 
  /* check empty space for new data (2 bytes alignment) */
  for(i = 0; i < size; i += 2) {
    value = (*(__IO uint16_t*)dataAddress);
    if(value != 0xFFFF) return EE_PAGE_FULL;
    dataAddress -= 2; // pointer to data flag
  }
 
  /* check empty space for data flag */
  value = (*(__IO uint16_t*)dataAddress);
  if(value != 0xFFFF) return EE_PAGE_FULL;
 
  /* write new block */
  status = FLASH_ProgramHalfWord(address, VALID_BLOCK); // block status
  if(status != FLASH_COMPLETE) return status;
 
  status = FLASH_ProgramHalfWord(address + 4, (dataAddress - base + 2)); // data offset (2 bytes after data flag)
  if(status != FLASH_COMPLETE) return status;
 
  status = FLASH_ProgramHalfWord(address + 6, size); // data length
  if(status != FLASH_COMPLETE) return status;
 
  /* write new data begin flag (0xCCCC)*/
  status = FLASH_ProgramHalfWord(dataAddress, DATA_FLAG);
  if(status != FLASH_COMPLETE) return status;
  dataAddress += 2;
 
//  printf("write data at: %x, space left: %d\n", dataAddress, (dataAddress - address - 8));
 
  /* write new data */
  for(i = 0; i < size; i++) {
    checksum = (checksum << 1) || (checksum >> 7);
    checksum += *(pdata + i);
 
    /* 2 bytes alignment */
    if((i & (uint16_t)0x1) == 0) {
      value = (i == (size - 1)) ? (uint16_t)(*(pdata + i)) : (*(uint16_t*)(pdata + i));
      status = FLASH_ProgramHalfWord(dataAddress, value);
      if(status != FLASH_COMPLETE) return status;
      dataAddress += 2;
    }
  }
 
  /* write key & checksum */
  value = ((uint16_t)checksum << 8 | key);
  status = FLASH_ProgramHalfWord(address + 2, value);
  return status;
}
 
/**
 * Function EE_PageTransfer
 * Transfer the last updated data from the passed page to an empty target page
 * and mark the target page as valid and erase passed page.
 * @param  page: page to be transfered
 * @return success or error status
 *         - FLASH_COMPLETE: on success
 *         - error code:     on error
 */
static uint16_t EE_PageTransfer(uint16_t page) {
  uint16_t status = FLASH_COMPLETE;
  uint32_t sourceBase = EEPROM_START_ADDRESS;
  uint32_t targetBase = EEPROM_START_ADDRESS;
  uint32_t address = EEPROM_START_ADDRESS;
  uint16_t value = 0;
  uint64_t block = 0;
  uint16_t *pcell = 0; // pointer to block cell in 2 bytes
  uint16_t dataOffset = 0;
  uint16_t dataLength = 0;
  uint32_t targetL = 0;
  uint32_t targetH = 0;
  uint16_t i = 0;
 
//  printf("transfer page%d\n", page);
 
  if(page == PAGE_0) {
    sourceBase = PAGE_0_BASE_ADDRESS;
    targetBase = PAGE_1_BASE_ADDRESS;
  }
  else if(page == PAGE_1) {
    sourceBase = PAGE_1_BASE_ADDRESS;
    targetBase = PAGE_0_BASE_ADDRESS;
  }
  else {
    return EE_NO_VALID_PAGE;
  }
 
  address = (uint32_t)(sourceBase + 8);         // source block address
  targetL = (uint32_t)(targetBase + 8);         // target block address
  targetH = (uint32_t)(targetBase + PAGE_SIZE); // target data address
 
  /* confirm target page erased */
  value = (*(__IO uint16_t*)targetBase);
  if(value != ERASED) {
    status = FLASH_ErasePage(targetBase);
    if(status != FLASH_COMPLETE) return status;
  }
 
  /* mark target page RECEIVE_DATA status */
  status = FLASH_ProgramHalfWord(targetBase, RECEIVE_DATA);
  if(status != FLASH_COMPLETE) return status;
 
  /* check each valid block in source page starting from begining */
  while(address < sourceBase + PAGE_SIZE) {
    value = (*(__IO uint16_t*)address); // block status
 
    /* in case of VALID_BLOCK */
    if(value == VALID_BLOCK) {
      block = (*(__IO uint64_t*)(address));
      pcell = (uint16_t*)(&block);
      dataOffset = (*(pcell + 2));
      dataLength = (*(pcell + 3));
 
      /* continue if data size error */
      if(dataLength == 0) {
        continue;
      }
      if((sourceBase + dataOffset + dataLength) > (sourceBase + PAGE_SIZE)) {
        continue;
      }
 
      /* calculate target data address */
      targetH = targetH - dataLength;
      if((targetH & (uint32_t)0x1) == 1) {
        targetH--; // 2 bytes alignment
      }
 
      if((targetH - targetL) < 10) continue; // block + data flag = 10 bytes
 
      /* update data offset cell in block */
      *(pcell + 2) = targetH - targetBase;
 
      /* write target block */
      for(i = 0; i < 4; i++) {
        status = FLASH_ProgramHalfWord(targetL + i * 2, *(pcell + i));
        if(status != FLASH_COMPLETE) return status;
      }
      targetL += 8;                                              // next targetL
 
      /* copy data */
      for(i = 0; i < dataLength; i += 2) {
        value = (*(__IO uint16_t*)(sourceBase + dataOffset + i));
        status = FLASH_ProgramHalfWord(targetH + i, value);
        if(status != FLASH_COMPLETE) return status;
      }
 
      /* write data begin flag (0xCCCC) */
      targetH = targetH - 2;                                     // next targetH
      status = FLASH_ProgramHalfWord(targetH, DATA_FLAG);
      if(status != FLASH_COMPLETE) return status;
    }
    else if(value != EXPIRED_BLOCK) { // end of block area
      break;
    }
    address += 8; // next source block
  }
 
  /* mark targer page as valid */
  status = FLASH_ProgramHalfWord(targetBase, VALID_PAGE);
  if(status != FLASH_COMPLETE) return status;
 
  /* erase source page */
  status = FLASH_ErasePage(sourceBase);
  return status;
}
 
/**
 * Function EE_CheckData
 * TODO: Verify data by calculating the checksum.
 */
static uint16_t EE_CheckData(void) {
  return FLASH_COMPLETE;
}
 
/**
 * Extensions
 */
uint16_t memcpy_to_eeprom_with_checksum(uint8_t key, const void *pdata, uint16_t size) {
  return EE_WriteData(key, (uint8_t*)pdata, size);
}
 
uint16_t memcpy_from_eeprom_with_checksum(void *pdata, uint8_t key, uint16_t size) {
  return EE_ReadData(key, (uint8_t*)pdata, size);
}
 
關閉窗口

相關文章

亚洲成人av网址| 日韩一区二区三区中文字幕| 国产喷水在线观看| 国产精品视频一二三四区| 中文字幕亚洲在| 午夜久久美女| 免费一级欧美在线大片| 国产高清视频在线| 自拍一级黄色片| 日本不卡二区| 欧美俄罗斯性视频| 91精品国产高清一区二区三区 | 久久国产精品久久久久久| 色综合久久久久久久久久久| av在线播放成人| 国产亚洲一级| 嫩草香蕉在线91一二三区| 人人爱人人爽| 亚洲av永久无码国产精品久久| 亚洲毛片亚洲毛片亚洲毛片| 午夜激情av在线| 加勒比海盗1在线观看免费国语版| 成人a在线观看| 久久国产精品久久久久久久久久| 精品久久国产字幕高潮| 欧美日韩国产综合新一区| 国产午夜精品在线观看| 久久丁香综合五月国产三级网站 | 亚洲av无一区二区三区久久| 国产aaa免费视频| 久久久久久久久久码影片| 亚洲成年人在线| 不卡视频在线看| aa级大片欧美三级| 成人羞羞视频在线看网址| 黑人一区二区三区| 调教一区二区| 在线免费观看电影网站入口| 精品久久久久中文慕人妻| 五月婷婷开心网| 中文字幕永久视频| 青青草综合视频| 日韩av电影免费在线| 亚洲一区二区在线| 国产精品久久久久久久久久小说| 欧美激情xxxxx| xxx欧美精品| 在线播放日韩欧美| 亚洲亚裔videos黑人hd| 亚洲最色的网站| 久久久久久久网| 国产精品一区二区视频| 久久成人久久鬼色| 日韩精品1区2区3区| 亚洲日本国产| 深夜福利网址| 亚洲wwwwww| 中文字幕av免费在线观看| 9.1成人看片免费版| www.17c.com喷水少妇| 一二三av在线| 激情久久综合网| 特级黄色片视频| 日本人dh亚洲人ⅹxx| 亚洲 自拍 另类 欧美 丝袜| 日本黄大片一区二区三区| 中文字幕第80页| 午夜肉伦伦影院| 国产成人a亚洲精v品无码| 成人性生交大片免费看视频直播 | 九色成人搞黄网站| 亚洲淫成人影院| ga∨成人网| 777.av| 男女免费网站| 国产一级粉嫩xxxx| 亚洲小说区图片区情欲小说| 国产黄色在线看| 欧美虐宫另类残忍视频| 国产又猛又粗| a级片在线播放| 亚洲精品国产精品国| 性欧美18一19性猛交| 国模无码一区二区三区| 午夜小视频免费| 日韩亚洲一区中文字幕| 国产精品自产拍在线观看2019| 国产69精品久久久久9999小说| 免费在线观看h| 国产男小鲜肉同志免费| 在线视频中文字幕| 国产裸舞福利在线视频合集| 国产福利在线播放麻豆| 极品av在线| 国产精品视频一区二区三区| 国内露脸中年夫妇交换精品| 99久久久久| 国产精品日韩| 国产精品主播直播| 久久嫩草精品久久久精品| 自拍视频在线观看一区二区| 午夜不卡在线视频| 日韩一区和二区| 中文字幕视频一区二区在线有码| 久久久久久久久久久91| 91亚洲国产精品| 亚洲精品日韩在线观看| 久久久久久久久久福利| 先锋资源av在线| 婷婷色中文字幕| 亚洲在线精品视频| 亚洲激情欧美色图| 中文字幕免费中文| xfplay每日更新av资源在线| 成人做爰视频网站| 国产一级片免费视频| 色婷婷av一区二区三区之红樱桃| 国产成人精品免费视频大全软件| av网站观看| 麻豆系列在线观看| 日韩国产一二三区| 97精品视频在线看| 欧美韩国日本在线观看| 亚洲一区日本| 99视频超级精品| 精品福利在线观看| 亚洲男人的天堂网站| 热久久免费国产视频| 美女一区视频| 秋霞毛片久久久久久久久| 岛国大片在线播放| 国产福利在线观看视频| av大片在线免费观看| 中文字幕在线观看av| www中文字幕| 国产浴室偷窥在线播放| 调教在线观看| 牛牛影视精品影视| 国产成人精品一区二区三区免费| 精品亚洲成人| 国产精品18久久久久久久久 | 四虎成人免费观看在线网址| 日韩欧美亚洲一区| 伊人色综合一区二区三区影院视频| 精品一区毛片| 国产精品18久久久久久久久久久久 | 欧洲精品99毛片免费高清观看| 视频一区日韩精品| 亚洲人人精品| 最新中文字幕一区二区三区 | 伊人网在线免费| 中文字幕在线视频播放| 奴色虐av一区二区三区| 天堂网www在线观看| 国产成人l区| 国产三级av在线| 正在播放日韩精品| 欧美成人tv| 国产精品久久国产精麻豆99网站| 亚洲国产一区自拍| 亚洲xxxxx电影| 国产小视频精品| 一区二区三区福利视频| 国产免费一区二区三区免费视频| 女生裸体免费视频| bbw在线视频| 欧美三区不卡| 亚洲视频在线一区| 日韩在线免费视频观看| 日韩欧美电影一区二区| 丝袜美腿中文字幕| 免费国产羞羞网站视频| 污视频免费在线看| 欧亚精品一区| 久久综合九色综合欧美98| 日韩av网站电影| 久久精品午夜一区二区福利| 国产精品无码一区二区三| 亚洲第一视频在线播放| 色视频在线看| 欧美丝袜一区| 国产精品美女久久久久久久| 在线观看欧美www| 日韩欧美三级电影| 成人18视频免费69| 国产精品自产拍在线观看2019| av手机免费在线观看| 首页亚洲欧美制服丝腿| 日本高清无吗v一区| 国产精品免费电影| 亚洲 国产 日韩 综合一区| 波多野结衣先锋影音| 午夜性色福利视频| 羞羞的视频在线观看| 亚洲三级视频| 在线免费不卡视频| 久久久久久久久国产| 久久久久久www| 激情视频网站在线观看| 真不卡电影网| 成人短片线上看| 夜夜嗨av一区二区三区四季av| 4438全国成人免费| √天堂资源在线| 在线观看亚洲电影| 日本xxxx高清色视频| jizz18欧美18| 国产日韩高清在线| 97精品在线视频| 国产又爽又黄ai换脸| 国产主播在线播放| 日本福利视频| 欧美日韩黑人| 婷婷综合五月天| 亚洲一区二区久久久久久| 北岛玲一区二区| 一级黄色免费| 99精品国产一区二区三区2021| 国产欧美一区二区精品性| 亚洲欧洲午夜| 欧美性开放视频| 99porn视频在线| 亚洲国产精品一区二区久久hs| 天天色av.com| 变态调教一区二区三区| 日韩电影免费网站| 亚洲成人精品影院| 91色精品视频在线| 天美传媒免费在线观看| 先锋av在线资源| 精品午夜久久| 欧美精品九九99久久| 日韩欧美视频一区二区| 无码人妻一区二区三区免费| av资源网在线观看| 欧美疯狂party性派对| 欧美在线综合视频| 亚洲v欧美v另类v综合v日韩v| 97人人澡人人爽人人模亚洲| 超碰在线91| 99精品国产一区二区三区2021 | 在线观看不卡| 精品成人一区二区三区四区| 亚洲精品天堂成人片av在线播放| 国产精品人人爽| 校园春色亚洲| 国产欧美一区在线| 成人免费激情视频| 加勒比婷婷色综合久久| 国产麻豆免费| 老牛精品亚洲成av人片| 午夜影院久久久| 日韩三级电影网站| 国产婷婷一区二区三区久久| 免费看av不卡| 一区视频在线播放| 国产日韩二区| 中国一级特黄视频| 成人线上视频| 亚洲精品免费播放| 欧美日韩综合久久| 一卡二卡在线视频| 成人看片网页| 亚洲一区二区欧美日韩| 国产精品日日摸夜夜添夜夜av| 懂色av蜜臀av粉嫩av永久| 经典三级在线| 国产精品18久久久久久久久 | 亚洲国产综合在线观看| 一区二区三区四区av| 欧美极品色图| wwwav网站| 国产精品久久久久av蜜臀| 精品视频1区2区| 成人小视频在线看| 黄色的毛片免费| 一本久道久久综合狠狠爱| 不卡av在线网站| 中文字幕精品一区二区三区在线| 狠狠色henhense| 亚洲啪啪91| 欧美激情视频给我| 少妇人妻丰满做爰xxx| av小次郎在线| 亚洲特黄一级片| 亚洲欧美日产图| 亚洲av无一区二区三区久久| 国产jizz| 国产精品一区二区男女羞羞无遮挡| 国产精品第七十二页| 国产一级免费视频| 先锋影音网一区二区| 欧洲一区二区av| 国产一二三区av| 国产香蕉视频在线观看| 国产91丝袜在线播放| 91探花福利精品国产自产在线| 在线免费观看高清视频| 日韩在线亚洲| 精品福利在线导航| a天堂视频在线观看| 在线视频婷婷| 最新热久久免费视频| 免费极品av一视觉盛宴| 美女翘臀白浆直流视频| 精品日产免费二区日产免费二区| 日韩av在线看| 亚洲成人网在线播放| 国产日产一区二区三区| 洋洋成人永久网站入口| 春日野结衣av| 91网页在线看| 久久久久99精品一区| 日韩免费中文专区| 天堂免费视频| 美女视频黄免费的久久| 99国产精品久久久久老师| 午夜黄色小视频| 国产精品分类| 国产精品极品尤物在线观看 | 欧美成人a∨高清免费观看| 亚洲自拍偷拍精品| 久久bbxx| 色狠狠色噜噜噜综合网| 天天干天天色天天干| 国产福利电影在线| 亚洲一区二区不卡免费| 国产三级日本三级在线播放| 在线看的网站你懂| 亚洲女人的天堂| 欧美两根一起进3p做受视频| 秋霞福利视频| 国产精品传媒在线| 人妻有码中文字幕| 国产私拍精品| 精品欧美激情精品一区| 久草福利在线观看| 丁香影院在线| 日韩欧美自拍偷拍| 国产高清视频免费在线观看| 777午夜精品电影免费看| 日韩精品在线影院| 伊人365影院| 精品人人人人| 久久久这里只有精品视频| 国产a级免费视频| 欧美+日本+国产+在线a∨观看| 国产精品久久久久久久电影| 亚洲色图偷窥| 毛片不卡一区二区| 日韩av电影免费在线| 国产性一级片| 亚洲精品老司机| xxxx国产视频| 亚洲精品福利电影| 亚洲日本中文字幕| 精品国产青草久久久久96| 欧美特黄一级| 精品久久久久久中文字幕动漫| 狠狠擦狠狠操| 中文字幕在线一区免费| 中文字幕12页| 成人性教育av免费网址| 国产亚洲a∨片在线观看| 经典三级在线视频| 天堂视频福利| 精品国产乱码久久久久酒店| 国产老熟女伦老熟妇露脸| 日本一区二区三区中文字幕| 日韩最新免费不卡| 亚洲AV无码精品自拍| 久久激五月天综合精品| 国产视频在线观看网站| 美女国产在线| 日韩精品极品毛片系列视频| 成人毛片一区二区三区| 亚洲国产1区| 亚洲一区二区三区在线观看视频| 中文字幕一区免费| 欧美巨大另类极品videosbest| 欧美国产日韩综合| 亚洲色图欧美| 欧美亚洲免费高清在线观看 | 天堂在线资源库| 激情综合网天天干| 久久国产亚洲精品无码| 国产www视频在线观看| 在线视频一区二区| 香港三日本三级少妇66| 成人午夜在线免费| 亚洲免费黄色录像| 在线成人免费| 日韩电影中文字幕一区| 懂色av蜜臀av粉嫩av喷吹| 亚洲一级在线| 国产精品久久久久久久乖乖| 日本色护士高潮视频在线观看| 国产一区二区三区免费视频| 婷婷在线免费观看| 26uuu另类欧美亚洲曰本|