STM32CubeMX学习笔记(50)——USB接口使用(DFU固件升级)

news2024/9/29 9:35:06

一、USB简介

USB(Universal Serial BUS)通用串行总线,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在 PC 领域的接口技术。USB 接口支持设备的即插即用和热插拔功能。USB 是在 1994 年底由英特尔、康柏、IBM、Microsoft 等多家公司联合提出的。

USB 发展到现在已经有 USB1.0/1.1/2.0/3.0 等多个版本。目前用的最多的就是 USB1.1 和 USB2.0,USB3.0 目前已经开始普及。STM32F103 自带的 USB 符合 USB2.0 规范,不过 STM32F103 的 USB 都只能用来做设备,而不能用作主机。

标准 USB 共四根线组成,除 VCC/GND 外,另外为 D+,D-; 这两根数据线采用的是差分电压的方式进行数据传输的。在 USB 主机上,D-和 D+都是接了 15K 的电阻到低的,所以在没有设备接入的时候,D+、D-均是低电平。而在 USB 设备中,如果是高速设备,则会在 D+上接一个 1.5K 的电阻到 VCC,而如果是低速设备,则会在 D-上接一个 1.5K 的电阻到 VCC。这样当设备接入主机的时候,主机就可以判断是否有设备接入,并能判断设备是高速设备还是低速设备。

STM32F103 的 MCU 自带 USB 从控制器,符合 USB 规范的通信连接;PC 主机和微控制器之间的数据传输是通过共享一专用的数据缓冲区来完成的,该数据缓冲区能被 USB 外设直接访问。这块专用数据缓冲区的大小由所使用的端点数目和每个端点最大的数据分组大小所决定,每个端点最大可使用 512 字节缓冲区(专用的 512 字节,和 CAN 共用),最多可用于 16 个单向或 8 个双向端点。USB 模块同 PC 主机通信,根据 USB 规范实现令牌分组的检测,数据发送/接收的处理,和握手分组的处理。整个传输的格式由硬件完成,其中包括 CRC 的生成和校验。

1.1 USB DFU简介

DFU全称为Download Firmware Update,是ST官方推出的一个通过USB接口进行IAP升级的方案,同串口ISP一样,他们都集成在了芯片内部的Bootloader区段,可以通过配置boot引脚来启动。(具体可参照ST文档:AN2606)。不过内置DFU的芯片大部分型号都比较新,如果你用的型号没有内置DFU程序,没关系我们也可以通过CubeMX来快速生成和移植一个DFU功能程序到你的Flash中来使用。

由于DFU是USB差分传输,相对而言速率和通讯稳定性上相当于UART更加快与稳定,但是由于设备端不知道待接收文件的大小,何时传输结束,只为传输而传输,相比较带有完整文件传输协议而言(Ymodem、Xmodem等)这个差太多,不过CDC可以替代解决这个问题。

二、新建工程

1. 打开 STM32CubeMX 软件,点击“新建工程”

2. 选择 MCU 和封装

3. 配置时钟
RCC 设置,选择 HSE(外部高速时钟) 为 Crystal/Ceramic Resonator(晶振/陶瓷谐振器)

选择 Clock Configuration,配置系统时钟 SYSCLK 为 72MHz
修改 HCLK 的值为 72 后,输入回车,软件会自动修改所有配置

4. 配置调试模式
非常重要的一步,否则会造成第一次烧录程序后续无法识别调试器
SYS 设置,选择 Debug 为 Serial Wire

三、USB

3.1 参数配置

Connectivity 中选择 USB 设置,并勾选 Device(FS) 激活 USB 设备。

Parameter Settings 进行具体参数配置。

  • Speed: Full Speed 12MBit/s(固定为全速)
  • Low Power: 默认 Disabled(在任何不需要使用usb模块的时候,通过写控制寄存器总可以使usb模块置于低功耗模式(low power mode ,suspend模式)。在这种模式下,不产生任何静态电流消耗,同时usb时钟也会减慢或停止。通过对usb线上数据传输的检测,可以在低功耗模式下唤醒usb模块。也可以将一特定的中断输入源直接连接到唤醒引脚上,以使系统能立即恢复正常的时钟系统,并支持直接启动或停止时钟系统。)

3.2 引脚配置

USB 的 DP 引脚必须上拉 1.5K 欧的电阻,电脑才能检测到 USB,否则检测不到。

查看野火指南者开发板原理图可知,需要将 PD6 配置为低电平使能 USB。

在右边图中找到 PD6 引脚,选择 GPIO_Output

GPIO output level 中选择 Low 输出低电平。

3.3 配置时钟

选择 Clock Configuration,USB 时钟配置为 48MHz,且来源最好是外部晶振分频得到。

3.4 USB Device

USB有主机(Host)和设备(Device)之分。一般电脑的USB接口为主机接口,而键盘、鼠标、U盘等则为设备。

部分型号的STM32芯片有1~2个USB接口。像STM32F103系列的有一个USB Device接口,STM32F407系列的有2个USB接口,既可以作为HOST,又可以作为Device,还可以作为OTG接口。

Middleware 中选择 USB_DEVICE 设置,在 Class For FS IP 设备类别选择 Download Firmware Update Class(DFU) 固件升级类。

修改参数配置。

  • USBD_DFU_XFER_SIZE(每次传输的最大字节数): 1024 Bytes
  • USBD_DFU_APP_DEFAULT_ADD (Base Address 0x)(升级时存入Application程序的起始地址):0x08005800

根据下面 六、编写Bootloader程序 编译后 .map 文件大小,可以了解程序存储到了哪些区域。来设置Application程序起始地址,避开Bootloader程序地址范围。

打开 map 文件后,查看文件最后部分的区域,可以看到一段以 “Memory Map of the image” 开头的记录(若找不到可用查找功能定位)

Bootloader程序的基地址是 0x08000000,大小为 0x00004a84,可知它占用的最高的地址空间为 0x08004a84。0x08000000~0x08005800 的 0x5800/1024=22KB 存储空间存储DFU程序。USBD_DFU_APP_DEFAULT_ADD 设置的起始地址就要避开这个范围。

  • USBD_DFU_MEDIA Interface(对芯片Flash使用的描述): @Internal Flash /0x08000000/11*002Ka,245*002Kg【这个参数是DfuSeDemo这个DFU升级软件需要识别的参数】
    • 0x08000000,表示起始地址
    • “a”代表的是Read-only,表示所指明的区域应该为Bootloader程序的空间不可擦除或者修改
    • “g”代表Read/Write/Erase,表示所指明的区域应该为Application程序的空间,大小由前面的数字决定
    • “*”前面的为Sector的个数,后面的为Sector的大小,这里的意思就是从0x08000000开始,前面11个Sector(每个Sector为2k字节)为Read-only,后面245个Sector(每个Sector为2k字节)为Read/Write/Erase等等。

注意:由于芯片不同,芯片的内部 Flash 分布情况也不一定相同,故请参考使用的芯片参考手册。

STM32F103VET6 型号芯片的参数,即 STM32F1 系列大容量产品。Flash 分为 256 页,每页大小为 2KB,共 512KB。

设备描述符保持默认。

四、添加按键

4.1 GPIO配置

System Core 中选择 GPIO 设置。

在右边图中找到按键对应引脚,选择 GPIO_Input

五、生成代码

输入项目名和项目路径

选择应用的 IDE 开发环境 MDK-ARM V5

每个外设生成独立的 ’.c/.h’ 文件
不勾:所有初始化代码都生成在 main.c
勾选:初始化代码生成在对应的外设文件。 如 GPIO 初始化代码生成在 gpio.c 中。

点击 GENERATE CODE 生成代码

六、编写Bootloader程序

6.1 修改usbd_dfu_if.c

打开工程文件夹Application/User/USB_DEVICE/Appusbd_dfu_if.c文件

6.1.1 修改内部Flash操作相关函数

  • MEM_If_Init_FS
    Flash初始化,将Flash解锁,并将所有的标志位清零,以便后续的写入动作
/**
  * @brief  Memory initialization routine.
  * @retval USBD_OK if operation is successful, MAL_FAIL else.
  */
uint16_t MEM_If_Init_FS(void)
{
  /* USER CODE BEGIN 0 */
    HAL_FLASH_Unlock();
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR);
  return (USBD_OK);
  /* USER CODE END 0 */
}
  • MEM_If_DeInit_FS
    Flash取消初始化,将Flash重新上锁,禁止对Flash的操作
/**
  * @brief  De-Initializes Memory
  * @retval USBD_OK if operation is successful, MAL_FAIL else
  */
uint16_t MEM_If_DeInit_FS(void)
{
  /* USER CODE BEGIN 1 */
    HAL_FLASH_Lock();
  return (USBD_OK);
  /* USER CODE END 1 */
}
  • MEM_If_Erase_FS
    Flash擦除
/**
  * @brief  Erase sector.
  * @param  Add: Address of sector to be erased.
  * @retval 0 if operation is successful, MAL_FAIL else.
  */
uint16_t MEM_If_Erase_FS(uint32_t Add)
{
  /* USER CODE BEGIN 2 */
    uint32_t PageError;
    /* Variable contains Flash operation status */
    HAL_StatusTypeDef status;
    FLASH_EraseInitTypeDef eraseinitstruct;
 
    eraseinitstruct.TypeErase = FLASH_TYPEERASE_PAGES;
    eraseinitstruct.PageAddress = Add;
    eraseinitstruct.NbPages = 1U;
    status = HAL_FLASHEx_Erase(&eraseinitstruct, &PageError);
 
    if(status != HAL_OK)
    {
        return (USBD_FAIL);
    }
  return (USBD_OK);
  /* USER CODE END 2 */
}
  • MEM_If_Write_FS
    Flash写入,将USB接收到的Flash数据写入到Flash中
/**
  * @brief  Memory write routine.
  * @param  src: Pointer to the source buffer. Address to be written to.
  * @param  dest: Pointer to the destination buffer.
  * @param  Len: Number of data to be written (in bytes).
  * @retval USBD_OK if operation is successful, MAL_FAIL else.
  */
uint16_t MEM_If_Write_FS(uint8_t *src, uint8_t *dest, uint32_t Len)
{
  /* USER CODE BEGIN 3 */
    uint32_t i = 0;
 
    for(i = 0; i < Len; i += 4)
    {
        /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
        * be done by byte */
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t)(dest + i), *(uint32_t *)(src + i)) == HAL_OK)
        {
            /* Check the written value */
            if(*(uint32_t *)(src + i) != *(uint32_t *)(dest + i))
            {
                /* Flash content doesn't match SRAM content */
                return (USBD_FAIL);
            }
        }
        else
        {
            /* Error occurred while writing data in Flash memory */
            return (USBD_FAIL);
        }
    }
  return (USBD_OK);
  /* USER CODE END 3 */
}
  • MEM_If_Read_FS
    Flash读取,读取指定地址的数据到目标数组中,并返回数组地址
/**
  * @brief  Memory read routine.
  * @param  src: Pointer to the source buffer. Address to be written to.
  * @param  dest: Pointer to the destination buffer.
  * @param  Len: Number of data to be read (in bytes).
  * @retval Pointer to the physical address where data should be read.
  */
uint8_t *MEM_If_Read_FS(uint8_t *src, uint8_t *dest, uint32_t Len)
{
  /* Return a valid address to avoid HardFault */
  /* USER CODE BEGIN 4 */
    uint32_t i = 0;
    uint8_t *psrc = src;
 
    for(i = 0; i < Len; i++)
    {
        dest[i] = *psrc++;
    }
    /* Return a valid address to avoid HardFault */
    return (uint8_t *)(dest);
  /* USER CODE END 4 */
}
  • MEM_If_GetStatus_FS
    获取Flash状态
/**
  * @brief  Get status routine
  * @param  Add: Address to be read from
  * @param  Cmd: Number of data to be read (in bytes)
  * @param  buffer: used for returning the time necessary for a program or an erase operation
  * @retval USBD_OK if operation is successful
  */
uint16_t MEM_If_GetStatus_FS(uint32_t Add, uint8_t Cmd, uint8_t *buffer)
{
  /* USER CODE BEGIN 5 */
    //擦除及写入时间应该按文档改写
    uint16_t FLASH_PROGRAM_TIME = 50;
    uint16_t FLASH_ERASE_TIME = 50;

    switch(Cmd)
    {
    case DFU_MEDIA_PROGRAM:
        buffer[1] = (uint8_t)FLASH_PROGRAM_TIME;
        buffer[2] = (uint8_t)(FLASH_PROGRAM_TIME << 8);
        buffer[3] = 0;
        break;
    case DFU_MEDIA_ERASE:
    default:
        buffer[1] = (uint8_t)FLASH_ERASE_TIME;
        buffer[2] = (uint8_t)(FLASH_ERASE_TIME << 8);
        buffer[3] = 0;
        break;
    }
    return (USBD_OK);
  /* USER CODE END 5 */
}

6.2 修改main.c

添加APP程序入口函数指针。

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef void (*pFunction)(void);
/* USER CODE END PTD */

添加用于加载APP程序的变量、外部按键的判断、APP程序加载以及USB DFU初始化功能。

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  pFunction JumpToApplication;
  uint32_t JumpAddress;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  printf("\r\n****** USB-DFU Example ******\r\n\r\n");
  
  //读取PA0引脚电平决定是否进入APP以及判断APP程序入口地址是否存在或正确
  //按下按键进入DFU,不按按键进入Application程序
  if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET)
  {
    printf("Enter Application\r\n");
    /* Test if user code is programmed starting from USBD_DFU_APP_DEFAULT_ADD address */
    if(((*(__IO uint32_t *)USBD_DFU_APP_DEFAULT_ADD) & 0x2FFE0000) == 0x20000000)
    {
      /* Jump to user application */
      JumpAddress = *(__IO uint32_t *)(USBD_DFU_APP_DEFAULT_ADD + 4);
      JumpToApplication = (pFunction)JumpAddress;
 
      /* Initialize user application's Stack Pointer */
      __set_MSP(*(__IO uint32_t *) USBD_DFU_APP_DEFAULT_ADD);
      __disable_irq(); //此处官方代码未放置关闭中断,在跳转app的时候会出问题!!!!!!
      JumpToApplication();
    }
  }
  printf("Key Down Enter DFU\r\n");
  MX_USB_DEVICE_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

将程序编译烧录到开发板中

七、编写Application程序

7.1 修改main.c

屏蔽掉多余代码,替换打印信息

7.2 修改程序下载地址

修改成跟STM32CubeMX中USBD_DFU_APP_DEFAULT_ADD设置的一样的地址

将程序编译烧录到开发板中

八、查看打印

  • 没有按下按键,经过Bootloader程序跳转到Application程序
  • 按下KEY1按键,并按RESET按键重启,在Bootloader程序中进入DFU模式

九、下载和使用DFU升级工具

9.1 DfuSe USB设备固件升级软件

官网下载:https://www.st.com/content/st_com/zh/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stsw-stm32080.html
百度网盘:https://pan.baidu.com/s/1xViNHEScvAjn9xH1s6Zrgw?pwd=0ypj 提取码:0ypj

  • 安装驱动
    找到安装DfuSe目录下的Bin\Driver对应的Windows版本驱动。

  • 编译待升级的Application程序,生成.hex文件
    这里修改了打印内容,表示升级后的程序。

    找到生成的.hex文件。

  • 打开Dfu file manager,将.hex文件转成.dfu文件
    找到安装DfuSe目录下的Dfu file manager。


    这里的Target ID有不同的值,其中0代表片内Flash;1代表外部Flash;2代表外部Nor Flash。因此我们这里选择0,点击S19 or Hex选择hex文件即可生成DFU文件。

  • 按下KEY1按键,进入DFU模式

注意: 如果设备带有感叹号,则参考下面十一、注意事项

  • 打开DfuSeDemo,更新固件
    找到安装DfuSe目录下的DfuSeDemo。

    点击Choose加载之前转换的.dfu文件;勾选校验功能。

    点击Update完成擦除与下载;另外,可以通过点击Verify验证是否下载成功。
  • 重启设备,查看打印
    Application程序升级成为Application2程序

9.2 STM32CubeProgrammer

官网下载:https://www.st.com/zh/development-tools/stm32cubeprog.html
百度网盘:https://pan.baidu.com/s/133ahMS2G6lswQzw-G_7fMA?pwd=hece 提取码:hece

  • 编译待升级的Application程序,生成.hex文件
    这里修改了打印内容,表示升级后的程序。

    找到生成的.hex文件。
  • 打开STM32CubeProgrammer,切换到Erasing&Programming擦除和烧录界面,勾选烧录验证和烧录后重启选项
  • 按下KEY1按键,进入DFU模式

注意: 如果设备带有感叹号,则参考下面十一、注意事项

  • 选择USB,刷新端口,点击Connect进行连接

    点击Browse加载之前新编译的.hex文件;开启烧录。
  • 重启设备,查看打印
    Application程序升级成为Application2程序

十、工程代码

链接:https://pan.baidu.com/s/1FKdwTyTmybeeNYFKDk43VA?pwd=t2an 提取码:t2an

十一、注意事项

用户代码要加在 USER CODE BEGIN NUSER CODE END N 之间,否则下次使用 STM32CubeMX 重新生成代码后,会被删除。

如果USB端口出现感叹号设备无法启动的问题,可适当将堆改大,如0x400


• 由 Leung 写于 2022 年 12 月 30 日

• 参考:利用STM32CubeMX软件生成USB_DEVICE_DFU升级程序
    STM32 USB DFU功能
    STM32F103 DFU功能实现(MXcube)(一)
    STM32 HAL学习(七)USB DFU升级BootLoader

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

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

相关文章

量子+智慧交通!玻色量子中标北京城市轨道交通项目

​2022年11月&#xff0c;玻色量子与北京交通大学国家重点实验室组成联合体&#xff0c;接受北京城市轨道交通咨询有限公司委托&#xff0c;三方共同探索和实施量子计算在智慧地铁中的应用场景研究工作。 北京城市轨道交通咨询有限公司 此次科研合作&#xff0c;玻色量子将充分…

IB学生申请牛津剑桥需要注意什么?

HL要选修3门颇具挑战性的课程&#xff0c;SL还要再选3门课程&#xff0c;写好IA&#xff0c;通过包括EE\CAS\TOK在内的3门核心科目&#xff0c;IB课程的学习压力确实挺大。。 对于志在牛剑这样顶尖高校的IB学生而言&#xff0c;压力更大&#xff0c;因为牛剑等顶尖高校对于IB小…

【JavaEE】在Linux上搭建一个Java部署环境

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录在Linux上搭建一个Java部署环境1. 安装jdk2. 安装tomcat3. 安装mysql小结普通小孩也要热爱生活&#xff01; 在Linux上搭建一个Java部署环境 为了部署java web程序&#xff0c;需要安装&#xff1a;jdk、tomcat、m…

Pandas处理大数据的性能优化技巧

Pandas是Python中最著名的数据分析工具。在处理数据集时&#xff0c;每个人都会使用到它。但是随着数据大小的增加&#xff0c;执行某些操作的某些方法会比其他方法花费更长的时间。所以了解和使用更快的方法非常重要&#xff0c;特别是在大型数据集中&#xff0c;本文将介绍一…

百趣代谢组学文献分享:《Food Function》发表过的封面文章

百趣代谢组学今日分享西北大学食品科学与工程学院曹炜教授团队在食品科学领域国际著名学术期刊《Food& Function》上发表封面文章&#xff1a;Effects of honey-extracted polyphenols on serum antioxidant capacity and metabolic phenotype in rats。该研究在国际上首次…

Springboot定时调度任务动态管理

前言 现在智能手表、手环&#xff0c;相信很多人都使用过&#xff0c;其中有一个功能&#xff0c;就是会有各种的提醒&#xff0c;如喝水提醒、运动提醒、远眺提醒&#xff0c;本质上根据用户的设置&#xff0c;间隔一定时间执行一个调度任务&#xff0c;提醒用户做某件事情。这…

myBaits Expert Human Affinities Kit ——捕获人类样本中的 SNPs 信息,化石、法医样本和降解 DNA 样本均适用

myBaits Expert Human Affinities Kit用于人类基因组SNPs富集&#xff0c;该试剂盒与古人类种群遗传学领域的专家合作设计和开发&#xff0c;针对古代和现代人类种群中已知的2M以上多态位点设计&#xff0c;特异性捕获人类基因组文库中标志性的有效信息&#xff0c;提高人类种群…

ardupilot EKF3核心算法《可以使用的传感器》

目录 文章目录 目录摘要1.可以使用的传感器2.可以使用的传感器如果从代码中提供原始数据2.1 IMU传感器提供的有用数据2.2地磁传感器提供的有用数据2.3 GPS传感器提供的有用数据2.4 气压计传感器提供的有用数据摘要 本节主要讲解Ardupilot EKF3核心算法《可以使用的传感器》。 …

java租房app房东直租系统租房网站

简介 本系统是前后端分离的项目&#xff0c;前端使用mui开发科打包成为安卓的apk。后端采用springboot开发。主要是房东登录注册后&#xff0c;可以发布房源信息&#xff0c;可以上架下架编辑删除房源信息等&#xff0c;租房者可以搜索自己需要的房子&#xff0c;然后进入详情…

Maven基础知识

第1章 Maven 介绍 1.1 什么是 Maven 1.1.1 什么是 Maven Maven 的正确发音是[ˈmevən]&#xff0c;而不是“马瘟”以及其他什么瘟。Maven 在美国是一个口语化的词 语&#xff0c;代表专家、内行的意思。 一个对 Maven 比较正式的定义是这么说的&#xff1a;Maven 是一个项…

代码随想录算法训练营第二天 java : 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II ,

文章目录Leecode977.有序数组的平方题目链接题目暴力解法双指针解法小结Leecode209.长度最小的子数组。题目连接题目难点 &#xff1a;滑动窗口Leecode59.螺旋矩阵II题目链接题目思路用到的变量代码总结今日收获Leecode977.有序数组的平方 题目链接 题目 给你一个按 非递减顺…

攻防世界-shrine

题目 访问题目场景 这个界面很乱奥&#xff0c;我们访问网页源代码&#xff0c;我们就能看见我们需要审计的源码了 我们把python源码复制下来&#xff0c;进行分析 import flask import osapp flask.Flask(__name__)app.config[FLAG] os.environ.pop(FLAG)app.route(/) def…

如何对企业内部进行知识内容有效性管理

企业内部文档管理版本的场景&#xff0c;如果日常没有比较好的工具进行内容控制&#xff0c;经常出现意外&#xff0c;有些意外很小、但是有些意外可能就伤筋动骨&#xff0c;例如标书里边的文件放错了&#xff0c;如果定性为串标&#xff0c;那么就非常严重了。JVS 企业文档管…

细刨进程状态,浅谈僵尸进程,孤儿进程,进程切换

文章目录进程状态宏观上操作系统层面上理解进程状态具体Linux操作系统的状态kill -19 pid &#xff1a;停止进程kill -18 pid &#xff1a;继续进程D&#xff08;disk sleep&#xff09;深度睡眠$和 $^僵尸状态和死亡状态僵尸进程孤儿进程进程优先级由此衍生出另外几个概念进程…

目标检测指标IOU和mAP

IOU(交并比) 交并比&#xff08;loU&#xff09;函数做的是计算两个边界框交集和并集之比。可以用来判断定位算法的好坏。 一般来说&#xff0c;IoU大于等于0.5&#xff0c;那么结果是可以接受的&#xff0c;就说检测正确。如果预测器和实际边界框完美重叠&#xff0c;loU就是…

HTML5中的FileReader对象

FileReader FileReader主要用于将文件内容读入内存&#xff0c;通过一系列异步接口&#xff0c;可以在主线程中访问本地文件。 方法 readAsArrayBuffer(file):void : 异步按字节读取文件内容&#xff0c;结果用ArrayBuffer对象表示readAsBinaryString(file):void : 异步按字…

重磅!中国电信物联网用户超4亿

近日&#xff0c;中国电信物联网发展规模取得新突破&#xff0c;物联网用户超4亿&#xff0c;物联网用户数超过移动电话用户数&#xff0c;全面迈入“物超人”时代。 “物超人”&#xff0c;即代表“物”的移动物联网终端用户数超出代表“人”的移动电话用户数。工信部公布的数…

591页22万字城市智慧应急指挥中心信息化设计方案

【版权声明】本资料来源网络&#xff0c;仅用于行业知识分享&#xff0c;供个人学习参考&#xff0c;请勿商用。【侵删致歉】如有侵权请联系小编&#xff0c;将在收到信息后第一时间进行删除&#xff01;完整资料领取见文末&#xff0c;部分资料内容&#xff1a; 目 录 第1章 项…

为有状态应用而生,云原生本地存储Carina正式进入CNCF沙箱

12月14日&#xff0c;云原生本地存储开源项目 Carina 通过了全球顶级开源基金会 CNCF 技术监督委员会&#xff08;TOC&#xff09;的评定&#xff0c;正式成为 CNCF 沙箱级项目&#xff08;Sandbox Projects&#xff09;。 Carina是由博云于2021年10月主导发起的云原生本地存储…

FISCO BCOS的PBFT共识算法流程详解

原文&#xff1a; https://fisco-bcos-doc.readthedocs.io/zh_CN/latest/docs/design/consensus/pbft.html PBFT模块主要包括PrepareReq、SignReq、CommitReq和ViewChangeReq四种共识消息&#xff1a; PrepareReqPacket: 包含区块的请求包&#xff0c;由leader产生并向所有Repl…