Skip to content

Commit eca6db9

Browse files
SPI Transactions for Arduino Due
1 parent 6ed26b0 commit eca6db9

File tree

2 files changed

+397
-4
lines changed

2 files changed

+397
-4
lines changed

libraries/SPI/SPI.cpp

+80-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2010 by Cristian Maglie <[email protected]>
3+
* Copyright (c) 2014 by Paul Stoffregen <[email protected]> (Transaction API)
34
* SPI Master library for arduino.
45
*
56
* This file is free software; you can redistribute it and/or modify
@@ -18,7 +19,6 @@ SPIClass::SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void)) :
1819

1920
void SPIClass::begin() {
2021
init();
21-
2222
// NPCS control is left to the user
2323

2424
// Default speed set to 4Mhz
@@ -46,12 +46,88 @@ void SPIClass::begin(uint8_t _pin) {
4646
void SPIClass::init() {
4747
if (initialized)
4848
return;
49+
interruptMode = 0;
50+
interruptMask = 0;
51+
interruptSave = 0;
4952
initCb();
5053
SPI_Configure(spi, id, SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS);
5154
SPI_Enable(spi);
5255
initialized = true;
5356
}
5457

58+
#ifndef interruptsStatus
59+
#define interruptsStatus() __interruptsStatus()
60+
static inline unsigned char __interruptsStatus(void) __attribute__((always_inline, unused));
61+
static inline unsigned char __interruptsStatus(void) {
62+
unsigned int primask;
63+
asm volatile ("mrs %0, primask" : "=r" (primask));
64+
if (primask) return 0;
65+
return 1;
66+
}
67+
#endif
68+
69+
void SPIClass::usingInterrupt(uint8_t interruptNumber)
70+
{
71+
uint8_t irestore;
72+
73+
irestore = interruptsStatus();
74+
noInterrupts();
75+
if (interruptMode < 2) {
76+
if (interruptNumber > NUM_DIGITAL_PINS) {
77+
interruptMode = 2;
78+
} else {
79+
uint8_t imask = interruptMask;
80+
Pio *pio = g_APinDescription[interruptNumber].pPort;
81+
if (pio == PIOA) {
82+
imask |= 1;
83+
} else if (pio == PIOB) {
84+
imask |= 2;
85+
} else if (pio == PIOC) {
86+
imask |= 4;
87+
} else if (pio == PIOD) {
88+
imask |= 8;
89+
}
90+
interruptMask = imask;
91+
interruptMode = 1;
92+
}
93+
}
94+
if (irestore) interrupts();
95+
}
96+
97+
void SPIClass::beginTransaction(uint8_t pin, SPISettings settings)
98+
{
99+
if (interruptMode > 0) {
100+
if (interruptMode == 1) {
101+
uint8_t imask = interruptMask;
102+
if (imask & 1) NVIC_DisableIRQ(PIOA_IRQn);
103+
if (imask & 2) NVIC_DisableIRQ(PIOB_IRQn);
104+
if (imask & 4) NVIC_DisableIRQ(PIOC_IRQn);
105+
if (imask & 8) NVIC_DisableIRQ(PIOD_IRQn);
106+
} else {
107+
interruptSave = interruptsStatus();
108+
noInterrupts();
109+
}
110+
}
111+
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(pin);
112+
bitOrder[ch] = settings.border;
113+
SPI_ConfigureNPCS(spi, ch, settings.config);
114+
}
115+
116+
void SPIClass::endTransaction(void)
117+
{
118+
if (interruptMode > 0) {
119+
if (interruptMode == 1) {
120+
uint8_t imask = interruptMask;
121+
if (imask & 1) NVIC_EnableIRQ(PIOA_IRQn);
122+
if (imask & 2) NVIC_EnableIRQ(PIOB_IRQn);
123+
if (imask & 4) NVIC_EnableIRQ(PIOC_IRQn);
124+
if (imask & 8) NVIC_EnableIRQ(PIOD_IRQn);
125+
} else {
126+
if (interruptSave) interrupts();
127+
}
128+
}
129+
}
130+
55131
void SPIClass::end(uint8_t _pin) {
56132
uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin);
57133
// Setting the pin as INPUT will disconnect it from SPI peripheral
@@ -95,12 +171,12 @@ byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) {
95171

96172
// SPI_Write(spi, _channel, _data);
97173
while ((spi->SPI_SR & SPI_SR_TDRE) == 0)
98-
;
174+
;
99175
spi->SPI_TDR = d;
100176

101177
// return SPI_Read(spi);
102178
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
103-
;
179+
;
104180
d = spi->SPI_RDR;
105181
// Reverse bit order
106182
if (bitOrder[ch] == LSBFIRST)
@@ -137,3 +213,4 @@ static void SPI_0_Init(void) {
137213

138214
SPIClass SPI(SPI_INTERFACE, SPI_INTERFACE_ID, SPI_0_Init);
139215
#endif
216+

0 commit comments

Comments
 (0)