Commit 243e25f2 authored by TMRh20's avatar TMRh20

Mutex handling for interrupts on RPi

- Create separate mutex for SPI vs User data handling
Problems:
A: Memory/Data conflicts became apparent after time without thread-safe
queues
B: Without implementing locking at the SPI level, even simple code
examples (rx_transfer.cpp) would hang if a write was done out of sync
with reads

Solutions:
A: Keep initial locking mechanism for users
B: Implement separate automatic mutex and locking mechanism for SPI

#172 #173
parent 715edc5e
......@@ -24,6 +24,7 @@ see <http://www.gnu.org/licenses/>
#define delay(x) bcm2835_delay(x)
static pthread_mutex_t pinMutex ;
static pthread_mutex_t spiMutex ;
static volatile int pinPass = -1 ;
// sysFds:
// Map a file descriptor from the /sys/class/gpio/gpioX/value
......@@ -92,8 +93,11 @@ void *interruptHandler (void *arg)
pinPass = -1 ;
for (;;)
if (waitForInterrupt (myPin, -1) > 0)
if (waitForInterrupt (myPin, -1) > 0){
pthread_mutex_lock (&pinMutex) ;
isrFunctions [myPin] () ;
pthread_mutex_unlock (&pinMutex) ;
}
return NULL ;
}
......@@ -176,3 +180,12 @@ void rfInterrupts(){
pthread_mutex_unlock (&pinMutex) ;
}
void spiNoInterrupts(){
pthread_mutex_lock (&spiMutex) ;
}
void spiInterrupts(){
pthread_mutex_unlock (&spiMutex) ;
}
......@@ -54,6 +54,8 @@ extern int piHiPri (const int pri);
extern int attachInterrupt (int pin, int mode, void (*function)(void));
extern void rfNoInterrupts();
extern void rfInterrupts();
extern void spiNoInterrupts();
extern void spiInterrupts();
#ifdef __cplusplus
}
#endif
\ No newline at end of file
......@@ -8,14 +8,13 @@ SPI::SPI() {
void SPI::begin( int busNo ) {
rfNoInterrupts();
spiNoInterrupts();
if (!bcm2835_init()){
return;
}
bcm2835_spi_begin();
rfInterrupts();
spiInterrupts();
}
void SPI::end() {
......@@ -23,27 +22,27 @@ void SPI::end() {
}
void SPI::setBitOrder(uint8_t bit_order) {
rfNoInterrupts();
spiNoInterrupts();
bcm2835_spi_setBitOrder(bit_order);
rfInterrupts();
spiInterrupts();
}
void SPI::setDataMode(uint8_t data_mode) {
rfNoInterrupts();
spiNoInterrupts();
bcm2835_spi_setDataMode(data_mode);
rfInterrupts();
spiInterrupts();
}
void SPI::setClockDivider(uint16_t spi_speed) {
rfNoInterrupts();
spiNoInterrupts();
bcm2835_spi_setClockDivider(spi_speed);
rfInterrupts();
spiInterrupts();
}
void SPI::chipSelect(int csn_pin){
rfNoInterrupts();
spiNoInterrupts();
bcm2835_spi_chipSelect(csn_pin);
rfInterrupts();
spiInterrupts();
}
SPI::~SPI() {
......
......@@ -14,6 +14,7 @@
#include "bcm2835.h"
#include "interrupt.h"
class SPI {
public:
......@@ -35,23 +36,23 @@ public:
uint8_t SPI::transfer(uint8_t _data) {
rfNoInterrupts();
spiNoInterrupts();
uint8_t data = bcm2835_spi_transfer(_data);
rfInterrupts();
spiInterrupts();
return data;
}
void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len){
rfNoInterrupts();
spiNoInterrupts();
bcm2835_spi_transfernb( tbuf, rbuf, len);
rfInterrupts();
spiInterrupts();
}
void SPI::transfern(char* buf, uint32_t len)
{
rfNoInterrupts();
spiNoInterrupts();
transfernb(buf, buf, len);
rfInterrupts();
spiInterrupts();
}
/**
* \endcond
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment