补充 用户态 GPIO 示例.
Signed-off-by: lion.chan <cy187lion@sina.com>
This commit is contained in:
parent
a50314c4e2
commit
6dddc8e048
|
@ -98,3 +98,208 @@ block 目录包含所有的块设备,devices 目录包含系统所有的设备
|
|||
在 /sys/bus 的 pci 等子目录下,又会在分出 drivers 和 devices 目录,而 devices 目录中的文件是对 /sys/devices 目录中文件的符号链接。同样地,/sys/class 目录下包含许多对 /sys/devices 下文件的链接。这与设备、驱动、总线和类的现实状况是直接对应的,也正符合 Linux 2.6 内核的设备模型。
|
||||
|
||||
![sysfs 文件系统下的文件相互交织](./imgs/8.5_Linux_文件系统与设备文件系统/002.png)
|
||||
|
||||
## 用户态 GPIO 示例
|
||||
|
||||
下面以 GPIO 操作为例,演示设备文件系统的使用方法,该示例为 c++ 工程,包含一个 cmake 文件,一个 Gpio 类和一个 main.cpp 文件,其中 Gpio 类封装了 GPIO 端口导出和读写机制。
|
||||
|
||||
main.cpp 内容如下:
|
||||
|
||||
```cpp
|
||||
/**
|
||||
* @file: main.cpp
|
||||
*/
|
||||
#include <iostream>
|
||||
#include "Gpio.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
const char* Gpio::GpioPortTbl[] =
|
||||
{
|
||||
"372",
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
Gpio* gpio = new Gpio(0, Gpio::EC_ATTR_R);
|
||||
Gpio::EU_PORT_LEVEL rlevel = gpio->ReadPort();
|
||||
cout << "Read GPIO Port Level: " << rlevel << endl;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Gpio.h 内容如下:
|
||||
|
||||
```cpp
|
||||
/**
|
||||
* @file: Gpio.h
|
||||
*/
|
||||
#ifndef GPIO_H
|
||||
#define GPIO_H
|
||||
|
||||
#include <string>
|
||||
#define POLL_TIMEOUT (1 * 1000)
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Gpio
|
||||
{
|
||||
public:
|
||||
enum EU_PORT_LEVEL
|
||||
{
|
||||
EC_PORT_N = 0,
|
||||
EC_PORT_L = '0',
|
||||
EC_PORT_H = '1'
|
||||
};
|
||||
|
||||
enum EU_PORT_ATTR
|
||||
{
|
||||
EC_ATTR_R, // Readable
|
||||
EC_ATTR_W // Writeable
|
||||
};
|
||||
|
||||
static const char* GpioPortTbl[];
|
||||
|
||||
Gpio(int id=0, EU_PORT_ATTR attr=EC_ATTR_R);
|
||||
|
||||
EU_PORT_ATTR GetAttr(void) const { return PortAttr; }
|
||||
const char* GetNo(void) const { return GpioPortTbl[PortID]; }
|
||||
int GetFd(void) const { return Fd; }
|
||||
|
||||
bool WritePort(EU_PORT_LEVEL val);
|
||||
EU_PORT_LEVEL ReadPort(void);
|
||||
|
||||
protected:
|
||||
const int PortID;
|
||||
const EU_PORT_ATTR PortAttr;
|
||||
|
||||
int Fd;
|
||||
char LastStu;
|
||||
char CurtStu;
|
||||
|
||||
private:
|
||||
void Export(void);
|
||||
|
||||
};
|
||||
|
||||
#endif // GPIO_H
|
||||
```
|
||||
|
||||
Gpio.cpp 内容如下:
|
||||
|
||||
```cpp
|
||||
/**
|
||||
* @file: Gpio.cpp
|
||||
*/
|
||||
#include "Gpio.h"
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
Gpio::Gpio(int id, EU_PORT_ATTR attr):
|
||||
PortID(id), PortAttr(attr)
|
||||
{
|
||||
Fd = -1;
|
||||
LastStu = EC_PORT_L;
|
||||
CurtStu = EC_PORT_L;
|
||||
Export();
|
||||
}
|
||||
|
||||
bool Gpio::WritePort(EU_PORT_LEVEL val)
|
||||
{
|
||||
int ret = -1;
|
||||
char wVal = (char)val;
|
||||
|
||||
if(0>=Fd)
|
||||
return false;
|
||||
if(EC_ATTR_W!=PortAttr)
|
||||
return false;
|
||||
|
||||
lseek(Fd, 0, SEEK_SET);
|
||||
ret = write(Fd, &wVal, 1);
|
||||
if(0>ret)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Gpio::EU_PORT_LEVEL Gpio::ReadPort(void)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if(0>=Fd)
|
||||
{
|
||||
cout << "Read Gpio" << GpioPortTbl[PortID] << "Error Fd=" << Fd;
|
||||
return EC_PORT_N;
|
||||
}
|
||||
|
||||
lseek(Fd, 0, SEEK_SET);
|
||||
ret = read(Fd, &CurtStu, 1);
|
||||
cout << "Read Gpio" << GpioPortTbl[PortID] << " Ret=" << ret << " Val=" << CurtStu << endl;
|
||||
|
||||
switch(CurtStu)
|
||||
{
|
||||
case EC_PORT_L:
|
||||
return EC_PORT_L;
|
||||
case EC_PORT_H:
|
||||
return EC_PORT_H;
|
||||
default:
|
||||
return EC_PORT_N;
|
||||
}
|
||||
}
|
||||
|
||||
void Gpio::Export(void)
|
||||
{
|
||||
// Export.
|
||||
int fd = open("/sys/class/gpio/export", O_WRONLY);
|
||||
if(fd<0)
|
||||
return;
|
||||
write(fd, GpioPortTbl[PortID], strlen(GpioPortTbl[PortID]));
|
||||
close(fd);
|
||||
|
||||
// Set direction.
|
||||
string dir = string("/sys/class/gpio/gpio")+
|
||||
string(GpioPortTbl[PortID])+
|
||||
string("/direction");
|
||||
fd = open(dir.c_str(), O_WRONLY);
|
||||
if(fd<0)
|
||||
return;
|
||||
if(PortAttr==EC_ATTR_R)
|
||||
write(fd, "in", 2);
|
||||
else
|
||||
write(fd, "out", 3);
|
||||
close(fd);
|
||||
|
||||
// Set edge.
|
||||
if(PortAttr==EC_ATTR_R)
|
||||
{
|
||||
string edge = string("/sys/class/gpio/gpio")+
|
||||
string(GpioPortTbl[PortID])+
|
||||
string("/edge");
|
||||
fd = open(edge.c_str(), O_WRONLY);
|
||||
if(fd<0)
|
||||
return;
|
||||
write(fd, "both", 4);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
string name = string("/sys/class/gpio/gpio")+
|
||||
string(GpioPortTbl[PortID])+
|
||||
string("/value");
|
||||
Fd = open(name.c_str(), (PortAttr==EC_ATTR_R) ? O_RDONLY|O_NONBLOCK : O_WRONLY|O_NONBLOCK);
|
||||
cout << "Open:" << name << "Fd=" << Fd << endl;
|
||||
}
|
||||
```
|
||||
|
||||
CMakeLists.txt 如下:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(c08_05 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_executable(c08_05 main.cpp Gpio.h Gpio.cpp)
|
||||
```
|
||||
|
|
Loading…
Reference in New Issue