移植之前所有驱动(基于linux-2.6.22.6)到linux-4.12内核

    之前编写的驱动都是基于linux-2.6.22.6内核的,下面将所有驱动移植到linux-4.12内核上,linux-4.12使用的是移植linux-4.12到JZ2440里移植的内核,使用2.4 制作补丁的方法获得该移植好的linux-4.12内核

目录

1. 移植网卡驱动
    1.1 准备文件

    1.2 解决错误
        1.2.1 解决错误1
            1.2.2 解决错误2
            1.2.3 解决错误3
            1.2.4 解决错误4
            1.2.5 解决错误5
            1.2.6 解决错误6
            1.2.7 解决错误7
            1.2.8 解决错误8
    1.3 测试
2. 移植第二个驱动(简单编写字符设备)
3. 移植第三个驱动(使用中断)
4. 移植第四个驱动(poll机制)
5. 移植第五个驱动(异步通知)
6. 移植第六个驱动(输入子系统)
7. 移植第七个驱动(platform总线设备驱动)
8. 移植第八个驱动(lcd驱动)
    8.1 配置内核
    8.2 测试
9. 移植第九个驱动(触摸屏驱动)
    9.1 配置内核
    9.2 重烧内核
    9.3 测试
    9.4 安装tslib
10. 移植第十个驱动(USB鼠标驱动)
11. 移植第十一个驱动(块设备驱动)
    11.1 测试
12. 移植第十二个驱动(nand flash驱动)
13. 移植第十三个驱动(nor flash驱动)
14. 移植第十四个驱动(网卡驱动)


1. 移植网卡驱动

    为了方便使用网络文件系统测试驱动,首先移植网卡驱动。移植好的文件下载地址:https://pan.baidu.com/s/1LWrR3MyvkNpkTo1Ym7TTDQ

1.1 准备文件

    在二十一、Linux驱动之移植DM9000C网卡驱动(下)里将厂家提供的DM9000网卡移植支持了linux-2.6.22.6内核,下面直接将该文章修改好的dm9dev9000c.c文件(下载地址:https://pan.baidu.com/s/1jTsBzozDllbHUVZz95dKcg)拷贝到服务器上,编写Makefile如下(/work/tools/linux-4.12必须是编译好的内核)

KERN_DIR = /work/tools/linux-4.12

all:
	make -C $(KERN_DIR) M=`pwd` modules 

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order

obj-m	+= dm9dev9000c.o

    放到服务器如下:
   
    执行make如下:
 
    可以看到许多错误。

1.2 解决错误

1.2.1 解决错误1

    先从第一个错误开始解决:

dm9dev9000c.c:97:39: error: asm/arch-s3c2410/regs-mem.h: No such file or directory

    提示新内核没有这个文件了,直接去掉:
   

1.2.2 解决错误2

    再看第二个错误:

dm9dev9000c.c:357: error: implicit declaration of function 'SET_MODULE_OWNER'

    没有SET_MODULE_OWNER这个函数,直接去掉:
   

1.2.3 解决错误3

    重新make编译如下:
   
    可以看到很多同样的错误:

error: 'struct net_device' has no member named 'priv'

    表示net_device结构体没有priv成员,在linux-4.12源码中搜索struct net_device,定位到linux-4.12/drivers/net/ethernet/davicom/dm9000.c文件中有如下代码:
   
    可以对比报错地方代码:
   
    可以发现新内核使用netdev_priv(dev)代替了dev->priv,所以修改该类型错误的地方,将dm9dev9000c.c文件里的所有dev->priv替换成netdev_priv(dev),再重新编译如下:
 

1.2.4 解决错误4

    错误少了许多,继续修改错误,提示还是net_device结构体不使用了许多成员,查看linux-4.12/drivers/net/ethernet/davicom/dm9000.c文件,发现新内核将许多网络操作函数放到了net_device_ops结构体里,如下(dm9000.c文件):
   
    然后使用如下代码指定操作函数结构体:
   
    仿造linux-4.12/drivers/net/ethernet/davicom/dm9000.c文件构造net_device_ops结构体,在dmfe_probe1函数前添加如下代码:

static const struct net_device_ops dm9k_netdev_ops = {
	.ndo_open			= dmfe_open,
	.ndo_stop			= dmfe_stop,
	.ndo_start_xmit		        = dmfe_start_xmit,
	.ndo_tx_timeout		        = dmfe_timeout,
	.ndo_set_rx_mode		= dm9000_hash_table,
	.ndo_do_ioctl			= dmfe_do_ioctl,
	.ndo_change_mtu		        = eth_change_mtu,
	.ndo_get_stats      	        = dmfe_get_stats,
	//.ndo_set_features	        = dm9000_set_features,
	.ndo_validate_addr		= eth_validate_addr,
	.ndo_set_mac_address	        = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	        = dm9000_poll_controller,
#endif
};

    然后将dmfe_probe1函数里的如下代码:
   
    修改为:

			/* driver system function */				
			dev->base_addr 		= iobase;
			dev->irq 		= irq;
			dev->watchdog_timeo	= 5*HZ;	
			dev->netdev_ops	= &dm9k_netdev_ops;
#if 0
			dev->open 		= &dmfe_open;
			dev->hard_start_xmit 	= &dmfe_start_xmit;
			dev->watchdog_timeo	= 5*HZ;	
			dev->tx_timeout		= dmfe_timeout;
			dev->stop 		= &dmfe_stop;
			dev->get_stats 		= &dmfe_get_stats;
			dev->set_multicast_list = &dm9000_hash_table;
			dev->do_ioctl 		= &dmfe_do_ioctl;
#endif

    重新编译如下:
   

1.2.5 解决错误5

    解决新编译后第一个错误:

dm9dev9000c.c:861: error: 'struct net_device' has no member named 'trans_start'

    在linux-4.12内核源码中搜索trans_start,发现linux-4.12/drivers/net/ethernet/ibm/ibmvnic.c文件中有如下代码:
   
    其中txqnetdev_queue结构体,如下:
   
    在linux-4.12内核源码搜索netdev_queue发现可以通过“struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);”来得到,所以修改dm9dev9000c.c文件:
   

1.2.6 解决错误6

    解决之前新编译后第二个错误:

error: 'struct net_device' has no member named 'last_rx'

    在linux-4.12内核源码搜索last_rx没有类似的使用,所以这里直接去掉该行代码:
   
    重新编译如下:
  

1.2.7 解决错误7

    先看第一个错误:

dm9dev9000c.c:1403: error: 'struct net_device' has no member named 'mc_list'

    表示net_device结构体没有mc_list成员,看一下dm9dev9000c.c文件里怎么使用的:
   
  
    在linux-4.12/drivers/net/ethernet/davicom/dm9000.c文件也有dm9000_hash_table函数,看看这个文件是如何实现的:
   
   
   
    可以看到新内核使用了新的方式,仿造dm9000.c文件该部分内容,修改dm9dev9000c.c文件如下:
   
   
    再将cal_CRC函数声明与定义去掉。
    重新编译如下:
   

1.2.8 解决错误8

    只剩下这4条错误:

error: unknown field 'get_rx_csum' specified in initializer
error: unknown field 'set_rx_csum' specified in initializer
error: unknown field 'get_tx_csum' specified in initializer
error: unknown field 'set_tx_csum' specified in initializer

    linux-4.12内核没有使用到这4个函数了,直接去掉:
   
    可以再将对应4个函数定义与声明去掉。
    重新编译如下:
   

1.3 测试

    将修改好的dm9dev9000c.c拷贝到/work/tools/linux-4.12/drivers/net/ethernet/davicom里,修改该目录下的Makefile如下:

#
# Makefile for the Davicom device drivers.
#

obj-$(CONFIG_DM9000) += dm9dev9000c.o
#obj-$(CONFIG_DM9000) += dm9000.o

    重新编译linux-4.12内核,然后将uImage烧写到NAND Flash里的kernel分区去,在uboot命令行输入如下命令:
      tftp 30000000 uImage    (下载内核到30000000地址)
      nand erase.part kernel    (擦除kernel分区)
      nand write 30000000 kernel    (将内核写入kernel分区)
   
启动新内核后如下:
   
    成功ping通,说明网卡移植成功。也能实现挂载网络文件系统了(保证三者互通前提下)
   
    在uboot命令行输入如下命令再启动内核即可自动挂载网络文件系统(文件系统制作看制作文件系统):
      set bootargs noinitrd root=/dev/nfs nfsroot=192.168.1.13:/work/tools/fs_mini ip=192.168.1.17:192.168.1.13:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0,115200

2. 移植第二个驱动(简单编写字符设备)

   
    下面移植二、Linux驱动之简单编写字符设备里编写的驱动, 驱动文件下载地址:https://pan.baidu.com/s/1huZ02mAPqQpvkKYr6Yyx4g
    移植好的文件下载地址:https://pan.baidu.com/s/1YncR7FY4SCoWR-DvfFYwjA
    首先将下载的基于linux-2.6.22.6内核驱动放到服务器上/work/tools/fs_mini/drivers目录,如下:
   
    修改Makefile如下:

KERN_DIR = /work/tools/linux-4.12

all:
	make -C $(KERN_DIR) M=`pwd` modules 

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order

obj-m	+= led_drv.o

    执行make编译如下:
   
    首先解决前两个错误,新内核没有asm/arch/regs-gpio.hasm/hardware.h这两个头文件了,直接删除,重新编译:
   
    报错没有找到copy_from_user函数,在linux-4.12内核中搜索“copy_from_user”,定位到include/linux/uaccess.h文件中,显然没有包含这个头文件,添加上“#include <linux/uaccess.h>”,重新编译:
   
    copy_from_user函数的错误没有了,出现如下警告:

led_drv.c:31: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result

    表示没有判断copy_from_user函数的返回值,修改led_drv.c第31行代码如下:

	if(copy_from_user(&val, buf, count))
		return -EFAULT;

    重新编译后如下:
   
    只剩这两个错误了,在新内核查看其它驱动发现新内核不使用这两个函数来创建类设备与销毁类设备了,使用device_createdevice_destroy函数来替代,修改如下:
   
   
    重新编译:
   
    驱动编译成功。测试方法与二、Linux驱动之简单编写字符设备测试完全一样。
   
    执行rmmod led_drv.ko卸载驱动时有如下问题:

rmmod: can't change directory to '/lib/modules': No such file or directory

    执行mkdir /lib/modules,再次执行rmmod led_drv.ko卸载驱动:

rmmod: can't change directory to '4.12.0': No such file or directory

    执行mkdir /lib/modules/4.12.0,再次执行rmmod led_drv.ko卸载驱动成功。

    后面的驱动移植就不一一贴图说明了,基本按照这几点来移植即可:
      1. 先编译驱动看报错信息
      2. 头文件找不到先删除
      3. 报错函数找不到去源码搜索,然后添加包含该函数的头文件
      4.
结构体成员改变、函数名字改变或者参数改变等则参考源码相关驱动来修改

3. 移植第三个驱动(使用中断)

    下面移植四、Linux驱动之使用中断里编写的驱动, 驱动原文件下载地址:https://pan.baidu.com/s/1gG1m92G0czNmhkSVnFmx6Q

    移植好的文件下载地址:https://pan.baidu.com/s/1O1KhO8TenzcSpFRt3z6deg

    测试方法与原文章类似。

4. 移植第四个驱动(poll机制)

    下面移植五、Linux驱动之poll机制里编写的驱动, 驱动原文件下载地址:https://pan.baidu.com/s/1j8jK6O3j6AFI1Ybmc3e2OQ

    移植好的文件下载地址:https://pan.baidu.com/s/1t_BUKOCyPbzPsnxo4wS4Cg

    测试方法与原文章类似。

5. 移植第五个驱动(异步通知)

    下面移植六、Linux驱动之异步通知里编写的驱动, 驱动原文件下载地址:https://pan.baidu.com/s/1ywybXhHZ-u6ABhZFIm5zMQ

    移植好的文件下载地址:https://pan.baidu.com/s/1gfqlw6OEX-6_NJo1QgerDw

    测试方法与原文章类似。

6. 移植第六个驱动(输入子系统)

    下面移植 十、Linux驱动之输入子系统使用里编写的驱动, 驱动原文件下载地址:https://pan.baidu.com/s/192LYbqPeYcW8xgjJGE-ymw

    移植好的文件下载地址:https://pan.baidu.com/s/10NRTFBtoNzHRNycFiNPi3A
    测试方法与原文章有出入,新出现的驱动是/dev/input/event0而不是/dev/event1。

7. 移植第七个驱动(platform总线设备驱动)

    下面移植十一、Linux驱动之platform总线设备驱动里编写的驱动, 驱动原文件下载地址:https://pan.baidu.com/s/18a-QllKCONygkFciDS7Rdg

    移植好的文件下载地址:https://pan.baidu.com/s/1JtTFoHGEhieiRTkn0lEnuA

    测试方法与原文章类似。

8. 移植第八个驱动(lcd驱动)

    下面移植十二、Linux驱动之LCD驱动里编写的驱动, 驱动原文件下载地址:https://pan.baidu.com/s/16nprVjGWn6AIrJgRaSlm7Q

    移植好的文件下载地址:https://pan.baidu.com/s/1zPzWCvMrtmteZdBQImFOaA

8.1 配置内核

    1. 重新配置内核,将内核自带的lcd驱动配置为模块。在linux-4.12内核目录下执行:
      make menuconfig
    2. 配置步骤如下:
      Device Drivers  --->
          Graphics support  --->
              Frame buffer Devices  --->
                  <M> S3C2410 LCD framebuffer support

    3. 编译内核与模块
      make uImage
      make modules

8.2 测试

    1. 重新编译linux-4.12内核,然后将uImage烧写到NAND Flash里的kernel分区去,在uboot命令行输入如下命令:
      tftp 30000000 uImage    (下载内核到30000000地址)
      nand erase.part kernel    (擦除kernel分区)
      nand write 30000000 kernel    (将内核写入kernel分区)
   
2. 服务器上编译lcd.c,并且拷贝cfbcopyarea.ko、cfbfillrect.ko、cfbimgblt.ko到网络文件系统。
      cp linux-4.12/drivers/video/fbdev/core/cfb*.ko /work/tools/fs_mini/drivers
    3. 开发板上装载驱动:
        insmod cfbcopyarea.ko
        insmod cfbfillrect.ko
        insmod cfbimgblt.ko
        insmod lcd.ko

    4. 开发板上执行:
      echo hello > /dev/tty1 (此时开发板lcd上有“hello”显示出来)
      cat lcd.ko > /dev/fb0   (此时开发板lcd花屏)
      vi /etc/inittab

# /etc/inittab
::sysinit:/etc/init.d/rcS
s3c2410_serial0::askfirst:-/bin/sh    //添加这行代码,将输出信息输出到lcd上
tty1::askfirst:-/bin/sh       
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r

    5. 安装6. 移植第六个驱动https://pan.baidu.com/s/10NRTFBtoNzHRNycFiNPi3A里的驱动:
      Insmod buttons.ko  (此时按下开发板上的按键值就能输出到lcd上了)

9. 移植第九个驱动(触摸屏驱动)

    下面移植十三、Linux驱动之触摸屏驱动里编写的驱动, 驱动原文件下载地址:https://pan.baidu.com/s/14681WySuqcifEI_pZM06AA

    移植好的文件下载地址:https://pan.baidu.com/s/1d4OQAwaAkY-zP2jNMQW5JA

9.1 配置内核

    1. 重新配置内核,将内核自带的触摸屏驱动配置为模块。在linux-4.12内核目录下执行:
      make menuconfig
    2. 配置步骤如下:
      Device Drivers  --->
          Input device support  --->
              [*]   Touchscreens  --->
                  < >   Samsung S3C2410/generic touchscreen input driver 
(将内核自带的触摸屏驱动去掉)

9.2 重烧内核

    1. 编译内核与模块
      make uImage
   
2. 将linux-4.12/arch/arm/boot下的uImage烧写到开发板,网络文件系统启动。

9.3 测试

     首先安装新驱动。在开发板目录上执行:
      insmod s3c_ts.ko
      ls /dev/input/event*

     
      此时新出现了/dev/input/event0这个设备,就是我们写的触摸屏驱动。继续执行:
      hexdump /dev/input/event0
      此时再点一下触摸屏,串口端输入如下:
     
    第1列表示hexdump序列号(如0000000)
    第2、3列表示秒(如007d 0000)
    第4、5列表示微妙(如f85b 0007)
    第6列表示type(如0003表示ABS绝对位移类型,0001表示按键类型)
    第7列表示code(如0000表示x方向ABS_X,0001表示y方向ABS_Y,0018表示ABS_PRESSURE,014a表示BTN_TOUCH)
    第8、9列表示对应type的对应code(如02a9 0000)

9.4 安装tslib

    1. 修改编译器的EV_VERSION变量
      vi /work/tools/usr/local/arm/4.4.3/arm-none-linux-gnueabi/sys-root/usr/include/linux/input.h +32
     
修改为:

#define EV_VERSION              0x010001

    2. 安装tslib
   
tslib-1.4.tar.gz放到服务器上,在ubuntu执行以下命令:
      tar xzf tslib-1.4.tar.gz  (解压文件)
      cd tslib
      ./autogen.sh
      mkdir tmp
      echo "ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache
      ./configure --host=arm-linux --cache-file=arm-linux.cache --prefix=$(pwd)/tmp
      make
 
(编译)
      make install  (安装到tmp)
      cp tmp /work/tools/fs_mini/ts_dir -rfd  (将tmp目录复制到网络文件系统目录)

    3. 网络文件系统启动开发板,进入刚才的ts_dir目录,执行:
      cd /ts_dir
      cp * / -rfd  (再将该目录里所有内容拷贝到网络文件系统目录)

    4. 安装lcd相关驱动
    lcd相关内容在8. 移植第八个驱动(lcd驱动)开发板上执行命令如下:
      insmod cfbcopyarea.ko
      insmod cfbfillrect.ko
      insmod cfbimgblt.ko
      insmod lcd.ko
 
(安装lcd相关驱动)
      insmod s3c_ts.ko  (安装触摸屏驱动)

    5. 修改 /etc/ts.conf文件,开发板上执行命令如下:
      vi /etc/ts.conf
     

    改为(去掉第二行的#号和第一个空格):
     

    5. 设置触摸屏的环境变量
    执行vi /work/tools/fs_mini/etc/profile (重启后自动执行如下命令,否则需在开发板上手动执行如下命令)修改profile文件内容如下:

export TSLIB_TSDEVICE=/dev/input/event0
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/lib/ts
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0 

    /dev/input/event0是我板子的触摸屏设备/dev/fb0lcd设备。不同板子选择对应的设备。

    6. 校验。开发板上执行如下:
      ts_calibrate  (开发板上此时会出现校验触摸点)
     

    7. 测试 。开发板上执行如下:
      ts_test  (就可以在lcd上绘画了!)
   

PS:在第1点中tmp目录复制到网络文件系统目录时,将一些测试程序如ts_calibrate 、ts_test等拷贝到了网络文件系统bin目录下。

10. 移植第十个驱动(USB鼠标驱动)

    下面移植十五、Linux驱动之USB鼠标驱动里编写的驱动, 驱动原文件下载地址:https://pan.baidu.com/s/141TOehBL1zMJUa5YF7iwNw

    移植好的文件下载地址:https://pan.baidu.com/s/1XGft6joniMJZqu4pWRnMPw
    测试方法与原文类似,注意USB驱动为/dev/input/event*

11. 移植第十一个驱动(块设备驱动)

    下面移植十六、Linux驱动之块设备驱动里编写的驱动, 驱动原文件下载地址:https://pan.baidu.com/s/1luKXCoTg2WcK7PQH5CFIAQ

    移植好的文件下载地址:https://pan.baidu.com/s/16wua_7gvynJu7JDIebNxJg

11.1 测试

    1. 首先编译驱动程序。在驱动文件目录下执行:
      make
    2. 安装驱动,在开发板上执行:
      insmod ramblock.ko
    3.
memblock块设备格式化为dos磁盘类型,在开发板上执行:
      mkdosfs /dev/ramblock    (mkdosfs工具在之前制作的文件系统fs_mini/sbin目录下)
    4. 挂载块设备到/tmp目录下,在开发板上执行:
      mount /dev/ramblock /tmp/
      出现如下错误:

yaffs: dev is 266338304 name is "ramblock" rw
yaffs: passed flags ""
yaffs: dev is 266338304 name is "ramblock" rw
yaffs: passed flags ""
mount: mounting /dev/ramblock on /tmp/ failed: Invalid argument

    根据提示应该是内核支持的文件系统错误,经过本人测试发现是由于之前移植linux-4.12内核时将如下配置项取消了:
      File systems  --->
          DOS/FAT/NT Filesystems  --->
             
< > MSDOS fs support
    make menuconfig
配置内核将MSDOS fs support选择编译进内核,再重新编译新内核即可,然后重新执行1~4的命令。
    5. 接下来在/tmp目录下创建编辑一个文件,最终都会保存在/dev/ memblock块设备里面。
      cd /tmp
      vi lzh.txt
(随便输入内容保存)
      cd /
      umount /tmp/
(不能在/tmp目录里进行卸载。此时重新挂接,刚才新建的lzh.txt依然存在)
      cat /dev/ramblock > /ramblock.bin(将/dev/ramblock磁盘内容存到bin文件里,也就是说刚才新建的lzh.txt会存入bin文件内)
    6.
使用”-o loop”将ramblock.bin文件模拟成磁盘挂接到/mntramblock.bin必须放在文件系统根目录里并在该目录执行该命令。注意:如果该磁盘没有格式化分区,或模拟磁盘的文件生成前没有格式化,会挂接不成功,提示“mount: you must specify the filesystem type”)如下:
      mount -o loop ramblock.bin /mnt
    mnt
目录下就有ramblock.bin文件里的内容了,如下:
   
    7. 磁盘分区   
        7.1 重装驱动
        7.2 fdisk /dev/ramblock    (磁盘分区命令)
        7.3 依次执行以下命令:
            m (查看帮助)
            n (添加分区)
            p (主分区)
            1 (第一个主分区)
            1 (最外面的几个柱面作为第一个主分区开始,这里设为1)
            5 (最外面的几个柱面作为第一个主分区结束,这里设为5)

     重复7.3步骤再添加第二个主分区,完成后输入p可以查看分区,输入w将配置写入分区表(该磁盘里的第一个扇区))。
    8. 查看效果,执行如下:
      ls /dev/ramblock* -l
   

    还可以分别进行磁盘格式化:
      mkdosfs /dev/ramblock1
      mkdosfs /dev/rambloc2

    分别挂接磁盘:
      mount /dev/ramblock1 /tmp/
      mount /dev/ramblock2 /tmp/

12. 移植第十二个驱动(nand flash驱动)

    下面移植十七、Linux驱动之nand flash驱动里编写的驱动, 驱动原文件下载地址:链接:https://pan.baidu.com/s/1r5X3wDoqsoNxDR6vQp0YuA

    移植好的文件下载地址:https://pan.baidu.com/s/1j9SUmuQQ08cfHY7Q3VoybA

    测试方法与原文章类似。

13. 移植第十三个驱动(nor flash驱动)

    下面移植十八、Linux驱动之nor flash驱动里编写的驱动, 驱动原文件下载地址:链接:https://pan.baidu.com/s/13rHDJAKaQAgYIGiymvFvZg

    移植好的文件下载地址:https://pan.baidu.com/s/1T8MYk7HAITrj47VOGHxEOw

    测试方法与原文章类似。

14. 移植第十四个驱动(网卡驱动)

    下面移植十九、Linux驱动之虚拟网卡驱动里编写的驱动, 驱动原文件下载地址:链接:https://pan.baidu.com/s/1O3gRbHUui3UR2qV8lFY9Sw

    移植好的文件下载地址:https://pan.baidu.com/s/1z670iudTO8SoR0O8XDM7wQ

    测试方法与原文章类似。

 

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值