1
0
mirror of https://github.com/arduino/Arduino.git synced 2024-12-01 12:24:14 +01:00

Fix interrupt masking on Arduino Due

This commit is contained in:
PaulStoffregen 2014-08-01 16:44:47 -07:00
parent ef06410d16
commit daa7e7dcc9
2 changed files with 43 additions and 28 deletions

View File

@ -47,8 +47,11 @@ void SPIClass::init() {
if (initialized)
return;
interruptMode = 0;
interruptMask = 0;
interruptSave = 0;
interruptMask[0] = 0;
interruptMask[1] = 0;
interruptMask[2] = 0;
interruptMask[3] = 0;
initCb();
SPI_Configure(spi, id, SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS);
SPI_Enable(spi);
@ -59,9 +62,11 @@ void SPIClass::init() {
#define interruptsStatus() __interruptsStatus()
static inline unsigned char __interruptsStatus(void) __attribute__((always_inline, unused));
static inline unsigned char __interruptsStatus(void) {
unsigned int primask;
unsigned int primask, faultmask;
asm volatile ("mrs %0, primask" : "=r" (primask));
if (primask) return 0;
asm volatile ("mrs %0, faultmask" : "=r" (faultmask));
if (faultmask) return 0;
return 1;
}
#endif
@ -72,23 +77,27 @@ void SPIClass::usingInterrupt(uint8_t interruptNumber)
irestore = interruptsStatus();
noInterrupts();
if (interruptMode < 2) {
if (interruptMode < 16) {
if (interruptNumber > NUM_DIGITAL_PINS) {
interruptMode = 2;
interruptMode = 16;
} else {
uint8_t imask = interruptMask;
Pio *pio = g_APinDescription[interruptNumber].pPort;
uint32_t mask = g_APinDescription[interruptNumber].ulPin;
if (pio == PIOA) {
imask |= 1;
interruptMode |= 1;
interruptMask[0] |= mask;
} else if (pio == PIOB) {
imask |= 2;
interruptMode |= 2;
interruptMask[1] |= mask;
} else if (pio == PIOC) {
imask |= 4;
interruptMode |= 4;
interruptMask[2] |= mask;
} else if (pio == PIOD) {
imask |= 8;
interruptMode |= 8;
interruptMask[3] |= mask;
} else {
interruptMode = 16;
}
interruptMask = imask;
interruptMode = 1;
}
}
if (irestore) interrupts();
@ -96,13 +105,13 @@ void SPIClass::usingInterrupt(uint8_t interruptNumber)
void SPIClass::beginTransaction(uint8_t pin, SPISettings settings)
{
if (interruptMode > 0) {
if (interruptMode == 1) {
uint8_t imask = interruptMask;
if (imask & 1) NVIC_DisableIRQ(PIOA_IRQn);
if (imask & 2) NVIC_DisableIRQ(PIOB_IRQn);
if (imask & 4) NVIC_DisableIRQ(PIOC_IRQn);
if (imask & 8) NVIC_DisableIRQ(PIOD_IRQn);
uint8_t mode = interruptMode;
if (mode > 0) {
if (mode < 16) {
if (mode & 1) PIOA->PIO_IDR = interruptMask[0];
if (mode & 2) PIOB->PIO_IDR = interruptMask[1];
if (mode & 4) PIOC->PIO_IDR = interruptMask[2];
if (mode & 8) PIOD->PIO_IDR = interruptMask[3];
} else {
interruptSave = interruptsStatus();
noInterrupts();
@ -111,17 +120,20 @@ void SPIClass::beginTransaction(uint8_t pin, SPISettings settings)
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(pin);
bitOrder[ch] = settings.border;
SPI_ConfigureNPCS(spi, ch, settings.config);
//setBitOrder(pin, settings.border);
//setDataMode(pin, settings.datamode);
//setClockDivider(pin, settings.clockdiv);
}
void SPIClass::endTransaction(void)
{
if (interruptMode > 0) {
if (interruptMode == 1) {
uint8_t imask = interruptMask;
if (imask & 1) NVIC_EnableIRQ(PIOA_IRQn);
if (imask & 2) NVIC_EnableIRQ(PIOB_IRQn);
if (imask & 4) NVIC_EnableIRQ(PIOC_IRQn);
if (imask & 8) NVIC_EnableIRQ(PIOD_IRQn);
uint8_t mode = interruptMode;
if (mode > 0) {
if (mode < 16) {
if (mode & 1) PIOA->PIO_IER = interruptMask[0];
if (mode & 2) PIOB->PIO_IER = interruptMask[1];
if (mode & 4) PIOC->PIO_IER = interruptMask[2];
if (mode & 8) PIOD->PIO_IER = interruptMask[3];
} else {
if (interruptSave) interrupts();
}

View File

@ -316,8 +316,11 @@ private:
}
}
config = (dataMode & 3) | SPI_CSR_CSAAT | SPI_CSR_SCBR(div) | SPI_CSR_DLYBCT(1);
//clockdiv = div;
//datamode = dataMode;
}
uint32_t config;
//uint8_t clockdiv, datamode;
BitOrder border;
friend class SPIClass;
};
@ -370,9 +373,9 @@ class SPIClass {
uint32_t mode[SPI_CHANNELS_NUM];
void (*initCb)(void);
bool initialized;
uint8_t interruptMode; // 0=none, 1=mask, 2=global
uint8_t interruptMask; // bits 0:3=pin change
uint8_t interruptSave; // temp storage, to restore state
uint8_t interruptMode; // 0=none, 1-15=mask, 16=global
uint8_t interruptSave; // temp storage, to restore state
uint32_t interruptMask[4];
};
#if SPI_INTERFACES_COUNT > 0