1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2025-07-21 12:28:55 +02:00

STM32: Remove I2C interrupt blocking waveform interrupt

This commit is contained in:
Harald Barth 2025-07-10 12:18:36 +02:00
parent 51c4b4d34a
commit 2e0a596afe
3 changed files with 36 additions and 4 deletions

View File

@ -208,7 +208,7 @@ void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
dcctimer.setOverflow(DCC_SIGNAL_TIME, MICROSEC_FORMAT); dcctimer.setOverflow(DCC_SIGNAL_TIME, MICROSEC_FORMAT);
// dcctimer.attachInterrupt(Timer11_Handler); // dcctimer.attachInterrupt(Timer11_Handler);
dcctimer.attachInterrupt(DCCTimer_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.refresh();
dcctimer.resume(); dcctimer.resume();

View File

@ -37,21 +37,42 @@
// it can replace use of noInterrupts/interrupts in other parts of DCC-EX. // it can replace use of noInterrupts/interrupts in other parts of DCC-EX.
// //
static inline uint8_t _deferInterrupts(void) { static inline uint8_t _deferInterrupts(void) {
#if defined(ARDUINO_ARCH_STM32)
NVIC_DisableIRQ(I2C1_EV_IRQn);
NVIC_DisableIRQ(I2C1_ER_IRQn);
#else
noInterrupts(); noInterrupts();
#endif
return 1; return 1;
} }
static inline void _conditionalEnableInterrupts(bool *wasEnabled) { 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(); if (*wasEnabled) interrupts();
#endif
} }
#define ATOMIC_BLOCK(x) \ #define ATOMIC_BLOCK(x) \
for (bool _int_saved __attribute__((__cleanup__(_conditionalEnableInterrupts))) \ for (bool _int_saved __attribute__((__cleanup__(_conditionalEnableInterrupts))) \
=_getInterruptState(),_ToDo=_deferInterrupts(); _ToDo; _ToDo=0) =_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. #if defined(__AVR__) // Nano, Uno, Mega2580, NanoEvery, etc.
static inline bool _getInterruptState(void) { static inline bool _getInterruptState(void) {
return bitRead(SREG, SREG_I); // true if enabled, false if disabled 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 ) { static inline bool _getInterruptState( void ) {
uint32_t reg; uint32_t reg;
__asm__ __volatile__ ("MRS %0, primask" : "=r" (reg) ); __asm__ __volatile__ ("MRS %0, primask" : "=r" (reg) );

View File

@ -211,9 +211,19 @@ void I2CManagerClass::I2C_init()
#if defined(I2C_USE_INTERRUPTS) #if defined(I2C_USE_INTERRUPTS)
// Setting NVIC // 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_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); NVIC_EnableIRQ(I2C1_ER_IRQn);
// CR2 Interrupt Settings // CR2 Interrupt Settings
@ -305,6 +315,7 @@ void I2CManagerClass::I2C_close() {
***************************************************************************/ ***************************************************************************/
void I2CManagerClass::I2C_handleInterrupt() { void I2CManagerClass::I2C_handleInterrupt() {
volatile uint16_t temp_sr1, temp_sr2; volatile uint16_t temp_sr1, temp_sr2;
(void) temp_sr2; // only used as target for reads
temp_sr1 = s->SR1; temp_sr1 = s->SR1;