2
2
* Copyright (c) 2010 by Cristian Maglie <[email protected] >
3
3
* Copyright (c) 2014 by Paul Stoffregen <[email protected] > (Transaction API)
4
4
* Copyright (c) 2014 by Matthijs Kooijman <[email protected] > (SPISettings AVR)
5
+ * Copyright (c) 2014 by Andrew J. Kroll <[email protected] > (atomicity fixes)
5
6
* SPI Master library for arduino.
6
7
*
7
8
* This file is free software; you can redistribute it and/or modify
14
15
15
16
SPIClass SPI;
16
17
18
+ uint8_t SPIClass::initialized = 0 ;
17
19
uint8_t SPIClass::interruptMode = 0 ;
18
20
uint8_t SPIClass::interruptMask = 0 ;
19
21
uint8_t SPIClass::interruptSave = 0 ;
@@ -23,32 +25,51 @@ uint8_t SPIClass::inTransactionFlag = 0;
23
25
24
26
void SPIClass::begin ()
25
27
{
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);
28
33
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);
33
38
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);
39
44
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;
48
56
}
49
57
50
58
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;
52
73
}
53
74
54
75
// mapping of interrupt numbers to bits within SPI_AVR_EIMSK
0 commit comments