基本信息

硬件信息

硬件平台:T507 (Android 10 Linux 4.9)

模组型号:EC200U-CN(Cat1)(展讯芯片)

相关文件

代理提供

longan/kernel/linux-4.9/drivers/net/usb/qmi_wwan_q.c
android/vendor/aw/public/prebuild/lib/librild/lib/lib32/libquectel-ril.so
android/vendor/aw/public/prebuild/lib/librild/lib/lib64/libquectel-ril.so

内核驱动

longan/kernel/linux-4.9/drivers/net/usb/Makefile
longan/kernel/linux-4.9/drivers/net/usb/qmi_wwan_q.c
longan/kernel/linux-4.9/drivers/usb/serial/option.c
longan/kernel/linux-4.9/drivers/usb/serial/usb_wwan.c

系统适配

android/hardware/ril/rild/rild.rc
android/hardware/ril/rild/radio.xml
android/device/softwinner/common/sepolicy/vendor/rild.te
android/vendor/aw/public/prebuild/lib/librild/radio_common.mk
android/vendor/aw/public/prebuild/lib/librild/lib/lib32/libquectel-ril.so
android/vendor/aw/public/prebuild/lib/librild/lib/lib64/libquectel-ril.so

驱动类型

  • GobiNet Driver

    会生成 /dev/qcqmiX 设备节点和虚拟的 ethX 网卡(2.6.39 以下版本为 usbX)。

    内核配置 驱动文件
    CONFIG_USB_NET_DRIVERS
    CONFIG_USB_USBNET
    linux-4.9/drivers/net/usb/GobiNet/GobiUSBNet.c
    linux-4.9/drivers/net/usb/GobiNet/QMIDevice.c
    linux-4.9/drivers/net/usb/GobiNet/QMI.c
  • qmi_wwan_q Driver

    会生成 /dev/cdc-wdmX 设备节点和虚拟的 wwanX 网卡。

    内核配置 驱动文件
    CONFIG_USB_NET_DRIVERS
    CONFIG_USB_USBNET
    CONFIG_USB_NET_QMI_WWAN
    CONFIG_USB_WDM
    linux-4.9/drivers/net/usb/qmi_wwan.c
    linux-4.9/drivers/net/usb/qmi_wwan_q.c
  • ACM/ECM/RNDIS/NCM/MBIM Driver

    会生成 /dev/ttyUSB0 ~ /dev/ttyUSB6 和虚拟的 usbX 网卡。

    驱动类型 内核配置 驱动文件
    ACM CONFIG_USB_ACM linux-4.9/drivers/usb/serial/option.c
    linux-4.9/drivers/usb/serial/usb_wwan.c
    linux-4.9/drivers/net/usb/cdc-acm.c
    ECM CONFIG_USB_NET_DRIVERS
    CONFIG_USB_USBNET
    CONFIG_USB_NET_CDCETHER
    linux-4.9/drivers/usb/serial/option.c
    linux-4.9/drivers/usb/serial/usb_wwan.c
    linux-4.9/drivers/net/usb/cdc-ether.c
    RNDIS CONFIG_USB_NET_DRIVERS
    CONFIG_USB_USBNET
    CONFIG_USB_NET_CDCETHER
    linux-4.9/drivers/usb/serial/option.c
    linux-4.9/drivers/usb/serial/usb_wwan.c
    linux-4.9/drivers/net/usb/rndis_host.c
    NCM CONFIG_USB_NET_DRIVERS
    CONFIG_USB_USBNET
    CONFIG_USB_NET_CDCETHER
    linux-4.9/drivers/usb/serial/option.c
    linux-4.9/drivers/usb/serial/usb_wwan.c
    linux-4.9/drivers/net/usb/cdc_ncm.c
    MBIM CONFIG_USB_NET_DRIVERS
    CONFIG_USB_USBNET
    CONFIG_USB_NET_CDCETHER
    linux-4.9/drivers/usb/serial/option.c
    linux-4.9/drivers/usb/serial/usb_wwan.c
    linux-4.9/drivers/net/usb/cdc_mbim.c

驱动适配

这里使用 ECM 的驱动方式,参考《Quectel_UMTS_LTE_5G_Linux_USB_Driver_User_Guide_V3.0.pdf》

驱动移植

未涉及到电源控制,调试时使用的是开发板,手动给模组开机,因此下列会缺少电源控制的步骤。

  • 涉及文件列表

    // 需要修改的内核配置
    longan/kernel/linux-4.9/.config // 需要修改的驱动文件
    longan/kernel/linux-4.9/drivers/usb/serial/option.c
    longan/kernel/linux-4.9/drivers/usb/serial/usb_wwan.c // 需要用到的驱动文件
    longan/kernel/linux-4.9/drivers/net/usb/cdc-acm.c
    longan/kernel/linux-4.9/drivers/net/usb/cdc-ether.c
  • 在 option_ids 列表内增加 EC200U-CN 的 PID\VID, 这样才能识别到该 USB 设备为串口设备,文档内可查。

    // linux-4.9/drivers/usb/serial/option.c
    static const struct usb_device_id option_ids[] = {
    #ifdef SUPPORT_QUECTEL
    { USB_DEVICE(0x2C7C, 0x0901) }, // support EC200U/EG915U
    #endif
    ......
    }
  • 一个 USB 设备可以有多个功能不同的接口,在 option_ids 添加该设备的 PID\VID 后,会导致该设备的所有接口都会绑定到 USB Serial Option 驱动上,导致 USBNet 驱动接口无法正常工作,因此需要在 option_probe 中根据类码、接口索引、端点数量、子类码将 USBNet 的接口排除出来。

    // linux-4.9/drivers/usb/serial/option.c
    static int option_probe(struct usb_serial *serial, const struct usb_device_id *id)
    {
    ......
    #ifdef SUPPORT_QUECTEL
    if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
    __u16 idProduct = le16_to_cpu(serial->dev->descriptor.idProduct);
    struct usb_interface_descriptor *intf = &serial->interface->cur_altsetting->desc;
    if (intf->bInterfaceClass != 0xFF || intf->bInterfaceSubClass == 0x42) {
    //ECM, RNDIS, NCM, MBIM, ACM, UAC, ADB
    return -ENODEV;
    }
    if ((idProduct&0xF000) == 0x0000) {
    //MDM interface 4 is QMI
    if (intf->bInterfaceNumber == 4 && intf->bNumEndpoints == 3 && intf->bInterfaceSubClass == 0xFF && intf->bInterfaceProtocol == 0xFF)
    return -ENODEV;
    }
    }
    #ifdef SUPPORT_QUECTEL_AUTO_SUSPEND
    //For USB Auto Suspend
    if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
    pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
    usb_enable_autosuspend(serial->dev);
    }
    #endif
    #ifdef SUPPORT_QUECTEL_REMOTE_WAKEUP
    //For USB Remote Wakeup
    if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
    device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
    }
    #endif
    #endif
    /* Store the device flags so we can use them during attach. */
    usb_set_serial_data(serial, (void *)device_flags);
    return 0;
    }
  • 根据USB协议的要求,在批量输出传输期间,通过设置 URB_ZERO_PACKET 标志来添加处理零数据包的机制。

    diff --git a/longan/kernel/linux-4.9/drivers/usb/serial/usb_wwan.c b/longan/kernel/linux-4.9/drivers/usb/serial/usb_wwan.c
    old mode 100644
    new mode 100755
    index 3dfdfc8..e56b275
    --- a/longan/kernel/linux-4.9/drivers/usb/serial/usb_wwan.c
    +++ b/longan/kernel/linux-4.9/drivers/usb/serial/usb_wwan.c
    @@ -36,6 +36,8 @@
    #include <linux/serial.h>
    #include "usb-wwan.h" +#define SUPPORT_QUECTEL 1
    +
    /*
    * Generate DTR/RTS signals on the port using the SET_CONTROL_LINE_STATE request
    * in CDC ACM.
    @@ -504,6 +506,14 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
    usb_fill_bulk_urb(urb, serial->dev,
    usb_sndbulkpipe(serial->dev, endpoint) | dir,
    buf, len, callback, ctx);
    +
    +#ifdef SUPPORT_QUECTEL
    + if (dir == USB_DIR_OUT) {
    + struct usb_device_descriptor *desc = &serial->dev->descriptor;
    + if (desc->idVendor == cpu_to_le16(0x2C7C))
    + urb->transfer_flags |= URB_ZERO_PACKET;
    + }
    +#endif return urb;
    }
  • 增加 USB 控制器复位后恢复操作

    // linux-4.9/drivers/usb/serial/option.c
    static struct usb_serial_driver option_1port_device = {
    ......
    #ifdef SUPPORT_QUECTEL
    .reset_resume = usb_wwan_resume,
    #endif
    };
  • 在内核中启用 USB SERIAL 配置

    CONFIG_USB_SERIAL=y
    CONFIG_USB_SERIAL_WWAN=y
    CONFIG_USB_SERIAL_OPTION=y
    CONFIG_USB_ACM=y
    CONFIG_USB_NET_DRIVERS=y
    CONFIG_USB_USBNET=y
    CONFIG_USB_NET_CDCETHER=y

完成标志

  • 内核日志

    [    6.254850] usb 2-1: not running at top speed; connect to a high speed hub
    [ 6.284643] cdc_ether 2-1:1.0 usb0: register 'cdc_ether' at usb-sunxi-ohci-1, CDC Ethernet Device, 02:4b:b3:b9:eb:e5
    [ 6.293812] vdc: Waited 0ms for vold
    [ 6.304202] option 2-1:1.2: GSM modem (1-port) converter detected
    [ 6.311813] usb 2-1: GSM modem (1-port) converter now attached to ttyUSB0
    [ 6.321412] option 2-1:1.3: GSM modem (1-port) converter detected
    [ 6.328994] usb 2-1: GSM modem (1-port) converter now attached to ttyUSB1
    [ 6.338217] option 2-1:1.4: GSM modem (1-port) converter detected
    [ 6.345935] usb 2-1: GSM modem (1-port) converter now attached to ttyUSB2
    [ 6.355219] option 2-1:1.5: GSM modem (1-port) converter detected
    [ 6.362914] usb 2-1: GSM modem (1-port) converter now attached to ttyUSB3
    [ 6.372287] option 2-1:1.6: GSM modem (1-port) converter detected
    [ 6.379951] usb 2-1: GSM modem (1-port) converter now attached to ttyUSB4
    [ 6.389179] option 2-1:1.7: GSM modem (1-port) converter detected
    [ 6.396772] usb 2-1: GSM modem (1-port) converter now attached to ttyUSB5
    [ 6.406217] option 2-1:1.8: GSM modem (1-port) converter detected
    [ 6.413736] usb 2-1: GSM modem (1-port) converter now attached to ttyUSB6
  • 虚拟串口

    mercury-demo:/ # ls -l /dev/ttyU*
    crwxrwxrwx 1 system system 188, 0 2022-12-30 21:00 /dev/ttyUSB0
    crwxrwxrwx 1 system system 188, 1 2022-12-30 21:00 /dev/ttyUSB1
    crwxrwxrwx 1 system system 188, 2 2022-12-30 21:00 /dev/ttyUSB2
    crwxrwxrwx 1 system system 188, 3 2022-12-30 21:00 /dev/ttyUSB3
    crw------- 1 root root 188, 4 2022-12-30 21:00 /dev/ttyUSB4
    crw------- 1 root root 188, 5 2022-12-30 21:00 /dev/ttyUSB5
    crw------- 1 root root 188, 6 2022-12-30 21:00 /dev/ttyUSB6
  • 虚拟网卡

    mercury-demo:/ # ifconfig -a
    ......
    usb0 Link encap:Ethernet HWaddr 02:4b:b3:b9:eb:e5 Driver cdc_ether
    BROADCAST MULTICAST MTU:1500 Metric:1
    RX packets:0 errors:0 dropped:0 overruns:0 frame:0
    TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:0 TX bytes:0
    ......

系统适配

主要是修改 ril 库相关的文件,实现拨号和衔接数据通路。

ril 库移植

  • 涉及文件列表

    android/hardware/ril/rild/radio.xml
    android/hardware/ril/rild/rild.rc
    android/device/softwinner/common/sepolicy/vendor/rild.te
    android/vendor/aw/public/prebuild/lib/librild/radio_common.mk
    android/vendor/aw/public/prebuild/lib/librild/lib/lib32/libquectel-ril.so
    android/vendor/aw/public/prebuild/lib/librild/lib/lib64/libquectel-ril.so
  • 构建文件拷贝脚本,将移远的 ril 库以及 apns-conf.xml、ql-ril.conf 文件更新到系统指定目录下

    android/vendor/aw/public/prebuild/lib/librild/lib/lib32/libquectel-ril.so
    android/vendor/aw/public/prebuild/lib/librild/lib/lib64/libquectel-ril.so
  • 修改 ril-daemon 服务启动参数

    diff --git a/android/hardware/ril/rild/rild.rc b/android/hardware/ril/rild/rild.rc
    old mode 100644
    new mode 100755
    index f6beb54..d259206
    --- a/android/hardware/ril/rild/rild.rc
    +++ b/android/hardware/ril/rild/rild.rc
    @@ -1,5 +1,5 @@
    service vendor.ril-daemon /vendor/bin/hw/rild
    class main
    - user radio
    - group radio cache inet misc audio log readproc wakelock
    + user root
    + group radio cache inet misc audio sdcard_rw log
    capabilities BLOCK_SUSPEND NET_ADMIN NET_RAW
  • 选择编译 android.hardware.radio@1.0

    diff --git a/android/vendor/aw/public/prebuild/lib/librild/radio_common.mk b/android/vendor/aw/public/prebuild/lib/librild/radio_common.mk
    old mode 100644
    new mode 100755
    index a7206b6..8ef8bd0
    --- a/android/vendor/aw/public/prebuild/lib/librild/radio_common.mk
    +++ b/android/vendor/aw/public/prebuild/lib/librild/radio_common.mk
    @@ -5,7 +5,7 @@ RIL_LIB_BASENAME ?= libsoftwinner-ril-$(RIL_LIB_VERSION) # 3G Data Card Packages
    PRODUCT_PACKAGES += \
    - android.hardware.radio@1.4 \
    + android.hardware.radio@1.0 \
    android.hardware.radio.config@1.1-service \
    android.hardware.radio.config@1.1 \
    pppd_vendor \
  • 修改 hidl 使用 radio 1.0 版本

    diff --git a/android/hardware/ril/rild/radio.xml b/android/hardware/ril/rild/radio.xml
    old mode 100644
    new mode 100755
    index 866b401..885b150
    --- a/android/hardware/ril/rild/radio.xml
    +++ b/android/hardware/ril/rild/radio.xml
    @@ -1,12 +1,11 @@
    <manifest version="1.0" type="device" target-level="4">
    - <hal format="hidl">
    - <name>android.hardware.radio</name>
    - <transport>hwbinder</transport>
    - <version>1.4</version>
    - <interface>
    - <name>IRadio</name>
    - <instance>slot1</instance>
    - </interface>
    - <fqname>@1.2::ISap/slot1</fqname>
    - </hal>
    + <hal format="hidl">
    + <name>android.hardware.radio</name>
    + <transport>hwbinder</transport>
    + <version>1.0</version>
    + <interface>
    + <name>IRadio</name>
    + <instance>slot1</instance>
    + </interface>
    + </hal>
    </manifest>
  • 修改 SELinux 权限

    diff --git a/android/device/softwinner/common/sepolicy/vendor/rild.te b/android/device/softwinner/common/sepolicy/vendor/rild.te
    index 8fdddc5..d29b4a2 100755
    --- a/android/device/softwinner/common/sepolicy/vendor/rild.te
    +++ b/android/device/softwinner/common/sepolicy/vendor/rild.te
    @@ -5,6 +5,7 @@ allow rild vendor_file:file execute_no_trans;
    allow rild vendor_ril_prop:file { read getattr open };
    allow rild vendor_ril_prop:property_service set;
    allow rild vendor_default_prop:file {open read getattr};
    +allow rild rild:packet_socket create_socket_perms_no_ioctl; allow rild vendor_toolbox_exec:file execute_no_trans;
    allow rild vendor_shell_exec:file execute_no_trans;

完成标志

  • 查看系统属性

    mercury-demo:/ # getprop | grep ril
    getprop | grep ril
    [gsm.version.ril-impl]: [Quectel_Android_RIL_Driver_V3.5.0]
    [init.svc.vendor.ril-daemon]: [running]
    [ro.boottime.vendor.ril-daemon]: [9918673186]
    [ro.radio.noril]: [false]
    [vendor.rild.libargs]: [-d/dev/ttyUSB2]
    [vendor.rild.libpath]: [/vendor/lib64/libquectel-ril.so]
  • 查看 raido log 信息:logcat -b radio -v time

    D/RILD    ( 1917): **RIL Daemon Started**
    D/RILD ( 1917): **RILd param count=3**
    D/RILD ( 1917): RIL_Init argc = 4 clientId = 0
    D/RILC ( 1917): Quectel RIL Version: Quectel_Android_RIL_Driver_V3.5.0
    D/RILC ( 1917): libquectel-ril build info: On branch master Your branch is up to date with 'origin/master'. e1552af97d835442b8f39f69118082650eb33081 09/27/22_14:42:59
    D/RILC ( 1917): t-prop_value is 2
    D/RILC ( 1917): before_dot is 10
    D/RILC ( 1917): [ro.build.version.release]: [10.0]
    D/RILC ( 1917): Android Version: 100, RIL_VERSION: 12 / 12
    E/RILC ( 1917): '/vendor/manifest.xml' not exist.
    D/RILC ( 1917): 1.1</version>
    D/RILC ( 1917): IRadioVersion 1.1
    D/RILC ( 1917): IRadioConfigVersion 1.-1
    ......
    D/SubscriptionController( 2450): [getPhoneId] asked for default subId=1
    D/SubscriptionController( 2450): [getPhoneId] asked for default subId=1
    D/SETUP_DATA_CALL( 1917): do_dhcp_request ipaddr=10.192.252.55, prefixLength=24
    D/SETUP_DATA_CALL( 1917): ql_set_data_call_info pdp=1, ifname=usb0, iptype=4, ipaddr=10.192.252.55
    E/SETUP_DATA_CALL( 1917): ifc_add_address() = -22
    D/SETUP_DATA_CALL( 1917): deactivateManually is 0
    D/SETUP_DATA_CALL( 1917): usb0 IPv4 Address: 10.192.252.55
    D/SETUP_DATA_CALL( 1917): usb0 IPv6 Address: 0:0:fe80::4b:b3ff
    D/SETUP_DATA_CALL( 1917): usb0 IP Address: 10.192.252.55
    D/SETUP_DATA_CALL( 1917): get_local_ip: 10.192.252.55, cost 4 sec

测试验证

  • 查看网卡是否出现 usb0 网卡,也检查是否有获取到 ip 地址:

    mercury-demo:/ # ifconfig
    ifconfig
    eth1 Link encap:Ethernet HWaddr 36:c9:e3:f1:b8:05 Driver sunxi-gmac
    UP BROADCAST MULTICAST MTU:1500 Metric:1
    RX packets:0 errors:0 dropped:0 overruns:0 frame:0
    TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:0 TX bytes:418
    Interrupt:66 lo Link encap:Local Loopback
    inet addr:127.0.0.1 Mask:255.0.0.0
    inet6 addr: ::1/128 Scope: Host
    UP LOOPBACK RUNNING MTU:65536 Metric:1
    RX packets:16 errors:0 dropped:0 overruns:0 frame:0
    TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1
    RX bytes:1920 TX bytes:1920 eth0 Link encap:Ethernet HWaddr 36:c9:e3:f1:b8:05 Driver sunxi-gmac
    UP BROADCAST MULTICAST MTU:1500 Metric:1
    RX packets:0 errors:0 dropped:0 overruns:0 frame:0
    TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:0 TX bytes:168
    Interrupt:65 usb0 Link encap:Ethernet HWaddr 02:4b:b3:b9:eb:e5 Driver cdc_ether
    inet addr:10.209.124.163 Bcast:10.209.124.255 Mask:255.255.255.0
    inet6 addr: fe80::4b:b3ff:feb9:ebe5/64 Scope: Link
    UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
    RX packets:123 errors:0 dropped:0 overruns:0 frame:0
    TX packets:175 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:20877 TX bytes:23570
  • 查看是否能正常 ping 通外网:

    mercury-demo:/ # ping www.qq.com
    ping www.qq.com
    PING ins-r23tsuuf.ias.tencent-cloud.net (101.91.22.57) 56(84) bytes of data.
    64 bytes from 101.91.22.57: icmp_seq=1 ttl=48 time=63.5 ms
    64 bytes from 101.91.22.57: icmp_seq=2 ttl=48 time=55.8 ms
    64 bytes from 101.91.22.57: icmp_seq=3 ttl=48 time=55.1 ms
    64 bytes from 101.91.22.57: icmp_seq=4 ttl=48 time=55.8 ms
    64 bytes from 101.91.22.57: icmp_seq=5 ttl=48 time=54.9 ms
    64 bytes from 101.91.22.57: icmp_seq=6 ttl=48 time=62.9 ms
    64 bytes from 101.91.22.57: icmp_seq=7 ttl=48 time=54.8 ms
    64 bytes from 101.91.22.57: icmp_seq=8 ttl=48 time=55.4 ms
    64 bytes from 101.91.22.57: icmp_seq=9 ttl=48 time=54.8 ms

调试技巧

模组测试

可以先将模组接到 PC 端,使用串口手动下发 AT 指令测试,确定模组可以正常使用。

AT +CPIN?
CPIN: READY OK
AT+QNWINFO
+QNWINFO:"FDD LTE","46011","LTE BAND 1",100 OK
AT+COPS?
+COPS: 0,0,"CHN-CT",7 OK
AT+QIACT=1
OK
AT+QIACT?
+QIACT: 1,1,1,"10.193.145.135" OK
AT+QPING=1,"www.baidu.com"
OK
+QPING: 0,"101.91.22.57",32,78,255
+QPING: 0,"101.91.22.57",32,83,255
+QPING: 0,"101.91.22.57",32,80,255

日志提取

启动日志保存,在 data 目录下创建 quectel_debug_log 目录,libquectel-ril.so 会自动生成日志文件。

mkdir /data/quectel_debug_log
mercury-demo:/data/quectel_debug_log $ ls -l
-rw-r--r-- 1 Administrator 197121 788266 12月 30 22:10 1229_144251_logcat.txt
-rw-r--r-- 1 Administrator 197121 37788 12月 30 22:10 1229_144251_radio.txt
-rw-r--r-- 1 Administrator 197121 87888 12月 30 22:10 1229_144251_usbmonlog.txt
-rw-r--r-- 1 Administrator 197121 77156 12月 30 22:10 1229_144316_dmesg_mainLoop.txt

【随笔记】T507 Android10 EC200U-CN 4G Cat1 移植的更多相关文章

  1. JZ2440使用笔记之熟悉uboot和Linux的移植

    目录 一.点亮开发板:移植uboot.Linux内核.文件系统 1.1 配置上位机交叉编译环境 1.2 制作U-boot镜像文件 1.3 通过oflash.exe / openJTAG 烧写u-boo ...

  2. LwIP应用开发笔记之一:LwIP无操作系统基本移植

    现在,TCP/IP协议的应用无处不在.随着物联网的火爆,嵌入式领域使用TCP/IP协议进行通讯也越来越广泛.在我们的相关产品中,也都有应用,所以我们结合应用实际对相关应用作相应的总结. 1.技术准备 ...

  3. 【学习笔记】XR872 GUI Littlevgl 8.0 移植(文件系统)

    不得不提 在移植的过程中,发现 LVGL 的文件操作接口并不十分完善,在我看来, LVGL 的文件操作接口,应该更多的是为了 LVGL 内部接口方便读取资源文件而设立的,例如读取图像文件,加载字库文件 ...

  4. 【学习笔记】XR872 GUI Littlevgl 8.0 移植(显示部分)

    LVGL 介绍 官方网站:LVGL - Light and Versatile Embedded Graphics Library 源码位置:GitHub - lvgl/lvgl: Powerful ...

  5. VueJs 学习笔记

    VueJs学习笔记 参考资料:https://cn.vuejs.org/ 特效库:TweenJS(补间动画库)  VelocityJS(轻量级JS动画库) Animate.css(CSS预设动画库) ...

  6. Spring Security OAuth 笔记

    1  单点登录 关于单点登录的原理,我觉得下面这位老哥讲的比较清楚,有兴趣可以看一下,下面我把其中的重点在此做个笔记总结 https://juejin.cn/post/6844904079274197 ...

  7. 我们是怎么管理QQ群的

    文章背景:腾讯平台上的qq群数以千万百万计,但99%的在吹水扯蛋,从早上的问好开始,到晚上的晚安,无一不浪费青春之时间,看之痛心,无力改变,只好自己建了一个,希望能以此来改变群内交流的氛围或环境. 以 ...

  8. Markdown 是什么

    tags: Markdown tags && syngx ###Markdown 是什么Markdown 是一种轻量级标记语言,创始人为约翰·格鲁伯(John Gruber).它允许人 ...

  9. 拷贝Java项目报错

    经常需要将一个项目,导出,然后发给同事,或者是自己用另一个Eclipse工具打开. 这时,导入项目后,就会出现各种各样的问题.大牛笔记:www.weixuehao.com 代码相同,环境不同,主要是修 ...

随机推荐

  1. CF815D

    模拟赛遇到的题目. 看各位大佬的做法都不是很懂,于是自己一通乱搞搞出来了. 题意 翻译清楚的不能再清楚了 做法 为了方便叙述,我们将每个给出的三元组表示成 \((a_i,b_i,c_i)\),所选的三 ...

  2. Halcon使用MeasurePos来实现检测边缘点

    (1)为了提高性能,测量句柄只需要初始化一次: 参数:测量矩形的中心点行坐标,测量矩形中心的列坐标,测量矩形的角度,测量矩形的宽,测量矩形的高,待处理图像的宽,待处理图像的高,使用的算法,输出测量句柄 ...

  3. Marktext语法——Emoji表情大全

    个人名片: 对人间的热爱与歌颂,可抵岁月冗长 Github‍:念舒_C.ying CSDN主页️:念舒_C.ying 个人博客 :念舒_C.ying People ️ ️ ️ ️ ‍♀️ ‍♀️ ‍♂ ...

  4. 数据结构(二):括号匹配(C++,栈)

    好家伙,写题,题目代码在最后 来吧, 1.栈 栈(stack)又名堆栈,它是一种运算受限的线性表.限定仅在表尾进行插入和删除操作的线性表. 这一端被称为栈顶,相对地,把另一端称为栈底. 向一个栈插入新 ...

  5. RocketMQ系列-搭建Namesrv源码调试环境

    RocketMQ系列-搭建Namesrv源码调试环境 在学习任何一个技术框架的时候,我们通常都是先了解是什么,有什么作用.解决什么问题.设计亮点和设计思想是什么:当然对于技术学习上来说,这只是纸上谈兵 ...

  6. Tkinter根据屏幕分辨率最大化适应屏幕

    还不能够实现所有组件随分辨率自动变化 # 实现的是界面覆盖整个屏幕 from tkinter import * import win32api, win32con # 获取屏幕的分辨率 width = ...

  7. On Java 8读书笔记

    第一章 什么是对象 1.1 抽象的历程 "对象":问题空间中的元素及其解决方案空间中的具体呈现. 理念即是通过添加各种新的对象,可以将程序改编为一种描述问题的语言. 对象是具有状态 ...

  8. python模块的含义

    目录 模块简介 模块的本质 python模块的历史 python模块的表现形式 模块的分类 导入模块的两种句式 强调 import句式 import流程推导 练习 from...import...句式 ...

  9. LeetCode HOT 100:在排序数组中查找元素的第一个和最后一个位置

    题目:34. 在排序数组中查找元素的第一个和最后一个位置 题目描述: 给你一个递增数组,和一个目标值target,最终返回数组中第一次出现target和最后一次出现target的下标.如果该数组中没有 ...

  10. Mattermost 笔记

    目录 部署 配置 客户端 桌面程序 Android 使用 扩展 Jenkins Hubot 机器人 Jira GitHub Mattermost 是一个开源.可私有化部署的在线通讯平台,可以和Gith ...