Skip to content

Commit 8344812

Browse files
committed
[avr] Made SPI.begin() and SPI.end() synchronized (Andrew Kroll)
1 parent 53e25d8 commit 8344812

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

hardware/arduino/avr/libraries/SPI/SPI.cpp

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Copyright (c) 2010 by Cristian Maglie <[email protected]>
33
* Copyright (c) 2014 by Paul Stoffregen <[email protected]> (Transaction API)
44
* Copyright (c) 2014 by Matthijs Kooijman <[email protected]> (SPISettings AVR)
5+
* Copyright (c) 2014 by Andrew J. Kroll <[email protected]> (atomicity fixes)
56
* SPI Master library for arduino.
67
*
78
* This file is free software; you can redistribute it and/or modify
@@ -14,6 +15,7 @@
1415

1516
SPIClass SPI;
1617

18+
uint8_t SPIClass::initialized = 0;
1719
uint8_t SPIClass::interruptMode = 0;
1820
uint8_t SPIClass::interruptMask = 0;
1921
uint8_t SPIClass::interruptSave = 0;
@@ -23,32 +25,51 @@ uint8_t SPIClass::inTransactionFlag = 0;
2325

2426
void SPIClass::begin()
2527
{
26-
// Set SS to high so a connected chip will be "deselected" by default
27-
digitalWrite(SS, HIGH);
28+
uint8_t sreg = SREG;
29+
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
30+
if (!initialized) {
31+
// Set SS to high so a connected chip will be "deselected" by default
32+
digitalWrite(SS, HIGH);
2833

29-
// When the SS pin is set as OUTPUT, it can be used as
30-
// a general purpose output port (it doesn't influence
31-
// SPI operations).
32-
pinMode(SS, OUTPUT);
34+
// When the SS pin is set as OUTPUT, it can be used as
35+
// a general purpose output port (it doesn't influence
36+
// SPI operations).
37+
pinMode(SS, OUTPUT);
3338

34-
// Warning: if the SS pin ever becomes a LOW INPUT then SPI
35-
// automatically switches to Slave, so the data direction of
36-
// the SS pin MUST be kept as OUTPUT.
37-
SPCR |= _BV(MSTR);
38-
SPCR |= _BV(SPE);
39+
// Warning: if the SS pin ever becomes a LOW INPUT then SPI
40+
// automatically switches to Slave, so the data direction of
41+
// the SS pin MUST be kept as OUTPUT.
42+
SPCR |= _BV(MSTR);
43+
SPCR |= _BV(SPE);
3944

40-
// Set direction register for SCK and MOSI pin.
41-
// MISO pin automatically overrides to INPUT.
42-
// By doing this AFTER enabling SPI, we avoid accidentally
43-
// clocking in a single bit since the lines go directly
44-
// from "input" to SPI control.
45-
// http://code.google.com/p/arduino/issues/detail?id=888
46-
pinMode(SCK, OUTPUT);
47-
pinMode(MOSI, OUTPUT);
45+
// Set direction register for SCK and MOSI pin.
46+
// MISO pin automatically overrides to INPUT.
47+
// By doing this AFTER enabling SPI, we avoid accidentally
48+
// clocking in a single bit since the lines go directly
49+
// from "input" to SPI control.
50+
// http://code.google.com/p/arduino/issues/detail?id=888
51+
pinMode(SCK, OUTPUT);
52+
pinMode(MOSI, OUTPUT);
53+
}
54+
initialized++; // reference count
55+
SREG = sreg;
4856
}
4957

5058
void SPIClass::end() {
51-
SPCR &= ~_BV(SPE);
59+
uint8_t sreg = SREG;
60+
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
61+
// Decrease the reference counter
62+
if (initialized)
63+
initialized--;
64+
// If there are no more references disable SPI
65+
if (!initialized) {
66+
SPCR &= ~_BV(SPE);
67+
interruptMode = 0;
68+
#ifdef SPI_TRANSACTION_MISMATCH_LED
69+
inTransactionFlag = 0;
70+
#endif
71+
}
72+
SREG = sreg;
5273
}
5374

5475
// mapping of interrupt numbers to bits within SPI_AVR_EIMSK

hardware/arduino/avr/libraries/SPI/SPI.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Copyright (c) 2010 by Cristian Maglie <[email protected]>
33
* Copyright (c) 2014 by Paul Stoffregen <[email protected]> (Transaction API)
44
* Copyright (c) 2014 by Matthijs Kooijman <[email protected]> (SPISettings AVR)
5+
* Copyright (c) 2014 by Andrew J. Kroll <[email protected]> (atomicity fixes)
56
* SPI Master library for arduino.
67
*
78
* This file is free software; you can redistribute it and/or modify
@@ -281,6 +282,7 @@ class SPIClass {
281282
inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); }
282283

283284
private:
285+
static uint8_t initialized;
284286
static uint8_t interruptMode; // 0=none, 1=mask, 2=global
285287
static uint8_t interruptMask; // which interrupts to mask
286288
static uint8_t interruptSave; // temp storage, to restore state

0 commit comments

Comments
 (0)