mirror of
https://github.com/arduino/Arduino.git
synced 2025-01-30 19:52:13 +01:00
[avr] Made SPI.begin() and SPI.end() synchronized (Andrew Kroll)
This commit is contained in:
parent
53e25d8b55
commit
8344812ce8
@ -2,6 +2,7 @@
|
|||||||
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
||||||
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
|
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
|
||||||
* Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
|
* Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
|
||||||
|
* Copyright (c) 2014 by Andrew J. Kroll <xxxajk@gmail.com> (atomicity fixes)
|
||||||
* SPI Master library for arduino.
|
* SPI Master library for arduino.
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* This file is free software; you can redistribute it and/or modify
|
||||||
@ -14,6 +15,7 @@
|
|||||||
|
|
||||||
SPIClass SPI;
|
SPIClass SPI;
|
||||||
|
|
||||||
|
uint8_t SPIClass::initialized = 0;
|
||||||
uint8_t SPIClass::interruptMode = 0;
|
uint8_t SPIClass::interruptMode = 0;
|
||||||
uint8_t SPIClass::interruptMask = 0;
|
uint8_t SPIClass::interruptMask = 0;
|
||||||
uint8_t SPIClass::interruptSave = 0;
|
uint8_t SPIClass::interruptSave = 0;
|
||||||
@ -23,32 +25,51 @@ uint8_t SPIClass::inTransactionFlag = 0;
|
|||||||
|
|
||||||
void SPIClass::begin()
|
void SPIClass::begin()
|
||||||
{
|
{
|
||||||
// Set SS to high so a connected chip will be "deselected" by default
|
uint8_t sreg = SREG;
|
||||||
digitalWrite(SS, HIGH);
|
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
|
||||||
|
if (!initialized) {
|
||||||
|
// Set SS to high so a connected chip will be "deselected" by default
|
||||||
|
digitalWrite(SS, HIGH);
|
||||||
|
|
||||||
// When the SS pin is set as OUTPUT, it can be used as
|
// When the SS pin is set as OUTPUT, it can be used as
|
||||||
// a general purpose output port (it doesn't influence
|
// a general purpose output port (it doesn't influence
|
||||||
// SPI operations).
|
// SPI operations).
|
||||||
pinMode(SS, OUTPUT);
|
pinMode(SS, OUTPUT);
|
||||||
|
|
||||||
// Warning: if the SS pin ever becomes a LOW INPUT then SPI
|
// Warning: if the SS pin ever becomes a LOW INPUT then SPI
|
||||||
// automatically switches to Slave, so the data direction of
|
// automatically switches to Slave, so the data direction of
|
||||||
// the SS pin MUST be kept as OUTPUT.
|
// the SS pin MUST be kept as OUTPUT.
|
||||||
SPCR |= _BV(MSTR);
|
SPCR |= _BV(MSTR);
|
||||||
SPCR |= _BV(SPE);
|
SPCR |= _BV(SPE);
|
||||||
|
|
||||||
// Set direction register for SCK and MOSI pin.
|
// Set direction register for SCK and MOSI pin.
|
||||||
// MISO pin automatically overrides to INPUT.
|
// MISO pin automatically overrides to INPUT.
|
||||||
// By doing this AFTER enabling SPI, we avoid accidentally
|
// By doing this AFTER enabling SPI, we avoid accidentally
|
||||||
// clocking in a single bit since the lines go directly
|
// clocking in a single bit since the lines go directly
|
||||||
// from "input" to SPI control.
|
// from "input" to SPI control.
|
||||||
// http://code.google.com/p/arduino/issues/detail?id=888
|
// http://code.google.com/p/arduino/issues/detail?id=888
|
||||||
pinMode(SCK, OUTPUT);
|
pinMode(SCK, OUTPUT);
|
||||||
pinMode(MOSI, OUTPUT);
|
pinMode(MOSI, OUTPUT);
|
||||||
|
}
|
||||||
|
initialized++; // reference count
|
||||||
|
SREG = sreg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPIClass::end() {
|
void SPIClass::end() {
|
||||||
SPCR &= ~_BV(SPE);
|
uint8_t sreg = SREG;
|
||||||
|
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
|
||||||
|
// Decrease the reference counter
|
||||||
|
if (initialized)
|
||||||
|
initialized--;
|
||||||
|
// If there are no more references disable SPI
|
||||||
|
if (!initialized) {
|
||||||
|
SPCR &= ~_BV(SPE);
|
||||||
|
interruptMode = 0;
|
||||||
|
#ifdef SPI_TRANSACTION_MISMATCH_LED
|
||||||
|
inTransactionFlag = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
SREG = sreg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mapping of interrupt numbers to bits within SPI_AVR_EIMSK
|
// mapping of interrupt numbers to bits within SPI_AVR_EIMSK
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
||||||
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
|
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
|
||||||
* Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
|
* Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
|
||||||
|
* Copyright (c) 2014 by Andrew J. Kroll <xxxajk@gmail.com> (atomicity fixes)
|
||||||
* SPI Master library for arduino.
|
* SPI Master library for arduino.
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* This file is free software; you can redistribute it and/or modify
|
||||||
@ -281,6 +282,7 @@ public:
|
|||||||
inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); }
|
inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static uint8_t initialized;
|
||||||
static uint8_t interruptMode; // 0=none, 1=mask, 2=global
|
static uint8_t interruptMode; // 0=none, 1=mask, 2=global
|
||||||
static uint8_t interruptMask; // which interrupts to mask
|
static uint8_t interruptMask; // which interrupts to mask
|
||||||
static uint8_t interruptSave; // temp storage, to restore state
|
static uint8_t interruptSave; // temp storage, to restore state
|
||||||
|
Loading…
x
Reference in New Issue
Block a user