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:
parent
ef06410d16
commit
daa7e7dcc9
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user