uboot移植Linux-SD驱动代码解析

2023-05-16

一、uboot与linux驱动

1.1、uboot本身是裸机程序

(1)狭义的驱动概念是指:操作系统中用来具体操控硬件的代码叫驱动
广义的驱动概念是指:凡是操控硬件的代码都叫驱动
(2)裸机程序中是直接使用寄存器的物理地址来操控硬件的,操作系统中必须通过驱动来操控硬件。
这两个有什么区别?本质区别就是分层。

1.2、uboot的虚拟地址对硬件操作的影响

(1)操作系统(指的是linux)下MMU肯定是开启的,也就是说linux驱动中使用的都是虚拟地址。
而纯裸机程序中根本没有使用MMU,全部使用的是物理地址。这是裸机和驱动操控硬件的一个重要区别。

(2)uboot早期也是使用纯物理地址工作的,但是现在的uboot开启了MMU做了虚拟地址映射,因此要将驱动移植到uboot必须考虑真实操控的是不是同一个物理地址。
查uboot中的虚拟地址映射表,发现除了0x30000000-0x3FFFFFFF映射到了0xC0000000-0xCFFFFFFF之外,其余的虚拟地址空间全是原样映射的。
而我们驱动中主要是操控硬件寄存器,而S5PV210的SFR都在0xExxxxxx地址空间,因此驱动中不必考虑虚拟地址。

1.3、uboot借用(移植)了linux驱动

(1)linux驱动本身做了分文件的模块化设计。linux驱动本身和linux内核不是强耦合的,这是linux驱动可以被uboot借用(移植)的关键。
(2)linux驱动本身有更复杂的框架,实现了很多的附带功能,而uboot本质上只是个裸机程序,uboot移植linux驱动时只是借用了linux驱动的一部分而已。

二、iNand/SD驱动解析(从start_armboot中的mmc_initialize开始)

(1)驱动整体非常庞大,涉及很多个文件夹下的很多文件,函数更多,我们从start_armboot函数中的驱动初始化部分入手。
(2)mmc_initialize在start_armboot函数604行处调用,函数定义在:uboot/drivers/mmc/mmc.c中。
uboot移植的linux驱动都放在了uboot/drivers目录。

int mmc_initialize(bd_t *bis)
{
    struct mmc *mmc;
    int err;

    INIT_LIST_HEAD(&mmc_devices);
    //1.这句代码的含义是:初始化全局变量mmc_devices
    //2.初始化的值是:将mmc_devices这个结构体类型的变量中的next、prev指针均指向自己
    //3.mmc_devices的作用:是用来记录系统中所有已经注册的SD/iNand设备
    //4.举例:向系统中插入一个SD卡/iNand设备,则系统驱动就会向mmc_devices链表中增加一个节点表示这个设备。
    cur_dev_num = 0;
    //cur_dev_num的作用:记录当前正在操作的SD卡设备的设备号

    if (board_mmc_init(bis) < 0)
        cpu_mmc_init(bis);

#if defined(DEBUG_S3C_HSMMC)
    print_mmc_devices(',');
#endif

#ifdef CONFIG_CHECK_X210CV3
    mmc = find_mmc_device(1);//lqm
#else
    mmc = find_mmc_device(0);
#endif
    if (mmc) {
        err = mmc_init(mmc);
        if (err)
            err = mmc_init(mmc);
        if (err) {
            printf("Card init fail!\n");
            return err;
        }
    }
    printf("%ldMB\n", (mmc->capacity/(1024*1024/(1<<9))));
    return 0;
}

(3)mmc_initialize这个函数的作用就是初始化板上的MMC系统。
MMC系统的初始化应该包含这么两部分:
SoC里的SD/MMC控制器初始化(MMC系统时钟的初始化、GPIO初始化、SFR初始化)
SD卡/iNand 内部控制器的初始化。
//SD卡有很多种状态,获取到不同的命令,就会执行不同的操作,然后进入下一种状态;
//在SD卡中有个小型控制器,封装了读写SD卡的函数。
//这里的初始化SD卡就是为了 初始化SD卡的状态到合适。

(4)mmc_devices链表(全局变量),用来记录系统中所有已经注册的SD/iNand设备。所以向系统中插入一个SD卡/iNand设备,则系统驱动就会向mmc_devices链表中插入一个数据结构表示这个设备。

2.1、cpu_mmc_init(mmc_initialize函数1191行处调用)

(1)函数定义在:uboot/cpu/s5pc11x/cpu.c中。实质是通过调用3个函数来完成的。

int cpu_mmc_init(bd_t *bis)
{
#ifdef CONFIG_S3C_HSMMC
    setup_hsmmc_clock();
    setup_hsmmc_cfg_gpio();
    return smdk_s3c_hsmmc_init();
#else
    return 0;
#endif
}

2.1.1、setup_hsmmc_clock

(1)函数定义在:uboot/cpu/s5pc11x/setup_hsmmc.c中。看名字函数是用来初始化SoC中MMC控制器的时钟部分的。


void setup_hsmmc_clock(void)
{
    u32 tmp;
    u32 clock;
    u32 i;

    /* MMC0 clock src = SCLKMPLL */
    //CLK_SRC4低4位设置为0110,意思是设置MMC0通道的源时钟为SCLKMPLL
    tmp = CLK_SRC4_REG & ~(0x0000000f);
    CLK_SRC4_REG = tmp | 0x00000006;

    /* MMC0 clock div */
    tmp = CLK_DIV4_REG & ~(0x0000000f);//CLK_DIV4di4位清0
    clock = get_MPLL_CLK()/1000000;//MPLL_CLK = 667MHz,clock = 667
    for(i=0; i<0xf; i++)
    {
        if((clock / (i+1)) <= 50) { 667/14 < 50, i+1 = 14, i = 13 = (1101)
            CLK_DIV4_REG = tmp | i<<0;    //对MPLL_CLK(667M)进行14分频得到SCLKMPLL(47M)
            break;
        }
    }


#ifdef USE_MMC2
    /* MMC2 clock src = SCLKMPLL */
    tmp = CLK_SRC4_REG & ~(0x00000f00);
    CLK_SRC4_REG = tmp | 0x00000600;

    /* MMC2 clock div */
    tmp = CLK_DIV4_REG & ~(0x00000f00);
    CLK_DIV4_REG = tmp | i<<8;
#endif


}

2.1.2、setup_hsmmc_cfg_gpio

(1)函数定义在:uboot/cpu/s5pc11x/setup_hsmmc.c中。看名字函数是用来配置SoC中MMC控制器相关的GPIO的。

2.1.3、smdk_s3c_hsmmc_init

(1)函数定义在:uboot/drivers/mmc/s3c_hsmmc.c中。函数内部通过宏定义USE_MMCx来决定是否调用s3c_hsmmc_initialize来进行具体的初始化操作。

int smdk_s3c_hsmmc_init(void)
{
    int err;

#ifdef USE_MMC0            //x210使用这里
    err = s3c_hsmmc_initialize(0);
    if(err)
        return err;
#endif

#ifdef USE_MMC1
    err = s3c_hsmmc_initialize(1);
    if(err)
        return err;
#endif    

#ifdef USE_MMC2           //x210使用这里
    err = s3c_hsmmc_initialize(2);
    if(err)
        return err;
#endif    

#ifdef USE_MMC3
    err = s3c_hsmmc_initialize(3);
    if(err)
        return err;
#endif
    return -1;
}

2.1.3.1、s3c_hsmmc_initialize

(1)函数定义在:uboot/drivers/mmc/s3c_hsmmc.c中。

static int s3c_hsmmc_initialize(int channel)
{
    struct mmc *mmc;
    //struct mmc封装了SD卡所有相关的信息和操作函数,和C++中使用类来面向对象很像。

    mmc = &mmc_channel[channel];

    sprintf(mmc->name, "S3C_HSMMC%d", channel);
    mmc->priv = &mmc_host[channel];
    mmc->send_cmd = s3c_hsmmc_send_command;
    mmc->set_ios = s3c_hsmmc_set_ios;
    mmc->init = s3c_hsmmc_init;

    mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
    mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS;
#if defined(USE_MMC0_8BIT) || defined(USE_MMC2_8BIT)
    mmc->host_caps |= MMC_MODE_8BIT;
#endif

    mmc->f_min = 400000;
    mmc->f_max = 52000000;

    mmc_host[channel].clock = 0;

    switch(channel) {
    case 0:
        mmc_host[channel].ioaddr = (void *)ELFIN_HSMMC_0_BASE;
        break;
    case 1:
        mmc_host[channel].ioaddr = (void *)ELFIN_HSMMC_1_BASE;
        break;
    case 2:
        mmc_host[channel].ioaddr = (void *)ELFIN_HSMMC_2_BASE;
        break;
#ifdef USE_MMC3
    case 3:
        mmc_host[channel].ioaddr = (void *)ELFIN_HSMMC_3_BASE;
        break;
#endif
    default:
        printk("mmc err: not supported channel %d\n", channel);
    }
    
    return mmc_register(mmc);
}

(2)定义一个指向struct mmc类型的指针,指向mmc_channel数组中的元素,mmc_channel数组中的每个元素都是struct mmc类型的对象,之后填充这个指针指向的对象的成员和成员函数,最后调用mmc_register函数来向驱动框架注册这个mmc设备驱动。

int mmc_register(struct mmc *mmc)
{
    /* Setup the universal parts of the block interface just once */
    mmc->block_dev.if_type = IF_TYPE_MMC;
    mmc->block_dev.dev = cur_dev_num++;
    mmc->block_dev.removable = 1;
    mmc->block_dev.block_read = mmc_bread;
    mmc->block_dev.block_write = mmc_bwrite;

    INIT_LIST_HEAD(&mmc->link);

    list_add_tail(&mmc->link, &mmc_devices);//将该设备插入内核链表

    return 0;
}

(3)mmc_register功能是进行mmc设备的注册,注册方法就是将当前这个mmc插入到mmc_devices这个内核链表中去。

(4)我们在x210_sd.h中定义了USE_MMC0和USE_MMC2,因此在我们的uboot初始化时会调用2次s3c_hsmmc_initialize函数,传递参数分别是0和2,因此完成之后系统中会注册上2个mmc设备,表示当前系统中有2个mmc通道在工作。

(5)至此cpu_mmc_init函数分析完成。完成了以下工作:
SoC里的MMC控制器初始化(MMC系统时钟的初始化、SFR初始化、GPIO初始化)

2.2、find_mmc_device

(1)函数定义在:uboot/drivers/mmc/mmc.c中。

struct mmc *find_mmc_device(int dev_num)
{
    struct mmc *m;
    struct list_head *entry;

    list_for_each(entry, &mmc_devices) {
        m = list_entry(entry, struct mmc, link);

        if (m->block_dev.dev == dev_num)
            return m;
	 }

    printf("MMC Device %d not found\n", dev_num);

    return NULL;
}

(2)这个函数的作用就是通过mmc设备号在内核链表中查找对应的mmc设备(struct mmc的对象,根据上面2.1.3.1.(4)分析系统中有2个mmc设备,编号分别是0和2)。函数工作原理就是遍历mmc_devices链表,去依次寻找注册了的mmc设备,然后对比设备编号,如果相同则就说明找到了设备。找到后调用mmc_init函数来初始化这个设备。

2.3、mmc_init

(1)函数定义在:drivers/mmc/mmc.c中。

(2)这个函数应该是要进行mmc卡的初始化了(前面已经完成了SoC端控制器的初始化)

(3)函数的调用关系为:

mmc_init                    //发送若干个命令码初始化SD卡内部的控制器
	mmc_go_idle            //命令1
		mmc_send_cmd        //发送命令1
	mmc_send_if_cond        //命令2
		mmc_send_cmd        //发送命令2
	······

可以看出,mmc_init函数内部就是依次通过向mmc卡发送命令码(CMD0、CMD2那些)来初始化SD卡/iNand内部的控制器,以达到初始化SD卡的目的。

三、总结

(1)至此整个MMC系统初始化结束。
uboot中的iNand/SD驱动总体的调用关系:
(2)整个MMC系统初始化分为2大部分:SoC这一端的MMC控制器的初始化,SD卡这一端卡本身的初始化。前一部分主要是在cpu_mmc_init函数中完成,后一部分主要是在mmc_init函数中完成。

(3)整个初始化完成后去使用sd卡/iNand时,操作方法和mmc_init函数中初始化SD卡的操作方式一样。读写sd卡时也是通过总线向SD卡发送命令、读取/写入数据来完成的。

(4)顺着mmc_init函数中发送命令的操作追下去,到了mmc_send_cmd函数处就断了,真正的向SD卡发送命令的硬件操作的函数找不到。

(5)struct mmc结构体是关键。两部分初始化之间用使用mmc结构体来联系,初始化完了后对mmc卡的常规读写操作也是通过mmc结构体来链接的。

四、linux驱动前奏

4.1、struct mmc

(1)驱动的设计中有一个关键数据结构,每个驱动都对应着一个数据结构。譬如MMC驱动的结构体就是struct mmc,这个结构体中包含一些变量和一些函数指针,变量用来记录SD卡相关的属性,函数指针用来记录SD卡相关的操作方法。这些变量和函数指针加起来就构成了驱动。驱动就被抽象为这个结构体。

(2)一个驱动工作时主要就分两部分(以iNand/SD驱动为例子):
驱动构建(构建一个struct mmc对象然后填充它)、驱动运行时(调用这个对象里的函数指针和变量)

4.2、分离思想—面向对象

(1)分离思想就是说在驱动中将操作方法和数据分开,然后封装在一个结构体中。

(2)操作方法就是函数,数据就是变量。所谓操作方法和数据分离的意思就是:在不同的地方来存储和管理驱动的操作方法和变量,这样的优势就是驱动便于移植。

4.3、分层思想

(1)分层思想是指一整个的驱动分为好多个层次。驱动分为很多个源文件,放在很多个文件夹中。

(2)以mmc驱动为例来分析各个文件的作用:
uboot/drivers/mmc/mmc.c:本文件的主要内容是和MMC卡操作有关的方法,譬如MMC卡设置复位状态的mmc_go_idle、卡读写数据等。但是本文件中并没有具体的硬件寄存器操作函数,操作最终指向的是struct mmc结构体中的函数指针send_cmd,这些函数指针是在驱动构建的时候和真正硬件操作函数挂勾的(真正的硬件操作函数在别的文件中)。

uboot/drivers/mmc/s3c_hsmmc.c:本文件中主要内容是SoC内部MMC控制器的硬件寄存器操作方法,真正的寄存器操作就在这里,譬如向SD卡发送命令的函数(s3c_hsmmc_send_command),譬如和SD卡读写数据的函数(s3c_hsmmc_set_ios),这些函数就是具体操作硬件的函数,也就是mmc.c中函数指针最终指向的函数。这些函数在mmc驱动初始化构建时(cpu_mmc_init-> smdk_s3c_hsmmc_init-> s3c_hsmmc_initialize函数中)和struct mmc对象挂勾起来备用。

分析:mmc.c和s3c_hsmmc.c构成了一个分层,mmc.c中调用了s3c_hsmmc.中的函数,所以mmc.c在上层,s3c_hsmmc.c在下层。这两个分层后我们发现mmc.c中不涉及具体硬件的操作,s3c_hsmmc.c中不涉及驱动工作时的时序操作(发送命令的先后顺序)。因此移植的时候就有好处:譬如我们要把这一套mmc驱动移植到别的SoC上,mmc.c就不用动,s3c_hsmmc.c动就可以了;譬如SoC没变但是SD卡升级了,这时候只需要更换mmc.c,不需要更换s3c_hsmmc.c即可。

cpu/s5pc110/下面还有一个setup_hsmmc.c,也和MMC驱动有关。但是这些代码为什么不能放到drivers目录下去,而要放到cpu目录下去?因为这里面的2个函数(setup_hsmmc_clock和setup_hsmmc_cfg_gpio)都是和SoC内部有关的初始化函数,这两个函数不能放到drivers目录下去。实际上如果非把这两个函数放在uboot/drivers/mmc/s3c_hsmmc.c文件中也能说过去。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

uboot移植Linux-SD驱动代码解析 的相关文章

  • 即使 makefile 和源代码存在,为什么“Build Project”在 Eclipse Helios CDT 中显示为灰色?

    我无法构建我的项目 我在 Eclipse Helios 中创建了一个新的 CDT 项目 并告诉它使用现有的源代码和 makefile 这两者都正确显示在 Package 和 Project 视图中 然而 项目 菜单中的 构建全部 和 构建项
  • Mono 和 WebRequest 速度 - 测试

    在 mono 4 6 2 linux 中 我注意到 wget 下载文件的速度与webclient DownloadString 所以我做了一个小测试来调查 为什么 wget 明显比 C 快 根据我自己的实验 使用 wget 下载 手动读取文
  • 从 Linux 命令行发送 SNMP 陷阱消息

    Folks 我需要从 Linux 命令行使用此命令 snmptrap 将自定义消息发送到陷阱侦听器 我需要根据用户设置在 v1 和 v2c 中发送相同的消息 这是我发现的 For v1 snmptrap v 1 c Tas hostname
  • 有关 Linux 内存类型的问题

    关于Linux内存我有以下问题 我知道活动内存是最常访问的内存部分 但是有人可以解释一下 linux 如何考虑将内存位置用于活动内存或非活动内存 主动存储器由哪些部分组成 磁盘 文件缓存是否被视为活动内存的一部分 有什么区别Buffers
  • 无法为 Python 3.4 创建工作虚拟环境

    I 安装Python 3 4 2 https docs python org 3 using unix html building python和我的 Linux Mint 17 1 中的 Virtualenv 12 0 5 然后我尝试创建
  • 对 sf:: 的未定义引用

    我想用 C 制作 GUI 应用程序 发现 SFML 是一个不错的选择 幸运的是 我使用的是 Linux 所以 SFML 2 4 已经安装在我的系统上 所以我开始搜索一些教程并找到了一个制作简单窗口的教程 但是当我运行代码时 出现错误 提示未
  • 如何使用libaudit?

    我试图了解如何使用 libaudit 我想接收有关使用 C C 的用户操作的事件 我不明白如何设置规则 以及如何获取有关用户操作的信息 例如 我想获取用户创建目录时的信息 int audit fd audit open struct aud
  • Linux TCP服务器:在接受连接之前读取客户端的IP地址

    Related C Winsock API如何在接受连接之前获取连接客户端IP https stackoverflow com questions 716209 c winsock api how to get connecting cli
  • 退出 bash 脚本但保持进程运行

    我正在运行服务器 需要使用参数执行以下命令 这些脚本目前工作得很好 但问题是当我运行脚本时我无法返回到控制台 它在控制台中保持运行 如果我强行停止它 那么该过程也会停止 我想继续运行该进程并返回到控制台 bin sh php home st
  • 如何使用ffmpeg重叠和合并多个音频文件?

    我正在尝试将多个音频文件合并到一个文件中 但我可以使用以下命令来连接 而不是连接 ffmpeg v debug i file1 wav i file2 wav i file3 wav filter complex 0 0 concat n
  • Xenomai 中的周期性线程实时失败

    我正在创建一个周期性线程 它在模拟输出上输出方波信号 我正在使用 Xenomai API 中的 Posix Skin 和 Analogy 我使用示波器测试了代码的实时性能 并查看了方波信号 频率为 1kHz 的延迟 我应该实现 250us
  • grails 上的同步块在 Windows 上有效,但在 Linux 上无效

    我有一个 grails 应用程序 它依赖于服务中的同步块 当我在 Windows 上运行它时 同步按预期工作 但当我在 ams linux 上运行时 会出现 StaleObjectStateException 该问题在以下示例中重现 cla
  • sqlite 插入需要很长时间

    我正在将不到 200 000 行插入到 sqlite 数据库表中 我只是在终端中通过 sqlite3 使用一个非常简单的 sql 文件 我打赌它已经运行了至少 30 分钟 这是正常现象还是我应该关闭该过程并尝试不同的方法 sqlite中的插
  • Windows 与 Linux 文本文件读取

    问题是 我最近从 Windows 切换到 Ubuntu 我的一些用于分析数据文件的 python 脚本给了我错误 我不确定如何正确解决 我当前仪器的数据文件输出如下 Header 有关仪器等的各种信息 Data 状态 代码 温度 字段等 0
  • 使用命令行将 MediaWiki 维基文本格式转换为 HTML

    我倾向于编写大量文档 因此 MediaWiki 格式对我来说很容易理解 而且比编写传统 HTML 节省了我很多时间 然而 我也写了一篇博客 发现一直从键盘切换到鼠标来输入正确的 HTML 标签会增加很多时间 我希望能够使用 Mediawik
  • 为什么 ld 无法从 /etc/ld.so.conf 中的路径找到库?

    我想添加 opt vertica lib64进入系统库路径 所以我执行以下步骤 1 添加 opt vertica lib64 into etc ld so conf 然后运行ldconfig 2 检查 bash ldconfig p gre
  • 如何从 Linux 的 shell 中删除所有以 ._ 开头的文件?

    确实如标题所示 我已将许多文件从 Mac 复制到 Raspberry Pi 这导致了许多以前缀开头的多余文件 我想删除以以下开头的文件夹中的每个文件 我该怎么做 尝试类似的方法 cd path to directory rm rf 或者 如
  • 错误:NVIDIA-SMI 失败,因为无法与 NVIDIA 驱动程序通信

    NVIDIA SMI 抛出此错误 NVIDIA SMI 失败 因为无法与 NVIDIA 通信 司机 确保安装了最新的 NVIDIA 驱动程序并且 跑步 我清除了 NVIDIA 并按照提到的步骤重新安装了它here https askubun
  • 如何从 Linux 命令行获取视频文件的分辨率(宽度和高度)?

    我一直在挖掘 mplayer mencoder 和 ffmpeg 文档 但我似乎无法想出anything 我对输出格式不是特别挑剔 因为我可以使用正则表达式将其拉出来 我只是似乎无法首先获取数据 Use ffprobe https ffmp
  • 如何调用位于其他目录的Makefile?

    我正在尝试这样做 我想打电话给 make Makefile存在于其他目录中 abc可以使用位于不同目录中的 shell 脚本的路径 我该怎么做呢 由于 shell 脚本不允许我cd进入Makefile目录并执行make 我怎样才能编写she

随机推荐

  • init.rc 启动 shell 脚本 开机执行脚本 init.rc执行shell脚本

    Android 重启时执行 shell 脚本 init rc 执行 shell 脚本 最近有个需求 xff0c 需要生成系统的默认配置 xff0c 使得在系统开机后 xff0c 直接读取已经配置好的文件 当时想的解决方案是 xff0c 在编
  • android 10 自定义系统服务接口给app调用

    Android 安卓自定义系统服务 最近有个需求 xff0c 要增加系统服务 xff0c 生成第三方 jar 包提供给第三方应用调用 xff0c 而且 jar 包必须用特定的包名 xff0c 最后生成的 jar 包不能包含 framewor
  • Android java.lang.NoSuchMethodError: No virtual method ;or its super classes (declaration of

    修改 AOSP 源码后调用错误 java lang NoSuchMethodError No virtual method in class or its super classes declaration of appears in sy
  • 谷歌使用技巧 20 招

    第一招 xff1a 使用搜索栏下方的 Tab 栏 xff0c 可以快速搜索 视频 图片 新闻第二招 xff1a 使用引号 xff0c 默认搜索会去搜索包含输入关键字的结果 xff0c 用 34 holy shit 34 会去进行整句搜索第三
  • 索引算法原理解析(B-tree以及磁盘存储原理)

    刚开始学习的时候 xff0c 百度去查 xff0c 但发现好多说得太复杂不好理解 xff0c 结合各个文章总结一下 xff08 建议大概看文字 xff0c 不理解不要紧 xff0c 然后再看图的执行步骤然后在结合文字 xff0c 这样一切就
  • C语言-----结构体内存对齐

    结构体内存对齐规则 xff1a 第一个成员在结构体变量偏移量为0 的地址处 其他成员变量要对齐到某个数字 xff08 对齐数 xff09 的整数倍的地址处 对齐数 61 编译器默认的一个对齐数与该成员大小中的较小值 vs中默认值是8 Lin
  • dpi计算 density 取值范围

    PPI DPI计算公式 Density 61 sqrt span class token punctuation span span class token punctuation span span class token car wp
  • Repo 流程

    First repo init creates the repo directory clones the git repository https android googlesource com tools repo to repo r
  • *** buffer overflow detected ***: terminatedAborted (core dumped)解决

    在执行一个程序的时候出现了下面的这个错误 xff0c 明明在Ubuntu下面已经编译好了 xff0c 执行的时候除了问题 xff0c 于是换了台电脑尝试还是一样 buffer overflow detected terminated Abo
  • 虚拟机Ubuntu远程启动Jetson nano RVIZ图形界面失败

    INFO 1644470251 178517 Rosapi started map manager 6 process has finished cleanly log file home jetson ros log fb3115c6 8
  • YOLOv5训练自己的数据集实现视频的识别

    写在前面 我本来是使用这个模型进行手写签名的定位 xff0c 但是因为比赛的主办方原因 xff0c 数据不允许公开 xff0c 所以我使用动物世界的一段开头视屏来制作我的数据集 这整个模型跑通的过程中 xff0c 我参考了很多不错的博客 x
  • stm32---OLED(SSD1306)

    OLED模块优缺点 优点 xff1a 尺寸小 xff0c 分辨率高 xff0c 低压3 3V就可工作 xff0c 支持多种接口方式 xff0c 该模块提供了总共4种接口包括 xff1a 6800 8080两种并行接口方式 4线的穿行SPI接
  • stm32---ADC模数转换

    ADC xff1a 模数转换器 xff0c 将模拟信号 xff08 0v xff0c 3v xff0c 6v等 xff09 转换为表示一定比例电压值的数字信号 xff08 1 xff0c 2 xff0c 3等 xff09 STM32F10x
  • stm32---DMA

    DMA 全称Direct Memory Access xff08 直接存储器访问 xff09 xff0c 把一个地址空间的值 复制 到另一个地址空间 xff0c 使用DMA传输方式无需CPU直接控制传输 xff0c 通过硬件为RAM和IO设
  • STM32通信---CAN

    一 CAN是什么 xff1f CAN xff0c 全称为 Controller Area Network xff0c 即控制器局域网 xff0c 是一种多主方式的串行通讯总线 xff0c 是国际上应用最广泛的现场总线之一 二 CAN的起源
  • 计算机网络学习笔记3-抓包工具的使用

    Wireshark win64 2 6 2的使用 安装一路next 在发送数据之前 运行抓包工具 当数据发送之后 记得停止抓包
  • linux运行java项目的shell脚本

    bin bash WORKDIR 61 home xiaohong Baowen cd WORKDIR WEB INF classes for file in 96 ls WORKDIR WEB INF lib jar 96 do CLAS
  • 基于STM32F103的智能门禁系统

    0 前言 本人大二软工菜鸟一枚 xff0c 大神不喜勿喷 1 功能演示 点这里功能演示 2 硬件选型 序号名称备注1STM32F103C8T6开发板用于主控2AS608指纹模块指纹解锁3RFID RC522射频模块刷卡解锁40 96寸四针O
  • uboot的环境变量相关源码分析

    一 uboot的环境变量基础 1 1 环境变量的作用 1 让我们可以不用修改uboot的源代码 xff0c 而是通过修改环境变量就可以影响uboot运行时的一些特性 譬如说修改bootdelay环境变量就可以更改系统开机自动启动时倒计时的秒
  • uboot移植Linux-SD驱动代码解析

    一 uboot与linux驱动 1 1 uboot本身是裸机程序 1 狭义的驱动概念是指 xff1a 操作系统中用来具体操控硬件的代码叫驱动 广义的驱动概念是指 xff1a 凡是操控硬件的代码都叫驱动 2 裸机程序中是直接使用寄存器的物理地