irpas技术客

ARM-linux系统驱动复习(二)_linux arm控制器驱动_five物糕

大大的周 5151

一、设备树

早期的linux是没有设备树概念的,早期这些板级信息文件 都是.c 或.h 文件,都会被硬编码进 Linux 内核中,导致内核的非常大,一年出的arm架构芯片有上千种,再做成电路板更多。 Linux的设备树一般是dts源文件编译成dtb文件,再又linux内核去读取他。 设备树上面记录了片内外设和片外外设的各种信息。 Linux驱动开发中,会间接的去驱动外设。通过读取设备树上的节点,来获取所对应的信息再进行操作。 如图:(树枝上就是对应的相应节点)

(1)设备树语法

语法上面跟C语言差不多,但是开头用一个/表示记录的信息从这里开始。 通过括号扩起来,上面的例如chosen,memory就是所对应的节点信息。 &代表节点上所追加的信息

(2)设备树节点 spi4 { compatible = "spi-gpio"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_spi4>; /* pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>; */ status = "okay"; gpio-sck = <&gpio5 11 0>; gpio-mosi = <&gpio5 10 0>; /* cs-gpios = <&gpio5 7 0>; */ num-chipselects = <1>; #address-cells = <1>; #size-cells = <0>; gpio_spi: gpio_spi@0 { compatible = "fairchild,74hc595"; gpio-controller; #gpio-cells = <2>; reg = <0>; registers-number = <1>; registers-default = /bits/ 8 <0x57>; spi-max-frequency = <100000>; }; };

spi上面的节点,节点下面套了一个gpio_spi的子节点。 这个节点记录了芯片spi4的信息, compatible为属性(这个随便写也行) pinctrl-names为设备的名字,他的名字叫默认”default” pinctrl-0 记录他的电气属性信息 status 记录状态,如果okay就是使能,disable就是不使能。 gpio-sck = <&gpio5 11 0>; 记录了sck线在哪个引脚,这个gpio-sck是可以随便起的。前面的不行。 gpio-mosi = <&gpio5 10 0>; 同上 num-chipselects = <1>; #address-cells = <1>; #size-cells = <0>; 上面三条就不解释了,看名字就知道是干嘛的。 然后这个节点下面追加了一个子节点 compatible = “fairchild,74hc595”; gpio-controller; #gpio-cells = <2>; reg = <0>; registers-number = <1>; registers-default = /bits/ 8 <0x57>; spi-max-frequency = <100000>; 子节点记录了属性信息,跟上面一样的就不说了。 节点下面是可以套节点的,有时候你这个功能不止给你一个外设使用,有多个外设给使用。

(3)Pinctrl

看这个名字就知道这个是引脚的属性信息,上面pinctrl-0 = <&pinctrl_spi4>; &后面就是追加的信息。 这个追加的引脚信息,MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10在这里所对应 #define MX6UL_PAD_BOOT_MODE0__GPIO5_IO10 0x0014 0x02A0 0x0000 0x5 0x0 第一个就是这个引脚的设置复用寄存器的偏移,第二个就是引脚电气属性寄存器的偏移,第三个就是输入的寄存器偏移,第四个就是设置复用的模式的值,第五个就设置输入的值。 他的电气属性设置值放在了设备树的这: MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10 0x70a1 0x70a1 这个就是配置引脚电气属性的值,寄存器手册我就懒得翻了

二、 并发与竞争

并发就是同个时间下,大家都要访问这个内存地址。大家一起来那谁先来就得排个队呀,两个数据都要访问或者改写这个内存段,得要有先来后到,不然这段数据读起来大家都不准。 这个函数太多太复杂,就不写啦。懒!!!

三、定时器

Linux里面启动内核后,有个系统时钟,这个系统时钟会记录使能后的时间,到达时间后可以触发,但不是硬件中断!!!这个使能后溢出后会从新置0并且自动关闭。这个系统时间用的时钟源是谁提供的呢?说实话我也不知道,因为我没研究他内核的结构。不同芯片系统时钟提供的时钟源可能不一样,这个一般是芯片厂商帮我们写好的。

(1)函数使用 init_timer(&pinctl_led.timer); //取这个结构体的信息,这个函数有点类似注册系统时钟。 void init_timer_key(struct timer_list *timer, unsigned int flags, const char *name, struct lock_class_key *key);

函数原型第一个是timer_list的类型的结构体,使用init_timer函数使用,别人已经帮我们写好了后面的,我们只需要写结构体里面的信息就行了。 timer_list类型的结构体里面只需要编写function,expires,data即可。 Function就是他时间到了后所触发的函数,类似于中断 Expires就是设置他定时器的时间,多久溢出,一般就jiffies+msecs_to_jiffies() 就可以设置多少毫秒溢出了。Jiffies在32位和64位溢出时间是完全不一样的。 在64位可以不用考虑溢出问题,因为他溢出得等上万天,32位好像溢出就只需要几天时间,Jiffies就是内核启动后所记录的时间。 设置配置信息之后,就只需要添加定时器就行了,也类似于使能 可以使用timer_add函数,也可以使用mod_timer函数。 要注销定时器的话使用extern int del_timer(struct timer_list * timer);函数。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #Linux #arm控制器驱动 #linux驱动复习笔记