当前位置: 首页 > news >正文

西宁高端网站制作公司网站建设合同审批

西宁高端网站制作公司,网站建设合同审批,哈尔滨小程序建设,上海人才网站首页在上一篇笔记中#xff0c;学习编写了基于设备树的LED驱动#xff0c;但是驱动的本质还是没变#xff0c;都是配置LED灯 所使用的GPIO寄存器#xff0c;驱动开发方式和裸机基本没区别。Linux是一个庞大而完善的系统#xff0c;尤其是驱动框架#xff0c;像GPIO这种最基本…在上一篇笔记中学习编写了基于设备树的LED驱动但是驱动的本质还是没变都是配置LED灯 所使用的GPIO寄存器驱动开发方式和裸机基本没区别。Linux是一个庞大而完善的系统尤其是驱动框架像GPIO这种最基本的驱动不可能采用裸机驱动开发方式。Linux内核提供了pinctrl和gpio子系统用于GPIO驱动本章就学习一下如何借助pinctrl和gpio子系统来简化GPIO驱动开发。 pinctrl子系统 pinctrl子系统简介 Linux驱动讲究驱动分离与分层pinctrl和gpio子系统就是驱动分离与分层思想下的产物驱动分离与分层其实就是按照面向对象编程的设计思想而设计的设备驱动框架。 先来回顾一下上一篇笔记中是怎么初始化LED灯所使用的GPIO步骤如下 修改设备树添加相应的节点节点里面重点是设置reg属性reg属性包括了GPIO相关寄存器。获取 reg属性中GPIOI_MODER、GPIOI_OTYPER、GPIOI_OSPEEDR、GPIOI_PUPDR和GPIOI_BSRR这些寄存器的地址并且初始化它们这些寄存器用于设置PI0这个PIN的复用功能、上下拉、速度等。在2里面将PI0这个PIN设置为通用输出功能因此需要设置PI0这个GPIO相关的寄存器也就是设置GPIOI_MODER寄存器。在2里面将PI0这个PIN设置为高速、上拉和推挽模式就要需要设置PI0的GPIOI_OTYPER、GPIOI_OSPEEDR和GPIOI_PUPDR这些寄存器。 对于大多数的32位 SOC而言引脚的设置基本都是这两方面因此Linux内核针对PIN的复用配置推出了pinctrl子系统对于GPIO的电气属性配置推出了gpio子系统。 大多数SOC的pin都是支持复用的比如STM32MP1的PI0既可以作为普通的GPIO使 用也可以作为SPI2的NSS引脚、TIM5的CH4引脚等等。此外还需要配置pin的电气特性比如上/下拉、速度、驱动能力等等。传统的配置pin的方式就是直接操作相应的寄存器但是这种配置方式比较繁琐、而且容易出问题(比如pin功能冲突)。pinctrl子系统就是为了解决这个问题而引入的pinctrl子系统主要工作内容如下 获取设备树中pin信息。根据获取到的pin信息来设置pin的复用功能。根据获取到的pin信息来设置pin的电气特性比如上/下拉、速度、驱动能力等。 对于使用者来讲只需要在设备树里面设置好某个pin的相关属性即可其他的初始化工作均由pinctrl子系统来完成pinctrl子系统源码目录为drivers/pinctrl。 STM32MP1的pinctrl子系统驱动 PIN配置信息详解 要使用pinctrl子系统需要在设备树里面设置PIN的配置信息一般会在设备树里面创建一个节点来描述PIN的配置信息。打开stm32mp151.dtsi文件找到一个叫做pinctrl的节点如下所示 第1815-1816行#address-cells属性值为1和#size-cells属性值为1也就是说pinctrl下的所有子节点的reg第一位是起始地址第二位为长度。 第1818行ranges属性表示STM32MP1的GPIO相关寄存器起始地址STM32MP1系列芯片最多拥有176个通用 GPIO分为12组分别为PA0-PA15、PB0-PB15、PC0-PC15、PD0-PD15、PE0-PE15、PF0-PF15、PG0-PG15、PH0-PH15、PI0-PI15、PJ0-PJ15、PK0-PK7、PZ0-PZ7。 其中PA-PK这11组 GPIO的寄存器都在一起起始地址为0X50002000终止地址为0X5000C3FF。PZ组寄存器起始地址为0X54004000终止地址为0X540043FF所以stm32mp151.dtsi文件里面还有个名为“pinctrl_z”的子节点来描述PZ组 IO。pinctrl节点用来描述PA-PK这11组IO因此ranges属性中的0x50002000表示起始地址 0xa400表示寄存器地址范围。 第1819行interrupt-parent属性值为“exti”父中断为exti。 后面的gpiox子节点先不分析这些子节点都是gpio子系统的内容到后面在去分析。打开stm32mp15-pinctrl.dtsi文件能找到如下内容 示例代码25.1.2.2就是向pinctrl节点追加数据不同的外设使用的PIN不同、其配置也不同将某个外设所使用的所有PIN都组织在一个子节点里面。示例代码25.1.2.2中m_can1_pins_a子节点就是CAN1的所有相关IO的PIN集合pwm1_pins_a子节点就是PWM1相关IO的PIN集合。绑定文档 Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml描述了如何在设备树中设置STM32的PIN信息。 集合里面存放当前外设用到哪些引脚(PIN)、这些引脚应该怎么配置、复用相关的配置、上下拉、 默认输出高电平还是低电平。一般这个存放pincrtl集的子节点名字是“pins”如果某个外设用到多种配置不同的引脚那么就需要多个pins子节点比如示例代码25.1.2.2中第535行和541行的pins1和pins2这两个子节点分别描述PH13和PI9的配置方法由于PH13和PI9这两个IO的配置不同因此需要两个pins子节点来分别描述。第555-562行的pins子节点是描述PWM1的相关引脚包括PE9、PE11、PE14由于这三个引脚的配置是一模一样的因此只需要一个pins子节点就可以了。 上面讲了在pins子节点里面存放外设的引脚描述信息这些信息包括 1、pinmux属性 此属性用来存放外设所要使用的所有IO通过STM32_PINMUX宏来配置引脚和引脚的复用功能定义在include/dt-bindings/pinctrl/stm32-pinfunc.h文件里面内容如下 可看出有3个参数含义如下 port表示用哪一组 GPIO(例H表示为GPIO第H组也就是GPIOH)。line表示这组GPIO的第几个引脚 (例13表示为GPIOH_13也就是PH13)。mode表示当前引脚要做那种复用功能 (例AF9表示为用第9个复用功能 )这个需要查阅STM32MP1数据手册来确定使用哪个复用功能。 这里要注意比如PH13做了FDCAN1的TX功能还能做UART4的TX功能这是不会冲突的因为pinctrl驱动只会把设备树pinctrl节点解析出来的数据存储到一个链表里只有当外设调用这个pinctrl节点的时候才会真的使用。但是如果要同时使用FDCAN1和UART4的话就会出问题因此PH13同一时间只能用于一个外设所以为了方便开发还是建议一个PIN最好只能被一个外设使用。 2、电气属性配置 接下来了解一下PIN的电气特性如何设置电气特性在pinctrl子系统里不是必须的可以不配置但是pinmux属性是必须要设置的。stm32-pinctrl.yaml文件里面也描述了如何设置STM32的电气属性如下图所示 上图中bootlean类型表示了在pinctrl子系统只要定义这个电气属性就行了例如要禁用内部电压只要在PIN的配置集里添加“bias-disable”即可这个时候bias-pull-down和bias-pull-up都不能使用了因为已经禁用了内部电压所以不能配置上下拉。enum类型使用方法更简单跟C语言的一样比如要设置PIN速度为最低就可以使用“slew-rate0”。 PIN驱动程序讲解 所有的东西都已经准备好了包括寄存器地址和寄存器值Linux内核相应的驱动文件就会根据这些值来做相应的初始化。接下来就找一下哪个驱动文件来做这一件事情pinctrl节点中compatible属性的值为“st,stm32mp157-pinctrl”在Linux内核中全局搜索“pinctrl”字符串就会找到对应的驱动文件。在文件drivers/pinctrl/stm32/pinctrl-stm32mp157.c中有如下内容 第2334-2344行of_device_id结构体类型的数组在讲解设备树的时候说过of_device_id里面保存着这个驱动文件的兼容性值设备树中的compatible属性值会和of_device_id中的所有兼容性字符串比较查看是否可以使用此驱动。stm32mp157_pctrl_match结构体数组一共有两个兼容分别为“st,stm32mp157-pinctrl”和 st,stm32mp157-z-pinctrl”设备树也定义了这两个兼容性值因此pinctrl和pinctrl_z节点都会和此驱动匹配所以pinctrl-stm32mp157.c会完成STM32MP1的PIN配置工作。 第2350-2357行platform_driver是平台设备驱动这个是后面章节要讲解的内容platform_driver是个结构体有个probe成员变量。在这里只需要知道当设备和驱动匹配成功以后platform_driver的probe成员变量所代表的函数就会执行在2351行设置probe成员变量为stm32_pctl_probe函数因此在本章实验中stm32_pctl_probe这个函数就会执行可以认为stm32_pctl_probe函数就是STM32MP157这个 SOC的PIN配置入口函数。 第2359-2362行就是一个简单的驱动入口函数platform_driver_register函数是一个标准的平台设备驱动注册函数用于向Linux内核注册一个platform_driver这里就是将stm32mp157_pinctrl_driver注册到Linux内核总线关于平台设备驱动后面章节会详细讲解。 重点来分析一下stm32_pctl_probe函数函数定义在drivers/pinctrl/stm32/pinctrl-stm32.c里面函数内容如下所示 第1458行看它的结构体的名字就知道是ST官方自定义的一个结构体类型用于存放STM32相关PIN属性集合。要想驱动能通用就要用结构体来保存数据和驱动里面尽量不要使用全局变量(在pinctrl驱动里就没有一个全局变量全部使用结构体来描述一个物体物体的所有属性都作为结构体成员变量)。接着去看下stm32_pinctrl结构体是如何定义的如下图所示 第103行pinctrl_desc结构体用来描述PIN控制器PIN控制器用于配置SOC的PIN复用功能和电气特性。 第107行这个stm32_gpio_bank结构体是用来注册GPIO驱动。到后面GPIO子系统再说。 pinctrl_desc结构体内容如下所示 第134-136行这三个“_ops”结构体指针非常重要因为这三个结构体就是PIN控制器的“工具”这三个结构体里面包含了很多操作函数Linux内核初始化PIN最终使用的就是这些操作函数。因此编写一个SOC的PIN控制器驱动的核心就是实现pinctrl_desc里面的pctlops、pmxops和confopspinctrl_desc结构体需要由用户提供结构体里面的成员变量也是用户编写的。但是这个用户并不是我们这些使用芯片的程序员而是半导体厂商半导体厂商发布的Linux内核源码中已经把这些工作做完了。 示例代码 25.1.2.8里第1536-1538行给这三个结构体赋值分别对应stm32_pconf_ops、stm32_prtrl_ops和stm32_pmx_ops三个结构体如下 pinctrl_desc结构体初始化完成以后需要调用pinctrl_register或者devm_pinctrl_register函 数就能够向Linux内核注册一个PIN控制器示例代码25.1.2.8中的1542行就是向Linux内核注册PIN控制器。 总结一下pinctrl驱动流程如下 定义pinctrl_desc结构体。初始化结构体 重点是pinconf_ops、pinmux_ops和pinctrl_ops这三个结构体成员变量但是这部分半导体厂商帮我们搞定。调用devm_pinctrl_register函数完成PIN控制器注册。 设备树中添加pinctrl节点模板 接下来学习一下如何在设备树中添加某个外设的PIN信息 。比如需要将PG11这个PIN复用为UART4_TX引脚pinctrl节点添加过程如下 创建对应节点在pinctrl节点下添加“uart4_pins”节点。添加“pins”属性这个子节点是真正来描述PIN配置的同一个pins子节点需要所有PIN电气属性一样。在“pins”节点中添加PIN配置信息。 最终结果如下 示例代码25.1.3.3完整的uart4_pins设备pinctrl子节点 1 pinctrl { 2 uart4_pins: uart4-0 { 3 pins1{ 4 pinmux STM32_PINMUX(G, 11, AF6); /* UART4_TX */ 5 bias-disable; 6 drive-push-pull; 7 }; 8 }; 9 };按理来说将IO用作GPIO功能也需要创建对应pinctrl节点并将IO复用为GPIO但是对于STM32MP1而言如果IO用作GPIO功能就可以不需要创建对应的pinctrl节点。 gpio子系统 gpio子系统简介 上一小节讲解了pinctrl子系统pinctrl子系统重点是设置PIN(有的SOC叫做PAD)的复用和电气属性如果pinctrl子系统将一个PIN复用为GPIO的话那么接下来就要用到gpio子系统了。gpio子系统顾名思义就是用于初始化GPIO并且提供相应的API函数比如设置GPIO为输入输出读取GPIO的值等。gpio子系统的主要目的就是方便驱动开发者使用gpio驱动开发者在设备树中添加gpio相关信息然后就可以在驱动程序中使用gpio子系统提供的API函数来操作GPIOLinux内核向驱动开发者屏蔽掉了GPIO的设置过程极大的方便了驱动开发者使用GPIO。 STM32MP1的gpio子系统驱动 设备树中的gpio信息 以PI0引脚所在的GPIOI为例打开stm32mp151.dtsi找到如下内容 第1912-1921行就是GPIOI的控制器信息属于pincrtl的子节点因此对于STM32MP1而言pinctrl和gpio这两个子系统的驱动文件是一样的都为pinctrl-stm32mp157.c所以在注册pinctrl驱动顺便会把gpio驱动程序一起注册。绑定文档 Documentation/devicetree/bindings/gpio/gpio.txt详细描述了gpio控制器节点各个属性信息。 第1913行“gpio-controller”表示gpioi节点是个GPIO控制器每个GPIO控制器节点必须包含“gpio-controller”属性。 第1914行“#gpio-cells”属性和“#address-cells”类似#gpio-cells应该为2表示一共有两个cell第一个cell为GPIO编号比如“gpioi 0”就表示PI0。第二个cell表示GPIO极性如果为0(GPIO_ACTIVE_HIGH)的话表示高电平有效如果为1(GPIO_ACTIVE_LOW)的话表示低电平有效。 第1917行reg属性设置了GPIOI控制器的寄存器基地址偏移为0X800因此GPIOI寄存器地址为0X500020000X8000X5000A000可以打《STM32MP157参考手册》就可以找到GPIOI控制器的基地址就是0X5000A000。 第1918行clocks属性指定这个GPIOI控制器的时钟。 示例代码25.2.2.1中的是GPIOI控制器节点当某个具体的引脚作为GPIO使用的时候还需要进一步设置。ST官方EVK开发板将PG1用作SD卡的检测(CD)引脚 PG1复用为GPIO功能通过读取这个 GPIO的高低电平就可以知道SD卡有没有插入。这里肯定需要设备树来告诉驱动在设备树中的SD卡节点下添加一个属性来描述SD卡的CD引脚就行了SD卡驱动直接读取这个属性值就知道SD卡的CD引脚使用的是哪个GPIO了。 ST官方EVK开饭的SD卡连接在STM32MP157的sdmmc1接口上在stm32mp15xx-edx.dtsi中找到名为“sdmmc1”的节点这个节点就是SD卡设备节点如下所示 第338行**属性“cd-gpios”描述了SD卡的CD引脚使用的哪个IO。**属性值一共有三个来看一下这三个属性值的含义“gpiog”表示CD引脚所使用的IO属于GPIOG组“1”表示 GPIOG组的第1号 IO通过这两个值SD卡驱动程序就知道CD引脚使用了PG1这个GPIO。最后一个是“GPIO_ACTIVE_LOW | GPIO_PULL_UP”Linux内核定义在include/linux/gpio/machine.h文件中定义了枚举类型gpio_lookup_flags内容如下 可以通过或运算组合不同的配置内容示例代码25.2.2.2中的338行“GPIO_ACTIVE_LOW”表示低电平有效“GPIO_PULL_UP”表示上拉所以PG1引脚默认上拉而且低电平有效(当 PG1被拉低的时候表示SD卡插入)。 GPIO驱动程序简介 前面一小节说过了STM32MP1的pinctrl驱动和gpio驱动是同一个驱动文件都为pinctrl-stm32mp157.c所以入口函数都是stm32_pctl_probe找到如下代码所示 第1586行判断设备树节点是否有gpio-controller。如果存在那么这个节点就是一个 GPIO控制器节点。 第1587行stm32_gpiolib_register_bank函数用来注册GPIO驱动包括生成回调函数注册的过程是跟pinctrl驱动注册是一样的。都是创建自己的结构体然后初始化结构体调用内核的注册函数这样把自己的结构体注册到内核。 gpio子系统API函数 对于驱动开发人员设置好设备树以后就可以使用gpio子系统提供的API函数来操作指定的GPIOgpio子系统向驱动开发人员屏蔽了具体的读写寄存器过程。gpio子系统提供的常用API有如下几个。 gpio_request函数 该函数用于申请一个GPIO管脚在使用一个GPIO之前一定要使用gpio_request进行申请函数原型如下 int gpio_request(unsigned gpio, const char *label) 函数参数和返回值含义如下 gpio要申请的gpio标号使用of_get_named_gpio函数从设备树获取指定GPIO属性信息此函数会返回这个GPIO的标号。label给gpio设置个名字。返回值0申请成功其他值申请失败。 gpio_free函数 如果不使用某个GPIO了那么就可以调用gpio_free函数进行释放。函数原型如下 void gpio_free(unsigned gpio)函数参数和返回值含义如下 gpio要释放的gpio标号。返回值无。 gpio_direction_input函数 此函数用于设置某个GPIO为输入函数原型如 下所示 int gpio_direction_input(unsigned gpio)函数参数和返回值含义如下 gpio要设置为输入的GPIO标号。返回值0设置成功负值设置失败。 gpio_direction_output函数 此函数用于设置某个GPIO为输出并且设置默认输出值函数原型如下 int gpio_direction_output(unsigned gpio, int value)函数参数和返回值含义如下 gpio要设置为输出的GPIO标号。valueGPIO默认输出值。返回值0设置成功负值设置失败。 gpio_get_value函数 此函数用于获取某个GPIO的值 (0或1)此函数是个宏定义如下所示 #define gpio_get_value __gpio_get_value int __gpio_get_value(unsigned gpio)函数参数和返回值含义如下 gpio要获取的GPIO标号。返回值非负值得到的GPIO值负值获取失败。 gpoio_set_value函数 此函数用于设置某个GPIO的值此函数是个宏定义如下 #define gpio_set_value __gpio_set_value void __gpio_set_value(unsigned gpio, int value)函数参数和返回值含义如下 gpio要设置的GPIO标号。value要设置的值。返回值无。 设备树中添加gpio节点模板 以正点原子STM32MP157开发板的LED0为例学习创建GPIO节点。LED0连到PI0引脚上 创建led设备节点。添加GPIO属性信息。 完成后如下所示 示例代码25.2.4.2 向led节点添加gpio属性 1 led { 2 compatible atk,led; 3 gpio gpioi 0 GPIO_ACTIVE_LOW; 4 status okay; 5 }; gpio相关OF函数 在驱动程序中需要读取gpio属性内容 Linux内核提供了几个与GPIO有关的OF函数常用的几个OF函数如下所示 of_gpio_named_count函数 该函数用于获取设备树某个属性里面定义了几个 GPIO信息要注意的是空的GPIO信息也会被统计到。此函数原型如下 int of_gpio_named_count(struct device_node *np, const char *propname)函数参数和返回值含义如下 np设备节点。propname要统计的GPIO属性。返回值正值统计到的GPIO数量负值失败。 of_gpio_count函数 此函数统计的是“gpios”这个属性的GPIO数量而of_gpio_named_count函数可以统计任意属性的GPIO信息函数原型如下所示 int of_gpio_count(struct device_node *np)函数参数和返回值含义如下 np设备节点。返回值正值统计到的GPIO数量负值失败。 of_get_named_gpio函数 此函数获取GPIO编号因为Linux内核中关于GPIO的API函数都要使用GPIO编号此函数会将设备树中类似gpioi 0(GPIO_ACTIVE_LOW | GPIO_PULL_UP)的属性信息转换为对应的GPIO编号此函数在驱动中使用很频繁函数原型如下 int of_get_named_gpio(struct device_node *np, const char *propname, int index)函数参数和返回值含义如下 np设备节点。propname包含要获取GPIO信息的属性名。indexGPIO索引因为一个属性里面可能包含多个GPIO此参数指定要获取哪个GPIO的编号如果只有一个GPIO信息的话此参数为0。返回值正值获取到的GPIO编号负值失败。 硬件原理图 就是之前的LED原理图。 实验程序编写 修改设备树文件 在stm32mp157d-atk.dts文件的根节点“/”下创建LED灯节点节点名为“gpioled”节点内容如下 示例代码25.4.1.1 创建LED灯节点 1 gpioled { 2 compatible alientek,led; 3 status okay; 4 led-gpio gpioi 0 GPIO_ACTIVE_LOW; 5 };第4行led-gpio属性指定了LED灯所使用的GPIO在这里就是GPIOI的0号低电平有效。稍后编写驱动程序的时候会获取led-gpio属性的内容来得到GPIO编号因为gpio子系统的API操作函数需要GPIO编号。设备树编写完成以后使用“make dtbs”命令重新编译设备树然后使用新编译出来的stm32mp157d-atk.dtb文件启动Linux系统。启动成功以后进入“/proc/device-tree”目录中查看“gpioled”节点是否存在如果存在的话就说明设备树基本修改成功(具体还要驱动验证)。 LED灯驱动程序编写 在之前设备树类似裸机开发的LED驱动基础上进行改写。 主要的区别在于 需要再色河北结构体gpioled_dev中添加led_gpio这个成员保存LED使用的GPIO编号然后将gpioled这个设备结构体变量设为filp的私有数据private_data之后读取private_data得到设备结构体变量gpioled然后就可以直接在led_write中使用gpio_set_value来完成LED开关。 之后在led_init中通过of_find_node_by_path(“/gpioled”)来获取设备节点并保存到gpioled.nd中之后通过of_property_read_string读取status属性通过of_property_read_string获取compatible属性通过of_get_named_gpio读取LED编号存入gpioled.led_gpio中之后通过gpio_request申请使用GPIO再由gpio_direction_output输出高电平来默认关闭LED。 编写测试APP 可以直接用之前的ledApp.c文件。 运行测试 编译驱动程序和测试APP 驱动只需要把Makefile中obj-m的值改为gpioled.o然后“make -j8”即可APP可以用如下命令编译 arm-none-linux-gnueabihf-gcc ledApp.c -o ledApp 运行测试 将之前编译得到的gpioled.ko和ledApp拷贝到rootfs/lib/modules/5.4.31目录中然后重启开发板进入/lib/modules/5.4.31目录输入如下命令加载gpioled.ko depmod //第一次加载驱动的时候需要运行此命令 modprobe gpioled //加载驱动 加载成功后可以通过如下命令打开和关闭LED ./ledApp /dev/gpioled 1 //打开LED灯 ./ledApp /dev/gpioled 0 //关闭LED灯 可以通过如下命令卸载驱动 rmmod dtsled.ko 总结 本章通过Linux最常用的pinctrl和gpio子系统结合设备树来控制LED灯。主要是通过修改设备树stm32mp157d-atk.dts添加gpioled节点然后在驱动程序中在gpioled_dev结构体中添加int led_gpio记录GPIO编号并申请结构体gpioled代表led设备led_write中就可以通过private_data获取设备信息然后由gpio_set_value来控制LEDled_init中就通过OF函数找到节点之后获取status和compatible属性来匹配最终由of_get_named_gpio读取LED编号并由gpio_request申请对LED的使用并通过gpio_direction_output输出高电平。
http://www.huolong8.cn/news/131626/

相关文章:

  • 网站添加在线支付app界面设计教程
  • 深圳宝安区网站建设51免费模板网
  • 如何修改网站发布时间湖北百度seo排名
  • 聚享游网站如何做推广WordPress黑镜
  • 查看网站服务器信息关键词权重
  • 宜昌做网站的许昌网站优化
  • 深圳网站建设服务类公司优缺点ckplayer整合WordPress
  • 使用php做的网站有哪些有没有教做蛋糕的网站
  • 南昌地宝网租房信息合肥seo排名扣费
  • 做视频哪个网站素材好玩具网站开发背景
  • 转转怎么做钓鱼网站小组网站建设方案书
  • php做网站实例电子商务网站设计说明
  • dw做的个人网站自己怎么创建一个网站
  • ppt免费制作网站网站建设中字样图片
  • 茂名网站制作公司wordpress5.0启多站点
  • 如何制作家具网站哪种网站名称容易通过备案审核
  • 网站建设的必要成都装饰公司十大排名榜
  • 网站关键词先后移动论坛网站模板免费下载
  • 在线花钱做网站网站建设捌金手指花总二
  • 手机网站制作推荐网站速度优化工具
  • python 建设网站一个网站多个域名备案吗
  • jsp做网站案例网站下面的站长统计很逗
  • 网站的空间和域名是啥做名片素材网站
  • 建设工程质量检测机构主管网站做建材网站怎么做
  • 外贸企业网站模板深圳软装公司排名前十强
  • 做网站的公司 设计好云南网络推广报价明细
  • 成都美誉网站设计做网站九州科技
  • 地区门户网站 wap app亚马逊雨林十大恐怖生物
  • app网站多少钱wordpress首页摘要设置
  • 网站建设参考文献外文设计兼职