【深度】韦东山:GPIO和Pinctrl子系统的使用_开发板中 释放被占用的gpio-程序员宅基地

技术标签: linux  Linux驱动开发  

在线课堂:https://www.100ask.net/index(课程观看)
论  坛:http://bbs.100ask.net/(学术答疑)
开 发 板:https://100ask.taobao.com/ (淘宝)
     https://weidongshan.tmall.com/(天猫)
交流群一:QQ群:869222007(鸿蒙开发/Linux/嵌入式/驱动/资料下载)
交流群二:QQ群:536785813(单片机-嵌入式)
公 众 号:百问科技


版本 日期 作者 说明
V1 2020 韦东山 技术文档

参考文档:
a. 内核 Documentation\devicetree\bindings\Pinctrl\ 目录下:
Pinctrl-bindings.txt

b. 内核 Documentation\gpio 目录下:
Pinctrl-bindings.txt

c. 内核 Documentation\devicetree\bindings\gpio 目录下:
gpio.txt

注意:本章的重点在于“使用”,深入讲解放在“驱动大全”的视频里。
前面的视频,我们使用直接操作寄存器的方法编写驱动。这只是为了让大家掌握驱动程序的本质,在实际开发过程中我们可不这样做,太低效了!如果驱动开发都是这样去查找寄存器,那我们就变成“寄存器工程师”了,即使是做单片机的都不执着于裸写寄存器了。
Linux下针对引脚有2个重要的子系统:GPIO、Pinctrl。

1.Pinctrl子系统重要概念

1.1 引入

无论是哪种芯片,都有类似下图的结构:
在这里插入图片描述

要想让pinA、B用于GPIO,需要设置IOMUX让它们连接到GPIO模块;
要想让pinA、B用于I2C,需要设置IOMUX让它们连接到I2C模块。
所以GPIO、I2C应该是并列的关系,它们能够使用之前,需要设置IOMUX。有时候并不仅仅是设置IOMUX,还要配置引脚,比如上拉、下拉、开漏等等。

现在的芯片动辄几百个引脚,在使用到GPIO功能时,让你一个引脚一个引脚去找对应的寄存器,这要疯掉。术业有专攻,这些累活就让芯片厂家做吧──他们是BSP工程师。我们在他们的基础上开发,我们是驱动工程师。开玩笑的,BSP工程师是更懂他自家的芯片,但是如果驱动工程师看不懂他们的代码,那你的进步也有限啊。

所以,要把引脚的复用、配置抽出来,做成Pinctrl子系统,给GPIO、I2C等模块使用。
BSP工程师要做什么?看下图:
在这里插入图片描述
等BSP工程师在GPIO子系统、Pinctrl子系统中把自家芯片的支持加进去后,我们就可以非常方便地使用这些引脚了:点灯简直太简单了。

等等,GPIO模块在图中跟I2C不是并列的吗?干嘛在讲Pinctrl时还把GPIO子系统拉进来?
大多数的芯片,没有单独的IOMUX模块,引脚的复用、配置等等,就是在GPIO模块内部实现的。
在硬件上GPIO和Pinctrl是如此密切相关,在软件上它们的关系也非常密切。
所以这2个子系统我们一起讲解。

1.2 重要概念

从设备树开始学习Pintrl会比较容易。
主要参考文档是:内核Documentation\devicetree\bindings\pinctrl\pinctrl-bindings.txt

这会涉及2个对象:pin controller、client device。
前者提供服务:可以用它来复用引脚、配置引脚。
后者使用服务:声明自己要使用哪些引脚的哪些功能,怎么配置它们。

a. pin controller:
在芯片手册里你找不到pin controller,它是一个软件上的概念,你可以认为它对应IOMUX──用来复用引脚,还可以配置引脚(比如上下拉电阻等)。
注意,pin controller和GPIO Controller不是一回事,前者控制的引脚可用于GPIO功能、I2C功能;后者只是把引脚配置为输入、输出等简单的功能。

b. client device
“客户设备”,谁的客户?Pinctrl系统的客户,那就是使用Pinctrl系统的设备,使用引脚的设备。它在设备树里会被定义为一个节点,在节点里声明要用哪些引脚。
下面这个图就可以把几个重要概念理清楚:
在这里插入图片描述
上图中,左边是pincontroller节点,右边是client device节点:
a. pin state:
对于一个“client device”来说,比如对于一个UART设备,它有多个“状态”:default、sleep等,那对应的引脚也有这些状态。

怎么理解?
比如默认状态下,UART设备是工作的,那么所用的引脚就要复用为UART功能。
在休眠状态下,为了省电,可以把这些引脚复用为GPIO功能;或者直接把它们配置输出高电平。
上图中,pinctrl-names里定义了2种状态:default、sleep。
第0种状态用到的引脚在pinctrl-0中定义,它是state_0_node_a,位于pincontroller节点中。
第1种状态用到的引脚在pinctrl-1中定义,它是state_1_node_a,位于pincontroller节点中。
当这个设备处于default状态时,pinctrl子系统会自动根据上述信息把所用引脚复用为uart0功能。
当这这个设备处于sleep状态时,pinctrl子系统会自动根据上述信息把所用引脚配置为高电平。

b. groups和function:
一个设备会用到一个或多个引脚,这些引脚就可以归为一组(group);
这些引脚可以复用为某个功能:function。
当然:一个设备可以用到多能引脚,比如A1、A2两组引脚,A1组复用为F1功能,A2组复用为F2功能。

c. Generic pin multiplexing node和Generic pin configuration node
在上图左边的pin controller节点中,有子节点或孙节点,它们是给client device使用的。
可以用来描述复用信息:哪组(group)引脚复用为哪个功能(function);
可以用来描述配置信息:哪组(group)引脚配置为哪个设置功能(setting),比如上拉、下拉等。

注意:pin controller节点的格式,没有统一的标准!!!!每家芯片都不一样。
甚至上面的group、function关键字也不一定有,但是概念是有的。

1.3 示例

在这里插入图片描述

1.4 代码中怎么引用pinctrl

这是透明的,我们的驱动基本不用管。当设备切换状态时,对应的pinctrl就会被调用。
比如在platform_device和platform_driver的枚举过程中,流程如下:
在这里插入图片描述
当系统休眠时,也会去设置该设备sleep状态对应的引脚,不需要我们自己去调用代码。

非要自己调用,也有函数:

devm_pinctrl_get_select_default(struct device *dev);      // 使用"default"状态的引脚
pinctrl_get_select(struct device *dev, const char *name); // 根据name选择某种状态的引脚
pinctrl_put(struct pinctrl *p);   // 不再使用, 退出时调用

2.GPIO子系统重要概念

2.1 引入

要操作GPIO引脚,先把所用引脚配置为GPIO功能,这通过Pinctrl子系统来实现。
然后就可以根据设置引脚方向(输入还是输出)、读值──获得电平状态,写值──输出高低电平。
以前我们通过寄存器来操作GPIO引脚,即使LED驱动程序,对于不同的板子它的代码也完全不同。
当BSP工程师实现了GPIO子系统后,我们就可以:
a. 在设备树里指定GPIO引脚
b. 在驱动代码中:
使用GPIO子系统的标准函数获得GPIO、设置GPIO方向、读取/设置GPIO值。
这样的驱动代码,将是单板无关的。

2.2 在设备树中指定引脚

在几乎所有ARM芯片中,GPIO都分为几组,每组中有若干个引脚。所以在使用GPIO子系统之前,就要先确定:它是哪组的?组里的哪一个?
在设备树中,“GPIO组”就是一个GPIO Controller,这通常都由芯片厂家设置好。我们要做的是找到它名字,比如“gpio1”,然后指定要用它里面的哪个引脚,比如<&gpio1 0>。
有代码更直观,下图是一些芯片的GPIO控制器节点,它们一般都是厂家定义好,在xxx.dtsi文件中:
在这里插入图片描述

我们暂时只需要关心里面的这2个属性:

gpio-controller;
#gpio-cells = <2>;

“gpio-controller”表示这个节点是一个GPIO Controller,它下面有很多引脚。
“#gpio-cells = <2>”表示这个控制器下每一个引脚要用2个32位的数(cell)来描述。
为什么要用2个数?其实使用多个cell来描述一个引脚,这是GPIO Controller自己决定的。比如可以用其中一个cell来表示那是哪一个引脚,用另一个cell来表示它是高电平有效还是低电平有效,甚至还可以用更多的cell来示其他特性。
普遍的用法是,用第1个cell来表示哪一个引脚,用第2个cell来表示有效电平:

GPIO_ACTIVE_HIGH : 高电平有效
GPIO_ACTIVE_LOW  :  低电平有效

定义GPIO Controller是芯片厂家的事,我们怎么引用某个引脚呢?在自己的设备节点中使用属性"[-]gpios",示例如下:
在这里插入图片描述

上图中,可以使用gpios属性,也可以使用name-gpios属性。

2.3 在驱动代码中调用GPIO子系统

在设备树中指定了GPIO引脚,在驱动代码中如何使用?
也就是GPIO子系统的接口函数是什么?
GPIO子系统有两套接口:基于描述符的(descriptor-based)、老的(legacy)。前者的函数都有前缀“gpiod_”,它使用gpio_desc结构体来表示一个引脚;后者的函数都有前缀“gpio_”,它使用一个整数来表示一个引脚。

要操作一个引脚,首先要get引脚,然后设置方向,读值、写值。

驱动程序中要包含头文件,
#include <linux/gpio/consumer.h> // descriptor-based

#include <linux/gpio.h> // legacy

下表列出常用的函数:
在这里插入图片描述

有前缀“devm_”的含义是“设备资源管理”(Managed Device Resource),这是一种自动释放资源的机制。它的思想是“资源是属于设备的,设备不存在时资源就可以自动释放”。
比如在Linux开发过程中,先申请了GPIO,再申请内存;如果内存申请失败,那么在返回之前就需要先释放GPIO资源。如果使用devm的相关函数,在内存申请失败时可以直接返回:设备的销毁函数会自动地释放已经申请了的GPIO资源。
建议使用“devm_”版本的相关函数。

举例,假设备在设备树中有如下节点:

	foo_device {
		compatible = "acme,foo";
		...
		led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>, /* red */
			    <&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
			    <&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */

		power-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
	};

那么可以使用下面的函数获得引脚:

struct gpio_desc *red, *green, *blue, *power;
red = gpiod_get_index(dev, "led", 0, GPIOD_OUT_HIGH);
green = gpiod_get_index(dev, "led", 1, GPIOD_OUT_HIGH);
blue = gpiod_get_index(dev, "led", 2, GPIOD_OUT_HIGH);
power = gpiod_get(dev, "power", GPIOD_OUT_HIGH);

要注意的是,gpiod_set_value设置的值是“逻辑值”,不一定等于物理值。
什么意思?
在这里插入图片描述

旧的“gpio_”函数没办法根据设备树信息获得引脚,它需要先知道引脚号。

引脚号怎么确定?
在GPIO子系统中,每注册一个GPIO Controller时会确定它的“base number”,那么这个控制器里的第n号引脚的号码就是:base number + n。
但是如果硬件有变化、设备树有变化,这个base number并不能保证是固定的,应该查看sysfs来确定base number。

2.4 sysfs中的访问方法

在sysfs中访问GPIO,实际上用的就是引脚号,老的方法。
a. 先确定某个GPIO Controller的基准引脚号(base number),再计算出某个引脚的号码。
方法如下:
① 先在开发板的/sys/class/gpio目录下,找到各个gpiochipXXX目录:
在这里插入图片描述

② 然后进入某个gpiochip目录,查看文件label的内容
③ 根据label的内容对比设备树
label内容来自设备树,比如它的寄存器基地址。用来跟设备树(dtsi文件)比较,就可以知道这对应哪一个GPIO Controller。
下图是在100asK_imx6ull上运行的结果,通过对比设备树可知gpiochip96对应gpio4:
在这里插入图片描述
所以gpio4这组引脚的基准引脚号就是96,这也可以“cat base”来再次确认。

b. 基于sysfs操作引脚:
以100ask_imx6ull为例,它有一个按键,原理图如下:
在这里插入图片描述
那么GPIO4_14的号码是96+14=110,可以如下操作读取按键值:

echo  110 > /sys/class/gpio/export
echo in > /sys/class/gpio/gpio110/direction
cat /sys/class/gpio/gpio110/value
echo  110 > /sys/class/gpio/unexport

注意:如果驱动程序已经使用了该引脚,那么将会export失败,会提示下面的错误:
在这里插入图片描述

对于输出引脚,假设引脚号为N,可以用下面的方法设置它的值为1:

echo  N > /sys/class/gpio/export
echo out > /sys/class/gpio/gpioN/direction
echo 1 > /sys/class/gpio/gpioN/value
echo  N > /sys/class/gpio/unexport

3. 基于GPIO子系统的LED驱动程序

3.1 编写思路

GPIO的地位跟其他模块,比如I2C、UART的地方是一样的,要使用某个引脚,需要先把引脚配置为GPIO功能,这要使用Pinctrl子系统,只需要在设备树里指定就可以。在驱动代码上不需要我们做任何事情。
GPIO本身需要确定引脚,这也需要在设备树里指定。
设备树节点会被内核转换为platform_device。
对应的,驱动代码中要注册一个platform_driver,在probe函数中:获得引脚、注册file_operations。
在file_operations中:设置方向、读值/写值。
在这里插入图片描述

下图就是一个设备树的例子:
在这里插入图片描述

3.2 在设备树中添加Pinctrl信息

有些芯片提供了设备树生成工具,在GUI界面中选择引脚功能和配置信息,就可以自动生成Pinctrl子结点。把它复制到你的设备树文件中,再在client device结点中引用就可以。
有些芯片只提供文档,那就去阅读文档,一般在内核源码目录Documentation\devicetree\bindings\pinctrl下面,保存有该厂家的文档。
如果连文档都没有,那只能参考内核源码中的设备树文件,在内核源码目录arch/arm/boot/dts目录下。
最后一步,网络搜索。
Pinctrl子节点的样式如下:
在这里插入图片描述

3.3 在设备树中添加GPIO信息

先查看电路原理图确定所用引脚,再在设备树中指定:添加”[name]-gpios”属性,指定使用的是哪一个GPIO Controller里的哪一个引脚,还有其他Flag信息,比如GPIO_ACTIVE_LOW等。具体需要多少个cell来描述一个引脚,需要查看设备树中这个GPIO Controller节点里的“#gpio-cells”属性值,也可以查看内核文档。
示例如下:
在这里插入图片描述

3.4编程示例

在实际操作过程中也许会碰到意外的问题,现场演示如何解决。
a. 定义、注册一个platform_driver
b. 在它的probe函数里:
b.1 根据platform_device的设备树信息确定GPIO:gpiod_get
b.2 定义、注册一个file_operations结构体
b.3 在file_operarions中使用GPIO子系统的函数操作GPIO:
gpiod_direction_output、gpiod_set_value

好处:这些代码对所有的代码都是完全一样的!
使用GIT命令载后,源码leddrv.c位于这个目录下:

01_all_series_quickstart\
04_快速入门_正式开始\
02_嵌入式Linux驱动开发基础知识\source\
05_gpio_and_pinctrl\
    01_led

摘录重点内容:
a. 注册platform_driver
注意下面第122行的"100ask,leddrv",它会跟设备树中节点的compatible对应:

121 static const struct of_device_id ask100_leds[] = {
122     { .compatible = "100ask,leddrv" },
123     { },
124 };
125
126 /* 1. 定义platform_driver */
127 static struct platform_driver chip_demo_gpio_driver = {
128     .probe      = chip_demo_gpio_probe,
129     .remove     = chip_demo_gpio_remove,
130     .driver     = {
131         .name   = "100ask_led",
132         .of_match_table = ask100_leds,
133     },
134 };
135

136 /* 2. 在入口函数注册platform_driver */

137 static int __init led_init(void)
138 {
139     int err;
140
141     printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
142
143     err = platform_driver_register(&chip_demo_gpio_driver);
144
145     return err;
146 }

b. 在probe函数中获得GPIO
核心代码是第87行,它从该设备(对应设备树中的设备节点)获取名为“led”的引脚。在设备树中,必定有一属性名为“led-gpios”或“led-gpio”。

77 /* 4. 从platform_device获得GPIO
78  *    把file_operations结构体告诉内核:注册驱动程序
79  */
80 static int chip_demo_gpio_probe(struct platform_device *pdev)
81 {
82      //int err;
83
84      printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
85
86      /* 4.1 设备树中定义有: led-gpios=<...>; */
87     led_gpio = gpiod_get(&pdev->dev, "led", 0);
88      if (IS_ERR(led_gpio)) {
89              dev_err(&pdev->dev, "Failed to get GPIO for led\n");
90              return PTR_ERR(led_gpio);
91      }
92

c. 注册file_operations结构体:
这是老套路了:

93      /* 4.2 注册file_operations      */
94      major = register_chrdev(0, "100ask_led", &led_drv);  /* /dev/led */
95
96      led_class = class_create(THIS_MODULE, "100ask_led_class");
97      if (IS_ERR(led_class)) {
98              printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
99              unregister_chrdev(major, "led");
100             gpiod_put(led_gpio);
101             return PTR_ERR(led_class);
102     }
103
104     device_create(led_class, NULL, MKDEV(major, 0), NULL, "100ask_led%d", 0); /* /dev/100ask_led0 */
105

d. 在open函数中调用GPIO函数设置引脚方向:

51 static int led_drv_open (struct inode *node, struct file *file)
52 {
53      //int minor = iminor(node);
54
55      printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
56      /* 根据次设备号初始化LED */
57      gpiod_direction_output(led_gpio, 0);
58
59      return 0;
60 }

e. 在write函数中调用GPIO函数设置引脚值:

34 /* write(fd, &val, 1); */
35 static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
36 {
37      int err;
38      char status;
39      //struct inode *inode = file_inode(file);
40      //int minor = iminor(inode);
41
42      printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
43      err = copy_from_user(&status, buf, 1);
44
45      /* 根据次设备号和status控制LED */
46      gpiod_set_value(led_gpio, status);
47
48      return 1;
49 }

f. 释放GPIO:

gpiod_put(led_gpio);

4.在100ASK_IMX6ULL上机实验

4.1 确定引脚并生成设备树节点

NXP公司对于IMX6ULL芯片,有设备树生成工具。我们也把它上传到GIT去了,使用GIT命令载后,在这个目录下:

01_all_series_quickstart\
04_快速入门_正式开始\
02_嵌入式Linux驱动开发基础知识\source\
05_gpio_and_pinctrl\
tools\
imx\

安装“Pins_Tool_for_i.MX_Processors_v6_x64.exe”后运行,打开IMX6ULL的配置文件“MCIMX6Y2xxx08.mex”,就可以在GUI界面中选择引脚,配置它的功能,这就可以自动生成Pinctrl的子节点信息。
100ASK_IMX6ULL使用的LED原理图如下,可知引脚是GPIO5_3:
在这里插入图片描述
在设备树工具中,如下图操作:
在这里插入图片描述

把自动生成的设备树信息,放到内核源码arch/arm/boot/dts/100ask_imx6ull-14x14.dts中,代码如下:
a. Pinctrl信息:

&iomuxc_snvs {
……
        myled_for_gpio_subsys: myled_for_gpio_subsys{ 
            fsl,pins = <
                MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03        0x000110A0
            >;
        };

b. 设备节点信息(放在根节点下):

        myled {
            compatible = "100ask,leddrv";
            pinctrl-names = "default";
            pinctrl-0 = <&myled_for_gpio_subsys>;
            led-gpios = <&gpio5 3 GPIO_ACTIVE_LOW>;
        };

4.2 编译程序

编译设备树后,要更新设备树。
编译驱动程序时,“leddrv_未测试的原始版本.c”是有错误信息的,“leddrv.c”是修改过的。
测试方法,在板子上执行命令:

#insmod  leddrv.ko
#ls /dev/100ask_led0
#./ledtest /dev/100ask_led0 on
#./ledtest /dev/100ask_led0 off
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/thisway_diy/article/details/105120667

智能推荐

1024 分辨率下最快模型,字节跳动文生图开放模型 SDXL-Lightning 发布_sdxllightning下载-程序员宅基地

文章浏览阅读1k次,点赞28次,收藏25次。很高兴跟大家分享我们最新的文生图模型 —— SDXL-Lightning,它实现了前所未有的速度和质量,并且已经向社区开放。_sdxllightning下载

关于cloacked-pixel的一些总结_03-cloacked-pixel-程序员宅基地

文章浏览阅读1.5k次,点赞2次,收藏2次。前两天遇到一道lsb隐写的题目,需要用到cloacked-pixel这个脚本。工具地址下载后解压即可,这里需要注意,该脚本是基于python2的!但我电脑anaconda里面只有python3并没有很好的python基础,但借助anaconda可以轻松解决很多问题!教程如下:anaconda中添加python2但是在运行脚本时还会提示缺库(注意运行时要activate pythonXX手动切换到你所配置的python2环境下)继续使用anaconda为python2装缺少的._03-cloacked-pixel

WPF DataGrid添加右键菜单-程序员宅基地

文章浏览阅读2k次,点赞2次,收藏2次。原文http://home.cnblogs.com/group/topic/54788.html用代码添加:View Code <DataGrid.ContextMenu> <ContextMenu Name="dgmenu1" StaysOpen="true"> &..._wpf datagrid右键菜单

EB Tresos Studio离线激活方法_ebtresos离线激活-程序员宅基地

文章浏览阅读1.9k次,点赞2次,收藏6次。EB Tresos Studio离线激活方法_ebtresos离线激活

B端系统-权限管理_如何将后台管理系统b端化-程序员宅基地

文章浏览阅读95次。当然用户组是可以拓展的,部门和职位常用在内部的管理系统,如果是面向c端的系统,比如淘宝网的商家,商家自身也有一套组织架构,如采购部,销售部,客服部,后勤部,有些人拥有客服权限,有些人拥有上架权限等,这就体现了用户组的扩展性。关于数据权限的处理,常见的有两种方式,一种是在角色内完成数据权限的定义,另一种是将角色和权限分开,两种方式各有偏重。即页面的功能按钮,包括查看,新增,修改,删除,审核等,用户点击删除按钮时,后台会校验用户角色下用户的所有权限是否包含该删除权限,如果是,就可以下一步,反之提示无权限。_如何将后台管理系统b端化

音乐节拍提取一-程序员宅基地

文章浏览阅读601次。前段时间倒腾了一下音乐节拍数检测,参考下面的网上的一个测试歌曲列表做了下对比,效果还不错,基本上都是准的。Itunes LinkNameTimeArtistBPMAlbumGenreAmazon LinkLoneliest Soul03:35Grace Potter and the Nocturnals168The Lion The Bea..._提取音乐节奏

随便推点

win11实时字幕无法下载问题_微软实时字幕下载不了-程序员宅基地

文章浏览阅读776次。一直卡着的话直接去Microsoft Store下载这个试试看。_微软实时字幕下载不了

如何让谷歌Chrome地址栏恢复显示“www”和“https://”标识符_chrome 地址显示原始-程序员宅基地

文章浏览阅读1.1w次。如何让谷歌Chrome地址栏恢复显示“www”和“https://”标识符地址栏隐藏“www”和“https://”标识符  谷歌 Chrome 现在默认在所有网站地址栏中少了一些内容,“www”子域和“https://”被隐藏起来了,因为谷歌认为这些不是大多数人要关注的信息。  Chrome 的产品经理 Emily Schechter 说,他们将开始从桌面版和 Android 版的第..._chrome 地址显示原始

目标跟踪数据集整理(四)----TColor-128(Temple Color 128)_encoding color information for visual tracking: al-程序员宅基地

文章浏览阅读3.5k次。文章目录Encoding Color Information for Visual Tracking:Algorithms and Benchmark 2015官网 下载数据集(4.4G)本文认为颜色信息可以提供丰富的判别线索对于视觉推理,大多数现代视觉跟踪器限制在灰度域。(也就是主要解决输入序列是灰度版本)因此我们在算法和基准两方面做了系统的研究,证明了颜色信息可以帮助提升视觉跟踪效果。..._encoding color information for visual tracking: algorithms and benchmark

论文解读--Visual Lane Tracking and Prediction for Autonomous Vehicles-程序员宅基地

文章浏览阅读860次,点赞20次,收藏21次。我们提出了一种用于自动驾驶汽车跟踪水平道路车道标记位置的可视化方法。我们的方法是基于预测滤波的。预测步骤估计在每个新的图像帧中期望的车道标记位置。它也是基于汽车的运动学模型和嵌入式测程传感器产生的信息。使用适当准备的测试车辆获得的实验结果表明,在某些条件下,如振荡和变道,预测步骤可以显著地减少跟踪误差。因此,我们相信我们的方法应用于基于图像的控制自动驾驶汽车可以提高系统性能。

sap 标准委外和工序委外_委外加工SAP的两种典型委外处理方法-程序员宅基地

文章浏览阅读1.2k次。通常提供两种基本处理方式:外包采购和工序外包。生产外包经营方式简介生产外包作为一种全新的生产经营方式,改善了传统方式的不足,主要类型有:一.OEM:(OrignalEquipmentManufactuce->原始设备制造商)典型的OEM方式为:拥有原始设备的OEM加工方(受委托方)按照委托方的要求,用自己的设备为其加工生产产品,而后贴上委托方商标交货,整个活动中,加工方只获得加工费用,自..._工序委外加工属于什么变更类型

yolov3算法详解_2020年阿里-算法工程师面经-程序员宅基地

文章浏览阅读432次。写在前面:暑期实习从申请到拿到阿里意向书大概持续了1个月的时间,和周围其他同学比较,我的面试流程算走的比较快的了。还没有拿到意向书的朋友们也不要太着急,调整好心态好好准备(虽然内心多多少少会有些焦虑),阿里走流程算是比较快的了。希望能对求职的你有所帮助。【阿里云1面(算法实习生)】1、自我介绍、项目介绍2、死锁出现的原因以及如何避免雾夜飞鹰:死锁产生的原因及四个必要条件​zhuanlan.zhih..._yolo模型的时间复杂度