正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6.4--汇编LED驱动程序

news2024/11/15 10:39:53

 前言:

本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。

引用:

正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com

《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》第 8.1 章

《正点原子资料_A盘/02开发板原理图/IMX6ULL_MINI_V2.2(Mini底板原理图).pdf》

  • 资料盘 开发板资料链接: https://pan.baidu.com/s/1j5Jzbdx9i-g0cWIi3wf2XA 提取码:ag1u


正文:

本文是 “正点原子[第二期]Linux之ARM(MX6U)裸机篇--第6.4讲” 的读书笔记。第6.4讲是编译汇编 led.s 程序,并烧录到SD卡。

1. 编写汇编 led.s 程序

在之前的两节博文中,通过查看正点云子 I.MX6ULL ALPHA/Mini 开发板电路原理图,已经从"正点原子I.MX6ULL Mini"电路原理图中知道Mini开发板的 LED 灯接在 I.MX6ULL 芯片的 GPIO1_IO03 管脚。接下来,我们需要编写 led.s 汇编程序来配置 I.MX6ULL 芯片 GPIO1_IO03  GPIO 管脚,来让 gpio1_io03 输出高电平/低电平来控制LED灯的亮灭。

1.1 使用I.MX6ULL GPIO 的步骤

  1. 使能I.MX6ULL 芯片GPIO外设时钟,通过寄存器 CCM_CCGRx (x为从0~6,共7个 CCM_CCGRx寄存器)来使能I.MX6U芯片外设时钟。
  2. 配置IOMUXC_SW_MUX_CTL_PAD_CPIO1_IO03 寄存器来配置芯片IO 复用为 GPIO模式。
  3. 配置IOMUXC_SW_PAD_CTL_PAD_CPIO1_IO03 寄存器来配置芯片IO 的电气特性,如压摆率,速率,等。
  4. 在第2,3 两步复用IO为GPIO模式,并且配置了IO的电气特性图之后。写 GPIO 寄存器开控制GPIO是输入/输出,GPIO输出低电平/高电平。通过寄存器 GPIOx_DR,GPIOx_GDR 两个寄存器。

1.2 编写I.MX6U led.s 汇编程序使用芯片 GPIO 管脚

根据上面的分析,我们按照上面的4个步骤来变下 I.MX6U 的汇编 led.s 程序,通过控制I.MX6U 新品的 GPIO 引脚的方式开控制LED灯的亮灭。

1.2.1 配置 I.MX6U CCM_CCGRx 外设时钟寄存器

从《IMX6ULL参考手册.pdf》手册第18章描述了 I.MX6U 的外设时钟寄存器,打开 CCM_CCGRx 时钟寄存器为 32 位的寄存器,从参考手册中可以看到每2个bit控制一个外设的时钟是否打开,如果外设时钟关闭可以达到省电的效果。参考手册中共有CCM_CCGR0~CCM_CCGR6 共7个芯片外设时钟控制寄存器,为了简单方便起见我们在 led.s 汇编程序中使能所有的外设时钟,也让就是让 

CCM_CCGRx = 0xFFFF_FFFF

CCM_CCGRx 寄存器的地址需要从参考手册中查询。

从参考手册中可以查到 CCM_CCGR0 ~ CCM_CCGR6 寄存器的地址,通过 ARM 汇编指令 LDR, STR 来配置这些寄存器为0xFFFF_FFFF,来使能所有I.MX6U 芯片的所有外设时钟。对应寄存器的地址从 0x020C_4068 开始,到 0x020C_4080 结束。

    /* 使能所有 I.MX6U 芯片外设时钟 */
    ldr r0, =0x020C4068     @CCM_CCGR0
    ldr r1, =0xFFFFFFFF     @将0xFFFFFFFF写入CCM_CCGR0写入的数据
    str r1, [r0]

    ldr r0, =0x020C406C     @CCM_CCGR1
    str r1, [r0]

    ldr r0, =0x020C4070     @CCM_CCGR2
    str r1, [r0]

    ldr r0, =0x020C4074     @CCM_CCGR3
    str r1, [r0]

    ldr r0, =0x020C4078     @CCM_CCGR4
    str r1, [r0]

    ldr r0, =0x020C407C     @CCM_CCGR5
    str r1, [r0]

    ldr r0, =0x020C4080     @CCM_CCGR6
    str r1, [r0]
1.2.2 配置 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 寄存器,复用IO为GPIO

配置 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 寄存器,复用IO为GPIO。查阅参考手册,对应寄存器地址为 0x020E_0068 。

从参考手册可以看到,配置 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 的比特位 bit[3:0] = 0x5,复用该 IO 位 GPIO 模式。编写 led.s 汇编代码,配置如下

    /* 配置 GPIO1_IO03 PIN 复用为GPIO,也就是设置
     * IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 5
     * 寄存器地址为 0X020E_0068
     */
    ldr r0, =0x020E0068     @IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03
    ldr r1, =0x5            @将0x5写入到 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 中
    str r1, [r0]
1.2.3 配置 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 寄存器,配置IO电气特性

配置 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 寄存器,复用IO为GPIO。查阅参考手册,对应寄存器地址为 0x020E_02F4 。

查阅参考手册,该寄存器的 bit[31:17]保留没有使用,bit[16:0] 这写bit位通过写对应bit位的值来设置IO的电气特性,例如,压摆率,速率,上拉/保持器,等IO的电气特性。对照这参考手册中 bit 位定义的物理电气特性,我们设置该 IO 的特性如下。

    /* 配置GPIO1_IO03 的电气属性(上下拉,偏摆率),也就是寄存器
     * IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03
     * IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 寄存器地址为 0X020E_02F4
     *
     *
     * bit0:          压摆率          值: 0       值含义:低速率
     * bit2-1:         保留未使用      值: NA      
     * bit5-3:         驱动能力        值: 110     值含义:R0/6 数值越小,驱动能里越强
     * bit7-6:         速率            值: 10      值含义:100MHz
     * bit 10-8:       保留未使用       值: NA 
     * bit11:          开路输出         值: 0       值含义:关闭开路输出
     * bit12:          上拉/保持使能     值:1       值含义: 使能 Pull/Keeper
     * bit13:          上拉/保持选择     值: 0       值含义:选择Keeper
     * bit15-14:       设置上下拉电阻   值: 00       值含义: 100K Ohm Pull Down
     * bit16:          hyst磁滞(输入有效) 值:0      值含义: Hystersis Disable 磁滞关闭, 关闭Hys
     * bit31-17:       保留未使用 
     */

使用 Windows 自带的计算器,通过二进制模式上设置上相应的寄存器bit值为 0/1,来看下最终应该写到寄存器里的值。

按照我们预期的 IO 电气特性,设置了寄存器上对应bit位之后,得到需要写到寄存器里的值为 0x10B0。编写 led.s 汇编代码,配置如下

    ldr r0, =0x020E02F4
    ldr r1, =0x10B0
    str r1, [r0]
1.2.4  配置 GPIOx_DR, GPIOx_GDIR 寄存器

在前面第2,3 步配置 I.MX6U 的管脚,把 IO 复用为GPIO模式,并且设置 IO 的电气特性之后,现在 PAD_GPIO1_IO03 已经被配置为复用为 GPIO 管脚,并且配置了管脚的 IO 电气特性()包括压摆率,速率,上拉电阻,驱动能力)。现在可以开始配置 GPIO1 的GPIO特性,配置GPIO是输入还是输出,GPIO输出是低电平还是输出高电平。

《IMX6ULL参考手册.pdf》手册第28章给出了I.MX6U 芯片GPIO 的使用说明。I.MX6U 芯片的GPIO分为 GPIO0~GPIO5 共6组寄存器。

    @ I.MUX6U的GPIO一共有5组:GPIO1,GPIO2,GPIO2,GPIO4 和 GPIO5
    @ 其中GPIO1有32个IO
    @ GPIO2有22个IO
    @ GPIO3有29个IO
    @ GPIO4有29个IO
    @ GPIO5最少,只有12个IO
    @ 这样一共 124 个GPIO
    @
    @ 如果想要看每个 IO 能复用成什么外设,可以直接查阅 《I.MX6U参考手册》的第
    @4章 Chapter 4:External Signals and Pin Multipexing。

通过 GPIOx_DR (数据寄存器Data)可以配置 GPIO1 这一组 32 个 GPIO 的输出电平是高电平还是低电平。GPIO1_DR 寄存器为32位,每一位对应一个 GPIO,从 GPIO1_IO00,GPIO1_IO01,到 GPIO1_IO31。

参考手册中 给出了 GPIOx_DR, GPIOx_GDIR 寄存器的地址,通过写对应GPIOx_DR,GPIOx_GDR 寄存器的值,可以控制对应的GPIO寄存器是工作在输入模式还是输出模式,GPIO是输出高电平还是输出低电平。


GPIOx_GDIR 方向寄存器,控制GPIO是工作在输入模式,还是工作在输出模式:

    /* 设置 GPIO
     * 设置 GPIO1_GDIR寄存器,设置 设置 GPIO1_IO03 为输出
     * GPIO1_GDIR 寄存器地址为 0X209_C004,设置 GPIO1_IO03 寄存器 bit3为1
     * 也就是 GPIO1_IO03为输出
     */
    ldr r0, =0X0209C004  @GPIO1_GDIR
    ldr r1, =0x8         @bit3,从0开始例如GPIO1_IO00,GPIO1_IO01,GPIO1_IO02,GPIO1_IO03
    str r1, [r0]

 GPIOx_DR 数据寄存器,控制GPIO输出高电平还是输出低电平:

根据"正点原子I.MX6ULL Mini"电路原理图的电路原理图,当LED灯连接的 GPIO1_IO03 输出低电平是LED灯点亮。

    /* 打开LED,也就是设置GPIO1_IO03为0,也就是输出低电平,
     * 根据正点原子I.M6ULL Mini 开发板电路原理图,GPIO1_IO03 输出低电平
     * LED灯就打开.
     * GPIO1_DR 寄存器的地址为 0X0209_C000
     * GPIOQ_DR bit3 设置为0,输出低电平
     */
    ldr r0, =0x0209C000
    ldr r1, =0x0
    str r1, [r0]

1.3 最终的 led.s 汇编程序

如下是正点原子提供了示例 led.s 汇编程序示例截图。

 我自己参考视频写的实力程序存放在 Gitee 代码仓库,可以通过如下链接访问。

led/led.s · iPickCan/imx6ull_mini - Gitee.com

2. 编译 led.s 汇编程序

2.1 arm-linux-gnueabihf-gcc 编译文件

使用ARM交叉编译工具 'arm-linux-gnueabihf-gcc' 编译 led.s 汇编程序,先将 led.s 编译为 .o 目标文件。

arm-linux-gnueabihf-gcc -g -c -o led.o led.s

上述命令将 led.s 编译为 led.o,其中 "-g" 选型是产生调试信息,GDB能够使用这些调试信息进行代码调试。"-c"是编译源文件生成 ".o" 文件,但是不链接。"-o"是指定编译产生的文件名,我们这里指定文件名为 led.o。执行上述编译之后会生成一个 led.o 文件

其中 led.o 文件不是我们可以现在到开发版中运行的文件,一个工程中所有的 C 文件和汇编文件都会编译生成一个对应的 .o 文件,我们需要将这些 .o 文件链接起来组合成可执行文件。

2.2 arm-linux-gnueabihf-ld 链接文件

arm-linux-gnueabihf-ld 用来将众多的 .o 文件链接到一个指定的链接为止。我们现在需要做的是就是确定一下本实验最终的可执行文件的起始地址,也就是链接地址。这里我们需要区分“存储地址”和“运行地址”这两个概念,存储地址就是可执行代码存储在哪里,可执行文件的存储地址可以随意选择。运行地址就是代码运行时所处的地址,这个我们链接的时候就已经确定好了,代码要运行,那就必须处于运行地址处,否则代码肯定会出错。比如 I.MX6U 支持 SD 卡,EMMC,NAND启动,因此代码可以存储到SD卡,EMMC,或者 NAND 中,但是要运行的话就必须将代码从SD卡,EMMC或者NAND中拷贝到其运行地址(链接地址)处,存储地址和运行地址可以一样,比如 STM32 的存储地址和运行起始地址都是 0x0800_0000。

本教程中的所有裸机程序都是烧写到 SD卡中,上电以后 I.MX6U 的内部 boot rom 程序会将可执行文件拷贝到链接地址处,这个链接地址可以在 I.MX6U 的内部 128KB RAM中 (0x0090_0000 ~ 0x0091_FFFF),也可以在外部的DDR中。本教程所有裸机例程的链接地址都在 DDR 中,链接的起始地址为 0x8780_0000。I.MX6U-ALPHA/Mini 开发板的DDR容量有两种:512MB和256MB,起始地址都是 0x8000_0000,只不过512MB的终止地市为 0x9FFF_FFFF (地址范围为: 0x8000_0000 ~ 0x9FFF_FFFF),而256MB容量的终止地址为 0x8FFF_FFFF (地址范围为: 0x8000_0000 ~ 0x8FFF_FFFF)。之所以选在 0x8780_0000 这个地址是因为后面要将的 Uboot 其连接地址就是 0x8780_0000 ,这样我们统一使用 0x8780_0000 这个链接地址,不容易记混。

确定了链接地址以后,就可以使用 am-linux-gnueabihf-ld 链将前面编译出来的 led.o 文件链接到 0x8780_0000 地址,使用如下命令:

arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf

上述命令中 "-Ttext" 就是指定链接地址,"-o" 选项指定链接生成的 elf 文件名,我们这里命名为 led.elf。上数命令执行完成后,就会在工程目录下多了一个 led.elf 文件,如下所示:

led.elf 也不是我们最终烧写到SD卡中的可执行文件,我们需要烧写 bin 文件,因此还需要将 led.elf 转换为 .bin 文件格式,这里我们需要用到 arm-linux-gnueabihf-objcopy 这个工具。

2.3  arm-linux-gnueabihf-objcopy 格式转换

arm-linux-gnueabihy-objcopy 更像是一个格式转换工具,我们要将 led.elf 文件转换为 led.bin 文件,命令如下

arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
  • 上述命令中,"-O"选项执行以什么格式输出,后面的“binary”表示以二进制格式输出,
  • 选型"-S"表示不要复制源文件中的重定位信息和符号信息,"
  • -g"表示不复制源文件中的调试信息。

上面的命令执行完成以后,工程目录如下所示

2.4 arm-linux-gnueabihf-objdump 反汇编

大多数情况下我们都是用 C语言编写实验例程的,有时候需要查看器汇编代码来调试代码,因此就需要进行反汇编,一般可以将 elf 文件反汇编,比如如下命令:

arm-linux-gnueabihf-objdump -D led.elf > led.dis

上述代码中的“-D”选项表示反汇编所有的段,反汇编以后在当前目录下出现一个名为 led.dis 的文件,如下图所示

可以打开看一下 led.s 文件的内容,看看是不是汇编代码,如下图所示

从图中可以看出 led.dis 里面是汇编代码,而且还可以看到内存分配情况。在 0x8780_0000 处就是全局标号 _start,也就是程序开始的地方。通过 led.dis 这个反汇编文件可以明显的看出我们的代码已经链接到了 0x8780_0000 为起始地址的区域。

总结一下我们我了编译ARM开发板上的运行的 led.o 这个文件使用了如下命令

arm-linux-gnueabihf-gcc -c -o led.o led.s
arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
arm-linux-gnueabihf-objdump -D led.elf > led.dis

如果我们修改了 led.s 文件,那么juice需要再重复一次上面的命令,太麻烦了,这个时候我们就可以使用 Makefile 文件了。

2.5 创建 Makefile 文件

使用 "touch"命令在工程根目录下创建一个名字为“Makefile”的文件,创建后Makefile文件后,就需要根据Makefile的语法编写文件。Makefile文件内容如下:

led.bin : led.s
    arm-linux-gnueabihf-gcc -c -o led.o led.s
    arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf
    arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
    arm-linux-gnueabihf-objdump -D led.elf > led.dis

clean:
    rm -f *.o led.bin led.elf led.dis

创建好Makefile以后,我们值需要执行一次"make'命令就可以完成编译,如下图所示

如果要执行清理工作的话,执行 "make clnea",如下图所示

至此有关代码编译,arm-linux-gunueabihf-xxx 交叉编译器的的使用就到这里了,接下来我们讲解如何将 led.bin 烧写到 SD 卡中。

3. 代码烧写

虽然 I.MX6U 内部有 96KB 的 ROM,但是这 96KB 的 ROM 是 NXP 自己用的,不向用户开放。所以相当于 I.MX6U 是没有内部Flash的,但是我们代码需要有地方存放,为此,I.MX6U 支持从外置的 NOR Flash,NAND Flash,SD/EMMC,SPI NOR Flash 和 QSPIFlash这些存储介质中启动,所以我们可以将代码烧写到这些存储介质中。在这些存储介质中,除了SD卡以外,其它一般都是焊接到了开发吧班上的,我们没法直接烧写。但是 SD 卡是活动可插拔的,我们可以将SD卡查到电脑PC上,在电脑上使用软件将 .bin 文件烧写到SD卡中,然后插到开发板上就可以了。其它集中存储介质是我们量产的时候用到了,量产的时候代码就不可能放在SD卡里面了,毕竟SD卡是活动了,不牢固,而其它的都是焊接到板子上的,很牢固。

因此,我们的调试裸机和uboot的时候是将代码现在到SD卡中, 因为这样很方便,当调试完成后量产的时候要将裸机程序或者Uboot稍息到 SPI NOR Flash, EMMC, NAND 这些存储介质中。那么,如何将前面我们编译出来的 led.bin 烧写到 SD 卡中哪?肯定有人认为直接复制 led.bin 到 SD卡中不就行了,错!编译出来的可执行文件是怎么存放在SD卡中的,存放的位置是什么?这是是NXP有详细规定的!我们必须按照NXP的规定来将代码烧写到SD卡中,否则代码是绝对运行不起来的。

《IMX6UL 参考手册》的第 8 章“Chapter 8 System Boot”就是专门讲解 I.MX6U 启动的,我们下一章会详细的讲解 I.MX6U 启动方式的。

正点原子专门编写了一个软件来将编译出来的.bin文件烧写到SD卡中,这个软件叫做 "imxdownlaod" ,软件已经放到了开发光盘中,路径为开发板光盘->5、开发工具->2、Ubuntu 下裸机烧写软件->imxdownload, imxdownlaod 只能在 Ubuntu 下使用,使用步骤如下:
1. 讲 imxdownload 拷贝到工程目录下

我们要将 imxdownload 拷贝到工程目录下,也就是和 led.bin 处在同一个文件夹下,要不然会序烧写失败的,拷贝完成后如下图所示:

2. 给与imxdownload可执行权限

chmod 777 imxdownload

3. 确定要烧写的SD卡

准备一张新的SD卡,确保SD卡里面没有数据,因为我们再烧写代码的时候可能会格式化SD卡!

Ubuntu下所有设备都在目录 “/dev”里面,所以插上SD卡以后会出现在 "/dev”里面,其中存储设备都是以 "/dev/sd"开头的。物流门先看一下不插SD卡是电脑有哪些存储设备,以防插入SD卡后分不清楚谁是谁。输入命令

ls /dev/sd*

从图中可以看到当前电脑有/dev/sda、 /dev/sda1、 /dev/sda2 和/dev/sda5 这 5 个存储设备,使用读卡器将 SD 卡插到电脑,一定要确保 SD 卡是挂载到了 Ubuntu 系统中,而不是 Windows下。 SD 卡挂载到电脑以后, VMware 右下角会出现如图 8.4.3.4 所示图标

如图 8.4.3.4 所示,在 VMware 右小角有个图标看着像硬盘一样的图标: ,这个图标就表示当前有存储设备插入,我们将鼠标放上去就会有提示当前设备名字,比如我这里提示“Realtek USB3.0 Card Reader”,这是我的读卡器的名字。如果 是灰色的话就表示 SD 卡挂载到了 Windows 下,而不是 Ubuntu 上,所以我现在这个电脑的 SD 卡就是挂载到了 Windiows 下,我 肯定要将其挂载到 Ubuntu 中,因为我要在 Ubuntu 下烧写代码。方法很简单,点击图标 ,点击以后如图 8.4.3.5 所示

点击图 8.4.3.5 中的“连接(断开与主机的连接)(C)”,点击以后会弹出如图 8.4.3.6 所示提示界面:

图 8.4.3.6 提示你有个 USB 要从主机(Windows)拔出,插入虚拟机中,点击“确定”按钮即
可。 SD 卡插入到 Ubuntu 以后,图标 就会变为 ,不是灰色的了。在输入命令“ls /dev/sd*”
来查看当前 Ubuutu 下的存储设备,如图 8.4.3.7 所示

4. 向SD卡烧写bin文件

使用 imxdownload 向 SD 卡烧写 led.bin 文件,命令个数如下

./imxdownload <.bin file> <SD Card>

其中.bin 就是要烧写的.bin 文件, SD Card 就是你要烧写的 SD 卡,比如我的电脑使用如下命令烧写 led.bin 到/dev/sdd 中:

./imxdownload led.bin /dev/sdd //不能烧写到/dev/sda 或 sda1 设备里面!那是系统磁盘

烧写的过程中可能会让你输入密码,输入你的 Ubuntu 密码即可完成烧写,烧写过程如图

在图 8.4.3.8 中,烧写的最后一行会显示烧写大小、用时和速度,比如 led.bin 烧写到 SD 卡中的大小是 3.2KB,用时 0.0160821s,烧写速度是 201KB/s。注意这个烧写速度,如果这个烧写速度在几百 KB/s 以下那么就是正常烧写。

烧写完成以后会在当前工程目录下生成一个 load.imx 的文件,如图 8.4.3.9 所示:

load.imx 这个文件就是软件 imxdownload 根据 NXP 官方启动方式介绍的内容,在 led.bin 文件前面添加了一些数据头以后生成的。最终烧写到 SD 卡里面的就是这个 load.imx 文件,而led.bin。至于具体添加了些什么内容,我们会在下一章讲解。

4. 代码验证

代码已经烧写到了 SD 卡中了,接下来就是将 SD 卡插到开发板的 SD 卡槽中,然后设置拨码开关为 SD 卡启动,拨码开关设置如图 8.4.4.1 所示:

设置好以后按一下开发板的复位键,如果代码运行正常的话 LED0 就会被点亮,
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1638375.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络安全之弱口令与命令爆破(中篇)(技术进阶)

目录 一&#xff0c;什么是弱口令&#xff1f; 二&#xff0c;为什么会产生弱口令呢&#xff1f; 三&#xff0c;字典的生成 四&#xff0c;使用Burpsuite工具验证码爆破 总结 笔记改错 一&#xff0c;什么是弱口令&#xff1f; 弱口令就是容易被人们所能猜到的密码呗&a…

Android数据恢复软件快速比较:Android数据恢复的7最佳工具

您在 Android 设备上保留哪些类型的数据&#xff1f;如果您和大多数人一样&#xff0c;那么您可能已经列出了文档、照片、视频和音频文件。如果您使用智能手机或平板电脑的时间足够长&#xff0c;我们愿意打赌您拥有Android数据丢失的第一手经验。 幸运的是&#xff0c;我们也…

JSON教程(非常详细)

参考文章来源&#xff1a;JSON教程&#xff08;非常详细&#xff09; 目录 JSON JSON 发展史 为什么要使用 JSON&#xff1f; JSON 的不足 存储格式 使用场景 1) 定义接口 2) 序列化 3) 生成 Token 4) 配置文件 JSON语法规则 JSON 与 JavaScript 对象的区别 JSON数…

Python | Leetcode Python题解之第62题不同路径

题目&#xff1a; 题解&#xff1a; class Solution:def uniquePaths(self, m: int, n: int) -> int:return comb(m n - 2, n - 1)

基于SSM的个人博客系统(三)

目录 第五章 系统实现 5.1 登录模块 5.1.1 博主登录 5.2 博客管理模块&#xff1a; 5.2.1 博客查询 5.2.2 博客新建 5.2.3 博客修改 5.2.4 博客删除 5.3 博客类别管理模块 前面内容请移步 基于SSM的个人博客系统&#xff08;二&#xff09; 个人博客系统的设计…

飞腾FT1500A-16 6U VPX高性能密集计算刀片

飞腾FT1500A-16 6U VPX高性能密集计算刀片 一款高性能6U VPX单板显示计算机&#xff0c;产品遵循OpenVPX Vita65规范。采用目前主流的GPGPU架构&#xff0c;其板载一颗天津飞腾公司的FT1500A-4四核处理器&#xff0c;并搭配AMD?公司的高性能嵌入式显卡Radeon? E8860 GPU。E88…

【论文阅读:Data Shapley: Equitable Valuation of Data for Machine Learning】

1.基于蒙特卡罗方法和截断的方法计算&#xff08;TMC—Shapley&#xff09; 输入 训练数据集D学习算法A表现分V 输出 各方数据的贡献 ϕ i \phi_i ϕi​ 初始化 初始化各方的贡献 ϕ i 0 \phi_i0 ϕi​0,并设置当前迭代轮次为0 过程 算法进入一个循环迭代&#xff0c;直到满足…

Vue 之 在当前页面的实现分页效果

目录 场景实现 场景 假设&#xff0c;我们现在有这么一个需求&#xff1a; 上述图片的空白内容是活动的&#xff0c;由下面的两个按钮控制上一页、下一页&#xff1b;我们应该可以怎么去实现&#xff1f; 实现 思路&#xff1a; 其实这个问题&#xff0c;我们仿照其他的UI框…

ctf web-部分

** web基础知识 ** *一.反序列化 在PHP中&#xff0c;反序列化通常是指将序列化后的字节转换回原始的PHP对象或数据结构的过程。PHP中的序列化和反序列化通过serialize()和unserialize()函数实现。 1.序列化serialize() 序列化说通俗点就是把一个对象变成可以传输的字符串…

2024年五一数学建模C题完整解题思路代码

2024年第二十一届五一数学建模竞赛题目 C题 煤矿深部开采冲击地压危险预测 煤炭是中国的主要能源和重要的工业原料。然而&#xff0c;随着开采深度的增加&#xff0c;地应力增大&#xff0c;井下煤岩动力灾害风险越来越大&#xff0c;严重影响着煤矿的安全高效开采。在各类深…

如何快速搭建nginx服务

华子目录 nginx简介概念特点nginx框架nginx关键工作机制 nginx正向代理功能nginx反向代理功能nginx反向代理的工作流程代理本质 nginx负载均衡部署nginx常用命令systemctl系列nginx自带命令 nginx配置文件主配置文件/etc/nginx/nginx.conf内容结构模块分析配置分析注意示例 ngi…

常见公式的几何解释

本文旨在深入探讨常见数学公式的几何意义&#xff0c;通过直观的图形和解释&#xff0c;帮助读者更好地理解并掌握这些公式的本质。文章首先概述了公式与几何图形之间的紧密联系&#xff0c;然后选取了几个典型的数学公式&#xff0c;进行详细解析。每个公式都将配以相应的几何…

Zynq 7000 系列之启动模式—JTAG启动

JTAG Boot&#xff08;JTAG启动&#xff09;是一种使用JTAG接口来启动设备的方法。JTAG&#xff08;Joint Test Action Group&#xff09;是一种国际标准测试协议&#xff0c;最初用于对芯片进行测试&#xff0c;现在已广泛应用于各种设备的调试和启动过程。在JTAG Boot过程中&…

是机遇?是未来?拥抱 AI Agent ,拥抱 AI 2.0时代~

✍️ 作者&#xff1a;哈哥撩编程&#xff08;视频号同名&#xff09; 博客专家全国博客之星第四名超级个体COC上海社区主理人特约讲师谷歌亚马逊演讲嘉宾科技博主极星会首批签约作者 &#x1f3c6; 推荐专栏&#xff1a; &#x1f3c5; 程序员&#xff1a;职场关键角色通识宝…

社交媒体数据恢复:飞机 X

飞机 X数据恢复方法 在本文中&#xff0c;我们将探讨如何在不使用特定数据恢复软件的情况下尝试恢复飞机 X聊天记录和文件。请注意&#xff0c;这些方法并不保证100%的成功率&#xff0c;但它们可以在一定程度上帮助您恢复丢失的数据。 1. 检查最近的备份 如果您启用了飞机 …

【17-模型选择与调优:交叉验证和网格搜索在Scikit-learn中的实践】

文章目录 前言交叉验证:保证模型的稳健性理论基础Scikit-learn中的实现网格搜索:寻找最佳参数理论基础Scikit-learn中的实现应用示例结论前言 模型选择和调优是机器学习项目成功的关键步骤。在Scikit-learn中,交叉验证和网格搜索是两个强大的工具,用于选择最佳模型和调整参…

Qt Creator导入第三方so库和jar包——Qt For Android

前言 之前了解了在Android Studio下导入so库和jar包&#xff0c;现在实现如何在Qt上导入so库和jar包。 实现 下面是我安卓开发&#xff08;需调用安卓接口的代码&#xff09;的目录&#xff08;图1&#xff09;&#xff0c;此目录结构和原生态环境&#xff08;Android Studi…

如何反向查看某个命令所属的rpm包的2个方法?(rpm -qf `which xxx`和yum provides和 rpm -ql xxx.rpm)

文章目录 快速回忆方法1&#xff1a; rpm -qf方法2&#xff1a;yum provides 其他rpm如何查看某个rpm包里面包含哪些命令: rpm -ql主推方法1&#xff1a; rpm -ql方法2&#xff1a;yum info 其他查看rdma-core中包含哪些cmd&#xff1a;一些其他命令所在包探索 快速回忆 rpm -…

使用Gitbook生成电子书

背景 《Google工程实践文档》相对原文Google’s Engineering Practices documentation &#xff0c;部分内容过时了。需要更新中文版&#xff0c;并使用Gitbook把Markdown文件转换成对应的PDF电子书。   上一次生成PDF电子书是5年前&#xff0c;当时生成电子书的环境早已不在…

在做题中学习(48):朴素的二分查找

. - 力扣&#xff08;LeetCode&#xff09; 解法一&#xff1a; 暴力求解 for循环中&#xff0c;从nums[0]枚举到nums[n-1]&#xff0c;依次判断&#xff0c;返回 target的值。 时间复杂度 : O(N) :因为要遍历一遍数组 解法二&#xff1a;二分查找 因为此数组为有序的…