Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
B
bbb_gpio_sys
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
humanoides
bbb_gpio_sys
Commits
73404038
There was a problem fetching the pipeline metadata.
Commit
73404038
authored
9 years ago
by
Sergi Hernandez
Browse files
Options
Downloads
Patches
Plain Diff
Some improvements on the original implementation.
parent
4703fd74
No related branches found
No related tags found
No related merge requests found
Pipeline
#
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
src/bbb_gpio.cpp
+119
-65
119 additions, 65 deletions
src/bbb_gpio.cpp
src/bbb_gpio.h
+206
-0
206 additions, 0 deletions
src/bbb_gpio.h
src/gpioexceptions.cpp
+2
-2
2 additions, 2 deletions
src/gpioexceptions.cpp
src/gpioexceptions.h
+24
-2
24 additions, 2 deletions
src/gpioexceptions.h
with
351 additions
and
69 deletions
src/bbb_gpio.cpp
+
119
−
65
View file @
73404038
...
...
@@ -9,11 +9,13 @@
#include
<sys/stat.h>
#include
<fcntl.h>
#include
<errno.h>
#include
<sys/stat.h>
CGPIO
::
CGPIO
(
gpio_ports
port
,
int
pin
)
{
int
fp
;
std
::
stringstream
text
;
struct
stat
sb
;
std
::
stringstream
text
,
gpio_file
;
/* try to export the desired pin */
if
((
fp
=
open
(
"/sys/class/gpio/export"
,
O_WRONLY
))
==-
1
)
...
...
@@ -31,12 +33,17 @@ CGPIO::CGPIO(gpio_ports port,int pin)
throw
CGPIOException
(
_HERE_
,
"Invalid pin identifier"
);
}
this
->
gpio_id
=
(
int
)
port
+
pin
;
text
<<
this
->
gpio_id
;
if
(
write
(
fp
,
text
.
str
().
c_str
(),
text
.
str
().
size
())
!=
(
int
)
text
.
str
().
size
())
gpio_file
<<
"/sys/class/gpio/gpio"
<<
this
->
gpio_id
;
/* check if the file already exists */
if
(
stat
(
gpio_file
.
str
().
c_str
(),
&
sb
)
!=
0
)
{
/* handle exceptions */
close
(
fp
);
throw
CGPIOException
(
_HERE_
,
"Error while writing to the export file"
);
text
<<
this
->
gpio_id
;
if
(
write
(
fp
,
text
.
str
().
c_str
(),
text
.
str
().
size
())
!=
(
int
)
text
.
str
().
size
())
{
/* handle exceptions */
close
(
fp
);
throw
CGPIOException
(
_HERE_
,
"Error while writing to the export file"
);
}
}
// close the export file
close
(
fp
);
...
...
@@ -55,9 +62,6 @@ CGPIO::CGPIO(gpio_ports port,int pin)
this
->
thread_server
->
create_thread
(
this
->
edge_thread_id
);
this
->
thread_server
->
attach_thread
(
this
->
edge_thread_id
,
this
->
edge_thread
,
this
);
this
->
input_fd
=-
1
;
// wait for the pin to be available
sleep
(
1
);
}
void
*
CGPIO
::
edge_thread
(
void
*
param
)
...
...
@@ -110,10 +114,13 @@ void *CGPIO::edge_thread(void *param)
void
CGPIO
::
set_direction
(
dir_t
direction
)
{
int
fp
;
struct
stat
sb
;
std
::
stringstream
text
;
//Open the GPIO's sysfs file for writing
text
<<
"/sys/devices/virtual/gpio/gpio"
<<
this
->
gpio_id
<<
"/direction"
;
//Open the GPIO's sysfs file for writing
while
(
stat
(
text
.
str
().
c_str
(),
&
sb
)
!=
0
||
(
sb
.
st_mode
&
(
S_IWUSR
|
S_IWGRP
))
!=
(
S_IWUSR
|
S_IWGRP
))
usleep
(
100000
);
if
((
fp
=
open
(
text
.
str
().
c_str
(),
O_WRONLY
))
==
-
1
)
{
/* handle exceptions */
...
...
@@ -153,12 +160,15 @@ void CGPIO::set_direction(dir_t direction)
void
CGPIO
::
set_value
(
bool
value
)
{
int
fp
;
struct
stat
sb
;
std
::
stringstream
text
;
if
(
this
->
direction
==
output
)
{
//Open the GPIO's sysfs file for reading and writing
text
<<
"/sys/devices/virtual/gpio/gpio"
<<
this
->
gpio_id
<<
"/value"
;
while
(
stat
(
text
.
str
().
c_str
(),
&
sb
)
!=
0
||
(
sb
.
st_mode
&
(
S_IWUSR
|
S_IWGRP
))
!=
(
S_IWUSR
|
S_IWGRP
))
usleep
(
100000
);
if
((
fp
=
open
(
text
.
str
().
c_str
(),
O_RDWR
))
==
-
1
)
{
/* handle exceptions */
...
...
@@ -183,79 +193,123 @@ void CGPIO::set_value(bool value)
bool
CGPIO
::
get_value
(
void
)
{
int
fp
;
struct
stat
sb
;
unsigned
char
value
;
std
::
stringstream
text
;
if
(
this
->
direction
==
input
)
{
//Open the GPIO's sysfs file for reading and writing
text
<<
"/sys/devices/virtual/gpio/gpio"
<<
this
->
gpio_id
<<
"/value"
;
while
(
stat
(
text
.
str
().
c_str
(),
&
sb
)
!=
0
||
(
sb
.
st_mode
&
(
S_IWUSR
|
S_IWGRP
))
!=
(
S_IWUSR
|
S_IWGRP
))
usleep
(
100000
);
if
((
fp
=
open
(
text
.
str
().
c_str
(),
O_RDWR
))
==
-
1
)
{
/* handle exceptions */
throw
CGPIOException
(
_HERE_
,
"Impossible to open the value file"
);
}
//Set pointer to begining of the file
lseek
(
fp
,
0
,
SEEK_SET
);
if
(
read
(
fp
,
&
value
,
1
)
!=
1
)
{
close
(
fp
);
throw
CGPIOException
(
_HERE_
,
"Error while writing to the value file"
);
}
close
(
fp
);
if
(
value
==
'0'
)
return
false
;
else
return
true
;
}
return
false
;
}
std
::
string
CGPIO
::
set_active_edge
(
edge_t
edge
)
{
int
fp
;
struct
stat
sb
;
std
::
stringstream
text
;
unsigned
char
buffer
[
1024
];
//Open the GPIO's sysfs file for reading and writing
text
<<
"/sys/devices/virtual/gpio/gpio"
<<
this
->
gpio_id
<<
"/edge"
;
if
((
fp
=
open
(
text
.
str
().
c_str
(),
O_WRONLY
))
==
-
1
)
if
(
this
->
direction
==
input
)
{
/* handle exceptions */
throw
CGPIOException
(
_HERE_
,
"Impossible to open the edge file"
);
}
//Set pointer to begining of the file
lseek
(
fp
,
0
,
SEEK_SET
);
//Write our value of "1" to the file
text
.
str
(
std
::
string
());
switch
(
edge
)
{
case
edge_none
:
text
<<
"none"
;
break
;
case
edge_rising
:
text
<<
"rising"
;
//Open the GPIO's sysfs file for reading and writing
text
<<
"/sys/devices/virtual/gpio/gpio"
<<
this
->
gpio_id
<<
"/edge"
;
while
(
stat
(
text
.
str
().
c_str
(),
&
sb
)
!=
0
||
(
sb
.
st_mode
&
(
S_IWUSR
|
S_IWGRP
))
!=
(
S_IWUSR
|
S_IWGRP
))
usleep
(
100000
);
if
((
fp
=
open
(
text
.
str
().
c_str
(),
O_WRONLY
))
==
-
1
)
{
/* handle exceptions */
throw
CGPIOException
(
_HERE_
,
"Impossible to open the edge file"
);
}
//Set pointer to begining of the file
lseek
(
fp
,
0
,
SEEK_SET
);
//Write our value of "1" to the file
text
.
str
(
std
::
string
());
switch
(
edge
)
{
case
edge_none
:
text
<<
"none"
;
break
;
case
edge_falling
:
text
<<
"falling"
;
case
edge_rising
:
text
<<
"rising"
;
break
;
case
edge_falling
:
text
<<
"falling"
;
break
;
case
edge_both
:
text
<<
"both"
;
break
;
case
edge_both
:
text
<<
"both"
;
break
;
}
if
(
write
(
fp
,
text
.
str
().
c_str
(),
text
.
str
().
size
())
!=
(
int
)
text
.
str
().
size
())
{
close
(
fp
);
throw
CGPIOException
(
_HERE_
,
"Error while writing to the edge file"
);
}
}
if
(
write
(
fp
,
text
.
str
().
c_str
(),
text
.
str
().
size
())
!=
(
int
)
text
.
str
().
size
())
{
close
(
fp
);
throw
CGPIOException
(
_HERE_
,
"Error while writing to the edge file"
);
}
close
(
fp
);
close
(
fp
);
this
->
edge
=
edge
;
this
->
edge
=
edge
;
// open the input file
text
.
str
(
std
::
string
(
""
));
text
<<
"/sys/devices/virtual/gpio/gpio"
<<
this
->
gpio_id
<<
"/value"
;
if
((
this
->
input_fd
=
open
(
text
.
str
().
c_str
(),
O_RDONLY
|
O_NONBLOCK
))
==
-
1
)
{
/* handle exceptions */
throw
CGPIOException
(
_HERE_
,
"Impossible to open the value file"
);
}
//Set pointer to begining of the file
lseek
(
this
->
input_fd
,
0
,
SEEK_SET
);
read
(
this
->
input_fd
,
buffer
,
1024
);
if
(
this
->
edge
!=
edge_none
)
{
if
(
this
->
thread_server
->
get_thread_state
(
this
->
edge_thread_id
)
==
attached
)
// open the input file
text
.
str
(
std
::
string
(
""
));
text
<<
"/sys/devices/virtual/gpio/gpio"
<<
this
->
gpio_id
<<
"/value"
;
while
(
stat
(
text
.
str
().
c_str
(),
&
sb
)
!=
0
||
(
sb
.
st_mode
&
(
S_IWUSR
|
S_IWGRP
))
!=
(
S_IWUSR
|
S_IWGRP
))
usleep
(
100000
);
if
((
this
->
input_fd
=
open
(
text
.
str
().
c_str
(),
O_RDONLY
|
O_NONBLOCK
))
==
-
1
)
{
// start the waiting thread
this
->
thread_server
->
start_thread
(
this
->
edge_thread_id
);
// create the edge event
text
.
str
(
std
::
string
(
""
));
text
<<
"pin_"
<<
this
->
gpio_id
<<
"_event"
;
this
->
edge_event_id
=
text
.
str
();
this
->
event_server
->
create_event
(
this
->
edge_event_id
);
/* handle exceptions */
throw
CGPIOException
(
_HERE_
,
"Impossible to open the value file"
);
}
//Set pointer to begining of the file
lseek
(
this
->
input_fd
,
0
,
SEEK_SET
);
read
(
this
->
input_fd
,
buffer
,
1024
);
if
(
this
->
edge
!=
edge_none
)
{
if
(
this
->
thread_server
->
get_thread_state
(
this
->
edge_thread_id
)
==
attached
)
{
// start the waiting thread
this
->
thread_server
->
start_thread
(
this
->
edge_thread_id
);
// create the edge event
text
.
str
(
std
::
string
(
""
));
text
<<
"pin_"
<<
this
->
gpio_id
<<
"_event"
;
this
->
edge_event_id
=
text
.
str
();
this
->
event_server
->
create_event
(
this
->
edge_event_id
);
}
}
else
{
// stop the thread if it is running
if
(
this
->
thread_server
->
get_thread_state
(
this
->
edge_thread_id
)
==
starting
||
this
->
thread_server
->
get_thread_state
(
this
->
edge_thread_id
)
==
active
)
{
this
->
event_server
->
set_event
(
this
->
finish_thread_event_id
);
this
->
thread_server
->
end_thread
(
this
->
edge_thread_id
);
}
if
(
this
->
edge_event_id
!=
""
)
this
->
event_server
->
delete_event
(
this
->
edge_event_id
);
this
->
edge_event_id
=
""
;
}
}
else
{
if
(
this
->
edge_event_id
!=
""
)
this
->
event_server
->
delete_event
(
this
->
edge_event_id
);
this
->
edge_event_id
=
""
;
}
return
this
->
edge_event_id
;
return
this
->
edge_event_id
;
}
else
return
std
::
string
(
""
);
}
CGPIO
::~
CGPIO
()
...
...
This diff is collapsed.
Click to expand it.
src/bbb_gpio.h
+
206
−
0
View file @
73404038
...
...
@@ -4,34 +4,240 @@
#include
"eventserver.h"
#include
"threadserver.h"
/*! \file */
/*!
* \brief GPIO direction ennumeration
*
* Specifies the direction of a given GPIO pin as either input or output.
* Bidirectional ports are not supported.
*/
typedef
enum
{
output
=
0
,
input
=
1
}
dir_t
;
/*!
* \brief GPIO edge sensitive ennumeration
*
* Specifies the input signal transitions that will generate an interal event
* only for GPIO pins configured as inputs.
*/
typedef
enum
{
edge_none
=
0
,
edge_rising
,
edge_falling
,
edge_both
}
edge_t
;
/*!
* \brief GPIO ports ennumeration
*
* Identifiers of the different GPIO ports available on the beaglebone black.
*/
typedef
enum
{
GPIO0
=
0
,
GPIO1
=
32
,
GPIO2
=
64
,
GPIO3
=
96
}
gpio_ports
;
/*!
* \brief Implmentation of a GPIO interface for ARM
*
* This class is a wrapper to the file system interface to GPIO signals for ARM
* processors. The file system interface required to open and close several
* files to perform any action on a given GPIO pin, which this class
* encapsulates, providing a simple user interface.
*
* This class requires some system configuration to allow standard users to
* access the GPIO signals. See section ?? on technical report ?? for more
* details on the required configuration.
*
* In its simplest form, this class allows to access any available GPIO pin
* as either an input or an ouput pin, providing functions to get the current
* value or set the desired value respectively.
*
* More advanced features are available when the GPIO isconfigured as an input.
* In this case, it is possible to select a sensitive transition on the input
* signal that will generate an internal event no notify it. This event is
* implemented as a CEvent from the iriutils library ???.
*
* This feature will allow an external process to wait on an input signal event
* without continuously polling the value of the input pin.
*/
class
CGPIO
{
private:
/**
* \brief input pin value file descriptor
*
* This attribute points to the value file of the GPIO pin when it is
* configured as an input, and it is used for handling the internal
* events usign the select() function.
*/
int
input_fd
;
/**
* \brief Identifier of the GPIO pin
*
* This attribute holds the unique system identifier number for the GPIO
* pin, which is build from the port identifier and the port bit.
*/
int
gpio_id
;
/**
* \brief Current direction of the GPIO pin
*
* This attribute holds the current direction configuration of the GPIO
* pin.
*/
dir_t
direction
;
/**
* \brief Current sensitive edge for the GPIO
*
* This attribute holds the kind of transition on the input signal that
* will generate an internal event only for GPIO pins configured as
* inputs.
*/
edge_t
edge
;
/* events */
/**
* \brief Identifier of the active transition event.
*
* This attribute is the string identifier for the active transition event
* for any GPIO configured as an input. This identifier should be used by
* any external process to wait for the desired event on the GPIO pin, and
* therefore a copy is returned by the set_active_edge() function.
*/
std
::
string
edge_event_id
;
/**
* \brief Identifier of the finish event
*
* This attribute is a string identifier for the internal event used to
* terminate the internal thread to detect the desired transitions on the
* input signal.
*/
std
::
string
finish_thread_event_id
;
/**
* \brief Reference to the event server
*
* This is a reference to the unique event server to handle the internal
* events.
*/
CEventServer
*
event_server
;
/* threads */
/**
* \brief Identifier of the internal thread
*
* This attribute is a string identifier for the internal thread used to
* monitor the desired transitions on the input value only for GPIO pins
* configured as inputs.
*/
std
::
string
edge_thread_id
;
/**
* \brief Reference to the thread server
*
* This is a reference to the unique thread server to handle the internal
* threads.
*/
CThreadServer
*
thread_server
;
protected:
/**
* \brief Input transitions monitor function
*
* This is the main function executed by the internal thread to detect
* any desired transition on the input value. This function is only called
* when the GPIO pin is configured as an input, and it is charge to
* activate the edge_event_id event whenever the desired transition is
* detected on the input value.
*
* \param param a pointer to the object itself (this) since the function is
* declared as static.
*
* \return Value passed to the process that created the thread when it
* finishes execution.
*/
static
void
*
edge_thread
(
void
*
param
);
public:
/*!
* \brief Constructor
*
* This constructor tries to create the file system entries for the GPIO pin
* specified by the input parameters. If successfull, all the internal
* attributes are initialized by default.
*
* The default configuration is as an input, but without monitoring any
* transitions on the input value.
*
* A CGPIOException object may be thrown in the following cases:
* * Not enough privileges to access the GPIO file system
* * Invalid port identifier
*
* \param port identifier of the desired GPIO port. It must be one of the
* #gpio_ports values.
* \param pin desired bit number inside the given GPIO port. It must be a
* non-negative integer between 0 and 31.
*/
CGPIO
(
gpio_ports
port
,
int
pin
);
/**
* \brief Function to change the direction of the current GPIO signal
*
* This function changes the direction of the current GPIO port. If the
* GPIO port changes from input to output, the monitoring of the input
* value is stopped (if it was active)
*
* A CGPIOException object may be thrown in the following cases:
* * Not enough privileges to access the GPIO file system
*
* \param direction The new direction identifier for the current GPIO
* port. It must be one of the #dir_t values.
*/
void
set_direction
(
dir_t
direction
);
/**
* \brief Function to set the output value of the current GPIO signal
*
* This functions changes the output value of the current GPIO signal if
* it is configured as an output. Otherwise, this function does nothing.
*
* A CGPIOException object may be thrown in the following cases:
* * Not enough privileges to access the GPIO file system
*
* \param value Desired output value for the current GPIO signal. True
* for a logic '1' and false for '0'.
*/
void
set_value
(
bool
value
);
/**
* \brief Function to get the current value of the current GPIO signal
*
* This function returns the current value of teh current GPIO signal if
* it is configured as an input. Otherwise, this function does nothing.
*
* A CGPIOException object may be thrown in the following cases:
* * Not enough privileges to access the GPIO file system
*
* \return The current value of the input port. True for a logic '1' and
* false for '0'.
*/
bool
get_value
(
void
);
/**
* \brief Function to enable the input monitoring
*
* This function starts the monitoring process on the input value if the
* GPIO pin is configured as an input. If the GPIO pin is configured as
* an output, this function does nothing.
*
* This function can also be used to stop the monitoring system by passing
* a value of none. This will stop the internal thread and will render
* inactive the previously returned event identifier.
*
* A CGPIOException object may be thrown in the following cases:
* * Not enough privileges to access the GPIO file system
*
* \param edge identifier of the desired transition on the input value to
* look for. It must be one of the #edge_t value.
*
* \return a string with the identifier of the internal event associated to
* the desired transition on the input value. This string will be
* empty if the GPIO is configured as an output or the desired edge
* is edge_none.
*/
std
::
string
set_active_edge
(
edge_t
edge
);
/**
* \brief Destructor
*
* This destructor stops the monitoring process, if it is active, and free
* all object resources.
*
* A CGPIOException object may be thrown in the following cases:
* * Not enough privileges to access the GPIO file system
*
*/
~
CGPIO
();
};
...
...
This diff is collapsed.
Click to expand it.
src/gpioexceptions.cpp
+
2
−
2
View file @
73404038
...
...
@@ -2,9 +2,9 @@
#include
<string.h>
#include
<stdio.h>
const
std
::
string
comm
_exception_msg
=
"[GPIO class] - "
;
const
std
::
string
gpio
_exception_msg
=
"[GPIO class] - "
;
CGPIOException
::
CGPIOException
(
const
std
::
string
&
where
,
const
std
::
string
&
error_msg
)
:
CException
(
where
,
comm
_exception_msg
)
CGPIOException
::
CGPIOException
(
const
std
::
string
&
where
,
const
std
::
string
&
error_msg
)
:
CException
(
where
,
gpio
_exception_msg
)
{
this
->
error_msg
+=
error_msg
;
}
This diff is collapsed.
Click to expand it.
src/gpioexceptions.h
+
24
−
2
View file @
73404038
...
...
@@ -4,8 +4,11 @@
#include
"exceptions.h"
/**
* \brief
*
* \brief Exception class for the CGPIO class
*
* This class is used as the main exception to be thrown from the CGPIO class.
* It inherits from the basic CException class from iriutils and preappends
* some additional information to the standard error message.
*/
class
CGPIOException
:
public
CException
{
...
...
@@ -13,6 +16,25 @@ class CGPIOException : public CException
/**
* \brief Constructor
*
* The constructor calls the base class constructor to add the general
* exception identifier and then adds the class identifier string
* "[CGPIO class]" and the supplied error message.
*
* So, the total exception message will look like this:
*
* \verbatim
* [Exception caught] - <where>
* [CGPIO class] - <error message>
* \endverbatim
*
* \param where a null terminated string with the information about the name
* of the function, the source code filename and the line where
* the exception was generated. This string must be generated
* by the _HERE_ macro.
*
* \param error_msg a null terminated string that contains the error message.
* This string may have any valid character and there is no
* limit on its length.
*/
CGPIOException
(
const
std
::
string
&
where
,
const
std
::
string
&
error_msg
);
};
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment