u-boot的DM驱动模型

0、本文基于U-Boot 2022.01-v2.07版本进行分析。

1、u-boot编译流程简要分析

2、u-boot启动流程简要分析

3、u-boot增加自定义命令

4、u-boot的DM驱动模型

  • 4.1、参考资料
    Uboot中的DM驱动模型:这篇文章详细介绍了DM驱动模型的原理。
    本文重点整理了几个数据结构和驱动示例讲解。
  • 4.2、DM驱动模型相关的数据结构
    DM模型主要依赖于下面四种数据结构:
    • 1)struct udevice,具有硬件设备的抽象, 和driver实例相关
      定义在include\dm\device.h中:
      /*** struct udevice - An instance of a driver** This holds information about a device, which is a driver bound to a* particular port or peripheral (essentially a driver instance).** A device will come into existence through a 'bind' call, either due to* a U_BOOT_DRVINFO() macro (in which case plat is non-NULL) or a node* in the device tree (in which case of_offset is >= 0). In the latter case* we translate the device tree information into plat in a function* implemented by the driver of_to_plat method (called just before the* probe method if the device has a device tree node.** All three of plat, priv and uclass_priv can be allocated by the* driver, or you can use the auto members of struct driver and* struct uclass_driver to have driver model do this automatically.** @driver: The driver used by this device* @name: Name of device, typically the FDT node name* @plat_: Configuration data for this device (do not access outside driver*	model)* @parent_plat_: The parent bus's configuration data for this device (do not*	access outside driver model)* @uclass_plat_: The uclass's configuration data for this device (do not access*	outside driver model)* @driver_data: Driver data word for the entry that matched this device with*		its driver* @parent: Parent of this device, or NULL for the top level device* @priv_: Private data for this device (do not access outside driver model)* @uclass: Pointer to uclass for this device* @uclass_priv_: The uclass's private data for this device (do not access*	outside driver model)* @parent_priv_: The parent's private data for this device (do not access*	outside driver model)* @uclass_node: Used by uclass to link its devices* @child_head: List of children of this device* @sibling_node: Next device in list of all devices* @flags_: Flags for this device DM_FLAG_... (do not access outside driver*	model)* @seq_: Allocated sequence number for this device (-1 = none). This is set up* when the device is bound and is unique within the device's uclass. If the* device has an alias in the devicetree then that is used to set the sequence* number. Otherwise, the next available number is used. Sequence numbers are* used by certain commands that need device to be numbered (e.g. 'mmc dev').* (do not access outside driver model)* @node_: Reference to device tree node for this device (do not access outside*	driver model)* @devres_head: List of memory allocations associated with this device.*		When CONFIG_DEVRES is enabled, devm_kmalloc() and friends will*		add to this list. Memory so-allocated will be freed*		automatically when the device is removed / unbound* @dma_offset: Offset between the physical address space (CPU's) and the*		device's bus address space*/
      struct udevice {const struct driver *driver;const char *name;void *plat_;void *parent_plat_;void *uclass_plat_;ulong driver_data;struct udevice *parent;void *priv_;struct uclass *uclass;void *uclass_priv_;void *parent_priv_;struct list_head uclass_node;struct list_head child_head;struct list_head sibling_node;
      #if !CONFIG_IS_ENABLED(OF_PLATDATA_RT)u32 flags_;
      #endifint seq_;
      #if CONFIG_IS_ENABLED(OF_REAL)ofnode node_;
      #endif
      #ifdef CONFIG_DEVRESstruct list_head devres_head;
      #endif
      #if CONFIG_IS_ENABLED(DM_DMA)ulong dma_offset;
      #endif
      };
      
    • 2)struct driver,特定udevice的硬件驱动,包含了驱动的绑定、初始化、probe和卸载等函数。使用U_BOOT_DRIVER来注册。
      struct driver定义在include\dm\device.h中:
      /*** struct driver - A driver for a feature or peripheral** This holds methods for setting up a new device, and also removing it.* The device needs information to set itself up - this is provided either* by plat or a device tree node (which we find by looking up* matching compatible strings with of_match).** Drivers all belong to a uclass, representing a class of devices of the* same type. Common elements of the drivers can be implemented in the uclass,* or the uclass can provide a consistent interface to the drivers within* it.** @name: Device name* @id: Identifies the uclass we belong to* @of_match: List of compatible strings to match, and any identifying data* for each.* @bind: Called to bind a device to its driver* @probe: Called to probe a device, i.e. activate it* @remove: Called to remove a device, i.e. de-activate it* @unbind: Called to unbind a device from its driver* @of_to_plat: Called before probe to decode device tree data* @child_post_bind: Called after a new child has been bound* @child_pre_probe: Called before a child device is probed. The device has* memory allocated but it has not yet been probed.* @child_post_remove: Called after a child device is removed. The device* has memory allocated but its device_remove() method has been called.* @priv_auto: If non-zero this is the size of the private data* to be allocated in the device's ->priv pointer. If zero, then the driver* is responsible for allocating any data required.* @plat_auto: If non-zero this is the size of the* platform data to be allocated in the device's ->plat pointer.* This is typically only useful for device-tree-aware drivers (those with* an of_match), since drivers which use plat will have the data* provided in the U_BOOT_DRVINFO() instantiation.* @per_child_auto: Each device can hold private data owned by* its parent. If required this will be automatically allocated if this* value is non-zero.* @per_child_plat_auto: A bus likes to store information about* its children. If non-zero this is the size of this data, to be allocated* in the child's parent_plat pointer.* @ops: Driver-specific operations. This is typically a list of function* pointers defined by the driver, to implement driver functions required by* the uclass.* @flags: driver flags - see DM_FLAGS_...* @acpi_ops: Advanced Configuration and Power Interface (ACPI) operations,* allowing the device to add things to the ACPI tables passed to Linux*/
      struct driver {char *name;enum uclass_id id;const struct udevice_id *of_match;int (*bind)(struct udevice *dev);int (*probe)(struct udevice *dev);int (*remove)(struct udevice *dev);int (*unbind)(struct udevice *dev);int (*of_to_plat)(struct udevice *dev);int (*child_post_bind)(struct udevice *dev);int (*child_pre_probe)(struct udevice *dev);int (*child_post_remove)(struct udevice *dev);int priv_auto;int plat_auto;int per_child_auto;int per_child_plat_auto;const void *ops;	/* driver-specific operations */uint32_t flags;
      #if CONFIG_IS_ENABLED(ACPIGEN)struct acpi_ops *acpi_ops;
      #endif
      };
      
      U_BOOT_DRIVER也定义在include\dm\device.h中:
      /* Declare a new U-Boot driver */
      #define U_BOOT_DRIVER(__name)						\ll_entry_declare(struct driver, __name, driver)
      
    • 3)struct uclass,维护一类驱动。
      struct uclass定义在include\dm\uclass.h中:
      /*** struct uclass - a U-Boot drive class, collecting together similar drivers** A uclass provides an interface to a particular function, which is* implemented by one or more drivers. Every driver belongs to a uclass even* if it is the only driver in that uclass. An example uclass is GPIO, which* provides the ability to change read inputs, set and clear outputs, etc.* There may be drivers for on-chip SoC GPIO banks, I2C GPIO expanders and* PMIC IO lines, all made available in a unified way through the uclass.** @priv_: Private data for this uclass (do not access outside driver model)* @uc_drv: The driver for the uclass itself, not to be confused with a* 'struct driver'* @dev_head: List of devices in this uclass (devices are attached to their* uclass when their bind method is called)* @sibling_node: Next uclass in the linked list of uclasses*/
      struct uclass {void *priv_;struct uclass_driver *uc_drv;struct list_head dev_head;struct list_head sibling_node;
      };
      
    • 4)struct uclass_driver,在编写驱动时,会使用UCLASS_DRIVER来注册一个uclass_driver对象。这个uclass驱动维护了这一类硬件驱动的接口,为上层的调用提供了统一的接口。
      struct uclass_driver定义在include\dm\uclass.h
      /*** struct uclass_driver - Driver for the uclass** A uclass_driver provides a consistent interface to a set of related* drivers.** @name: Name of uclass driver* @id: ID number of this uclass* @post_bind: Called after a new device is bound to this uclass* @pre_unbind: Called before a device is unbound from this uclass* @pre_probe: Called before a new device is probed* @post_probe: Called after a new device is probed* @pre_remove: Called before a device is removed* @child_post_bind: Called after a child is bound to a device in this uclass* @child_pre_probe: Called before a child in this uclass is probed* @child_post_probe: Called after a child in this uclass is probed* @init: Called to set up the uclass* @destroy: Called to destroy the uclass* @priv_auto: If non-zero this is the size of the private data* to be allocated in the uclass's ->priv pointer. If zero, then the uclass* driver is responsible for allocating any data required.* @per_device_auto: Each device can hold private data owned* by the uclass. If required this will be automatically allocated if this* value is non-zero.* @per_device_plat_auto: Each device can hold platform data* owned by the uclass as 'dev->uclass_plat'. If the value is non-zero,* then this will be automatically allocated.* @per_child_auto: Each child device (of a parent in this* uclass) can hold parent data for the device/uclass. This value is only* used as a fallback if this member is 0 in the driver.* @per_child_plat_auto: A bus likes to store information about* its children. If non-zero this is the size of this data, to be allocated* in the child device's parent_plat pointer. This value is only used as* a fallback if this member is 0 in the driver.* @flags: Flags for this uclass (DM_UC_...)*/
      struct uclass_driver {const char *name;enum uclass_id id;int (*post_bind)(struct udevice *dev);int (*pre_unbind)(struct udevice *dev);int (*pre_probe)(struct udevice *dev);int (*post_probe)(struct udevice *dev);int (*pre_remove)(struct udevice *dev);int (*child_post_bind)(struct udevice *dev);int (*child_pre_probe)(struct udevice *dev);int (*child_post_probe)(struct udevice *dev);int (*init)(struct uclass *class);int (*destroy)(struct uclass *class);int priv_auto;int per_device_auto;int per_device_plat_auto;int per_child_auto;int per_child_plat_auto;uint32_t flags;
      };
      
      UCLASS_DRIVER也定义在include\dm\uclass.h
      /* Declare a new uclass_driver */
      #define UCLASS_DRIVER(__name)						\ll_entry_declare(struct uclass_driver, __name, uclass_driver)
      
      最后做个总结:
      struct driverU_BOOT_DRIVER:用于注册硬件驱动,为编写底层硬件驱动提供了一个框架。适配不同的硬件时编写的就是这个驱动。
      struct uclass_driverUCLASS_DRIVER:用于维护一类驱动,是在U_BOOT_DRIVER注册的驱动层之上的一个框架,主要是为u-boot的上层应用提供一个统一的接口。大部分框架u-boot已具备,开发人员一般不用编写。
  • 4.3、驱动实例
    下面以drivers\mtd\altera_qspi.c驱动为例进行分析:
    • 1)U_BOOT_DRIVER:和硬件相关
      部分代码如下:

      U_BOOT_DRIVER(altera_qspi) = {.name	= "altera_qspi",.id	= UCLASS_MTD,.of_match = altera_qspi_ids,.of_to_plat = altera_qspi_of_to_plat,.plat_auto	= sizeof(struct altera_qspi_plat),.probe	= altera_qspi_probe,
      };
      

      其中,U_BOOT_DRIVER是注册硬件驱动的接口;
      .name:驱动名字;
      .id:指明驱动的类型,用于匹配UCLASS_DRIVER
      .of_match:设备树匹配表;
      .of_to_plat:获取设备树的属性的函数;
      .plat_auto:驱动平台私有数据,在设备匹配时会自动为私有数据分配空间;
      .probe:和设备树匹配后,会进入这个函数;

    • 2)UCLASS_DRIVER:为u-boot上层提供统一接口
      这部分一般不用开发者编写,这里主要是为了梳理DM的流程。
      UCLASS_MTD类的注册代码在drivers\mtd\mtd-uclass.c如下:

      /** Implement a MTD uclass which should include most flash drivers.* The uclass private is pointed to mtd_info.*/UCLASS_DRIVER(mtd) = {.id		= UCLASS_MTD,.name		= "mtd",.per_device_auto	= sizeof(struct mtd_info),
      };
      

      这里可以看出UCLASS_MTD的设备,驱动和上层之间的桥梁是通过struct mtd_info实现的。
      include\linux\mtd\mtd.h中定义如下:

      struct mtd_info {
      u_char type;
      uint32_t flags;
      uint64_t size;	 // Total size of the MTD/* "Major" erase size for the device. Naïve users may take this* to be the only erase size available, or may use the more detailed* information below if they desire*/
      uint32_t erasesize;
      /* Minimal writable flash unit size. In case of NOR flash it is 1 (even* though individual bits can be cleared), in case of NAND flash it is* one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR* it is of ECC block size, etc. It is illegal to have writesize = 0.* Any driver registering a struct mtd_info must ensure a writesize of* 1 or larger.*/
      uint32_t writesize;/** Size of the write buffer used by the MTD. MTD devices having a write* buffer can write multiple writesize chunks at a time. E.g. while* writing 4 * writesize bytes to a device with 2 * writesize bytes* buffer the MTD driver can (but doesn't have to) do 2 writesize* operations, but not 4. Currently, all NANDs have writebufsize* equivalent to writesize (NAND page size). Some NOR flashes do have* writebufsize greater than writesize.*/
      uint32_t writebufsize;uint32_t oobsize;   // Amount of OOB data per block (e.g. 16)
      uint32_t oobavail;  // Available OOB bytes per block/** If erasesize is a power of 2 then the shift is stored in* erasesize_shift otherwise erasesize_shift is zero. Ditto writesize.*/
      unsigned int erasesize_shift;
      unsigned int writesize_shift;
      /* Masks based on erasesize_shift and writesize_shift */
      unsigned int erasesize_mask;
      unsigned int writesize_mask;/** read ops return -EUCLEAN if max number of bitflips corrected on any* one region comprising an ecc step equals or exceeds this value.* Settable by driver, else defaults to ecc_strength.  User can override* in sysfs.  N.B. The meaning of the -EUCLEAN return code has changed;* see Documentation/ABI/testing/sysfs-class-mtd for more detail.*/
      unsigned int bitflip_threshold;// Kernel-only stuff starts here.
      #ifndef __UBOOT__const char *name;
      #elsechar *name;
      #endifint index;/* OOB layout description */const struct mtd_ooblayout_ops *ooblayout;/* ECC layout structure pointer - read only! */struct nand_ecclayout *ecclayout;/* the ecc step size. */unsigned int ecc_step_size;/* max number of correctible bit errors per ecc step */unsigned int ecc_strength;/* Data for variable erase regions. If numeraseregions is zero,* it means that the whole device has erasesize as given above.*/int numeraseregions;struct mtd_erase_region_info *eraseregions;/** Do not call via these pointers, use corresponding mtd_*()* wrappers instead.*/int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
      #ifndef __UBOOT__int (*_point) (struct mtd_info *mtd, loff_t from, size_t len,size_t *retlen, void **virt, resource_size_t *phys);int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
      #endifunsigned long (*_get_unmapped_area) (struct mtd_info *mtd,unsigned long len,unsigned long offset,unsigned long flags);int (*_read) (struct mtd_info *mtd, loff_t from, size_t len,size_t *retlen, u_char *buf);int (*_write) (struct mtd_info *mtd, loff_t to, size_t len,size_t *retlen, const u_char *buf);int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len,size_t *retlen, const u_char *buf);int (*_read_oob) (struct mtd_info *mtd, loff_t from,struct mtd_oob_ops *ops);int (*_write_oob) (struct mtd_info *mtd, loff_t to,struct mtd_oob_ops *ops);int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len,size_t *retlen, struct otp_info *buf);int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from,size_t len, size_t *retlen, u_char *buf);int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len,size_t *retlen, struct otp_info *buf);int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from,size_t len, size_t *retlen, u_char *buf);int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to,size_t len, size_t *retlen, u_char *buf);int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from,size_t len);
      #ifndef __UBOOT__int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs,unsigned long count, loff_t to, size_t *retlen);
      #endifvoid (*_sync) (struct mtd_info *mtd);int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len);int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs);int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
      #ifndef __UBOOT__int (*_suspend) (struct mtd_info *mtd);void (*_resume) (struct mtd_info *mtd);void (*_reboot) (struct mtd_info *mtd);
      #endif/** If the driver is something smart, like UBI, it may need to maintain* its own reference counting. The below functions are only for driver.*/int (*_get_device) (struct mtd_info *mtd);void (*_put_device) (struct mtd_info *mtd);#ifndef __UBOOT__/* Backing device capabilities for this device* - provides mmap capabilities*/struct backing_dev_info *backing_dev_info;struct notifier_block reboot_notifier;  /* default mode before reboot */
      #endif/* ECC status information */struct mtd_ecc_stats ecc_stats;/* Subpage shift (NAND) */int subpage_sft;void *priv;struct module *owner;
      #ifndef __UBOOT__struct device dev;
      #elsestruct udevice *dev;
      #endifint usecount;/* MTD devices do not have any parent. MTD partitions do. */struct mtd_info *parent;/** Offset of the partition relatively to the parent offset.* Is 0 for real MTD devices (ie. not partitions).*/u64 offset;/** List node used to add an MTD partition to the parent* partition list.*/struct list_head node;/** List of partitions attached to this MTD device (the parent* MTD device can itself be a partition).*/struct list_head partitions;
      };
      

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

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

相关文章

超详细的Scrapy框架的基本使用教程

Scrapy的介绍 scrapy的工作流程(重点!!!) 如下图所示: 爬虫: 负责向引擎提供要爬取网页的URL,引擎会把这个URL封装成request对象并传递给调度器,把引擎传递过来的resp…

常用区块链安全关键名词和攻击方法解释

文章目录 一、重点名词解释1.1 钱包(Wallet)1.2 冷钱包(Cold Wallet)1.3 热钱包 (Hot Wallet)1.4 公钥(Public Key)1.5 私钥(Private Key)1.6 助记词(Mnemonic)1.7 Keystore1.8 公链(Public Blockchain)1.9 交易所 Exchange1.10 节…

API 常用的序列化协议详解

目录 JSON (JavaScript Object Notation) XML (Extensible Markup Language) Protocol Buffers (Protobuf) MessagePack Thrift Avro 小结 API(Application Programming Interface,应用程序编程接口)在软件开发中扮演着至关重要的角色…

leetcode 673.最长递增子序列的个数

上一题只需要知道最长递增子序列的长度就行了,那样的话直接一个dp就完事了,但是呢,这里说了需要记录这个最长长度递增子序列的个数,这下的话,如果你想用原先的思路,其实可以,但是要能做到计数的…

vue3 (六)自定义指令

1.定义自定义指令: app.directive(pos,{mounted(el,bunding){el.style[bunding.arg] bunding.value px;}, updated(el,bunding){el.style[bunding.arg] bunding.value px;} }) app.directive(指令名,{ mounted(el,bunding){}, updated(el,bunding){} }) 如果只…

安卓app软件开发的费用

我们公司总结的开发价格根据安卓APP,苹果APP行业的报价,开发的APP软件费用主要受到两个方面的影响。安卓和苹果APP软件应用的复杂性,第二个是定制开发的APP软件,开发成本和人员的投入成本,以下就是不同的报价费用是怎么…

面试经典150题【51-60】

文章目录 面试经典150题【51-60】71.简化路径155.最小栈150.逆波兰表达式求值224.基本计算器141.环形链表2.两数相加21.合并两个有序链表138.随机链表的复制19.删除链表的倒数第N个节点82.删除链表中的重复元素II 面试经典150题【51-60】 71.简化路径 先用split(“/”)分开。然…

10. Nginx进阶-Return

简介 什么是Return? nginx的return指令是用于在nginx配置文件中进行重定向或返回特定的HTTP响应码的指令。 它可以根据不同的条件来执行不同的操作,如重定向到其他URL、返回指定的HTTP响应码或自定义响应内容等。 Return适用范围 return指令只能在se…

四平方和 刷题笔记

/* 四平方和 直接暴力搜索 可能会超时 使用二分辅助搜索 先枚举出 c*cd*d并存入数组 用式子算出 a*ab*b还剩下多少查找sum数组里面是否存在符合条件的数 查找方式使用二分搜索 当逼近答案后 检查一下是否为所需的数 如果是 直接输出 */ #include <cstring> #includ…

rabbitmq基础(1)

1、背景 能实现消息队列的框架软件有很多&#xff0c;kafka、rabbitmq、RocketMq、activeMq、Redis&#xff08;非专业&#xff09;&#xff0c;各有各的特点和优缺点。但是之前的公司数据需求规模并非很大&#xff0c;所以采用rabbitmq作为消息队列。 2、rabbitMq的基础架构…

大批量接口请求的前端优化

接到一个需求&#xff0c;需要做一个运维的功能&#xff0c;对公司下平台子系统做一个开关界面&#xff0c;要求可以大批量对系统进行修改。这样大批量的修改&#xff0c;如果有个老哥手一抖点了全选&#xff0c;那可能同时会发送几十上百个接口&#xff0c;对浏览器和服务器都…

C++面试宝典【配文档,全方面学习】

原word文档[链接: https://pan.baidu.com/s/1CKnm7vHDmHSDskAgxgZgKA?pwdr4wv 提取码: r4wv 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 --来自百度网盘超级会员v5的分享] 一、C / C基础 1、简述C的内存分区&#xff1f; 一个C、C程序的内存分区主要有5个…

使用html网页播放多个视频的几种方法

前言 因为项目测试需要&#xff0c;我需要可以快速知道自己推流的多路视频流质量&#xff0c;于是我想到可以使用html网页来播放视频&#xff0c;实现效果极其简单&#xff0c;方法有好几种&#xff0c;以下是几种记录&#xff1a; 注意&#xff1a;测试过&#xff0c;VLC需要使…

Java:类加载器

参考 JavaGuide 简介 类加载器的主要作用是加载Java类的字节码即.class文件到JVM中。每个Java类都有一个引用指向加载它的类加载器。数组类是JVM直接生成而非加载的。根据需要动态加载&#xff0c;已加载的类放到ClassLoader中&#xff0c;相同二进制名称的类只会被加载一次…

C++从零开始的打怪升级之路(day43)

这是关于一个普通双非本科大一学生的C的学习记录贴 在此前&#xff0c;我学了一点点C语言还有简单的数据结构&#xff0c;如果有小伙伴想和我一起学习的&#xff0c;可以私信我交流分享学习资料 那么开启正题 今天分享的是关于多态的知识点 1.多态的概念及定义&#xff0c;…

[Python] 添加重试机制来处理某些可能出现异常的函数

在 Python 中&#xff0c;如果你想要添加重试机制来处理某些可能出现异常的函数&#xff0c;可以使用 retry 装饰器。虽然 Python 标准库中没有提供内置的 retry 装饰器&#xff0c;但你可以使用第三方库 tenacity 来实现这个功能。 tenacity 是一个流行的 Python 库&#xff…

Ubuntu18.04运行ORB-SLAM3

ORB-SLAM3复现(ubuntu18) 文章目录 ORB-SLAM3复现(ubuntu18)1 坐标系与外参Intrinsic parameters2 内参Intrinsic parameters2.1 相机内参① 针孔模型Pinhole② KannalaBrandt8模型③ Rectified相机 2.2 IMU内参 3 VI标定—外参3.1 Visual calibration3.2 Inertial calibration…

STM32类别概述、下载程序及启动过程分析

STM32类别概述、下载程序及启动过程分析 STM32类别STM32下载程序STM32启动过程分析 STM32类别 STM32 目前总共有 5 大类&#xff0c;18 个系列 结合 STM32F1 的芯片来说&#xff0c;其 CMSIS 应用程序的简单结构框图&#xff0c;不包括实时操作系统和 中间设备等组件&#xf…

find函数-秒了道题

秒了 笑死 还是规规矩矩做吧 string类的find()函数用于在字符串中查找字符或子串&#xff0c;返回第一个匹配的位置。 class Solution { public:int strStr(string haystack, string needle) {return haystack.find(needle);} };

搜维尔科技:Manus Prime X系列手套介绍,由 PrimeXMarkerMocap 和Prime X Haptic VR 手套组成

搜维尔科技&#xff1a;Manus Prime X系列手套介绍&#xff0c;由 PrimeXMarkerMocap 和Prime X Haptic VR 手套组成 Manus Prime X&#xff08;点击进入官网&#xff09;系列手套介绍&#xff0c;由 PrimeXMarkerMocap 和Prime X Haptic VR 手套组成