Skip to content

Commit b6d0897

Browse files
committed
[avr] Made SPI.begin() and SPI.end() synchronized (Andrew Kroll)
1 parent 2ef946f commit b6d0897

File tree

2 files changed

+38
-21
lines changed

2 files changed

+38
-21
lines changed

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

Lines changed: 36 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
@@ -20,32 +21,47 @@ uint8_t SPIClass::interruptSave = 0;
2021

2122
void SPIClass::begin()
2223
{
23-
// Set SS to high so a connected chip will be "deselected" by default
24-
digitalWrite(SS, HIGH);
24+
uint8_t sreg = SREG;
25+
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
26+
if (!modeFlags.initialized) {
27+
modeFlags.initialized = true;
28+
// Set SS to high so a connected chip will be "deselected" by default
29+
digitalWrite(SS, HIGH);
2530

26-
// When the SS pin is set as OUTPUT, it can be used as
27-
// a general purpose output port (it doesn't influence
28-
// SPI operations).
29-
pinMode(SS, OUTPUT);
31+
// When the SS pin is set as OUTPUT, it can be used as
32+
// a general purpose output port (it doesn't influence
33+
// SPI operations).
34+
pinMode(SS, OUTPUT);
3035

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

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

4754
void SPIClass::end() {
48-
SPCR &= ~_BV(SPE);
55+
uint8_t sreg = SREG;
56+
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
57+
if (!modeFlags.interruptMode && modeFlags.initialized) {
58+
SPCR &= ~_BV(SPE);
59+
modeFlags.initialized = false;
60+
#ifdef SPI_TRANSACTION_MISMATCH_LED
61+
modeFlags.inTransaction = false;
62+
#endif
63+
}
64+
SREG = sreg;
4965
}
5066

5167
// mapping of interrupt numbers to bits within SPI_AVR_EIMSK

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

Lines changed: 2 additions & 1 deletion
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
@@ -52,7 +53,7 @@
5253
// Flags for the state of SPI, used as needed.
5354
// Normally inTransaction is not used.
5455
typedef struct SPIflags {
55-
bool padding : 1;
56+
bool initialized : 1; // tells us that begin() was called
5657
bool inTransaction : 1;
5758
uint8_t interruptMode : 6; // 0=none, 1=mask, 2=global (more can be added)
5859
} __attribute__((packed)) SPIflags_t;

0 commit comments

Comments
 (0)