【Linux 驱动基础】设备树驱动

# 前置知识

        在图中,树的主干就是系统总线, IIC 控制器、  SPI 控制器等都是接到系统主线上的分支。其中 IIC1 上接了 AT24C02这个 IIC 设备, DTS 文件的主要功能就是按照图所示的结构来描述板子上的设备信息。

1. Device格式

DTS文件格式

/dts-v1/; // 表示版本
[memory reservations] // 格式为: /memreserve/ <address> <length>;
/ {
    [property definitions]
    [child nodes]
};

node格式

[label:] node-name[@unit-address] {
    [properties definitions]
    [child nodes]
};

label:标号,可以省略,可以使用&label来引用node;

node-name:节点的名称,长度应该为 1-31 个字符,命名应该以小写或者大写字母开头

unit-address:表示设备地址或者寄存器首地址

properties

简单地说, properties 就是“name=value”, value 有多种取值方式

  • Property 格式 1:

[label:] property-name = value;

  • Property 格式 2(没有值):

[label:] property-name;

  • Property 取值只有 3 种:

arrays of cells(1 个或多个 32 位数据, 64 位数据使用 2 个 32 位数据表示, eg:interrupts = <17 0xc>;),

string(字符串,eg:compatible = "simple-bus"),

bytestring(1 个或多个字节,eg:local-mac-address = [00 00 12 34 56 78]; // 每个 byte 使用 2 个 16 进制数来表示)

 2. 标准属性

2.1 compatible

compatible 属性值由 string list 组成,定义了设备的兼容性,推荐格式为manufacturer,model,manufacturer 描述了生产商,model 描述了型号:

compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";

        根节点下 compatible 属性,用来选择哪一个“ machine desc”:一个内核可以支持 machine A,也支持 machine B,内核启动后会根据根节点的compatible 属性找到对应的 machine desc 结构体,执行其中的初始化函数 

compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960"

         设备节点下的compatible属性,是用来匹配驱动程序的,一般驱动程序文件都会有一个 OF 匹配表,此 OF 匹配表保存着一些 compatible 值,如果设备节点的 compatible 属性值核 OF 匹配表中的任何一个值相等,那么就表示这个设备可以使用这个驱动。如下:

static const struct of_device_id imx_wm8960_dt_ids[] = {
 { .compatible = "fsl,imx-audio-wm8960", },
 { /* sentinel */ }
};

2.2 model 

model 属性值是一个 string,指明了设备的厂商和型号,推荐格式为manufacturer,model

model = "Freescale i.MX6 ULL 14x14 EVK Board";

2.3 phandle

phandle 属性值是一个 u32,为设备树中唯一的节点指定一个数字标识符,用于其它节点指明关系。 

2.4 status

status 属性值是一个 string,表示设备的运行状态,可用值如下表:

2.5 #address-cells 和 #size-cells 

        #address-cells and #size-cells 属性值是一个 u32,可以用在任何拥有子节点的设备中,并描述子设备节点应该如何寻址

  #address-cells属性定义子节点 reg 属性中地址字段所占用的字长,也就是占用 u32 单元格的数量。

  #size-cells属性定义子节点 reg 属性值的长度所占用的 u32 单元格的数量。

2.6 reg

reg 属性值是一个 prop-encoded-array,用来描述设备地址空间资源信息,一般是某个外设的寄存器地址范围信息,包括起始地址和地址长度。

reg = <address1 length1 address2 length2 address3 length3……>

2.7 name(过时了,建议不用)

        它的值是字符串,用来表示节点的名字。在跟 platform_driver 匹配时,优先级最低。

        compatible 属性在匹配过程中,优先级最高

3. 常用节点

3.1 根节点

        树是由树根开始的,在设备树中称之为根节点,路径为/,根节点不需要节点名称,所有子节点都是挂在根节点上的,可以看到最简单的根节点如下:

/ {

};

根节点的属性有:

3.2 aliases

        aliases 节点用来定义别名,为了内核方便访问节点。

aliases {
		can0 = &flexcan1;
		can1 = &flexcan2;
		ethernet0 = &fec1;
		ethernet1 = &fec2;
		gpio0 = &gpio1;
		gpio1 = &gpio2;
		gpio2 = &gpio3;
		gpio3 = &gpio4;
		gpio4 = &gpio5;
		i2c0 = &i2c1;
		i2c1 = &i2c2;
		i2c2 = &i2c3;
		i2c3 = &i2c4;
		mmc0 = &usdhc1;
		mmc1 = &usdhc2;
		serial0 = &uart1;
		serial1 = &uart2;
		serial2 = &uart3;
		serial3 = &uart4;
		serial4 = &uart5;
		serial5 = &uart6;
		serial6 = &uart7;
		serial7 = &uart8;
		spi0 = &ecspi1;
		spi1 = &ecspi2;
		spi2 = &ecspi3;
		spi3 = &ecspi4;
		usbphy0 = &usbphy1;
		usbphy1 = &usbphy2;
	};

 3.3 chosen

        chosen 节点是为了uboot 向 Linux 内核传递数据,重点是 bootargs 参数,一般.dts 文件中 chosen 节点通常为空或者内容很少。

chosen {
		stdout-path = &uart1;
	};

3.4  CPU

        一般不需要我们设置,在 dtsi 文件中都定义好了:

cpus {
    #address-cells = <1>;
    #size-cells = <0>;
    cpu0: cpu@0 {
        .......
    }
};

3.5 memory

        芯片厂家不可能事先确定你的板子使用多大的内存,所以 memory 节点需要板厂设置,比如:

memory {
		reg = <0x80000000 0x20000000>;
	};

4. OF 操作函数

of.h // 提供设备树的一般处理函数,
// 比如 of_property_read_u32(读取某个属性的 u32 值),
// of_get_child_count(获取某个 device_node 的子节点数)
of_address.h // 地址相关的函数,
// 比如 of_get_address(获得 reg 属性中的 addr, size 值)
// of_match_device (从 matches 数组中取出与当前设备最匹配的一项)
of_dma.h // 设备树中 DMA 相关属性的函数
of_gpio.h // GPIO 相关的函数
of_graph.h // GPU 相关驱动中用到的函数, 从设备树中获得 GPU 信息
of_iommu.h // 很少用到
of_irq.h // 中断相关的函数
of_mdio.h // MDIO (Ethernet PHY) API
of_net.h // OF helpers for network devices.
of_pci.h // PCI 相关函数
of_pdt.h // 很少用到
of_reserved_mem.h // reserved_mem 的相关函数

4.1 查找节点 

通过节点名字查找节点

extern struct device_node *of_find_node_by_name(struct device_node *from,
 const char *name);

参数意义如下:

  • from:开始查找的节点,NULL 表示根节点
  • name:要查找的节点名称

返回值为找到的节点,NULL 为查找失败。

通过节点类型查找节点

extern struct device_node *of_find_node_by_type(struct device_node *from,
 const char *type);

 type 参数指定要查看节点对应的 type 字符串,也就是 device_type 属性值。

通过 device_type 和 compatible 查找节点

extern struct device_node *of_find_compatible_node(struct device_node *from,
 const char *type, const char *compat);

 通过 of_device_id 匹配表来查找节点

extern struct device_node *of_find_matching_node_and_match(
 struct device_node *from,
 const struct of_device_id *matches,
 const struct of_device_id **match);

 通过路径来查找节点

static inline struct device_node *of_find_node_by_path(const char *path)
{
 return of_find_node_opts_by_path(path, NULL);
}

4.2 获取父子节点

获取父节点

extern struct device_node *of_get_parent(const struct device_node *node);

迭代查找子节点

extern struct device_node *of_get_next_child(const struct device_node *node,
          struct device_node *prev);

4.3 提取属性值

查找指定节点的属性

extern struct property *of_find_property(const struct device_node *np,
      const char *name,
      int *lenp);

参数 name 指属性名字,lenp 指属性值的字节数。

获取属性中元素的数量

extern int of_property_count_elems_of_size(const struct device_node *np,
    const char *propname, int elem_size);

参数 propname 是需要统计元素数量的属性名字,参数 elem_size 是元素的长度。

返回值是获取到的属性元素数量。

eg. reg 属性的值通常是一个数组,使用此函数可以获取的数组的大小。

从属性中获取指定索引的 u32 类型数据值

extern int of_property_read_u32_index(const struct device_node *np,
           const char *propname,
           u32 index, u32 *out_value);

参数 out_value 用来返回获取到的值。

返回值用来表示是否获取成功。

 从属性中获取数组值

extern int of_property_read_u8_array(const struct device_node *np,
   const char *propname, u8 *out_values, size_t sz);
extern int of_property_read_u16_array(const struct device_node *np,
   const char *propname, u16 *out_values, size_t sz);
extern int of_property_read_u32_array(const struct device_node *np,
          const char *propname,
          u32 *out_values,
          size_t sz);
extern int of_property_read_u64_array(const struct device_node *np,
          const char *propname,
          u64 *out_values,
          size_t sz);

 eg. reg 属性的值通常是一个数组,使用这个函数可以一次读取出一个数组,也就是 reg 属性的全部值。

从属性中获取布尔值/整形值

/**
 * of_property_read_bool - Findfrom a property
 * @np:  device node from which the property value is to be read.
 * @propname: name of the property to be searched.
 *
 * Search for a property in a device node.
 * Returns true if the property exist false otherwise.
 */
static inline bool of_property_read_bool(const struct device_node *np,
      const char *propname)
{
 struct property *prop = of_find_property(np, propname, NULL);

 return prop ? true : false;
}

static inline int of_property_read_u8(const struct device_node *np,
           const char *propname,
           u8 *out_value)
{
 return of_property_read_u8_array(np, propname, out_value, 1);
}

static inline int of_property_read_u16(const struct device_node *np,
           const char *propname,
           u16 *out_value)
{
 return of_property_read_u16_array(np, propname, out_value, 1);
}

static inline int of_property_read_u32(const struct device_node *np,
           const char *propname,
           u32 *out_value)
{
 return of_property_read_u32_array(np, propname, out_value, 1);
}

static inline int of_property_read_s32(const struct device_node *np,
           const char *propname,
           s32 *out_value)
{
 return of_property_read_u32(np, propname, (u32*) out_value);
}

 从属性中获取字符串

extern int of_property_read_string(struct device_node *np,
       const char *propname,
       const char **out_string);

获取#address-cells 和#size-cells 属性值

extern int of_n_addr_cells(struct device_node *np);
extern int of_n_size_cells(struct device_node *np);

# 驱动示例

	atk-led{
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "atk,led";
		status = "okay";
		reg = < 0x20C406C 4
				0x20E0068 4 
				0x20E02F4 4 
				0x209C000 4>;
	};
#include <linux/console.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/ipu-v3.h>
#include <linux/module.h>
#include <linux/mxcfb.h>
#include <linux/mxc_v4l2.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/of.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <linux/of_platform.h>
#include <linux/uaccess.h>

typedef struct
{
    volatile uint32_t GPIO_DR;
    volatile uint32_t GPIO_GDIR;
    volatile uint32_t GPIO_PSR;
    volatile uint32_t GPIO_ICR1;
    volatile uint32_t GPIO_ICR2;
    volatile uint32_t GPIO_IMR;
    volatile uint32_t GPIO_ISR;
    volatile uint32_t GPIO_EDGE_SEL;
}GPIO_TypeDef;

static GPIO_TypeDef *GPIO;

static volatile uint32_t *CCM_CCGR;
static volatile uint32_t *IOMUXC_SW_MUX_CTL_PAD;
static volatile uint32_t *IOMUXC_SW_PAD_CTL_PAD;

typedef struct
{
    struct device_node *devNode;    /* 设备节点 */
    int reg_num;        /* reg长度 */
    u32 *reg_value;

    char drv_name[50];  /* 驱动名称 */
    int major;      /* 主设备号 */
    int minor;      /* 次设备号 */
    dev_t devt;     /* 设备号 */

    struct device *device;   /* 设备 */
    char device_name[50];    /* 设备名称 */

    struct class *class;    /* 类 */
    char class_name[50];    /* 类名称 */
}atk_led_private;

atk_led_private led_pri = {
    .devNode = NULL,
    .drv_name = "led_drv",
    .reg_value = NULL,
    .major  = 0,
    .minor  = 0,
    .devt   = 0,
    .device = NULL,
    .device_name = "led_dev",
    .class  = NULL,
    .class_name  = "led_class",
};

static int led_open(struct inode *inode, struct file *file)
{
    uint32_t val;
    /* 使能GPIO1时钟 */
    *CCM_CCGR |= (3 << 26);

    /* 设置IO复用 */
    val = *IOMUXC_SW_MUX_CTL_PAD;
    val &= ~(0x0F);
    val |= 5;
    *IOMUXC_SW_MUX_CTL_PAD = val;

    /* 设置IO属性 */

    /* 设置IO方向,设置GPIO1_IO03为输出 */
    GPIO->GPIO_GDIR |= (1 << 3);

    return 0;
}

static int led_release(struct inode *inode, struct file *file)
{
    return 0;
}

static ssize_t led_write(struct file *file, const char __user *buff, size_t size, loff_t *ppos)
{
    uint8_t status;
    int err;

    err = copy_from_user(&status, buff, 1);

    if(status == 1)
    {
        GPIO->GPIO_DR &= ~(1<<3);
    }
    else
    {
        GPIO->GPIO_DR |= (1<<3);
    }

    return 1;
}

static const struct file_operations led_op = {
    .owner      = THIS_MODULE,
    .open       = led_open,
    .release    = led_release,
    .write      = led_write,
};

static int atk_led_probe(struct platform_device *device)
{
    int err;
    int i;
    printk("atk_led_probe\r\n");

    /* 获取节点 */
    led_pri.devNode = of_find_node_by_path("/atk-led");
    if(led_pri.devNode == NULL)
    {
        printk("of_find_node_by_path fail\r\n");
        return -1;
    }

    /* 获取数字属性的长度 */
    led_pri.reg_num = of_property_count_elems_of_size(led_pri.devNode, "reg", sizeof(uint32_t));
    if(led_pri.reg_num < 0) {
        printk("of_property_count_elems_of_size error\r\n");
        return -1;
    }

    /* 读取数字属性 */
    led_pri.reg_value = (u32*)kmalloc(sizeof(u32)*led_pri.reg_num, GFP_KERNEL);
    err = of_property_read_u32_array(led_pri.devNode, "reg", led_pri.reg_value, led_pri.reg_num);
    if(err != 0) {
        printk("of_property_read_u32_array fail\r\n");
        return -1;
    }

    /* 打印属性值 */
    for(i=0; i<led_pri.reg_num; i+=2) {
        printk("reg = %x  %x \r\n", led_pri.reg_value[i], led_pri.reg_value[i+1]);
    }

    
    CCM_CCGR = ioremap(led_pri.reg_value[0], led_pri.reg_value[1]);
    IOMUXC_SW_MUX_CTL_PAD = ioremap(led_pri.reg_value[2], led_pri.reg_value[3]);
    IOMUXC_SW_PAD_CTL_PAD = ioremap(led_pri.reg_value[4], led_pri.reg_value[5]);
    GPIO = ioremap(led_pri.reg_value[6], led_pri.reg_value[7]);


    led_pri.major = register_chrdev(0, led_pri.drv_name, &led_op);
    led_pri.devt = MKDEV(led_pri.major, led_pri.minor);

    led_pri.class = class_create(THIS_MODULE, led_pri.class_name);
    if(IS_ERR(led_pri.class))
    {
        printk("class_create error\r\n");
        err = PTR_ERR(led_pri.class);
        goto err_class_create_out;
    }

    led_pri.device = device_create(led_pri.class, NULL, led_pri.devt, NULL, led_pri.device_name);
    if(IS_ERR(led_pri.device))
    {
        printk("device_create error\r\n");
        err = PTR_ERR(led_pri.device);
        goto err_device_create_out;
    }

    return 0;

err_device_create_out:
    class_destroy(led_pri.class);
err_class_create_out:
    unregister_chrdev(led_pri.major, led_pri.drv_name);
    return err;
}

static int atk_led_remove(struct platform_device *device)
{
    printk("atk_led_drv_remove\r\n");

    device_destroy(led_pri.class, led_pri.devt);
    class_destroy(led_pri.class);
    unregister_chrdev(led_pri.major, led_pri.drv_name);

    return 0;
}

static struct of_device_id atk_led_id[] = {
    {.compatible = "atk,led"},
    {}
};

static struct platform_driver atk_led_driver = 
{
    .probe = atk_led_probe,
    .remove = atk_led_remove,
    .driver = {
        .owner = THIS_MODULE,
        .name = "atk,led",
        .of_match_table = atk_led_id,
        
    },
};

static int __init atk_led_init(void)
{
    int err;

    printk("atk_led_init");
    err = platform_driver_register(&atk_led_driver);

    return 0;
}

static void __exit atk_led_exit(void)
{
    platform_driver_unregister(&atk_led_driver);
}

module_init(atk_led_init);
module_exit(atk_led_exit);

MODULE_LICENSE("GPL");

# 补充信息

1. 查看设备树信息

cd /sys/firmware/devicetree/base/

         节点是目录,属性是文件,比如当前设备树下既有个atk-led的设备节点,这个就是书写的LED的设备树

还可以使用 cat  指令查看属性值:

2. 查看 platform_device 的信息 

cd /sys/devices/platform

20c406c.atk-led就是编写的led的platform_device,进去看一下

 其中driver就是和atk-led驱动设备匹配的驱动程序了

3. 查看 platform_driver 的信息 

cd /sys/bus/platform/drivers/

 这个就是和atk-led平台设备匹配的驱动程序啦

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

移植day3

思维导图 重点README文档 1、解压tf-a源码 $> tar xfz tf-a-stm32mp-2.2.r2-r0.tar.gz 2、进入tf-a源码目录 $> cd tf-a-stm32mp-2.2.r2 3、打补丁命令&#xff0c;作用&#xff1a;补丁文件中存放默认的一些配置文件&#xff0c;对于程序员来说&#xff0c;需要将补丁…

Rust---有关介绍

目录 Rust---有关介绍变量的操作Rust 数值库&#xff1a;num某些基础数据类型序列(Range)字符类型单元类型 发散函数表达式&#xff08;&#xff01; 语句&#xff09; Rust—有关介绍 得益于各种零开销抽象、深入到底层的优化潜力、优质的标准库和第三方库实现&#xff0c;Ru…

20240401,ALOHA WORLD

C了&#xff0c;虽然练习C还有9题不会做&#xff0c;但是不先继续往下学&#xff0c;肯定就凉了 #include <iostream> int main() {if (__cplusplus 201703L)std::cout << "C17\n";else if (__cplusplus 201402L)std::cout << "C14\n"…

Java零基础入门-异常、线程(中)

一、本期教学目标 能够列举出常见的三个运行期的异常。能够使用try...catch、throws等关键字处理异常。能够自定义异常类。能够处理自定义异常类。 二、前言 上一期我们是学习了异常相关的一些概念知识&#xff0c;然后演示了一下异常的触发及控制台异常的一些信息如何判断及…

【html威廉希尔体育体育羽毛球页面带注册】学生网页设计作业源码APP是不是真的?

Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 校园篮球网页设计 | 足球体育运动 | 体育游泳运动 | 兵乓球 | 网球 | 等网站的设计与制作 | HTML期末大学生网页设计作业 HTML&#xff1a;结构CSS&#xff1a;样式 在操作方面…

中断服务程序模板

通常定时器初始化过程如下: ①对 TMOD赋值,以确定TO和T1的工作方式。 ②计算初值,并将初值写入THO、TLO或TH1、TL1。 ③中断方式时&#xff0c;则对IE赋值&#xff0c;开放中断。 ④使TRO或TR1置位&#xff0c;启动定时器/计数器定时或计数。 代码 利用定时器0工作方式1&…

Vision-Language Models for Vision Tasks: A Survey

论文地址&#xff1a;https://arxiv.org/pdf/2304.00685.pdf 项目地址&#xff1a;https://github.com/jingyi0000/VLM_survey 一、综述动机 视觉语言模型&#xff0c;如CLIP&#xff0c;以其独特的训练方式显著简化了视觉识别任务的流程。它减少了对大量精细标注数据的依赖&a…

【Python刷题】将有序数组转换为二叉搜索树

问题描述 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 高度平衡的意思是&#xff1a;二叉树是一颗满足“每个结点的左右两个子树的高度差的绝对值不超过1”的二叉树。 示例 1&#xff1a; 输入&#xf…

012——LED模块驱动开发(基于I.MX6uLL)

目录 一、 硬件原理图 二、 驱动程序 三、 应用程序 四、 Makefile 五、操作 一、 硬件原理图 又是非常经典的点灯环节 &#xff0c;每次学新语言第一步都是hello world&#xff0c;拿到新板子或者学习新的操作系统&#xff0c;第一步就是点灯。 LED 的驱动方式&#xff0…

3.26号arm

1. SPI相关理论 1.1 概述 spi是一种同步全双工串行总线&#xff0c;全称串行外围设备接口 通常SPI通过4个引脚与外部器件相连&#xff1a; MISO&#xff1a;主设备输入/从设备输出引脚。该引脚在从模式下发送数据&#xff0c;在主模式下接收数据。 MOSI&#xff1a;主设备输…

ZKFair 创新之旅,新阶段如何塑造财富前景

在当前区块链技术的发展中&#xff0c;Layer 2&#xff08;L2&#xff09;解决方案已成为提高区块链扩容性、降低交易成本和提升交易速度的关键技术&#xff0c;但它仍面临一些关键问题和挑战&#xff0c;例如用户体验的改进、跨链互操作性、安全性以及去中心化程度。在这些背景…

如何让光猫4个网口都有网络

一般情况光猫只有LAN1口有网络&#xff0c;LAN2、LAN3和LAN4口都是预留给电视用的&#xff0c;那么如何让这3个网口也有网络呢&#xff1f; 使用场景&#xff1a; 光猫在弱电箱内&#xff0c;弱电箱中有三根网线&#xff08;网线1、网线2和网线3&#xff09;分别接入到了三个房…

Day60:WEB攻防-XMLXXE安全无回显方案OOB盲注DTD外部实体黑白盒挖掘

目录 XML&XXE-传输-原理&探针&利用&玩法 XXE 黑盒发现 XXE 白盒发现 XXE修复防御方案 有回显 无回显 XML&XXE-黑盒-JSON&黑盒测试&类型修改 XML&XXE-白盒-CMS&PHPSHE&无回显 知识点&#xff1a; 1、XXE&XML-原理-用途&…

【滑动窗口】Leetcode 串联所有单词的子串

题目解析 30. 串联所有单词的子串 本题的意思就是在目标串s中寻找能够找到的words字符串的全排列&#xff0c;返回起始位置 算法讲解 我们可以将这道题转化为寻找目标串的words字母的异位词&#xff0c;按照上一次讲解的【滑动窗口】Leetcode 找到字符串中所有字母异位词我们…

ssm015基于java的健身房管理系统的设计与实现+vue

健身房管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本健身房管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间…

【目标检测】YOLOv6 的网络结构,图解RepBlock重参数化

YOLOv6 是美团推出的&#xff0c;在这个版本里面&#xff0c;不再使用之前 YOLOv4 和 YOLOv5 的带 CSP 结构的 CSPDarknet-53 作为 backbone 了&#xff0c;而是在 RepVGG 的启发下&#xff0c;推出了新的 EfficientRep 作为 YOLOv6 的 backbone。 RepVGG 最重要的一点是&…

【操作系统】FCFS、SJF、HRRN、RR、EDF、LLF调度算法及python实现代码

文章目录 一、先来先服务调度算法&#xff08;FCFS&#xff09; 二、短作业优先调度算法&#xff08;SJF&#xff09; 三、高响应比优先调度算法&#xff08;HRRN&#xff09; 四、轮转调度算法&#xff08;RR&#xff09; 五、最早截至时间优先算法&#xff08;EDF&#…

单V及多V感知在自动驾驶在恶劣环境条件下的感知提升方案

单V及多V感知在自动驾驶在恶劣环境条件下的感知提升方案 附赠自动驾驶学习资料和量产经验&#xff1a;链接 自动驾驶中的视觉感知是车辆在不同交通条件下安全、可持续地行驶的关键部分。然而&#xff0c;在大雨和雾霾等恶劣天气下&#xff0c;视觉感知性能受到多种降级效应的极…

EasyCVR视频汇聚平台海康Ehome2.0与5.0设备接入时的配置区别

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

excel中文本列显示e+17这样的科学计数法如何处理

我的excel中文本列显示e17这样的科学计数法 然后右键&#xff0c;设置单元格格式&#xff0c;为特殊&#xff0c;邮政编码&#xff0c;点确定即可 最后效果如下