随身WIFI折腾日记(一)---霓虹灯
通过对高通410芯片的随身WIFI刷写Debain系统,我们已经拥有了一台带4G功能的迷你ARM64单板电脑。现在我们可以基于此此平台进行一下二次开发。因为此项目基于随身WIFI的优势就是价格低廉,性能和树莓派zero2、树莓派3b差不多。硬件配置如下:外设的io定义如下:我主要是想通过点亮LED灯学习一下Linux如何控制底层硬件设备。随身WIFI存在三个led灯,openstick作者设置默认
引言
通过对高通410芯片的随身WIFI刷写Debain系统,我们已经拥有了一台带4G功能的迷你ARM64单板电脑。现在我们可以基于此此平台进行一下二次开发。
随身WIFI的优势就是价格低廉,性能和树莓派zero2、树莓派3b差不多。
硬件配置如下:
- msm8916 主控 Cortex-A53 * 4 on 0.9GHZ
- 512MB内存+4GB储存emcp
- WCN3620 & WCN3680b
- pm8916 PMIC
- USB接口
外设的io定义如下:
型号 | red led | green led | blue led | 按键 |
---|---|---|---|---|
ufi001b/c | gpio22 | gpio21 | gpio20 | gpio37 |
一、霓虹灯
我主要是想通过点亮LED灯学习一下Linux如何控制底层硬件设备。
1.1 点灯
随身WIFI存在三个led灯,openstick作者设置默认blue表示wifi连接状态,red表示系统是否还处于正常运行状态。
-
可以通过 echo <行为> > /sys/class/led/<名字>/trigger 来修改led行为。
可用的行为如下:root@openstick:/sys/class/leds/green:internet# cat trigger [none] usb-gadget usb-host rfkill-any rfkill-none kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock timer heartbeat cpu cpu0 cpu1 cpu2 cpu3 default-on panic mmc0 bluetooth-power hci0-power rfkill0 phy0rx phy0tx phy0assoc phy0radio rfkill1
可以看到green:internet设备的trigger属性为[none],触发事件为无,即关灯。
-
设置green led为常量状态
root@openstick:/sys/class/leds/green:internet# echo default-on > trigger
-
green led的行为定义为usb device模式的活动状态
root@openstick:/sys/class/leds/green:internet# echo usb-gadget > trigger
写入该字符串后led行为立刻生效,重启失效。配置完成后绿色LED在每次USB接口有数据传输时都会闪烁。
1.2 命令解析
root@openstick:/sys/class/leds/green:internet# echo usb-gadget > trigger
/sys
: sysfs是一种虚拟的文件系统,可以查看和控制Linux系统中的设备驱动程序和硬件信息。通过sysfs,可以获得系统中已经加载的驱动程序的信息,包括文件系统,输入设备,串口,以太网等等。我们可以通过读写/sys目录下虚拟出来的设备文件控制底层硬件。class
- sysfs目录中的一个部分,包含所有的类,用于实现驱动程序中的设备模型。leds
- 设备类的名称,用于控制和访问系统的LED组。green:internet
- 设备的名称,用于指示您要使用的特定的LED。trigger
- 设备属性,表示LED触发器。允许你改变LED工作的模式(例如常亮、闪烁等)。常见的一些trigger值包括none
(常亮)、timer
(闪烁)、heartbeat
(心跳等节律),不同的LED设备支持不同的trigger。可以使用cat
命令读取该文件来查看LED设备支持哪些trigger。LED有很多其他常用属性,例如brightness
- LED亮度,值为0-255之间的整数。max_brightness
- LED的最大亮度值。可以使用cat
命令读取该文件来获取LED的最大亮度值。delay_on
和delay_off
- 用于设置闪烁效果的LED特有属性。delay_on
表示LED打开状态的时间长度,delay_off
表示LED关闭状态的时间长度。
>
-重定向符号,即将前面的命令的输出结果(标准输出流stdout)写入到其后面指定的文件中。即向trigger设备文件中写入usb-gadget字符。
总结来说,通过sysfs虚拟文件系统控制底层设备的方法如下:
# 写数据到设备
$/sys/class/设备组/设备名称# echo 属性值 > 属性名称
# 从设备读数据
$/sys/class/设备组/设备名称# cat 属性名称
1.3 硬件控制方式
除sysfs之外,我们还可以通过以下方式来控制底层硬件:
- 控制寄存器 - 通过使用适当的驱动程序和底层编程语言(如C语言或汇编语言),直接访问控制硬件设备的寄存器。这需要了解硬件设备的寄存器地址和寄存器的具体功能和使用方法。
- I/O端口 - 通过使用适当的驱动程序和底层编程语言(如C语言或汇编语言),访问控制硬件设备的I/O端口。这需要了解硬件设备I/O端口的地址和具体的输入输出方法。
- 设备文件 - 一些设备可以视为文件,并提供类似文件操作的接口来进行控制。比如,通过
/dev/ttyS0
设备文件访问串口设备。这需要了解设备文件的访问方法以及设备的具体使用方法。
这些方法都需要了解硬件设备的具体实现细节,因此需要较高水平的技能才能进行硬件控制。如果你想更简单地控制硬件,可以考虑使用通用的高级硬件控制框架或库。这些框架和库一般隐藏了底层硬件控制的实现细节,提供了易于使用和跨平台的高级接口,使得你可以用更简单的方式来控制硬件。
一些流行的高级硬件控制框架或库包括:
- WiringPi(用于树莓派)
- RPi.GPIO(树莓派Python库)
- Adafruit-GPIO(通用的Python GPIO库)
- libusb(通用的USB设备控制库)
- PyUSB(通用的Python USB库)
使用这些框架或库,你可以用更高级别的代码(通常是Python或其他易于使用的脚本语言)来控制硬件,并且不需要深入了解硬件控制的实现细节,因为这些库已经将它们隐藏在后台中。需要注意的是,使用这些库的好处是简单易用,但是它们可能会带来一些性能和可定制性方面的限制。如果你是高级硬件控制的专家或需要特定的功能,你可能需要更深入地了解底层硬件控制,然后自己实现控制逻辑。
1.4 底层实现:设备树和驱动
为了了解操作系统如何从底层控制LED,我们先需要了解 驱动和设备树(Device Tree)2个概念:
-
驱动程序:实际上是内核的一个模块,用于控制和管理硬件设备。当一个硬件设备插入计算机时,内核会根据其硬件信息来加载相应的驱动程序。驱动程序能够访问硬件设备的寄存器,从而控制设备的操作,例如读写设备状态、发送和接收数据、控制设备的电源等。其它还在操作系统与硬件之间建立了一个桥梁,使得应用程序可以和硬件设备进行交互。通过驱动程序,应用程序可以访问硬件设备。驱动程序建立了一个硬件抽象层,向应用程序提供一些统一用户接口或API,使得用户可以访问某些硬件设备的特性或操作。
-
设备树:在kernel 3.0以及之后的版本,都是采用设备树的方法实现驱动与设备之间的联系。当内核启动时,会在设备树文件中查找与当前系统中硬件设备匹配的节点,之后内核会加载相应的驱动程序来控制设备。这个过程可以通过设备树绑定(Device Tree Binding)来实现。驱动程序需要知道它所控制硬件设备的详细信息,包括设备的寄存器、中断路由、时序等信息。这些信息可以在设备树文件中定义。因此,在编写驱动程序时,需要编写相应的设备树绑定,并根据绑定的规范来编写相应的驱动程序。
设备树文件通常是系统供应商提供的二进制文件或源代码文件,而在开发中,也会根据具体需求编写或修改。通过设备树文件,内核可以识别硬件并加载相应的设备驱动程序。
简单来说,设备树文件描述了一个系统中的硬件设备及其属性,而驱动程序则实现了针对这些硬件设备的控制和操作。他们的作用总结如下。
-
驱动程序:提供了一系列的操作系统调用和接口,使得应用程序可以与硬件设备进行交互,方便应用程序开发。
-
设备树:设备树以文本描述的方式表达硬件结构,与平台无关,方便硬件的移植和维护。可以为不同的硬件平台提供一致的接口,简化驱动程序的开发。
因为随身WIFI的根文件系统中没有Linux源码,所以要想看到设备树和驱动程序的源码,估计需要解包boot.img镜像。太复杂了,没有再深入探究。
1.5 霓虹灯
做点有趣的事,随身WIFI有红 绿 蓝 三个LED灯,尽管不能控制灯的亮度,但应该依旧可以组合出黄色(红+绿),洋红色(红+蓝),青色(绿+蓝),混合(绿+蓝+红)4种颜色。我们来写一个shell脚本,让LED在这些颜色中交替变化吧
for i in $(seq 1 20)
do
echo none > /sys/class/leds/green:internet/trigger
echo none > /sys/class/leds/blue:wifi/trigger
echo none > /sys/class/leds/red:os/trigger
echo 1 > /sys/class/leds/green:internet/brightness
sleep 0.25
echo 0 > /sys/class/leds/green:internet/brightness
echo 1 > /sys/class/leds/blue:wifi/brightness
sleep 0.25
echo 0 > /sys/class/leds/blue:wifi/brightness
echo 1 > /sys/class/leds/red:os/brightness
sleep 0.25
echo 1 > /sys/class/leds/green:internet/brightness
sleep 0.25
echo 0 > /sys/class/leds/red:os/brightness
echo 1 > /sys/class/leds/blue:wifi/brightness
sleep 0.25
echo 0 > /sys/class/leds/green:internet/brightness
echo 1 > /sys/class/leds/red:os/brightness
sleep 0.25
echo 1 > /sys/class/leds/green:internet/brightness
sleep 0.25
echo 0 > /sys/class/leds/green:internet/brightness
echo 0 > /sys/class/leds/red:os/brightness
echo 0 > /sys/class/leds/blue:wifi/brightness
done
echo none > /sys/class/leds/green:internet/trigger
echo none > /sys/class/leds/blue:wifi/trigger
echo none > /sys/class/leds/red:os/trigger
echo 0 > /sys/class/leds/green:internet/brightness
echo 0 > /sys/class/leds/blue:wifi/brightness
echo 0 > /sys/class/leds/red:os/brightness
这个shell脚本中,我们使用 for
循环运行 20 次,每次间隔 0.25 秒钟,最终脚本会运行 35秒钟。最后,我们再次关闭所有灯的闪烁模式,并用 echo 0
控制所有灯都熄灭。这样可以保证脚本最终状态不会有任何灯闪烁。灯光闪烁的顺序是:绿–蓝–红–黄–青–洋红–混合。
更多推荐
所有评论(0)