文章目錄
- 1應用層控制外設的兩種方式
- 2 sysfs和/sys關系
- 3 LED控制方式
- 3.1 基本情況
- 3.2 LED屬性文件介紹
- 3.3 命令行屬性測試
- 3.4 led程序
- 3.5 開發板上測試
1應用層控制外設的兩種方式
- 使用設備文件控制
在Linux系統下,一切皆是文件。應用層控制底層硬件同樣也是通過文件IO的方式。設備文件可以理解為硬件層向應用層提供的接口
。應用層通過對設備文件IO的操作來操控硬件設備。設備文件通常在/dev/
目錄下,所以/dev
目錄下的文件成為設備節點。 - 使用sysfs文件系統
還有一種方式是通過sysfs
文件系統控制。sysfs文件系統是基于內存的文件系統,也是一種虛擬文件系統,他的作用是將內核信息已文件形式提供給應用層使用。他的主要功能是對系統設備進行管理,產生一個包含所有硬件層次的試圖。
sysfs提供可一種機制,可以顯示的描述內核對象、對象屬性以及對象間關系,用來導出內核對象的數據、屬性到用戶空間,以文件目錄結構的形式為用戶空間提供對這些數據、屬性的訪問支持。內核對象、對象屬性以及對象間關系在用戶空間sysfs中的表現如下表:內核中的組成要素 sysfs中的表現 內核對象(硬件設備) 目錄 對象屬性(設備屬性) 文件 對象關系 鏈接文件 - 總結
應用層對底層硬件控制的兩種方式:- /dev/目錄下的設備文件(設備節點)
- /sys/目錄下設備的屬性文件
具體使用哪種方式需要根據不同功能類型設備進行選擇,有些設備只能通過設備節點進行操控,而有些文件只能通過sysfs方式進行操控。通常情況下,一般簡單的設備會是用sysfs方式操作,例如led、GPIO等。對于復雜的文件,例如LCD、觸摸屏、攝像頭等,需要使用設備節點操作。
2 sysfs和/sys關系
sysfs文件系統掛載在/sys
目錄下。sysfs文件系統中的目錄包括block、bus、dev、devices、firmware、fs、kernel、modules、power
等,每個目錄下有許多文件或者子目錄,對于這些目錄的說’‘明如下所示(/sys目錄下內容):
-
devices
系統中所有設備存放目錄,sysfs管理設備的最重要的目錄結構。
-
block
塊設備的存放目錄,過時的接口
,該目錄下的文件通常是連接到’/sys/devices’目錄下的文件。
-
bus
所有設備按總線類型分類放置的目錄結構,'/sys/devices’目錄下的每種設備都是掛載在某種總線下的,例如i2c總線,同樣,該目錄下的文件也是鏈接到’sys/devices’目錄下的。
-
class
所有設備按照其功能分類放置的目錄結構,例如led設備。'/sys/class/input’目錄存放著所有輸入類設備。
-
dev
按照設備號的方式放置目錄結構,該目錄下有很多以主設備號:次設備號命令的文件,這些文件都是鏈接文件,連接到’/sys/devices’目錄下。
-
firmware
描述內核中的固件
-
fs
描述系統中所有文件系統,包括文件系統本身和按文件系統分類存放的已掛載點。
-
kernel
內核中所有的可調參的位置
-
module
系統中所有模塊信息
-
power
系統中電源選項,有一些屬性可以用于控制整個系統的電源狀態
系統中所有設備都會在/sys/devices
中體現出來,是sysfs文件系統最重要的目錄結構。
3 LED控制方式
3.1 基本情況
硬件情況:使用底板上的DS0 led(用戶可以控制的唯一LED)
開發板啟動方式:emmc啟動
mmc中的系統:正點原子的系統
交叉編譯器:arm-linux-guneabihf-
控制方式:sysfs文件系統
控制目錄:/sys/class/led
3.2 LED屬性文件介紹
進入到/sys/class/led
目錄下,該目錄中存放著所有的LED設備,目錄如下圖所示:
可以看到該目錄中有一個sys-led
的文件夾,這個就是底板上LED的設備文件,該目錄下文件如下圖所示:
這里主要關注brightness、max_brightness以及trigger三個文件,這三個都是LED的屬性文件。
- brightness:亮度
可讀可寫,設置led的亮度等級,
0:滅
正整數:pwm控制的led:值越大,led越亮
GPIO控制的led:亮 - max_brightness:最大亮度等級
只讀文件 - trigger:觸發模式
可讀可寫,設置當前LED觸發模式,讀表示獲取當前觸發模式,寫表示設置當前觸發模式。
觸發模式:方括號[ ]
括起來的表示當前觸發模式- none:無觸發
- mmc0:對mmc0設備讀寫時led會閃爍
- timer:有一定規律的亮滅,定時器控制
- heartbeat:心跳呼吸模式
通常系統啟動之后,都會將板子上的一顆led設置為heartbeat
觸發模式,表示系統正在正常運行。
3.3 命令行屬性測試
通過echo
命令進行LED控制
echo timer > trigger // 將led觸發模式設置為定時觸發
echo none > trigger // 將led觸發模式設置為無觸發模式
echo 1 > brightness // 點亮led
3.4 led程序
gitee:LED
#include "stdio.h"
#include "stdlib.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "unistd.h"
#include "string.h"#define LED_TRIGGER "/sys/class/leds/sys-led/trigger"
#define LED_BRIGHTNESS "/sys/class/leds/sys-led/brightness"#define USAGE() fprintf(stderr, "usage:\n" \" %s<on|off>\n" \" %s<trigger><type>\n", argv[0],argv[0])int main(int argc, char *argv[])
{int fd_trigger, fd_brightness;/* 判斷輸入參數個數 */if( argc < 2 ) {USAGE();exit(-1);}/* 打開文件 */fd_trigger = open(LED_TRIGGER, O_RDWR);if (fd_trigger < 0 ) {perror("open trigger error");exit(-1);}fd_brightness = open(LED_BRIGHTNESS, O_RDWR);if (fd_brightness < 0 ) {perror("open brightness error");exit(-1);}/* 判斷輸入參數 */if ( !strcmp(argv[1],"on") ) {write(fd_trigger, "none", 4);write(fd_brightness, "1", 1);} else if ( !strcmp(argv[1], "off") ) {write(fd_trigger, "none", 4);write(fd_brightness, "0", 1);} else if ( !strcmp(argv[1], "trigger")) {if ( argc != 3 ) {USAGE();exit(-1);}if ( write(fd_trigger, argv[2], strlen(argv[2]) ) < 0 ) {perror("set trigger faile");}} else {USAGE();}close(fd_trigger);close(fd_brightness);exit(0);
}
因為是運行在I.MX6ULL平臺上,所以要是用交叉編譯器編譯,makefile文件內容如下:
TARGET ?= led # 目標文件
CROSS_COMPILE ?= arm-linux-gnueabihf- # 交叉編譯器CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld src = led.c # 源碼文件$(TARGET):$(src)$(CC) -o $@ $<.PHONY: clean # 偽目標# 清除工程
clean:rm -rf *.o $(TARGET)
3.5 開發板上測試
將編譯好的二進制文件使用scp
命令發送到開發板上。在開發板中執行下面命令,觀察led變化。二進制文件一定要有可執行權限。
./led on // 亮
./led off // 滅
./led trigger heartbeat // 呼吸模式