Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
R
RF24
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
xpstem
RF24
Commits
9e717722
Commit
9e717722
authored
Apr 02, 2016
by
akatran
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://github.com/TMRh20/RF24
parents
a9255c80
a1d346a9
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
555 additions
and
108 deletions
+555
-108
Makefile
Makefile
+2
-1
RF24.cpp
RF24.cpp
+43
-31
RF24_config.h
RF24_config.h
+1
-2
examples/GettingStarted/GettingStarted.ino
examples/GettingStarted/GettingStarted.ino
+5
-5
library.properties
library.properties
+1
-1
nRF24L01.h
nRF24L01.h
+1
-1
utility/BBB/gpio.cpp
utility/BBB/gpio.cpp
+20
-6
utility/BBB/includes.h
utility/BBB/includes.h
+1
-0
utility/BBB/interrupt.c
utility/BBB/interrupt.c
+226
-0
utility/BBB/interrupt.h
utility/BBB/interrupt.h
+69
-0
utility/BBB/spi.cpp
utility/BBB/spi.cpp
+23
-16
utility/RPi/bcm2835.c
utility/RPi/bcm2835.c
+101
-29
utility/RPi/bcm2835.h
utility/RPi/bcm2835.h
+62
-16
No files found.
Makefile
View file @
9e717722
...
...
@@ -66,7 +66,8 @@ CCFLAGS=-Ofast -mfpu=vfp -mfloat-abi=hard -march=$(ARCH) -mtune=arm1176jzf-s
else
DRIVER_DIR
=
$(ARCH_DIR)
/BBB
OBJECTS
+=
gpio.o compatibility.o
OBJECTS
+=
gpio.o compatibility.o interrupt.o
SHARED_LINKER_FLAGS
+=
-pthread
endif
...
...
RF24.cpp
View file @
9e717722
...
...
@@ -290,10 +290,12 @@ uint8_t RF24::read_payload(void* buf, uint8_t data_len)
status
=
*
prx
++
;
// 1st byte is status
while
(
--
data_len
)
// Decrement before to skip 1st status byte
*
current
++
=
*
prx
++
;
if
(
data_len
>
0
)
{
while
(
--
data_len
)
// Decrement before to skip 1st status byte
*
current
++
=
*
prx
++
;
*
current
=
*
prx
;
*
current
=
*
prx
;
}
endTransaction
();
#else
...
...
@@ -553,13 +555,13 @@ void RF24::printDetails(void)
print_byte_register
(
PSTR
(
"EN_RXADDR"
),
EN_RXADDR
);
print_byte_register
(
PSTR
(
"RF_CH
\t
"
),
RF_CH
);
print_byte_register
(
PSTR
(
"RF_SETUP"
),
RF_SETUP
);
print_byte_register
(
PSTR
(
"CONFIG
\t
"
),
CONFIG
);
print_byte_register
(
PSTR
(
"CONFIG
\t
"
),
NRF_
CONFIG
);
print_byte_register
(
PSTR
(
"DYNPD/FEATURE"
),
DYNPD
,
2
);
printf_P
(
PSTR
(
"Data Rate
\t
= "
PRIPSTR
"
\r\n
"
),
pgm_read_word
(
&
rf24_datarate_e_str_P
[
getDataRate
()]));
printf_P
(
PSTR
(
"Model
\t\t
= "
PRIPSTR
"
\r\n
"
),
pgm_read_word
(
&
rf24_model_e_str_P
[
isPVariant
()]));
printf_P
(
PSTR
(
"CRC Length
\t
= "
PRIPSTR
"
\r\n
"
),
pgm_read_word
(
&
rf24_crclength_e_str_P
[
getCRCLength
()]));
printf_P
(
PSTR
(
"PA Power
\t
= "
PRIPSTR
"
\r\n
"
),
pgm_read_word
(
&
rf24_pa_dbm_e_str_P
[
getPALevel
()]));
printf_P
(
PSTR
(
"Data Rate
\t
= "
PRIPSTR
"
\r\n
"
),
pgm_read_word
(
&
rf24_datarate_e_str_P
[
getDataRate
()]));
printf_P
(
PSTR
(
"Model
\t\t
= "
PRIPSTR
"
\r\n
"
),
pgm_read_word
(
&
rf24_model_e_str_P
[
isPVariant
()]));
printf_P
(
PSTR
(
"CRC Length
\t
= "
PRIPSTR
"
\r\n
"
),
pgm_read_word
(
&
rf24_crclength_e_str_P
[
getCRCLength
()]));
printf_P
(
PSTR
(
"PA Power
\t
= "
PRIPSTR
"
\r\n
"
),
pgm_read_word
(
&
rf24_pa_dbm_e_str_P
[
getPALevel
()]));
}
...
...
@@ -573,8 +575,6 @@ bool RF24::begin(void)
#if defined (RF24_LINUX)
SPI
();
#if defined (MRAA)
GPIO
();
gpio
.
begin
(
ce_pin
,
csn_pin
);
...
...
@@ -632,8 +632,8 @@ bool RF24::begin(void)
// WARNING: Delay is based on P-variant whereby non-P *may* require different timing.
delay
(
5
)
;
// Reset CONFIG and enable 16-bit CRC.
write_register
(
CONFIG
,
0b00001100
)
;
// Reset
NRF_
CONFIG and enable 16-bit CRC.
write_register
(
NRF_
CONFIG
,
0b00001100
)
;
// Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
// WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
...
...
@@ -649,8 +649,8 @@ bool RF24::begin(void)
{
p_variant
=
true
;
}
/*
setup = read_register(RF_SETUP);
if( setup == 0b00001110 ) // register default for nRF24L01P
setup
=
read_register
(
RF_SETUP
);
/*
if( setup == 0b00001110 ) // register default for nRF24L01P
{
p_variant = true ;
}*/
...
...
@@ -684,7 +684,7 @@ bool RF24::begin(void)
// Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp )
// PTX should use only 22uA of power
write_register
(
CONFIG
,
(
read_register
(
CONFIG
)
)
&
~
_BV
(
PRIM_RX
)
);
write_register
(
NRF_CONFIG
,
(
read_register
(
NRF_
CONFIG
)
)
&
~
_BV
(
PRIM_RX
)
);
// if setup is 0 or ff then there was no response from module
return
(
setup
!=
0
&&
setup
!=
0xff
);
...
...
@@ -697,7 +697,7 @@ void RF24::startListening(void)
#if !defined (RF24_TINY) && ! defined(LITTLEWIRE)
powerUp
();
#endif
write_register
(
CONFIG
,
read_register
(
CONFIG
)
|
_BV
(
PRIM_RX
));
write_register
(
NRF_CONFIG
,
read_register
(
NRF_
CONFIG
)
|
_BV
(
PRIM_RX
));
write_register
(
NRF_STATUS
,
_BV
(
RX_DR
)
|
_BV
(
TX_DS
)
|
_BV
(
MAX_RT
)
);
ce
(
HIGH
);
// Restore the pipe0 adddress, if exists
...
...
@@ -734,7 +734,7 @@ void RF24::stopListening(void)
flush_tx
();
}
//flush_rx();
write_register
(
CONFIG
,
(
read_register
(
CONFIG
)
)
&
~
_BV
(
PRIM_RX
)
);
write_register
(
NRF_CONFIG
,
(
read_register
(
NRF_
CONFIG
)
)
&
~
_BV
(
PRIM_RX
)
);
#if defined (RF24_TINY) || defined (LITTLEWIRE)
// for 3 pins solution TX mode is only left with additonal powerDown/powerUp cycle
...
...
@@ -754,7 +754,7 @@ void RF24::stopListening(void)
void
RF24
::
powerDown
(
void
)
{
ce
(
LOW
);
// Guarantee CE is low on powerDown
write_register
(
CONFIG
,
read_register
(
CONFIG
)
&
~
_BV
(
PWR_UP
));
write_register
(
NRF_CONFIG
,
read_register
(
NRF_
CONFIG
)
&
~
_BV
(
PWR_UP
));
}
/****************************************************************************/
...
...
@@ -762,11 +762,11 @@ void RF24::powerDown(void)
//Power up now. Radio will not power down unless instructed by MCU for config changes etc.
void
RF24
::
powerUp
(
void
)
{
uint8_t
cfg
=
read_register
(
CONFIG
);
uint8_t
cfg
=
read_register
(
NRF_
CONFIG
);
// if not powered up then power up and wait for the radio to initialize
if
(
!
(
cfg
&
_BV
(
PWR_UP
))){
write_register
(
CONFIG
,
read_register
(
CONFIG
)
|
_BV
(
PWR_UP
));
write_register
(
NRF_CONFIG
,
cfg
|
_BV
(
PWR_UP
));
// For nRF24L01+ to go from power down mode to TX or RX mode it must first pass through stand-by mode.
// There must be a delay of Tpd2stby (see Table 16.) after the nRF24L01+ leaves power down mode before
...
...
@@ -803,7 +803,7 @@ bool RF24::write( const void* buf, uint8_t len, const bool multicast )
while
(
!
(
get_status
()
&
(
_BV
(
TX_DS
)
|
_BV
(
MAX_RT
)
)))
{
#if defined (FAILURE_HANDLING) || defined (RF24_LINUX)
if
(
millis
()
-
timer
>
8
5
){
if
(
millis
()
-
timer
>
9
5
){
errNotify
();
#if defined (FAILURE_HANDLING)
return
0
;
...
...
@@ -849,7 +849,7 @@ bool RF24::writeBlocking( const void* buf, uint8_t len, uint32_t timeout )
if
(
millis
()
-
timer
>
timeout
){
return
0
;
}
//If this payload has exceeded the user-defined timeout, exit and return 0
}
#if defined (FAILURE_HANDLING) || defined (RF24_LINUX)
if
(
millis
()
-
timer
>
(
timeout
+
8
5
)
){
if
(
millis
()
-
timer
>
(
timeout
+
9
5
)
){
errNotify
();
#if defined (FAILURE_HANDLING)
return
0
;
...
...
@@ -896,7 +896,7 @@ bool RF24::writeFast( const void* buf, uint8_t len, const bool multicast )
//From the user perspective, if you get a 0, just keep trying to send the same payload
}
#if defined (FAILURE_HANDLING) || defined (RF24_LINUX)
if
(
millis
()
-
timer
>
8
5
){
if
(
millis
()
-
timer
>
9
5
){
errNotify
();
#if defined (FAILURE_HANDLING)
return
0
;
...
...
@@ -970,7 +970,7 @@ bool RF24::txStandBy(){
return
0
;
}
#if defined (FAILURE_HANDLING) || defined (RF24_LINUX)
if
(
millis
()
-
timeout
>
8
5
){
if
(
millis
()
-
timeout
>
9
5
){
errNotify
();
#if defined (FAILURE_HANDLING)
return
0
;
...
...
@@ -1003,7 +1003,7 @@ bool RF24::txStandBy(uint32_t timeout, bool startTx){
}
}
#if defined (FAILURE_HANDLING) || defined (RF24_LINUX)
if
(
millis
()
-
start
>
(
timeout
+
8
5
)){
if
(
millis
()
-
start
>
(
timeout
+
9
5
)){
errNotify
();
#if defined (FAILURE_HANDLING)
return
0
;
...
...
@@ -1022,7 +1022,12 @@ bool RF24::txStandBy(uint32_t timeout, bool startTx){
void
RF24
::
maskIRQ
(
bool
tx
,
bool
fail
,
bool
rx
){
write_register
(
CONFIG
,
(
read_register
(
CONFIG
)
)
|
fail
<<
MASK_MAX_RT
|
tx
<<
MASK_TX_DS
|
rx
<<
MASK_RX_DR
);
uint8_t
config
=
read_register
(
NRF_CONFIG
);
/* clear the interrupt flags */
config
&=
~
(
1
<<
MASK_MAX_RT
|
1
<<
MASK_TX_DS
|
1
<<
MASK_RX_DR
);
/* set the specified interrupt flags */
config
|=
fail
<<
MASK_MAX_RT
|
tx
<<
MASK_TX_DS
|
rx
<<
MASK_RX_DR
;
write_register
(
NRF_CONFIG
,
config
);
}
/****************************************************************************/
...
...
@@ -1474,7 +1479,7 @@ rf24_datarate_e RF24::getDataRate( void )
void
RF24
::
setCRCLength
(
rf24_crclength_e
length
)
{
uint8_t
config
=
read_register
(
CONFIG
)
&
~
(
_BV
(
CRCO
)
|
_BV
(
EN_CRC
))
;
uint8_t
config
=
read_register
(
NRF_
CONFIG
)
&
~
(
_BV
(
CRCO
)
|
_BV
(
EN_CRC
))
;
// switch uses RAM (evil!)
if
(
length
==
RF24_CRC_DISABLED
)
...
...
@@ -1490,7 +1495,7 @@ void RF24::setCRCLength(rf24_crclength_e length)
config
|=
_BV
(
EN_CRC
);
config
|=
_BV
(
CRCO
);
}
write_register
(
CONFIG
,
config
)
;
write_register
(
NRF_
CONFIG
,
config
)
;
}
/****************************************************************************/
...
...
@@ -1499,7 +1504,7 @@ rf24_crclength_e RF24::getCRCLength(void)
{
rf24_crclength_e
result
=
RF24_CRC_DISABLED
;
uint8_t
config
=
read_register
(
CONFIG
)
&
(
_BV
(
CRCO
)
|
_BV
(
EN_CRC
))
;
uint8_t
config
=
read_register
(
NRF_
CONFIG
)
&
(
_BV
(
CRCO
)
|
_BV
(
EN_CRC
))
;
uint8_t
AA
=
read_register
(
EN_AA
);
if
(
config
&
_BV
(
EN_CRC
)
||
AA
)
...
...
@@ -1517,8 +1522,8 @@ rf24_crclength_e RF24::getCRCLength(void)
void
RF24
::
disableCRC
(
void
)
{
uint8_t
disable
=
read_register
(
CONFIG
)
&
~
_BV
(
EN_CRC
)
;
write_register
(
CONFIG
,
disable
)
;
uint8_t
disable
=
read_register
(
NRF_
CONFIG
)
&
~
_BV
(
EN_CRC
)
;
write_register
(
NRF_
CONFIG
,
disable
)
;
}
/****************************************************************************/
...
...
@@ -1550,6 +1555,13 @@ void RF24::setRetries(uint8_t delay, uint8_t count)
# define DO 15 // PB6
# define USCK 16 // PB7
# define SS 13 // PB4
#elif defined(__AVR_ATtiny861__)
// these depend on the core used (check pins_arduino.h)
// tested with google-code core
# define DI 9 // PB0
# define DO 8 // PB1
# define USCK 7 // PB2
# define SS 6 // PB3
#endif
#if defined(RF24_TINY)
...
...
RF24_config.h
View file @
9e717722
...
...
@@ -38,8 +38,7 @@
#include "utility/includes.h"
//ATTiny
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny2313__) || defined(__AVR_ATtiny4313__)
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny2313__) || defined(__AVR_ATtiny4313__) || defined(__AVR_ATtiny861__)
#define RF24_TINY
#include "utility/ATTiny/RF24_arch_config.h"
...
...
examples/GettingStarted/GettingStarted.ino
View file @
9e717722
...
...
@@ -56,8 +56,8 @@ if (role == 1) {
Serial
.
println
(
F
(
"Now sending"
));
unsigned
long
time
=
micros
();
// Take the time, and send it. This will block until complete
if
(
!
radio
.
write
(
&
time
,
sizeof
(
unsigned
long
)
)){
unsigned
long
start_
time
=
micros
();
// Take the time, and send it. This will block until complete
if
(
!
radio
.
write
(
&
start_
time
,
sizeof
(
unsigned
long
)
)){
Serial
.
println
(
F
(
"failed"
));
}
...
...
@@ -78,15 +78,15 @@ if (role == 1) {
}
else
{
unsigned
long
got_time
;
// Grab the response, compare, and send to debugging spew
radio
.
read
(
&
got_time
,
sizeof
(
unsigned
long
)
);
unsigned
long
time
=
micros
();
unsigned
long
end_
time
=
micros
();
// Spew it
Serial
.
print
(
F
(
"Sent "
));
Serial
.
print
(
time
);
Serial
.
print
(
start_
time
);
Serial
.
print
(
F
(
", Got response "
));
Serial
.
print
(
got_time
);
Serial
.
print
(
F
(
", Round-trip delay "
));
Serial
.
print
(
time
-
go
t_time
);
Serial
.
print
(
end_time
-
star
t_time
);
Serial
.
println
(
F
(
" microseconds"
));
}
...
...
library.properties
View file @
9e717722
name
=
RF24
version
=
1.1.
5
version
=
1.1.
6
author
=
TMRh20
maintainer
=
TMRh20
sentence
=
A library for NRF24L01(+) communication.
...
...
nRF24L01.h
View file @
9e717722
...
...
@@ -24,7 +24,7 @@
*/
/* Memory Map */
#define CONFIG 0x00
#define
NRF_
CONFIG 0x00
#define EN_AA 0x01
#define EN_RXADDR 0x02
#define SETUP_AW 0x03
...
...
utility/BBB/gpio.cpp
View file @
9e717722
...
...
@@ -10,6 +10,8 @@
*/
#include "gpio.h"
#include <stdlib.h>
#include <unistd.h>
GPIO
::
GPIO
()
{
}
...
...
@@ -24,12 +26,24 @@ void GPIO::open(int port, int DDR)
fprintf
(
f
,
"%d
\n
"
,
port
);
fclose
(
f
);
char
file
[
128
];
sprintf
(
file
,
"/sys/class/gpio/gpio%d/direction"
,
port
);
f
=
fopen
(
file
,
"w"
);
if
(
DDR
==
0
)
fprintf
(
f
,
"in
\n
"
);
else
fprintf
(
f
,
"out
\n
"
);
fclose
(
f
);
int
counter
=
0
;
char
file
[
128
];
sprintf
(
file
,
"/sys/class/gpio/gpio%d/direction"
,
port
);
while
(
(
f
=
fopen
(
file
,
"w"
))
==
NULL
){
//Wait 10 seconds for the file to be accessible if not open on first attempt
sleep
(
1
);
counter
++
;
if
(
counter
>
10
){
perror
(
"Could not open /sys/class/gpio/gpio%d/direction"
);
exit
(
0
);
}
}
if
(
DDR
==
0
)
fprintf
(
f
,
"in
\n
"
);
else
fprintf
(
f
,
"out
\n
"
);
fclose
(
f
);
}
void
GPIO
::
close
(
int
port
)
...
...
utility/BBB/includes.h
View file @
9e717722
...
...
@@ -4,5 +4,6 @@
#define RF24_BBB
#include "BBB/RF24_arch_config.h"
#include "BBB/interrupt.h"
#endif
\ No newline at end of file
utility/BBB/interrupt.c
0 → 100644
View file @
9e717722
/*
Interrupts functions extruded from wiringPi library by Oitzu.
wiringPi Copyright (c) 2012 Gordon Henderson
https://projects.drogon.net/raspberry-pi/wiringpi
wiringPi is free software: GNU Lesser General Public License
see <http://www.gnu.org/licenses/>
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <sys/stat.h>
#include "interrupt.h"
#include <pthread.h>
//#define delay(x) bcm2835_delay(x)
static
pthread_mutex_t
pinMutex
=
PTHREAD_MUTEX_INITIALIZER
;
static
volatile
int
pinPass
=
-
1
;
pthread_t
threadId
[
64
];
// sysFds:
// Map a file descriptor from the /sys/class/gpio/gpioX/value
static
int
sysFds
[
64
]
=
{
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
}
;
// ISR Data
static
void
(
*
isrFunctions
[
64
])(
void
)
;
int
waitForInterrupt
(
int
pin
,
int
mS
)
{
int
fd
,
x
;
uint8_t
c
;
struct
pollfd
polls
;
if
((
fd
=
sysFds
[
pin
])
==
-
1
)
return
-
2
;
// Setup poll structure
polls
.
fd
=
fd
;
polls
.
events
=
POLLPRI
;
// Urgent data!
// Wait for it ...
x
=
poll
(
&
polls
,
1
,
mS
)
;
// Do a dummy read to clear the interrupt
// A one character read appars to be enough.
// Followed by a seek to reset it.
(
void
)
read
(
fd
,
&
c
,
1
)
;
lseek
(
fd
,
0
,
SEEK_SET
)
;
return
x
;
}
int
piHiPri
(
const
int
pri
)
{
struct
sched_param
sched
;
memset
(
&
sched
,
0
,
sizeof
(
sched
))
;
if
(
pri
>
sched_get_priority_max
(
SCHED_RR
))
sched
.
sched_priority
=
sched_get_priority_max
(
SCHED_RR
)
;
else
sched
.
sched_priority
=
pri
;
return
sched_setscheduler
(
0
,
SCHED_RR
,
&
sched
)
;
}
void
*
interruptHandler
(
void
*
arg
)
{
int
myPin
;
(
void
)
piHiPri
(
55
)
;
// Only effective if we run as root
myPin
=
pinPass
;
pinPass
=
-
1
;
for
(;;)
if
(
waitForInterrupt
(
myPin
,
-
1
)
>
0
){
pthread_mutex_lock
(
&
pinMutex
)
;
isrFunctions
[
myPin
]
()
;
pthread_mutex_unlock
(
&
pinMutex
)
;
pthread_testcancel
();
//Cancel at this point if we have an cancellation request.
}
return
NULL
;
}
int
attachInterrupt
(
int
pin
,
int
mode
,
void
(
*
function
)(
void
))
{
const
char
*
modeS
;
char
fName
[
64
]
;
char
pinS
[
8
]
;
pid_t
pid
;
int
count
,
i
;
char
c
;
int
bcmGpioPin
;
bcmGpioPin
=
pin
;
if
(
mode
!=
INT_EDGE_SETUP
)
{
/**/
if
(
mode
==
INT_EDGE_FALLING
)
modeS
=
"falling"
;
else
if
(
mode
==
INT_EDGE_RISING
)
modeS
=
"rising"
;
else
modeS
=
"both"
;
sprintf
(
pinS
,
"%d"
,
bcmGpioPin
)
;
if
((
pid
=
fork
())
<
0
)
// Fail
return
printf
(
"wiringPiISR: fork failed: %s
\n
"
,
strerror
(
errno
))
;
if
(
pid
==
0
)
// Child, exec
{
/**/
if
(
access
(
"/usr/local/bin/gpio"
,
X_OK
)
==
0
)
{
execl
(
"/usr/local/bin/gpio"
,
"gpio"
,
"edge"
,
pinS
,
modeS
,
(
char
*
)
NULL
)
;
return
printf
(
"wiringPiISR: execl failed: %s
\n
"
,
strerror
(
errno
))
;
}
else
if
(
access
(
"/usr/bin/gpio"
,
X_OK
)
==
0
)
{
execl
(
"/usr/bin/gpio"
,
"gpio"
,
"edge"
,
pinS
,
modeS
,
(
char
*
)
NULL
)
;
return
printf
(
"wiringPiISR: execl failed: %s
\n
"
,
strerror
(
errno
))
;
}
else
return
printf
(
"wiringPiISR: Can't find gpio program
\n
"
)
;
}
else
// Parent, wait
wait
(
NULL
)
;
}
if
(
sysFds
[
bcmGpioPin
]
==
-
1
)
{
sprintf
(
fName
,
"/sys/class/gpio/gpio%d/value"
,
bcmGpioPin
);
if
((
sysFds
[
bcmGpioPin
]
=
open
(
fName
,
O_RDWR
))
<
0
)
return
printf
(
"wiringPiISR: unable to open %s: %s
\n
"
,
fName
,
strerror
(
errno
))
;
}
ioctl
(
sysFds
[
bcmGpioPin
],
FIONREAD
,
&
count
)
;
for
(
i
=
0
;
i
<
count
;
++
i
)
read
(
sysFds
[
bcmGpioPin
],
&
c
,
1
)
;
isrFunctions
[
pin
]
=
function
;
pthread_mutex_lock
(
&
pinMutex
)
;
pinPass
=
pin
;
pthread_create
(
&
threadId
[
bcmGpioPin
],
NULL
,
interruptHandler
,
NULL
)
;
while
(
pinPass
!=
-
1
)
delay
(
1
)
;
pthread_mutex_unlock
(
&
pinMutex
)
;
return
0
;
}
int
detachInterrupt
(
int
pin
)
{
char
pinS
[
8
];
const
char
*
modeS
=
"none"
;
pid_t
pid
;
if
(
!
pthread_cancel
(
threadId
[
pin
]))
//Cancel the thread
{
return
0
;
}
if
(
!
close
(
sysFds
[
pin
]))
//Close filehandle
{
return
0
;
}
/* Set wiringPi to 'none' interrupt mode */
sprintf
(
pinS
,
"%d"
,
pin
)
;
if
((
pid
=
fork
())
<
0
)
// Fail
return
printf
(
"wiringPiISR: fork failed: %s
\n
"
,
strerror
(
errno
))
;
if
(
pid
==
0
)
// Child, exec
{
/**/
if
(
access
(
"/usr/local/bin/gpio"
,
X_OK
)
==
0
)
{
execl
(
"/usr/local/bin/gpio"
,
"gpio"
,
"edge"
,
pinS
,
modeS
,
(
char
*
)
NULL
)
;
return
printf
(
"wiringPiISR: execl failed: %s
\n
"
,
strerror
(
errno
))
;
}
else
if
(
access
(
"/usr/bin/gpio"
,
X_OK
)
==
0
)
{
execl
(
"/usr/bin/gpio"
,
"gpio"
,
"edge"
,
pinS
,
modeS
,
(
char
*
)
NULL
)
;
return
printf
(
"wiringPiISR: execl failed: %s
\n
"
,
strerror
(
errno
))
;
}
else
return
printf
(
"wiringPiISR: Can't find gpio program
\n
"
)
;
}
else
// Parent, wait
wait
(
NULL
)
;
return
1
;
}
void
rfNoInterrupts
(){
pthread_mutex_lock
(
&
pinMutex
)
;
}
void
rfInterrupts
(){
pthread_mutex_unlock
(
&
pinMutex
)
;
}
\ No newline at end of file
utility/BBB/interrupt.h
0 → 100644
View file @
9e717722
/*
Interrupts functions extruded from wiringPi library by Oitzu.
wiringPi Copyright (c) 2012 Gordon Henderson
https://projects.drogon.net/raspberry-pi/wiringpi
wiringPi is free software: GNU Lesser General Public License
see <http://www.gnu.org/licenses/>
*/
#include "RF24_arch_config.h"
#define INT_EDGE_SETUP 0
#define INT_EDGE_FALLING 1
#define INT_EDGE_RISING 2
#define INT_EDGE_BOTH 3
/*
* interruptHandler:
* This is a thread and gets started to wait for the interrupt we're
* hoping to catch. It will call the user-function when the interrupt
* fires.
*********************************************************************************
*/
void
*
interruptHandler
(
void
*
arg
);
#ifdef __cplusplus
extern
"C"
{
#endif
/*
* waitForInterrupt:
* Pi Specific.
* Wait for Interrupt on a GPIO pin.
* This is actually done via the /sys/class/gpio interface regardless of
* the wiringPi access mode in-use. Maybe sometime it might get a better
* way for a bit more efficiency.
*********************************************************************************
*/
extern
int
waitForInterrupt
(
int
pin
,
int
mS
);
/*
* piHiPri:
* Attempt to set a high priority schedulling for the running program
*********************************************************************************
*/
extern
int
piHiPri
(
const
int
pri
);
/*
* attachInterrupt (Original: wiringPiISR):
* Pi Specific.
* Take the details and create an interrupt handler that will do a call-
* back to the user supplied function.
*********************************************************************************
*/
extern
int
attachInterrupt
(
int
pin
,
int
mode
,
void
(
*
function
)(
void
));
/*
* detachInterrupt:
* Pi Specific detachInterrupt.
* Will cancel the interrupt thread, close the filehandle and
* setting wiringPi back to 'none' mode.
*********************************************************************************
*/
extern
int
detachInterrupt
(
int
pin
);
extern
void
rfNoInterrupts
();
extern
void
rfInterrupts
();
#ifdef __cplusplus
}
#endif
\ No newline at end of file
utility/BBB/spi.cpp
View file @
9e717722
...
...
@@ -10,8 +10,10 @@
#include "spi.h"
SPI
::
SPI
()
{
#include <pthread.h>
static
pthread_mutex_t
spiMutex
;
SPI
::
SPI
()
:
fd
(
-
1
)
{
}
void
SPI
::
begin
(
int
busNo
){
...
...
@@ -48,17 +50,16 @@ void SPI::init()
{
int
ret
;
if
(
this
->
fd
>
0
)
{
close
(
this
->
fd
);
if
(
this
->
fd
<
0
)
// check whether spi is already open
{
this
->
fd
=
open
(
this
->
device
.
c_str
(),
O_RDWR
);
if
(
this
->
fd
<
0
)
{
perror
(
"can't open device"
);
abort
();
}
}
this
->
fd
=
open
(
this
->
device
.
c_str
(),
O_RDWR
);
if
(
this
->
fd
<
0
)
{
perror
(
"can't open device"
);
abort
();
}
/*
* spi mode
...
...
@@ -113,6 +114,7 @@ void SPI::init()
uint8_t
SPI
::
transfer
(
uint8_t
tx_
)
{
pthread_mutex_lock
(
&
spiMutex
);
int
ret
;
uint8_t
tx
[
1
]
=
{
tx_
};
uint8_t
rx
[
1
];
...
...
@@ -124,10 +126,10 @@ uint8_t SPI::transfer(uint8_t tx_)
tr
.
len
=
1
,
//ARRAY_SIZE(tx),
tr
.
delay_usecs
=
0
,
tr
.
cs_change
=
1
,
tr
.
speed_hz
=
this
->
speed
,
tr
.
bits_per_word
=
this
->
bits
,
};
tr
.
speed_hz
=
this
->
speed
,
//Note: On RPi, for some reason I started getting 'bad message' errors, and changing the struct as below fixed it, until an update...??
//
/* // One byte is transfered at once
...
...
@@ -146,10 +148,12 @@ uint8_t SPI::transfer(uint8_t tx_)
ret
=
ioctl
(
this
->
fd
,
SPI_IOC_MESSAGE
(
1
),
&
tr
);
if
(
ret
<
1
)
{
pthread_mutex_unlock
(
&
spiMutex
);
perror
(
"can't send spi message"
);
abort
();
}
pthread_mutex_unlock
(
&
spiMutex
);
return
rx
[
0
];
}
...
...
@@ -157,6 +161,7 @@ uint8_t SPI::transfer(uint8_t tx_)
void
SPI
::
transfernb
(
char
*
tbuf
,
char
*
rbuf
,
uint32_t
len
)
{
pthread_mutex_lock
(
&
spiMutex
);
int
ret
;
this
->
init
();
struct
spi_ioc_transfer
tr
=
{
...
...
@@ -165,9 +170,9 @@ void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len)
tr
.
len
=
len
,
//ARRAY_SIZE(tx),
tr
.
cs_change
=
1
,
tr
.
delay_usecs
=
0
,
tr
.
speed_hz
=
this
->
speed
,
tr
.
bits_per_word
=
this
->
bits
,
};
tr
.
speed_hz
=
this
->
speed
,
//Note: On RPi, for some reason I started getting 'bad message' errors, and changing the struct as below fixed it, until an update...??
// One byte is transfered at once
...
...
@@ -187,10 +192,11 @@ void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len)
ret
=
ioctl
(
this
->
fd
,
SPI_IOC_MESSAGE
(
1
),
&
tr
);
if
(
ret
<
1
)
{
pthread_mutex_unlock
(
&
spiMutex
);
perror
(
"can't send spi message"
);
abort
();
}
pthread_mutex_unlock
(
&
spiMutex
);
//return rx[0];
}
...
...
@@ -201,6 +207,7 @@ void SPI::transfern(char* buf, uint32_t len)
SPI
::~
SPI
()
{
close
(
this
->
fd
);
if
(
!
(
this
->
fd
<
0
))
close
(
this
->
fd
);
}
utility/RPi/bcm2835.c
View file @
9e717722
...
...
@@ -18,6 +18,7 @@
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#define BCK2835_LIBRARY_BUILD
#include "bcm2835.h"
...
...
@@ -271,6 +272,13 @@ uint8_t bcm2835_gpio_eds(uint8_t pin)
return
(
value
&
(
1
<<
shift
))
?
HIGH
:
LOW
;
}
uint32_t
bcm2835_gpio_eds_multi
(
uint32_t
mask
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPEDS0
/
4
;
uint32_t
value
=
bcm2835_peri_read
(
paddr
);
return
(
value
&
mask
);
}
/* Write a 1 to clear the bit in EDS */
void
bcm2835_gpio_set_eds
(
uint8_t
pin
)
{
...
...
@@ -280,6 +288,12 @@ void bcm2835_gpio_set_eds(uint8_t pin)
bcm2835_peri_write
(
paddr
,
value
);
}
void
bcm2835_gpio_set_eds_multi
(
uint32_t
mask
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPEDS0
/
4
;
bcm2835_peri_write
(
paddr
,
mask
);
}
/* Rising edge detect enable */
void
bcm2835_gpio_ren
(
uint8_t
pin
)
{
...
...
@@ -396,16 +410,22 @@ void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on)
/* Read GPIO pad behaviour for groups of GPIOs */
uint32_t
bcm2835_gpio_pad
(
uint8_t
group
)
{
if
(
bcm2835_pads
==
MAP_FAILED
)
return
0
;
volatile
uint32_t
*
paddr
=
bcm2835_pads
+
BCM2835_PADS_GPIO_0_27
/
4
+
group
;
return
bcm2835_peri_read
(
paddr
);
}
/* Set GPIO pad behaviour for groups of GPIOs
// powerup value for al pads is
// powerup value for al
l
pads is
// BCM2835_PAD_SLEW_RATE_UNLIMITED | BCM2835_PAD_HYSTERESIS_ENABLED | BCM2835_PAD_DRIVE_8mA
*/
void
bcm2835_gpio_set_pad
(
uint8_t
group
,
uint32_t
control
)
{
if
(
bcm2835_pads
==
MAP_FAILED
)
return
;
volatile
uint32_t
*
paddr
=
bcm2835_pads
+
BCM2835_PADS_GPIO_0_27
/
4
+
group
;
bcm2835_peri_write
(
paddr
,
control
|
BCM2835_PAD_PASSWRD
);
}
...
...
@@ -520,10 +540,13 @@ void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud)
bcm2835_gpio_pudclk
(
pin
,
0
);
}
void
bcm2835_spi_begin
(
void
)
int
bcm2835_spi_begin
(
void
)
{
volatile
uint32_t
*
paddr
;
if
(
bcm2835_spi0
==
MAP_FAILED
)
return
0
;
/* bcm2835_init() failed, or not root */
/* Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them */
bcm2835_gpio_fsel
(
RPI_GPIO_P1_26
,
BCM2835_GPIO_FSEL_ALT0
);
/* CE1 */
bcm2835_gpio_fsel
(
RPI_GPIO_P1_24
,
BCM2835_GPIO_FSEL_ALT0
);
/* CE0 */
...
...
@@ -537,6 +560,8 @@ void bcm2835_spi_begin(void)
/* Clear TX and RX fifos */
bcm2835_peri_write_nb
(
paddr
,
BCM2835_SPI0_CS_CLEAR
);
return
1
;
// OK
}
void
bcm2835_spi_end
(
void
)
...
...
@@ -551,7 +576,7 @@ void bcm2835_spi_end(void)
void
bcm2835_spi_setBitOrder
(
uint8_t
__attribute__
((
unused
))
order
)
{
/* BCM2835_SPI_BIT_ORDER_MSBFIRST is the only one suported by SPI0 */
/* BCM2835_SPI_BIT_ORDER_MSBFIRST is the only one sup
p
orted by SPI0 */
}
/* defaults to 0, which means a divider of 65536.
...
...
@@ -718,10 +743,14 @@ void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active)
bcm2835_peri_set_bits
(
paddr
,
active
<<
shift
,
1
<<
shift
);
}
void
bcm2835_i2c_begin
(
void
)
int
bcm2835_i2c_begin
(
void
)
{
uint16_t
cdiv
;
if
(
bcm2835_bsc0
==
MAP_FAILED
||
bcm2835_bsc1
==
MAP_FAILED
)
return
0
;
/* bcm2835_init() failed, or not root */
#ifdef I2C_V1
volatile
uint32_t
*
paddr
=
bcm2835_bsc0
+
BCM2835_BSC_DIV
/
4
;
/* Set the I2C/BSC0 pins to the Alt 0 function to enable I2C access on them */
...
...
@@ -741,6 +770,8 @@ void bcm2835_i2c_begin(void)
// 9 = Clocks per byte : 8 bits + ACK
*/
i2c_byte_wait_us
=
((
float
)
cdiv
/
BCM2835_CORE_CLK_HZ
)
*
1000000
*
9
;
return
1
;
}
void
bcm2835_i2c_end
(
void
)
...
...
@@ -1177,6 +1208,10 @@ void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros)
void
bcm2835_pwm_set_clock
(
uint32_t
divisor
)
{
if
(
bcm2835_clk
==
MAP_FAILED
||
bcm2835_pwm
==
MAP_FAILED
)
return
;
/* bcm2835_init() failed or not root */
/* From Gerts code */
divisor
&=
0xfff
;
/* Stop PWM clock */
...
...
@@ -1192,6 +1227,10 @@ void bcm2835_pwm_set_clock(uint32_t divisor)
void
bcm2835_pwm_set_mode
(
uint8_t
channel
,
uint8_t
markspace
,
uint8_t
enabled
)
{
if
(
bcm2835_clk
==
MAP_FAILED
||
bcm2835_pwm
==
MAP_FAILED
)
return
;
/* bcm2835_init() failed or not root */
uint32_t
control
=
bcm2835_peri_read
(
bcm2835_pwm
+
BCM2835_PWM_CONTROL
);
if
(
channel
==
0
)
...
...
@@ -1225,6 +1264,10 @@ void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled)
void
bcm2835_pwm_set_range
(
uint8_t
channel
,
uint32_t
range
)
{
if
(
bcm2835_clk
==
MAP_FAILED
||
bcm2835_pwm
==
MAP_FAILED
)
return
;
/* bcm2835_init() failed or not root */
if
(
channel
==
0
)
bcm2835_peri_write_nb
(
bcm2835_pwm
+
BCM2835_PWM0_RANGE
,
range
);
else
if
(
channel
==
1
)
...
...
@@ -1233,6 +1276,10 @@ void bcm2835_pwm_set_range(uint8_t channel, uint32_t range)
void
bcm2835_pwm_set_data
(
uint8_t
channel
,
uint32_t
data
)
{
if
(
bcm2835_clk
==
MAP_FAILED
||
bcm2835_pwm
==
MAP_FAILED
)
return
;
/* bcm2835_init() failed or not root */
if
(
channel
==
0
)
bcm2835_peri_write_nb
(
bcm2835_pwm
+
BCM2835_PWM0_DATA
,
data
);
else
if
(
channel
==
1
)
...
...
@@ -1304,35 +1351,60 @@ int bcm2835_init(void)
}
/* else we are prob on RPi 1 with BCM2835, and use the hardwired defaults */
/* Now get ready to map the peripherals block */
/* Now get ready to map the peripherals block
* If we are not root, try for the new /dev/gpiomem interface and accept
* the fact that we can only access GPIO
* else try for the /dev/mem interface and get access to everything
*/
memfd
=
-
1
;
ok
=
0
;
/* Open the master /dev/memory device */
if
((
memfd
=
open
(
"/dev/mem"
,
O_RDWR
|
O_SYNC
)
)
<
0
)
if
(
geteuid
()
==
0
)
{
fprintf
(
stderr
,
"bcm2835_init: Unable to open /dev/mem: %s
\n
"
,
strerror
(
errno
))
;
goto
exit
;
/* Open the master /dev/mem device */
if
((
memfd
=
open
(
"/dev/mem"
,
O_RDWR
|
O_SYNC
)
)
<
0
)
{
fprintf
(
stderr
,
"bcm2835_init: Unable to open /dev/mem: %s
\n
"
,
strerror
(
errno
))
;
goto
exit
;
}
/* Base of the peripherals block is mapped to VM */
bcm2835_peripherals
=
mapmem
(
"gpio"
,
bcm2835_peripherals_size
,
memfd
,
(
uint32_t
)
bcm2835_peripherals_base
);
if
(
bcm2835_peripherals
==
MAP_FAILED
)
goto
exit
;
/* Now compute the base addresses of various peripherals,
// which are at fixed offsets within the mapped peripherals block
// Caution: bcm2835_peripherals is uint32_t*, so divide offsets by 4
*/
bcm2835_gpio
=
bcm2835_peripherals
+
BCM2835_GPIO_BASE
/
4
;
bcm2835_pwm
=
bcm2835_peripherals
+
BCM2835_GPIO_PWM
/
4
;
bcm2835_clk
=
bcm2835_peripherals
+
BCM2835_CLOCK_BASE
/
4
;
bcm2835_pads
=
bcm2835_peripherals
+
BCM2835_GPIO_PADS
/
4
;
bcm2835_spi0
=
bcm2835_peripherals
+
BCM2835_SPI0_BASE
/
4
;
bcm2835_bsc0
=
bcm2835_peripherals
+
BCM2835_BSC0_BASE
/
4
;
/* I2C */
bcm2835_bsc1
=
bcm2835_peripherals
+
BCM2835_BSC1_BASE
/
4
;
/* I2C */
bcm2835_st
=
bcm2835_peripherals
+
BCM2835_ST_BASE
/
4
;
ok
=
1
;
}
else
{
/* Not root, try /dev/gpiomem */
/* Open the master /dev/mem device */
if
((
memfd
=
open
(
"/dev/gpiomem"
,
O_RDWR
|
O_SYNC
)
)
<
0
)
{
fprintf
(
stderr
,
"bcm2835_init: Unable to open /dev/gpiomem: %s
\n
"
,
strerror
(
errno
))
;
goto
exit
;
}
/* Base of the peripherals block is mapped to VM */
bcm2835_peripherals_base
=
0
;
bcm2835_peripherals
=
mapmem
(
"gpio"
,
bcm2835_peripherals_size
,
memfd
,
(
uint32_t
)
bcm2835_peripherals_base
);
if
(
bcm2835_peripherals
==
MAP_FAILED
)
goto
exit
;
bcm2835_gpio
=
bcm2835_peripherals
;
ok
=
1
;
}
/* Base of the peripherals block is mapped to VM */
bcm2835_peripherals
=
mapmem
(
"gpio"
,
bcm2835_peripherals_size
,
memfd
,
(
uint32_t
)
bcm2835_peripherals_base
);
if
(
bcm2835_peripherals
==
MAP_FAILED
)
goto
exit
;
/* Now compute the base addresses of various peripherals,
// which are at fixed offsets within the mapped peripherals block
// Caution: bcm2835_peripherals is uint32_t*, so divide offsets by 4
*/
bcm2835_gpio
=
bcm2835_peripherals
+
BCM2835_GPIO_BASE
/
4
;
bcm2835_pwm
=
bcm2835_peripherals
+
BCM2835_GPIO_PWM
/
4
;
bcm2835_clk
=
bcm2835_peripherals
+
BCM2835_CLOCK_BASE
/
4
;
bcm2835_pads
=
bcm2835_peripherals
+
BCM2835_GPIO_PADS
/
4
;
bcm2835_spi0
=
bcm2835_peripherals
+
BCM2835_SPI0_BASE
/
4
;
bcm2835_bsc0
=
bcm2835_peripherals
+
BCM2835_BSC0_BASE
/
4
;
/* I2C */
bcm2835_bsc1
=
bcm2835_peripherals
+
BCM2835_BSC1_BASE
/
4
;
/* I2C */
bcm2835_st
=
bcm2835_peripherals
+
BCM2835_ST_BASE
/
4
;
ok
=
1
;
exit:
if
(
memfd
>=
0
)
...
...
utility/RPi/bcm2835.h
View file @
9e717722
...
...
@@ -23,7 +23,7 @@
BCM 2835).
The version of the package that this documentation refers to can be downloaded
from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.
48
.tar.gz
from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.
50
.tar.gz
You can find the latest version at http://www.airspayce.com/mikem/bcm2835
Several example programs are provided.
...
...
@@ -38,7 +38,7 @@
Before asking a question or reporting a bug, please read http://www.catb.org/esr/faqs/smart-questions.html
Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian
and Occidentalisv01
and Occidentalisv01
, 2016-02-09 Raspbian Jessie.
CAUTION: it has been observed that when detect enables such as bcm2835_gpio_len()
are used and the pin is pulled LOW
it can cause temporary hangs on 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian
...
...
@@ -48,6 +48,24 @@
If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with
bcm2835_gpio_clr_len() and friends after use.
\par Running as root
Prior to the release of Raspbian Jessie in Feb 2016, access to any
peripheral device via /dev/mem on the RPi required the process to
run as root. Raspbian Jessie permits non-root users to access the
GPIO peripheral (only) via /dev/gpiomem, and this library supports
that limited mode of operation.
If the library runs with effective UID of 0 (ie root), then
bcm2835_init() will attempt to open /dev/mem, and, if successful, it
will permit use of all peripherals and library functions.
If the library runs with any other effective UID (ie not root), then
bcm2835_init() will attempt to open /dev/gpiomem, and, if
successful, will only permit GPIO operations. In particular,
bcm2835_spi_begin() and bcm2835_i2c_begin() will return false and all
other non-gpio operations may fail silently or crash.
\par Installation
This library consists of a single non-shared library and header file, which will be
...
...
@@ -421,6 +439,15 @@
Added patch from Eckhardt Ulrich that fixed problems that could cause hanging with bcm2835_i2c_read_register_rs
and others.
\version 1.49 2016-01-05
Added patch from Jonathan Perkin with new functions bcm2835_gpio_eds_multi() and bcm2835_gpio_set_eds_multi().
\version 1.50 2016-02-28
Added support for running as non-root, permitting access to GPIO only. Functions
bcm2835_spi_begin() and bcm2835_i2c_begin() will now return 0 if not running as root
(which prevents access to the SPI and I2C peripherals, amongst others).
Testing on Raspbian Jessie.
\author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS
*/
...
...
@@ -431,7 +458,7 @@
#include <stdint.h>
#define BCM2835_VERSION 100
48
/* Version 1.48
*/
#define BCM2835_VERSION 100
50
/* Version 1.50
*/
/* RPi 2 is ARM v7, and has DMB instruction for memory barriers.
Older RPis are ARM v6 and don't, so a coprocessor instruction must be used instead.
...
...
@@ -503,7 +530,7 @@ extern uint32_t bcm2835_peripherals_size;
extern
uint32_t
*
bcm2835_peripherals
;
/*! Base of the ST (System Timer) registers.
Available after bcm2835_init has been called
Available after bcm2835_init has been called
(as root)
*/
extern
volatile
uint32_t
*
bcm2835_st
;
...
...
@@ -513,32 +540,32 @@ extern volatile uint32_t *bcm2835_st;
extern
volatile
uint32_t
*
bcm2835_gpio
;
/*! Base of the PWM registers.
Available after bcm2835_init has been called
Available after bcm2835_init has been called
(as root)
*/
extern
volatile
uint32_t
*
bcm2835_pwm
;
/*! Base of the CLK registers.
Available after bcm2835_init has been called
Available after bcm2835_init has been called
(as root)
*/
extern
volatile
uint32_t
*
bcm2835_clk
;
/*! Base of the PADS registers.
Available after bcm2835_init has been called
Available after bcm2835_init has been called
(as root)
*/
extern
volatile
uint32_t
*
bcm2835_pads
;
/*! Base of the SPI0 registers.
Available after bcm2835_init has been called
Available after bcm2835_init has been called
(as root)
*/
extern
volatile
uint32_t
*
bcm2835_spi0
;
/*! Base of the BSC0 registers.
Available after bcm2835_init has been called
Available after bcm2835_init has been called
(as root)
*/
extern
volatile
uint32_t
*
bcm2835_bsc0
;
/*! Base of the BSC1 registers.
Available after bcm2835_init has been called
Available after bcm2835_init has been called
(as root)
*/
extern
volatile
uint32_t
*
bcm2835_bsc1
;
...
...
@@ -552,7 +579,7 @@ typedef enum
BCM2835_REGBASE_PWM
=
3
,
/*!< Base of the PWM registers. */
BCM2835_REGBASE_CLK
=
4
,
/*!< Base of the CLK registers. */
BCM2835_REGBASE_PADS
=
5
,
/*!< Base of the PADS registers. */
BCM2835_REGBASE_SPI0
=
6
,
/*! Base of the SPI0 registers. */
BCM2835_REGBASE_SPI0
=
6
,
/*!
<
Base of the SPI0 registers. */
BCM2835_REGBASE_BSC0
=
7
,
/*!< Base of the BSC0 registers. */
BCM2835_REGBASE_BSC1
=
8
/*!< Base of the BSC1 registers. */
}
bcm2835RegisterBase
;
...
...
@@ -826,7 +853,7 @@ typedef enum
Figures below give the divider, clock period and clock frequency.
Clock divided is based on nominal base clock rate of 250MHz
It is reported that (contrary to the documentation) any even divider may used.
The frequencies shown for each divider have been confirmed by measurement
The frequencies shown for each divider have been confirmed by measurement
.
*/
typedef
enum
{
...
...
@@ -1015,12 +1042,16 @@ extern "C" {
@{
*/
/*! Initialise the library by opening /dev/mem and getting pointers to the
/*! Initialise the library by opening /dev/mem (if you are root)
or /dev/gpiomem (if you are not)
and getting pointers to the
internal memory for BCM 2835 device registers. You must call this (successfully)
before calling any other
functions in this library (except bcm2835_set_debug).
If bcm2835_init() fails by returning 0,
calling any other function may result in crashes or other failures.
If bcm2835_init() succeeds but you are not running as root, then only gpio operations
are permitted, and calling any other functions may result in crashes or other failures. .
Prints messages to stderr in case of errors.
\return 1 if successful else 0
*/
...
...
@@ -1186,6 +1217,13 @@ extern "C" {
*/
extern
uint8_t
bcm2835_gpio_eds
(
uint8_t
pin
);
/*! Same as bcm2835_gpio_eds() but checks if any of the pins specified in
the mask have detected a level or edge.
\param[in] mask Mask of pins to check. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05)
\return Mask of pins HIGH if the event detect status for the given pin is true.
*/
extern
uint32_t
bcm2835_gpio_eds_multi
(
uint32_t
mask
);
/*! Sets the Event Detect Status register for a given pin to 1,
which has the effect of clearing the flag. Use this afer seeing
an Event Detect Status on the pin.
...
...
@@ -1193,6 +1231,12 @@ extern "C" {
*/
extern
void
bcm2835_gpio_set_eds
(
uint8_t
pin
);
/*! Same as bcm2835_gpio_set_eds() but clears the flag for any pin which
is set in the mask.
\param[in] mask Mask of pins to clear. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05)
*/
extern
void
bcm2835_gpio_set_eds_multi
(
uint32_t
mask
);
/*! Enable Rising Edge Detect Enable for the specified pin.
When a rising edge is detected, sets the appropriate pin in Event Detect Status.
The GPRENn registers use
...
...
@@ -1370,10 +1414,11 @@ extern "C" {
Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1)
to alternate function ALT0, which enables those pins for SPI interface.
You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to
their default functions
their default functions
.
\sa bcm2835_spi_end()
\return 1 if successful, 0 otherwise (perhaps because you are not running as root)
*/
extern
void
bcm2835_spi_begin
(
void
);
extern
int
bcm2835_spi_begin
(
void
);
/*! End SPI operations.
SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1)
...
...
@@ -1476,9 +1521,10 @@ extern "C" {
to alternate function ALT0, which enables those pins for I2C interface.
You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to
their default functions
\return 1 if successful, 0 otherwise (perhaps because you are not running as root)
\sa bcm2835_i2c_end()
*/
extern
void
bcm2835_i2c_begin
(
void
);
extern
int
bcm2835_i2c_begin
(
void
);
/*! End I2C operations.
I2C pins P1-03 (SDA) and P1-05 (SCL)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment