导航

    全志在线开发者论坛

    • 注册
    • 登录
    • 搜索
    • 版块
    • 话题
    • 在线文档
    • 社区主页

    F1C200S TX Empty trigger 设置成1/2触发要怎么做?

    其它全志芯片讨论区
    2
    9
    3718
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • S
      smbzd LV 4 最后由 编辑

      我想把发送FIFO设置成1/2空就触发中断,但一直修改不了。我估计是THRE_MODE_USER没有启用,但在用户手册上没有找到它的使用说明。

      请问要怎么做才能修改发送FIFO的中断触发模式呢?

      bc3a3db4-e9b7-43ef-bd2b-482bc7c1bb52-图片.png

      S 1 条回复 最后回复 回复 引用 分享 0
      • S
        smbzd LV 4 @smbzd 最后由 编辑

        😞 😞 😞 帮帮孩子吧。我在串口写FCR,在terminal用devmem写FCR,都写不动FIFO的TX Empty Trigger。是不是f1c100s、f1c200s根本就不让修改它?

        A 1 条回复 最后回复 回复 引用 分享 1
        • A
          Alb702 LV 5 @smbzd 最后由 编辑

          @smbzd

          F1C100s/F1C200s 用户手册指出 UART 与 16550 兼容。 您可能应该参考 16550 文档以获取更详细的编程信息。

          你想得到什么结果?

          S 1 条回复 最后回复 回复 引用 分享 0
          • S
            smbzd LV 4 @Alb702 最后由 编辑

            @alb702 感谢回复!我在实现一个功能,控制485的in/out转换的gpio脚在合适的时候处于它应该在的电平:发送时拉高,接受时拉低。
            现在遇到的问题是:通过示波器发现,发送数据时控制引脚提前转换电平,导致数据没有完全发完。
            我想知道有没有什么好方法知道串口的数据在物理上什么时候实际地发送完成,然后尽量在1MS内的转换控制引脚的电平

            S 1 条回复 最后回复 回复 引用 分享 0
            • S
              smbzd LV 4 @smbzd 最后由 编辑

              即使是在接受到THEM(tx FIFOS holding register empty)中断之后才改变控制引脚的电平,仍然是在处于数据未发送完全的情形下就把控制引脚提前改变,导致数据传输不完全

              A 1 条回复 最后回复 回复 引用 分享 0
              • A
                Alb702 LV 5 @smbzd 最后由 编辑

                @smbzd
                监控FIFO的状态是控制485切换的错误方法。FIFO是一个中间存储器,这不知道发射器在做什么。 当最后一个字节的最后一个停止位离开发送器移位寄存器时,必须切换 485。
                最正确的方法是控制器是否有 TX_COMPLETE 中断。 485 的控制必须在发送最后一个字节时在中断中完成。
                但有些系统没有TX_COMPLETE中断,而只有TX_EMPTY中断。 在这种情况下,需要多传输1个字节,并在TX_EMPTY中断中切换控制485。这不是很正确,但它有效。

                在我们的项目中,我们使用专门的串口驱动程序,它也控制 485。
                该驱动程序可用于多种系统,包括 F1C200s。 如果你有兴趣,我可以贴出原文的片段 驱动程序文本在这里。

                S 1 条回复 最后回复 回复 引用 分享 0
                • S
                  smbzd LV 4 @Alb702 最后由 编辑

                  @alb702 感谢您一直以来的帮助。关于驱动的片段,我十分感兴趣,如果能提供就真是帮大忙了。非常感谢您的慷慨

                  A 1 条回复 最后回复 回复 引用 分享 0
                  • A
                    Alb702 LV 5 @smbzd 最后由 编辑

                    @smbzd
                    驱动程序算法的解释。

                    驱动程序开发很久以前就开始了,在 Allwinner A20 的 legacy kernel 版本 3.xx 时期。 为了不使驱动程序适应Linux内核的不同API,采用直接写入GPIO和UART寄存器的方式。
                    在我们的项目中,内核驱动程序和用户应用程序之间的数据交换是通过缓冲区进行的。 mmap 用于从用户空间访问缓冲区。 缓冲区包含用于接收和发送的数据以及控制结构。 为了开始传输,应用程序在缓冲区中设置一个特殊位。 驱动程序在 bum_poll() 函数的定时器中断中扫描该位(它位于不同的源代码中)。
                    您很可能会使用其他方法:read()/write()、ioctl()...,并且您不需要计时器。

                    /*
                     * suniv xbus driver
                     * (timer+uart)
                     * 
                     *
                     * This program is free software; you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License version 2
                     * as published by the Free Software Foundation.
                     *
                     * You should have received a copy of the GNU General Public License
                     * along with this programOC; if not, write to the Free Software
                     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     */
                    #include <linux/module.h>
                    #include <linux/kernel.h>   
                    #include <linux/moduleparam.h>
                    #include <asm/uaccess.h>
                    #include <asm/pgtable.h>
                    #include <linux/fs.h>
                    #include <linux/gfp.h>
                    #include <linux/cdev.h>
                    #include <linux/sched.h>
                    #include <linux/interrupt.h>
                    #include <linux/of.h>
                    #include <linux/of_irq.h>
                    #include <linux/of_platform.h>
                    #include <linux/platform_device.h>
                    #include <linux/delay.h>
                    #include <linux/ioport.h>
                    #include <linux/slab.h>
                    #include <linux/io.h>
                    #include <linux/clk.h>
                    #include <linux/reset.h>
                    #include <linux/mm.h>
                    #include <linux/miscdevice.h>
                    #include <linux/wait.h>
                    #include <linux/poll.h>
                    
                    static int hw_init;
                    static int bum_init(void);
                    static void bum_poll(void);
                    
                    static void gpio_set(int port, int pin);
                    static void gpio_clr(int port, int pin);
                    
                    static enum hrtimer_restart xbus_periodic(struct hrtimer *);
                    static struct hrtimer htimer;
                    static int k_period; 
                    static uint32_t norecv_timer;
                    
                    static int htimer_init(void)
                    {
                        k_period = ktime_set(0, 1000000); //1 ms
                        hrtimer_init(&htimer, CLOCK_REALTIME, HRTIMER_MODE_REL);
                        htimer.function = xbus_periodic;
                        hrtimer_start(&htimer, k_period, HRTIMER_MODE_REL);
                        return 0;
                    }
                    static void htimer_exit(void)
                    {
                        hrtimer_cancel(&htimer);
                    }
                    
                    static void stop_send(void);
                    
                    static uint8_t *  xbus_iobuf = 0;
                    #define xbus_mmap_mem()	(xbus_iobuf)
                    
                    /* -----------------------------Hardware registers mini description --------------------*/
                    
                    /*GPIO--------------------------------------*/
                    
                    typedef struct 
                    {
                        uint32_t	CFG[4];
                        uint32_t	DAT;
                        uint32_t	DRV[2];
                        uint32_t	PULL[2];
                    } 
                    port_struct_t;
                    
                    enum {PORTA, PORTB, PORTC, PORTD, PORTE, PORTF, PORTG, PORTH,PORTI};
                    
                    #define PORT_IO_BASE	0x01C20800	
                    #define UART_IO_BASE	0x01C25000
                    
                    static volatile __u8 *  port_io_base;
                    static volatile __u8 *  uart_io_base;
                    
                    #define __gpio ((volatile port_struct_t *)(port_io_base))
                    
                    /*UART---------------------------------------*/
                    #define UART_BASE       (uart_io_base)
                    #define UART_BASE_OS    (0x400)
                    #define UARTx_BASE(x)   (UART_BASE + (x) * UART_BASE_OS)
                    #define RESSIZE(res)    (((res)->end - (res)->start)+1)
                    
                    //#define UART_HALT           0x29 /* Halt TX register */
                    #define UART_FORCE_CFG      (1 << 1)
                    #define UART_FORCE_UPDATE   (1 << 2)
                    
                    #define __uart_reg(num, off) (*(volatile __u32 *)((UARTx_BASE(num)) + (off)))
                    
                    #define UART_RBR(n)	__uart_reg(n, 0x00) // DLAB=0
                    #define UART_THR(n)	__uart_reg(n, 0x00) // DLAB=0
                    #define UART_DLL(n)	__uart_reg(n, 0x00) // DLAB=1
                    #define UART_DLH(n)	__uart_reg(n, 0x04) // DLAB=1  
                    #define UART_IER(n)	__uart_reg(n, 0x04) 
                    #define UART_IIR(n)	__uart_reg(n, 0x08)
                    #define UART_FCR(n)	__uart_reg(n, 0x08)
                    #define UART_LCR(n)	__uart_reg(n, 0x0c)
                    #define UART_MCR(n)	__uart_reg(n, 0x10)
                    #define UART_LSR(n)	__uart_reg(n, 0x14)
                    #define UART_MSR(n)	__uart_reg(n, 0x18)
                    #define UART_SCH(n)	__uart_reg(n, 0x1c)
                    #define UART_USR(n)	__uart_reg(n, 0x7c)
                    #define UART_TFL(n)	__uart_reg(n, 0x80)
                    #define UART_RFL(n)	__uart_reg(n, 0x84)
                    #define UART_HALT(n)	__uart_reg(n, 0xa4)
                    
                    /*APB1---------------------------------------------*/ 
                    #define __ccu_reg(off) (*(volatile __u32 *)((ccu_io_base) + (off)))
                    #define APB1_GATING_REG	__ccu_reg(0x6c)
                    /*--------------------------------------------------------------------------*/
                    
                    #define DTR_PORT	PORTE
                    #define DTR_PIN		6
                    
                    //#define TIMERn		2
                    //#define IRQn_TIM	19//52
                    
                    #define UARTn	2
                    #define UART_BAUDRATE 	19200
                    #define IRQn_UART	33
                    
                    #define CDEV_MAJOR	230
                    #define CDEV_NAME	"b&ast;m"
                    
                     
                    //========================== GPIO functions======================
                    #define FMUX_IN		0
                    #define FMUX_OUT	1
                    #define FMUX_UART	3
                    
                    static void gpio_init_pin(int port, int pin, int mux)
                    {   
                        uint32_t tmp;
                        int n = 0;
                        while( pin > 7)  { pin -= 8; n++;  }
                        tmp = __gpio[port].CFG[n] & ~(0xf << (pin << 2));
                        __gpio[port].CFG[n] = tmp | (mux << (pin << 2));
                    }
                    
                    static spinlock_t gpio_lock;
                    
                    static void gpio_set(int port, int pin)
                    {
                        spin_lock(&gpio_lock);
                        __gpio[port].DAT |= (1 << pin);
                        spin_unlock(&gpio_lock);
                    }
                    
                    static void gpio_clr(int port, int pin)
                    {
                        spin_lock(&gpio_lock);
                        __gpio[port].DAT &= ~(1 << pin);
                        spin_unlock(&gpio_lock);
                    
                    } 
                    
                    // ========================= UART functions =======================
                    inline static void start_send(void)
                    {
                        gpio_set(DTR_PORT, DTR_PIN);
                        UART_IER(UARTn) |= (1 << 1); // set ETBEI (transmit holding register interrupt)     
                    }    
                    
                    inline static void stop_send(void)
                    {
                        UART_IER(UARTn) &= ~(1 << 1);  // clr ETBEI    
                        gpio_clr(DTR_PORT, DTR_PIN);
                    }    
                    
                    static enum hrtimer_restart xbus_periodic(struct hrtimer * unused)
                    {
                        if(hw_init)
                        {
                    	norecv_timer++; 
                    	if (norecv_timer > 2000) // 4s
                    	{
                    	    gpio_clr(DTR_PORT, DTR_PIN);
                    	    norecv_timer = 0;
                    	} 
                            bum_poll();
                        }
                        hrtimer_forward_now(&htimer, k_period);
                        return HRTIMER_RESTART;
                    }
                    
                    //=================================================================
                    #include "b&ast;m-core.c"
                    static char tdata[128];
                    static int idx; 	 
                    
                    static irqreturn_t irq_serial_handle(int irq, void *dev_id)
                    {
                        /*UART interrupt handler*/
                    
                       /* See "A20 User Manual 2013-03-22.pdf" , pp. 109 ... 122 */
                        int data;
                        uint32_t tmp = UART_IIR(UARTn) & 0xf;
                        
                        if (tmp == 2) // THR empty
                        {
                    	data = bum_uart_isr(-1);
                    	if (data == -1)
                    	    stop_send();
                    	else
                    	    UART_THR(UARTn) = data;    
                        }
                        else
                            if (tmp == 4) // receiver data available
                    	{
                    	    norecv_timer = 0;
                    	    bum_uart_isr(UART_RBR(UARTn));
                    	}    
                        return IRQ_HANDLED;
                    }
                    
                    static int divisor;
                    static int serial_hardware_init(void)
                    {
                        gpio_init_pin(DTR_PORT, DTR_PIN, FMUX_OUT);
                    
                     /* configure UART registers*/
                    /* See "A20 User Manual 2013-03-22.pdf" , pp. 645 ... 665 */
                    
                        UART_HALT(UARTn) |= 1; 		    
                        UART_LCR(UARTn) |= (1 << 7); // set DLAB (LCR.7)
                        UART_DLH(UARTn) = (divisor >> 8);
                        UART_DLL(UARTn) = (divisor & 0xff);
                        UART_FCR(UARTn) = 0;// disable FIFO
                        UART_MCR(UARTn) = 0;// disable modem control
                        UART_LCR(UARTn) = (3 << 0) // DLS, 8 bits word width 
                                        | (0 << 2) // STOP , 1 stop bit
                    		    | (0 << 3) // PEN, parity = disabled
                    		    | (0 << 4) // EPS  parity  select,
                    		    | (0 << 6) // BC, no break control
                    		    | (0 << 7) // clear DLAB
                    		    ;
                        UART_IER(UARTn) = (1 << 0);// set ERBFI / Enable Receiver Data available interrupt
                        UART_HALT(UARTn) = 0; //clear HALT		    
                        return 0;
                    }
                    
                    inline static void serial_hardware_stop(int irq, void * id)
                    {
                        free_irq(irq, id); 
                    }
                    
                    /* ==================== mmap implementation ======================*/
                    
                    struct mmap_info
                    {
                        char * data;
                        int reference;
                    };
                    
                    static void mmap_open(struct vm_area_struct *vma)
                    {
                    //    struct mmap_info * info = (struct mmap_info *)vma->vm_private_data;
                    //    info->reference++; 
                    }
                    	
                    static void  mmap_close(struct vm_area_struct *vma)
                    {
                    //    struct mmap_info * info = (struct mmap_info *)vma->vm_private_data;
                    //    info->reference--; 
                    }	
                    
                    static unsigned int mmap_fault(struct vm_fault * vmf)
                    {
                        struct page * page;
                        struct vm_area_struct *vma = vmf->vma;
                        unsigned long size = (unsigned long)(vma->vm_end-vma->vm_start); 
                    //    struct mmap_info * info = (struct mmap_info *)vma->vm_private_data;
                        size = (unsigned long)(vma->vm_end-vma->vm_start);
                        if (size > PAGE_SIZE)
                            return -EINVAL;
                        page = virt_to_page(xbus_iobuf);
                        get_page(page);
                        vmf->page = page;
                        return 0;
                    }
                    
                    static const struct vm_operations_struct vm_ops = 
                    {
                        .open  = mmap_open,
                        .close = mmap_close, 
                        .fault = mmap_fault
                    };
                    /*=========================== -- mmap  =================================*/
                    
                    static int xbus_mmap_init(void)
                    {
                        xbus_iobuf = (uint8_t*)get_zeroed_page(GFP_KERNEL);
                        if (!xbus_iobuf) {
                    	printk(KERN_ERR "mmap init failed\n");
                    	return 0;
                        }
                        return 0;
                    }
                    
                    static void xbus_mmap_cleanup(void)
                    {
                        if (xbus_iobuf)
                    	free_page((unsigned long)xbus_iobuf);
                        xbus_iobuf = 0;
                    }
                     
                    #ifndef VM_RESERVED
                    #define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP)
                    #endif 
                    
                    static int mmap_xbus(struct file *filp, struct vm_area_struct *vma)
                    {
                        vma->vm_ops = &vm_ops;
                        vma->vm_flags |= VM_RESERVED;    
                        vma->vm_private_data = filp->private_data;
                        return 0; 
                    }
                    
                    //////////////////////////////////////////////////////////////////////////////
                    
                    static DECLARE_WAIT_QUEUE_HEAD(wait);
                    static int check_data_ready(void);
                    
                    static void indicate_data_ready(void)
                    {
                        wake_up_interruptible(&wait);
                    }
                    
                    static unsigned int poll_xbus(struct file *f, struct poll_table_struct *p)
                    {
                        unsigned int mask = 0;
                        poll_wait(f, &wait, p);
                        if(check_data_ready())
                    	mask |= POLLIN | POLLRDNORM;
                        return mask;
                    }
                    
                    // VFS methods:
                    static struct file_operations xbus_fops =
                    {
                        .owner = THIS_MODULE,
                        .mmap = mmap_xbus,
                        .poll = poll_xbus,
                    };
                     
                    static struct miscdevice miscdev = { MISC_DYNAMIC_MINOR, "xbus", &xbus_fops };
                    
                    static const struct of_device_id xbus_of_match[] = {
                    	{ .compatible = "xbus-uart" },
                    	{ /* Sentinel */ }
                    };
                    MODULE_DEVICE_TABLE(of, xbus_of_match);
                    
                    struct xbus_serial_data {
                    	int 			irq;
                    	struct clk		*clk;
                    	struct clk		*pclk;
                    	struct reset_control	*rst;
                    };
                    
                    static struct xbus_serial_data xbus_serial;
                    
                    static void serial_remove( struct platform_device * pdev)
                    {
                        struct xbus_serial_data *data = platform_get_drvdata(pdev);
                    
                    	reset_control_assert(data->rst);
                    
                    	if (!IS_ERR(data->pclk))
                    		clk_disable_unprepare(data->pclk);
                    
                    	if (!IS_ERR(data->clk))
                    		clk_disable_unprepare(data->clk);
                    }
                    
                    static int serial_setup( struct platform_device * pdev)
                    {
                    	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
                    	int irq = platform_get_irq(pdev, 0);
                    	struct device *dev = &pdev->dev;
                    	struct xbus_serial_data *data;
                    	int err = -1;
                    	int uart_clk;
                    
                    	if (!regs) {
                    		dev_err(dev, "no registers defined\n");
                    		return -EINVAL;
                    	}
                    
                    	if (irq < 0) {
                    		if (irq != -EPROBE_DEFER)
                    			dev_err(dev, "cannot get irq\n");
                    		return irq;
                    	}
                    
                    	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
                    	if (!data)
                    		return -ENOMEM;
                    
                    	data->clk = devm_clk_get(dev, "baudclk");
                    	if (IS_ERR(data->clk) && PTR_ERR(data->clk) != -EPROBE_DEFER)
                    		data->clk = devm_clk_get(dev, NULL);
                    	if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER)
                    		return -EPROBE_DEFER;
                    	if (!IS_ERR_OR_NULL(data->clk)) {
                    		err = clk_prepare_enable(data->clk);
                    		if (err)
                    			dev_warn(dev, "could not enable optional baudclk: %d\n",
                    				 err);
                    	}
                    
                    	/* If no clock rate is defined, fail. */
                    	if (err) {
                    		dev_err(dev, "clock rate not defined\n");
                    		return -EINVAL;
                    	}
                    
                    	data->pclk = devm_clk_get(dev, "apb_pclk");
                    	if (IS_ERR(data->pclk) && PTR_ERR(data->pclk) == -EPROBE_DEFER) {
                    		err = -EPROBE_DEFER;
                    		goto err_clk;
                    	}
                    	if (!IS_ERR(data->pclk)) {
                    		err = clk_prepare_enable(data->pclk);
                    		if (err) {
                    			dev_err(dev, "could not enable apb_pclk\n");
                    			goto err_clk;
                    		}
                    	}
                    
                    	uart_clk = clk_get_rate(data->clk);
                        	divisor = DIV_ROUND_CLOSEST(uart_clk, 16 * UART_BAUDRATE);
                    
                    	data->rst = devm_reset_control_get_optional(dev, NULL);
                    	if (IS_ERR(data->rst)) {
                    		err = PTR_ERR(data->rst);
                    		goto err_pclk;
                    	}
                    	reset_control_deassert(data->rst);
                    	platform_set_drvdata(pdev, data);
                    
                    	return irq;
                    //err_reset:
                    	reset_control_assert(data->rst);
                    err_pclk:
                    	if (!IS_ERR(data->pclk))
                    		clk_disable_unprepare(data->pclk);
                    err_clk:
                    	if (!IS_ERR(data->clk))
                    		clk_disable_unprepare(data->clk);
                    	return err;
                    }
                    
                    static int xbus_probe(struct platform_device *pdev)
                    {
                        int irq;
                        printk(KERN_ERR "xbus loading..\n");
                        hw_init = 0;
                        int err = misc_register(&miscdev);
                        if(err != 0)
                        {
                    	printk("misc_register() error :%d\n", err);
                    	return -EPROBE_DEFER;
                        }
                    
                        irq = serial_setup(pdev);
                        if (irq < 0)
                        {
                    	return -EPROBE_DEFER;
                        }	
                        
                        xbus_serial.irq = irq;
                        
                        if (request_irq(irq, irq_serial_handle, IRQF_SHARED, 
                    	    "xbus-suniv", &xbus_serial))
                        {
                             printk (KERN_ERR "request irq %d error.\n", irq);
                             return -EPROBE_DEFER;
                        }
                    
                        port_io_base	= (__u8 * )ioremap(PORT_IO_BASE, 0x400);
                        uart_io_base	= (__u8 * )ioremap(UART_IO_BASE, 0x400);
                    	
                        if (uart_io_base == 0 || port_io_base == 0 ) 
                        {
                    	printk(KERN_ERR "resource ioremap failed\n");
                    	return -EPROBE_DEFER;
                        }
                    
                    
                        if (htimer_init() < 0)
                        {
                    	iounmap(port_io_base);
                    	iounmap(uart_io_base);
                    	return -EPROBE_DEFER;
                        }
                        serial_hardware_init();
                        
                        xbus_mmap_init();
                        bum_init();
                        hw_init = 1;
                        return 0;
                    }
                    
                    static int xbus_remove(struct platform_device *pdev)
                    {
                        printk(KERN_ERR "xbus unloading..\n");
                        hw_init = 0;
                        htimer_exit();
                        serial_hardware_stop(xbus_serial.irq, &xbus_serial);
                        serial_remove(pdev);
                        iounmap(port_io_base);
                        iounmap(uart_io_base);
                        xbus_mmap_cleanup();
                        misc_deregister(&miscdev);
                        return 0;
                    }
                    
                    static struct platform_driver xbus_platform_driver = {
                    	.driver = {
                    		.name		= "xbus-suniv",
                    		.owner		= THIS_MODULE,
                    		.of_match_table	= xbus_of_match,
                    	},
                    	.probe			= xbus_probe,
                    	.remove			= xbus_remove,
                    };
                    
                    module_platform_driver(xbus_platform_driver);
                    
                    MODULE_LICENSE("GPL");
                    MODULE_AUTHOR("albert@sokrat.ru");
                    MODULE_AUTHOR("jean@sokrat.ru");
                    
                    

                    bum_uart_isr() 它用于接收和传输。基本算法是:

                    static uint8_t tx_buf[MAX_TX];
                    static uint8_t rx_buf[MAX_RX];
                    static int rx_count;
                    static int tx_count;
                    static int snd_size;
                    
                    int bum_uart_isr(int value)
                    {
                    	if (value < 0) // TX IRQ
                    	{
                    		if (tx_count < snd_size && tx_count < MAX_TX)
                    			value = (int)tx_buf[tx_count++];
                    	}
                    	else  // RX IRQ
                    	{
                    		if (rx_count < MAX_RX)
                    			rx_buf[rx_count++] = (uint8_t)value;
                    	}	
                    	return value;
                    }
                    
                    S 1 条回复 最后回复 回复 引用 分享 0
                    • S
                      smbzd LV 4 @Alb702 最后由 编辑

                      @alb702 感谢您提供的编码,真的。祝福您。

                      1 条回复 最后回复 回复 引用 分享 0
                      • 1 / 1
                      • First post
                        Last post

                      Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号

                      行为准则 | 用户协议 | 隐私权政策