Несколько друзей предложили запрограммировать управляющий код как модуль ядра, но я не совсем уверен, что хочу этим заниматься.
Я почти уверен, что если бы это не было тесно связано с аппаратным обеспечением, оно было бы отклонено ядром Linux. Цель пользовательского системного вызова и доступа к sysfs — поместить вашу пользовательскую логику в Linux поверх аппаратной абстракции (модель OSI).
Что вам нужно сделать, так это сначала проверить, обеспечивает ли ядро Linux всю аппаратную поддержку ваших устройств. Тогда вы можете взять мой класс промежуточного программного обеспечения для управления GPIO на языке C++. Наконец, вы можете написать небольшое основное приложение для тестирования ядра и класса C++. Это приложение будет делать что-то простое, например создавать экземпляр класса GPIO, экспортировать GPIO и затем записывать значения.
(Как это связано с вашим вопросом PWM, неясно, но вы, кажется, смешиваете две разные области драйвера ядра)
Вы можете сделать что-то вроде приведенного ниже кода через sysfs в соответствии с документация gpio ядра Linux. Вам, конечно, нужно убедиться, что ваше аппаратное gpio поддерживается ядром Linux.
gpio.h
#ifndef FOOBAR_GENERALPURPOSEIO_H
#define FOOBAR_GENERALPURPOSEIO_H
namespace Foobar
{
class FOOBAR_EXPORT GeneralPurposeIO
{
public:
enum Direction {
Input,
Output
};
explicit GeneralPurposeIO(quint32 gpioNumber = 0);
~GeneralPurposeIO();
int gpioExport();
int gpioUnexport();
bool isGpioExported();
quint32 gpioNumber() const;
void setGpioNumber(quint32 gpioNumber);
Direction direction() const;
int setDirection(Direction direction);
qint32 value() const;
int setValue(qint32 value);
private:
class Private;
Private *const d;
};
}
#endif // FOOBAR_GENERALPURPOSEIO_H
gpio.cpp
#include "generalpurposeio.h"
#include <QtCore/QDebug>
#include <QtCore/QFile>
using namespace Foobar;
class GeneralPurposeIO::Private
{
public:
Private()
{
}
~Private()
{
}
static const QString gpioExportFilePath;
static const QString gpioUnexportFilePath;
static const QString gpioDirectionFilePath;
static const QString gpioValueFilePath;
static const QString gpioFilePath;
quint32 gpioNumber;
};
const QString GeneralPurposeIO::Private::gpioExportFilePath = "/sys/class/gpio/export";
const QString GeneralPurposeIO::Private::gpioUnexportFilePath = "/sys/class/gpio/unexport";
const QString GeneralPurposeIO::Private::gpioDirectionFilePath = "/sys/class/gpio/gpio%1/direction";
const QString GeneralPurposeIO::Private::gpioValueFilePath = "/sys/class/gpio/gpio%1/value";
const QString GeneralPurposeIO::Private::gpioFilePath = "/sys/class/gpio/gpio%1";
GeneralPurposeIO::GeneralPurposeIO(quint32 gpioNumber)
: d(new Private)
{
d->gpioNumber = gpioNumber;
}
GeneralPurposeIO::~GeneralPurposeIO()
{
}
/*
* Exports the desired gpio number.
*
* Note: Unfortunately, it is not possible to just call this method "export"
* since that is a reserved keyword in C++. Systematically the unexport method
* cannot be called "unexport" either for consistency.
*/
int GeneralPurposeIO::gpioExport()
{
if (isGpioExported()) {
// TODO: Proper error mutator mechanism for storing different error
// enumeration values internally that can be requested by the API user
qDebug() << "Cannot export the gpio pin since it is already exported:" << d->gpioNumber;
return -1;
}
QFile gpioExportFile(d->gpioExportFilePath);
if (!gpioExportFile.open(QIODevice::Append)) {
qDebug() << "Cannot open the gpio export file:" << d->gpioExportFilePath;
return -1;
}
/*
* Seek to begining of the file
*/
gpioExportFile.seek(0);
/*
* Write our value of "gpioPinNumber" to the file
*/
if (gpioExportFile.write(QByteArray::number(d->gpioNumber)) == -1) {
qDebug() << Q_FUNC_INFO << "Error while writing the file:" << d->gpioExportFilePath;
gpioExportFile.close();
return -1;
}
gpioExportFile.close();
return 0;
}
int GeneralPurposeIO::gpioUnexport()
{
if (!isGpioExported()) {
// TODO: Proper error mutator mechanism for storing different error
// enumeration values internally that can be requested by the API user
qDebug() << "Cannot unexport the gpio pin since it is not exported yet:" << d->gpioNumber;
return -1;
}
QFile gpioUnexportFile(d->gpioUnexportFilePath);
if (!gpioUnexportFile.open(QIODevice::Append)) {
qDebug() << "Cannot open the gpio export file:" << d->gpioUnexportFilePath;
return -1;
}
/*
* Seek to begining of the file
*/
gpioUnexportFile.seek(0);
/*
* Write our value of "gpioPinNumber" to the file
*/
if (gpioUnexportFile.write(QByteArray::number(d->gpioNumber)) == -1) {
qDebug() << Q_FUNC_INFO << "Error while writing the file:" << d->gpioUnexportFilePath;
gpioUnexportFile.close();
return -1;
}
gpioUnexportFile.close();
return 0;
}
bool GeneralPurposeIO::isGpioExported()
{
if (!QFile(d->gpioFilePath.arg(d->gpioNumber)).exists()) {
return false;
}
return true;
}
quint32 GeneralPurposeIO::gpioNumber() const
{
return d->gpioNumber;
}
void GeneralPurposeIO::setGpioNumber(quint32 gpioNumber)
{
d->gpioNumber = gpioNumber;
}
GeneralPurposeIO::Direction GeneralPurposeIO::direction() const
{
// TODO: Implement me
return GeneralPurposeIO::Output;
}
int GeneralPurposeIO::setDirection(Direction direction)
{
if (!isGpioExported()) {
if (gpioExport() == -1) {
return -1;
}
}
/*
* Set the direction
*/
QFile gpioDirectionFile(d->gpioDirectionFilePath.arg(d->gpioNumber));
if (!gpioDirectionFile.open(QIODevice::ReadWrite)) {
qDebug() << "Cannot open the relevant gpio direction file:" << d->gpioDirectionFilePath;
return -1;
}
int retval = 0;
/*
* Seek to begining of the file
*/
gpioDirectionFile.seek(0);
switch (direction) {
case Output:
if (gpioDirectionFile.write("high") == -1) {
qDebug() << Q_FUNC_INFO << "Error while writing the file:" << d->gpioDirectionFilePath;
retval = -1;
}
break;
case Input:
if (gpioDirectionFile.write("low") == -1) {
qDebug() << Q_FUNC_INFO << "Error while writing the file:" << d->gpioDirectionFilePath;
retval = -1;
}
break;
default:
break;
}
gpioDirectionFile.close();
return retval;
}
qint32 GeneralPurposeIO::value() const
{
// TODO: Implement me
return 0;
}
int GeneralPurposeIO::setValue(qint32 value)
{
if (direction() != GeneralPurposeIO::Output) {
qDebug() << "Cannot set the value for an input gpio pin:" << d->gpioNumber;
return -1;
}
/*
* Set the value
*/
QFile gpioValueFile(d->gpioValueFilePath.arg(d->gpioNumber));
if (!gpioValueFile.open(QIODevice::ReadWrite)) {
qDebug() << "Cannot open the relevant gpio value file:" << d->gpioValueFilePath.arg(d->gpioNumber);
gpioValueFile.close();
return -1;
}
/*
* Seek to begining of the file
*/
gpioValueFile.seek(0);
if (gpioValueFile.write(QByteArray::number(value)) == -1) {
qDebug() << Q_FUNC_INFO << "Error while writing the file:" << d->gpioValueFilePath.arg(d->gpioNumber);
gpioValueFile.close();
return -1;
}
gpioValueFile.close();
return 0;
}
person
lpapp
schedule
22.12.2013
nice
задачам придется уступить время задачам ядра и т. д. - person artless noise   schedule 03.01.2014