diff --git a/DCCTimerSTM32.cpp b/DCCTimerSTM32.cpp index df00df3..9b5d2f3 100644 --- a/DCCTimerSTM32.cpp +++ b/DCCTimerSTM32.cpp @@ -208,7 +208,7 @@ void DCCTimer::begin(INTERRUPT_CALLBACK callback) { dcctimer.setOverflow(DCC_SIGNAL_TIME, MICROSEC_FORMAT); // dcctimer.attachInterrupt(Timer11_Handler); dcctimer.attachInterrupt(DCCTimer_Handler); - dcctimer.setInterruptPriority(0, 0); // Set highest preemptive priority! + dcctimer.setInterruptPriority(1, 0); // Set second highest preemptive priority! dcctimer.refresh(); dcctimer.resume(); diff --git a/I2CManager_NonBlocking.h b/I2CManager_NonBlocking.h index 83e1a2f..f57bdaf 100644 --- a/I2CManager_NonBlocking.h +++ b/I2CManager_NonBlocking.h @@ -37,21 +37,42 @@ // it can replace use of noInterrupts/interrupts in other parts of DCC-EX. // static inline uint8_t _deferInterrupts(void) { +#if defined(ARDUINO_ARCH_STM32) + NVIC_DisableIRQ(I2C1_EV_IRQn); + NVIC_DisableIRQ(I2C1_ER_IRQn); +#else noInterrupts(); +#endif return 1; } static inline void _conditionalEnableInterrupts(bool *wasEnabled) { +#if defined(ARDUINO_ARCH_STM32) + (void)wasEnabled; + NVIC_EnableIRQ(I2C1_EV_IRQn); + NVIC_EnableIRQ(I2C1_ER_IRQn); +#else if (*wasEnabled) interrupts(); +#endif } #define ATOMIC_BLOCK(x) \ for (bool _int_saved __attribute__((__cleanup__(_conditionalEnableInterrupts))) \ =_getInterruptState(),_ToDo=_deferInterrupts(); _ToDo; _ToDo=0) +// The construct of +// "variable __attribute__((__cleanup__(func)))" +// calls the func with *variable when variable goes out of scope + #if defined(__AVR__) // Nano, Uno, Mega2580, NanoEvery, etc. static inline bool _getInterruptState(void) { return bitRead(SREG, SREG_I); // true if enabled, false if disabled } -#elif defined(__arm__) // STM32, SAMD, Teensy +#elif defined(ARDUINO_ARCH_STM32) + static inline bool _getInterruptState( void ) { + // as we do ony mess with the I2C interrupts in the STM32 case, + // we do not care about their previous state + return true; + } +#elif defined(__arm__) // SAMD, Teensy static inline bool _getInterruptState( void ) { uint32_t reg; __asm__ __volatile__ ("MRS %0, primask" : "=r" (reg) ); diff --git a/I2CManager_STM32.h b/I2CManager_STM32.h index 45c924f..be9c3df 100644 --- a/I2CManager_STM32.h +++ b/I2CManager_STM32.h @@ -211,9 +211,19 @@ void I2CManagerClass::I2C_init() #if defined(I2C_USE_INTERRUPTS) // Setting NVIC - NVIC_SetPriority(I2C1_EV_IRQn, 1); // Match default priorities + NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); // 4 means that we have all bits for preemptive grouping + // prio scheme: + // systick : 0 + // waveform timer : 1 + // i2c : 2 + // one must call NVIC_EncodePriority() to bitshift the priorities + // according to the active priority grouping and then use that + // value as argument to NVIC_SetPriority(). + NVIC_SetPriority(I2C1_EV_IRQn, + NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 2, 0)); NVIC_EnableIRQ(I2C1_EV_IRQn); - NVIC_SetPriority(I2C1_ER_IRQn, 1); // Match default priorities + NVIC_SetPriority(I2C1_ER_IRQn, + NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 2, 0)); NVIC_EnableIRQ(I2C1_ER_IRQn); // CR2 Interrupt Settings @@ -305,6 +315,7 @@ void I2CManagerClass::I2C_close() { ***************************************************************************/ void I2CManagerClass::I2C_handleInterrupt() { volatile uint16_t temp_sr1, temp_sr2; + (void) temp_sr2; // only used as target for reads temp_sr1 = s->SR1;