22 * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
33 * Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
44 * Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
5+ * Copyright (c) 2014 by Andrew J. Kroll <xxxajk@gmail.com> (atomicity fixes)
56 * SPI Master library for arduino.
67 *
78 * This file is free software; you can redistribute it and/or modify
1415
1516SPIClass SPI;
1617
18+ uint8_t SPIClass::initialized = 0 ;
1719uint8_t SPIClass::interruptMode = 0 ;
1820uint8_t SPIClass::interruptMask = 0 ;
1921uint8_t SPIClass::interruptSave = 0 ;
@@ -23,32 +25,51 @@ uint8_t SPIClass::inTransactionFlag = 0;
2325
2426void 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
5058void 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
0 commit comments