青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 60, 文章 - 0, 評論 - 197, 引用 - 0
數(shù)據(jù)加載中……

學習 ARM 系列 -- FS2410 開發(fā)板上通過串口實現(xiàn) printf

一、目的
   到目前為止我們所編寫的程序都是直接燒到裸板(FS2410)上運行,沒有借助操作系統(tǒng),
如果哪個環(huán)節(jié)出錯了,就只能揣測代碼的邏輯,無法借助 GDB 調(diào)試,這無形增加了編寫代
碼的難度,如果任意時刻我們能把某個變量的值打印出來多好啊...呵呵, 你也許有同樣的
困惑,上一個實驗我們對 UART 串口編程實現(xiàn)了對超級終端接收和發(fā)送數(shù)據(jù),也許我們可以
編寫一個類似 C 語言里的 printf,作用就是向上位機的超級終端發(fā)送我們指定的任何數(shù)據(jù)。
懷著這樣美好的愿望,隨我一起踏上征程吧。


二、代碼
   很多代碼是在前面幾個實驗的基礎上進行整理復用之,更多細節(jié)請參考前面隨筆,這里
僅附簡略注解。
  
   @ 文件 head.s
   @ 作用:關閉看門狗、SDRAM 的初始化設置、搬移 Nand Flash 4K 以后
   @ 的代碼到 SDRAM 的指定位置、執(zhí)行 SDRAM 中的代碼
   .text
   .global _start
   _start:
    ldr r0, =0x53000000 @ Close Watch Dog Timer
    mov r1, #0x0
    str r1, [r0]
  
    bl  memory_setup @ Initialize memory setting
    bl  flash_to_sdram @ Copy code to sdram
    
        ldr sp, =0x34000000 @ Set stack pointer
    ldr pc, =main           @ execute the code in SDRAM


   @ 文件 mem.s
   @ 作用:SDRAM 的初始化設置
   @ 關于初始化的更多細節(jié),請參考我前面的隨筆
   .global memory_setup
   memory_setup:
    mov  r1, #0x48000000
    adrl r2, mem_cfg_val
    add  r3, r1, #13*4
   1: 
    @ write initial values to registers
    ldr  r4, [r2], #4
    str  r4, [r1], #4
    cmp  r1, r3
    bne  1b
    mov  pc, lr
    
    .align 4
   mem_cfg_val:
    .long 0x22111110 @ BWSCON
    .long 0x00000700 @ BANKCON0
    .long 0x00000700 @ BANKCON1
    .long 0x00000700 @ BANKCON2
    .long 0x00000700 @ BANKCON3
    .long 0x00000700 @ BANKCON4
    .long 0x00000700 @ BANKCON5
    .long 0x00018005 @ BANKCON6
    .long 0x00018005 @ BANKCON7 9bit
    .long 0x008e07a3 @ REFRESH
    .long 0x000000b2 @ BANKSIZE
    .long 0x00000030 @ MRSRB6
    .long 0x00000030 @ MRSRB7


   @ 文件 flash.s
   @ 作用:設置 Nand Flash 的控制寄存器、讀取 Nand Flash
   @ 中的代碼到 SDRAM 的指定位置,更多細節(jié)請參考我前面的隨筆
   .equ NFCONF, 0x4e000000
   .equ NFCMD,  0x4e000004
   .equ NFADDR, 0x4e000008
   .equ NFDATA, 0x4e00000c
   .equ NFSTAT, 0x4e000010
   .equ NFECC,  0x4e000014
   .global flash_to_sdram
   flash_to_sdram:
        @ Save return addr
        mov r10,lr
    
        @ Initialize Nand Flash
        mov r0,#NFCONF
        ldr r1,=0xf830
        str r1,[r0]
   
        @ First reset and enable Nand Flash
        ldr r1,[r0]
        bic r1, r1, #0x800
        str r1,[r0]
   
        ldr r2,=NFCMD
        mov r3,#0xff
        str r3,[r2]
    
        @ for delay
        mov r3, #0x0a
   1:
        subs r3, r3, #1
        bne 1b
  
   @ Wait until Nand Flash bit0 is 1
   wait_nfstat:
        ldr r2,=NFSTAT
        ldr r3,[r2]
        tst r3,#0x01
        beq wait_nfstat
          
    @ Disable Nand Flash
    ldr r0,=NFCONF
    ldr r1,[r0]
    orr r1,r1,#0x8000
    str r1,[r0]
   
    @ Initialzie stack
    ldr sp,=4096
  
    @ Set arguments and call 
    @ function nand_read defined in nand_read.c
    ldr r0,=0x30000000
    mov r1,#0
    mov r2,#1024*40
    bl nand_read
   
    @ return
    mov pc,r10


   /* 文件 nand_read.c
    * 作用:從 Nand Flash 中讀取一塊數(shù)據(jù)到 SDRAM 中的指定位置
    */
   #define NFCONF (*(volatile unsigned long *)0x4e000000)
   #define NFCMD  (*(volatile unsigned long *)0x4e000004)
   #define NFADDR (*(volatile unsigned long *)0x4e000008)
   #define NFDATA (*(volatile unsigned long *)0x4e00000c)
   #define NFSTAT (*(volatile unsigned long *)0x4e000010)
   #define NFECC  (*(volatile unsigned long *)0x4e000014)
  
   #define NAND_SECTOR_SIZE 512
   #define NAND_BLOCK_MASK  0x1ff
  
   void wait_idle() {
     int i;
     for (i = 0; i < 50000; ++i) ;
   }
  
   int nand_read(unsigned char *buf, unsigned long start_addr, int size){
     int i, j;
     /*
      * detect the argument
      */ 
     if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
       return -1;    
     }
   
     /* chip Enable */
     NFCONF &= ~0x800;
     for (i=0; i<10; i++) {
       ;
     }
   
     for (i=start_addr; i < (start_addr + size); i+=NAND_SECTOR_SIZE) {
       NFCMD = 0;
   
       /* Write Address */
       NFADDR = i & 0xff;
       NFADDR = (i >> 9)  & 0xff;
       NFADDR = (i >> 17) & 0xff;
       NFADDR = (i >> 25) & 0xff;
   
       wait_idle();
   
       for(j=0; j < NAND_SECTOR_SIZE; j++) {
         *buf++ = (NFDATA & 0xff);
       }
     }
   
     NFCONF |= 0x800;    /* chip disable */
     return 0;
   }


   /* 頭文件 serl.h
    * 作用:定義相關寄存器、UART 初始化函數(shù)聲明、串口讀寫函數(shù)的聲明
    */  
   #ifndef __SERL_H__
   #define __SERL_H__
  
   #define GPHCON  (*(volatile unsigned long *)0x56000070)
  
   /* PORT PULL-UP REGISTER*/
   #define GPHUP   (*(volatile unsigned long *)0x56000078)
  
   /* UART FIFO control register 0*/
   #define UFCON0  (*(volatile unsigned long *)0x50000008)
  
   /* UART line control register 0*/
   #define ULCON0  (*(volatile unsigned long *)0x50000000)
  
   /* UART CONTROL REGISTER 0*/
   #define UCON0   (*(volatile unsigned long *)0x50000004)
  
   /* UART modem control register 0*/
   #define UMCON0  (*(volatile unsigned long *)0x5000000C)
  
   /* UART baud rate divisor register 0*/
   #define UBRDIV0 (*(volatile unsigned long *)0x50000028)
  
   /* UART TX/RX STATUS REGISTER 0*/
   #define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
  
  
   #define UTXH0 (*(volatile unsigned char *)0x50000020)
   #define URXH0 (*(volatile unsigned char *)0x50000024)
  
  
   #define TXD0_READY 0x2
   #define RXD0_READY 0x1
  
   void init_uart();
   unsigned char uart_getc();
   void uart_putc(unsigned char ch);
   void uart_puts(unsigned char* src);
  
   #endif


   /* 文件 serl.c*/
   #include "serl.h"
  
   void init_uart() {
     GPHCON |= 0xa0; /* GPH2, GPH3 used as RXD0, TXD0*/
     GPHUP = 0x0c;   /* GPH2, GPH3 poll-up */
  
     ULCON0 = 0x03;  /* normal mode, no parity, one stop bit, 8-bit*/
     UCON0 = 0x05;   /* Loopback mode*/
     UFCON0 = 0x00;  /* not use FIFO*/
     UMCON0 = 0x00;  /* disable flow control*/
     UBRDIV0 = 12;   /* baud rate 57600*/
   }
  
   void uart_putc(unsigned char ch) {
     while (!(UTRSTAT0 & TXD0_READY));
     UTXH0 = ch;
   }
  
   unsigned char uart_getc(){
     while (! (UTRSTAT0 & RXD0_READY));
     return URXH0;
   }
  
   void uart_puts(unsigned char* src) {
     unsigned char *p = src;
     while (*p != '\0') {
       if (*p == 0x0a)
         uart_putc(0x0d);
       uart_putc(*p);
       p++;
     }
   }
  

   /*
    * 頭文件 printf.h
    * 作用:對外提供調(diào)用接口 uart_printf
    */  
   #ifndef __PRINTF_HH__
   #define __PRINTF_HH__
  
   void uart_printf(char *fmt, ...);
  
   #endif

  
   /*
    * 文件 printf.c
    * 文件中大部分代碼來自 linux 0.11 內(nèi)核的 vsprintf.c, 只是作了相應的刪減,
    * <<Linux 內(nèi)核完全注釋>> 上有更詳細的解釋
    */
   #include <stdarg.h>
   #include <linux/types.h>
   #include <linux/ctype.h>
   #include "printf.h"
   #include "serl.h"
  
   #define ZEROPAD  1    /* pad with zero */
   #define SIGN           2    /* unsigned/signed long */
   #define PLUS           4    /* show plus */
   #define SPACE        8    /* space if plus */
   #define LEFT           16   /* left justified */
   #define SPECIAL     32  /* 0x */
   #define LARGE        64  /* use 'ABCDEF' instead of 'abcdef' */
  
   #define is_digit(c) ((c) >= '0' && (c) <= '9')

   #define do_div(n,base) ({    \
         int __res;     \
         __res = ((unsigned long) n) % (unsigned) base; \
         n = ((unsigned long) n) / (unsigned) base; \
         __res; })
  
   static unsigned char sprint_buf[1024];
  
   int strnlen(const char * s, int count)
   {
     const char *sc;
  
     for (sc = s; count-- && *sc != '\0'; ++sc)
       /* nothing */;
     return sc - s;
   }
  
   unsigned char _ctype[] = {
     _C,_C,_C,_C,_C,_C,_C,_C,   /* 0-7 */
     _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
     _C,_C,_C,_C,_C,_C,_C,_C,   /* 16-23 */
     _C,_C,_C,_C,_C,_C,_C,_C,   /* 24-31 */
     _S|_SP,_P,_P,_P,_P,_P,_P,_P,  /* 32-39 */
     _P,_P,_P,_P,_P,_P,_P,_P,   /* 40-47 */
     _D,_D,_D,_D,_D,_D,_D,_D,   /* 48-55 */
     _D,_D,_P,_P,_P,_P,_P,_P,   /* 56-63 */
     _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
     _U,_U,_U,_U,_U,_U,_U,_U,   /* 72-79 */
     _U,_U,_U,_U,_U,_U,_U,_U,   /* 80-87 */
     _U,_U,_U,_P,_P,_P,_P,_P,   /* 88-95 */
     _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
     _L,_L,_L,_L,_L,_L,_L,_L,   /* 104-111 */
     _L,_L,_L,_L,_L,_L,_L,_L,   /* 112-119 */
     _L,_L,_L,_P,_P,_P,_P,_C,   /* 120-127 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 128-143 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 144-159 */
     _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
     _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
     _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
     _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
     _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
     _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
  
   static int skip_atoi(const char **s)
   {
     int i=0;
  
     while (is_digit(**s))
       i = i*10 + *((*s)++) - '0';
     return i;
   }
  
   static char * number(char * str, long num, int base, int size, int precision
          ,int type)
   {
     char c,sign,tmp[66];
     const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
     int i;
  
     if (type & LARGE)
       digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     if (type & LEFT)
       type &= ~ZEROPAD;
     if (base < 2 || base > 36)
       return 0;
     c = (type & ZEROPAD) ? '0' : ' ';
     sign = 0;
     if (type & SIGN) {
       if (num < 0) {
         sign = '-';
         num = -num;
         size--;
       } else if (type & PLUS) {
         sign = '+';
         size--;
       } else if (type & SPACE) {
         sign = ' ';
         size--;
       }
     }
     if (type & SPECIAL) {
       if (base == 16)
         size -= 2;
       else if (base == 8)
         size--;
     }
     i = 0;
     if (num == 0)
       tmp[i++]='0';
     else while (num != 0)
     tmp[i++] = digits[do_div(num,base)];
     if (i > precision)
       precision = i;
     size -= precision;
     if (!(type&(ZEROPAD+LEFT)))
       while(size-->0)
         *str++ = ' ';
     if (sign)
       *str++ = sign;
     if (type & SPECIAL) {
       if (base==8)
         *str++ = '0';
       else if (base==16) {
         *str++ = '0';
         *str++ = digits[33];
       }
     }
     if (!(type & LEFT))
       while (size-- > 0)
         *str++ = c;
     while (i < precision--)
       *str++ = '0';
     while (i-- > 0)
       *str++ = tmp[i];
     while (size-- > 0)
       *str++ = ' ';
     return str;
   }
  
   int __vsprintf(char *buf, const char *fmt, va_list args)
   {
     int len;
     unsigned long num;
     int i, base;
     char * str;
     const char *s;
  
     int flags;  /* flags to number() */
  
     int field_width; /* width of output field */
     int precision;    /* min. # of digits for integers; max number of chars for from string */
     int qualifier;      /* 'h', 'l', or 'L' for integer fields */
  
     for (str=buf ; *fmt ; ++fmt) {
       if (*fmt != '%') {
         *str++ = *fmt;
         continue;
       }
      
       /* process flags */
       flags = 0;
     repeat:
       ++fmt;  /* this also skips first '%' */
       switch (*fmt) {
         case '-': flags |= LEFT; goto repeat;
         case '+': flags |= PLUS; goto repeat;
         case ' ': flags |= SPACE; goto repeat;
         case '#': flags |= SPECIAL; goto repeat;
         case '0': flags |= ZEROPAD; goto repeat;
       }
     
       /* get field width */
       field_width = -1;
       if (is_digit(*fmt))
         field_width = skip_atoi(&fmt);
       else if (*fmt == '*') {
         ++fmt;
         /* it's the next argument */
         field_width = va_arg(args, int);
         if (field_width < 0) {
           field_width = -field_width;
           flags |= LEFT;
         }
       }
  
       /* get the precision */
       precision = -1;
       if (*fmt == '.') {
         ++fmt; 
         if (is_digit(*fmt))
           precision = skip_atoi(&fmt);
         else if (*fmt == '*') {
           ++fmt;
           /* it's the next argument */
           precision = va_arg(args, int);
         }
         if (precision < 0)
           precision = 0;
       }
  
       /* get the conversion qualifier */
       qualifier = -1;
       if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
         qualifier = *fmt;
         ++fmt;
       }
  
       /* default base */
       base = 10;
  
       switch (*fmt) {
       case 'c':
         if (!(flags & LEFT))
           while (--field_width > 0)
               *str++ = ' ';
         *str++ = (unsigned char) va_arg(args, int);
         while (--field_width > 0)
           *str++ = ' ';
         continue;
  
       case 's':
         s = va_arg(args, char *);
         if (!s)
           s = "<NULL>";
  
         len = strnlen(s, precision);
  
         if (!(flags & LEFT))
           while (len < field_width--)
             *str++ = ' ';
         for (i = 0; i < len; ++i)
          *str++ = *s++;
         while (len < field_width--)
           *str++ = ' ';
         continue;
  
       case 'p':
         if (field_width == -1) {
           field_width = 2*sizeof(void *);
           flags |= ZEROPAD;
         }
         str = number(str,
        (unsigned long) va_arg(args, void *), 16, field_width, precision, flags);
         continue;
  
  
       case 'n':
         if (qualifier == 'l') {
           long * ip = va_arg(args, long *);
           *ip = (str - buf);
         } else {
             int * ip = va_arg(args, int *);
             *ip = (str - buf);
         }
         continue;
  
         /* integer number formats - set up the flags and "break" */
       case 'o':
         base = 8;
         break;
  
       case 'X':
         flags |= LARGE;
       case 'x':
         base = 16;
         break;
  
       case 'd':
       case 'i':
         flags |= SIGN;
       case 'u':
         break;
  
       default:
         if (*fmt != '%')
           *str++ = '%';
         if (*fmt)
           *str++ = *fmt;
         else
           --fmt;
         continue;
       }
       if (qualifier == 'l')
         num = va_arg(args, unsigned long);
       else if (qualifier == 'h') {
         num = (unsigned short) va_arg(args, int);
         if (flags & SIGN)
    num = (short) num;
       } else if (flags & SIGN)
         num = va_arg(args, int);
       else
         num = va_arg(args, unsigned int);
       str = number(str, num, base, field_width, precision, flags);
     }
     *str = '\0';
     return str-buf;
   }
  
   /* 這就我們的 printf, 注意我們將參數(shù)輸出到串口 UART0,而非標準輸出*/
   void uart_printf(char *fmt, ...)
   {
     va_list args;
  
     va_start(args, fmt);
     __vsprintf(sprint_buf, fmt,args);
     va_end(args);
  
     /* 將緩沖區(qū)的字符輸出到串口*/
     uart_puts(sprint_buf);
   }
  

   /*
    * 文件 main.c
    * 作用:測試代碼
    */
   #include "serl.h"
   #include "printf.h"
  
   #define GPFCON (*(volatile unsigned long *)0x56000050)
   #define GPFDAT (*(volatile unsigned long *)0x56000054)
  
   int main()
   {
     int a = 10;
     init_uart();

     /*
      * 調(diào)用我們自己的 uart_printf,將數(shù)據(jù)輸出到串口,稍后你將
      * 在超級終端上看到顯示結果。之所以不叫 printf 是為了不與
      * arm-linux-gcc 的庫函數(shù) printf 相沖突
      */
     uart_printf("Hello,Embeded!\n");
     uart_printf("%d\n",a);

     return 0;
   }
  

   最后要說的是 Makefile,這個Makefile 在前面 Makefile的基礎上作了很大的改進,
它不需要你再指定源文件,而是在當前目錄下讀取擴展名為 .s 和 .c 的文件作為輸入文件,
你只需指定最終要生成的可執(zhí)行文件即可,只是它還是不太完美, 你還要指定它依賴的目標文
件,因為 head.o mem.o flash.o nand_read.o 這些文件被連接生成可執(zhí)行文件后它
們的代碼必須位于前 4K, 這樣才能保證它們自動被 ARM 加載,從而設置堆棧、初始化內(nèi)存、
讀取 Nand Flash 的代碼完成自身到 SDRAM 的 self-copying。將來我們會用連接腳本
來解決這個問題。

   # Makefile for compiling ARM program
   # Author: Jianbin Wang
  
   CC=arm-linux-gcc
   CFLAGS=-Wall -g -c
   LD=arm-linux-ld
   LDFLAGS:=$(LDFLAGS) -Ttext 0x30000000
  
   INCLUDES=-I./
   CFLAGS:=$(CFLAGS) $(INCLUDES)
   LIBS=-lgcc -L/usr/local/arm/3.3.2/lib/gcc-lib/arm-linux/3.3.2
  
   CONVERT=arm-linux-objcopy
   CVFLAGS=-O binary -S
   RM=rm -f
  
   SRCDIRS=.
   TARGET=main
   TMPOBJ=$(TARGET)_tmp.o
   SRCS=$(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c $(dir)/*.s))
   OBJS=head.o mem.o flash.o nand_read.o main.o printf.o serl.o
  
   all:$(TARGET)
  
   $(TARGET):$(OBJS)
    $(LD) $(LDFLAGS) -o $(TMPOBJ) $(OBJS) $(LIBS)
    $(CONVERT) $(CVFLAGS) $(TMPOBJ) $(TARGET)
  
   $(OBJS):$(SRCS)
    $(CC) $(CFLAGS) $(SRCS)
  
   clean:
    $(RM) $(TARGET)
    $(RM) $(TMPOBJ)
    $(RM) $(OBJS)  


三、編譯、燒寫、測試
   Make 一下就會生成我們要的文件 main, 將其通過 JTAG 燒入 Nand Flash。用超級終
連接到開發(fā)板,注意波特率設為 57600,數(shù)據(jù)位 8,無奇偶校正,停止位1,無數(shù)據(jù)流控制。現(xiàn)
在 Reset 一下的開發(fā)板,然后靜靜的等待吧,生成的二進制文件 main 有 39K 大呢,要等它
完全復制到 SDRAM 至少要兩三分鐘...之后,在超級終端上是不是出現(xiàn)了字符串:

     Hello,Embeded!
     10

呵呵,至此我們的愿望變現(xiàn)實,是不是很不可思議 :-)

posted on 2008-01-17 15:53 Normandy 閱讀(3626) 評論(1)  編輯 收藏 引用 所屬分類: Embeded Area

評論

# re: 學習 ARM 系列 -- FS2410 開發(fā)板上通過串口實現(xiàn) printf  回復  更多評論   

樓主實在是太棒了!
2008-01-17 16:01 | free
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            午夜一区不卡| 欧美日韩国产成人在线观看| 亚洲韩国青草视频| 欧美大色视频| 亚洲视频成人| 欧美成人性生活| 性久久久久久久| 亚洲第一网站| 国产精品高潮粉嫩av| 久久精品一区二区| 夜夜嗨av一区二区三区网页| 久久久久久穴| 亚洲永久免费观看| 亚洲国产岛国毛片在线| 国产欧美一区二区三区沐欲| 一区二区激情视频| 欧美成年网站| 久久精品一区二区三区不卡牛牛| 99日韩精品| 亚洲人成亚洲人成在线观看图片| 黄色成人在线| 国产欧美日韩一区二区三区| 亚洲欧美日韩人成在线播放| 免费久久99精品国产自在现线| 亚洲欧美日本在线| 亚洲精品欧美激情| 亚洲人成在线播放| 亚洲福利专区| 亚洲福利视频免费观看| 精品成人在线观看| 1000精品久久久久久久久| 欧美精品18videos性欧美| 在线亚洲高清视频| 99热在这里有精品免费| 亚洲国产日韩一级| 有码中文亚洲精品| 黄色精品在线看| 亚洲第一偷拍| 亚洲精华国产欧美| 亚洲精品美女91| 亚洲欧洲美洲综合色网| 国产日韩免费| 国产一区美女| 韩国一区电影| 亚洲风情在线资源站| 在线视频国产日韩| 亚洲人成亚洲人成在线观看图片| 亚洲国产乱码最新视频| 亚洲精品一区久久久久久| 欧美无乱码久久久免费午夜一区 | 欧美一区久久| 亚洲一二区在线| 亚洲调教视频在线观看| 日韩午夜电影av| 亚洲视频一区二区免费在线观看| 亚洲欧美不卡| 欧美成人a视频| 99riav久久精品riav| 中日韩美女免费视频网址在线观看| 亚洲一区久久久| 亚洲激情av| 亚洲黄页一区| 亚洲欧美日韩一区在线| 久久久国产精品一区二区中文| 欧美+日本+国产+在线a∨观看| 欧美黄色片免费观看| 国产精品视频免费观看| 尤物在线精品| 久久国产加勒比精品无码| 欧美国产精品一区| 亚洲免费观看高清在线观看 | 国内外成人免费激情在线视频网站 | 美女精品在线| 欧美高清视频一区二区| 亚洲黄色在线观看| 亚洲一区二区黄色| 毛片一区二区三区| 欧美激情亚洲激情| 久久亚洲精品视频| 久久久人成影片一区二区三区观看 | 欧美一区二区久久久| 老色批av在线精品| 国产精品乱码一区二三区小蝌蚪| 欧美福利一区二区| 欧美精品v日韩精品v国产精品 | 欧美福利一区二区| 国产综合视频在线观看| 亚洲视频精品在线| 免费人成精品欧美精品| 亚洲专区一区| 欧美视频免费在线| 好看的av在线不卡观看| 亚洲免费伊人电影在线观看av| 美女精品在线| 久久精品国产综合精品| 国产精品美女久久久久久免费| 亚洲激情国产| 欧美电影在线观看完整版| 猛干欧美女孩| 久久国产婷婷国产香蕉| 国产精品国产三级国产aⅴ入口| 亚洲电影毛片| 久久久五月天| 欧美激情视频给我| 欧美一区二区精美| 国语自产在线不卡| 久久蜜臀精品av| 亚洲欧美日韩精品久久奇米色影视| 欧美日韩精品免费观看视一区二区 | 亚洲一区三区视频在线观看| 欧美在线精品免播放器视频| 亚洲国产欧美日韩精品| 99精品热6080yy久久| 韩国福利一区| 99成人免费视频| 1000部国产精品成人观看| 午夜久久久久久| 亚洲一级免费视频| 久久精品一区二区国产| 午夜精品久久| 欧美日韩午夜在线| 欧美黑人国产人伦爽爽爽| 国产一区二区三区久久久久久久久 | 免费不卡视频| 国产欧美日韩伦理| 日韩视频免费| 9色国产精品| 欧美成ee人免费视频| 美女精品视频一区| 激情久久五月| 久久精品噜噜噜成人av农村| 午夜精品久久久久久久久久久| 欧美日本韩国一区二区三区| 亚洲承认在线| 1769国产精品| 嫩草影视亚洲| 亚洲日本中文字幕| 一道本一区二区| 欧美日韩八区| 久久精品视频导航| 欧美日韩综合| 99视频精品免费观看| 日韩一级免费| 国产精品chinese| 中文久久精品| 欧美一区日韩一区| 国产一区99| 久久美女性网| 女人香蕉久久**毛片精品| 亚洲国产精品女人久久久| 久久综合一区二区| 欧美不卡一区| 99国产精品一区| 国产精品久久精品日日| 午夜伦欧美伦电影理论片| 久久精品国产一区二区电影 | 国产伦精品一区二区三区免费| 制服诱惑一区二区| 久久av一区二区| 国产日韩欧美不卡在线| 久久在线播放| 亚洲福利电影| 亚洲一区二区三区久久| 国产欧美三级| 欧美成人精品高清在线播放| 欧美va亚洲va香蕉在线| 亚洲国产精品久久| 国产精品久久国产三级国电话系列| 亚洲国产成人精品女人久久久 | 国产精品视频免费观看www| 亚洲在线视频观看| 欧美不卡视频| 亚洲综合色激情五月| 国产一区二区三区四区五区美女| 美女精品一区| 中国成人亚色综合网站| 久久精品国产亚洲a| 亚洲日韩欧美视频一区| 欧美四级电影网站| 麻豆精品在线视频| 亚洲无限av看| 免费日韩一区二区| 亚洲少妇在线| 伊人蜜桃色噜噜激情综合| 欧美精品三区| 欧美在线一级视频| 一个色综合av| 久久久噜噜噜久久人人看| 亚洲人线精品午夜| 国产日韩欧美高清| 国产麻豆精品视频| 久久这里只精品最新地址| 99精品久久免费看蜜臀剧情介绍| 久久国产精品久久国产精品| 亚洲精选在线观看| 一色屋精品视频在线看| 国产精品久久一卡二卡| 欧美日韩1区2区3区| 欧美jizzhd精品欧美巨大免费| 性色一区二区三区|