1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-30 03:26:13 +01:00

Update I2CManager_NonBlocking.h

Rework ATOMIC_BLOCK to further simplify and clarify.
This commit is contained in:
Neil McKechnie 2023-02-10 19:52:24 +00:00
parent 1cfe5a1e46
commit c315895cd9

View File

@ -33,28 +33,35 @@
// This has the advantage over simple noInterrupts/Interrupts that the // This has the advantage over simple noInterrupts/Interrupts that the
// original interrupt state is restored when the block finishes. // original interrupt state is restored when the block finishes.
// //
#if defined(__AVR__) // (This should really be defined in an include file somewhere more global, so
// 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) {
noInterrupts(); noInterrupts();
return 1; return 1;
} }
#define ATOMIC_BLOCK(x) \ static inline void _enableInterruptsIf(uint8_t wasEnabled) {
for (uint8_t _int_saved=SREG,_ToDo=_deferInterrupts(); \ if (wasEnabled) interrupts();
_ToDo; _ToDo=0, SREG=_int_saved)
#elif defined(__arm__)
static inline uint8_t _deferInterrupts(void) {
__set_PRIMASK(1);
return 1;
} }
#define ATOMIC_BLOCK(x) \ #if defined(__AVR__) // Nano, Uno, Mega2580, NanoEvery, etc.
for (uint8_t _int_saved=__get_PRIMASK(),_ToDo=_deferInterrupts(); \ #define ATOMIC_BLOCK(x) \
_ToDo; _ToDo=0, __set_PRIMASK(_int_saved)) for (bool _int_saved=(SREG & (1<<SREG_I)),_ToDo=_deferInterrupts(); \
_ToDo; _ToDo=0, _enableInterruptsIf(_int_saved))
#elif defined(__arm__) // STM32, SAMD, Teensy
static __inline__ bool _getInterruptState( void ) {
uint32_t reg;
__asm__ __volatile__ ("MRS %0, primask" : "=r" (reg) );
return !(reg & 1); // true if interrupts enabled, false otherwise
}
#define ATOMIC_BLOCK(x) \
for (bool _int_saved=_getInterruptState(),_ToDo=_deferInterrupts(); \
_ToDo; _ToDo=0, _enableInterruptsIf(_int_saved))
#else #else
// If it's not a recognised target, don't use interrupts in the I2C driver #warning "ATOMIC_BLOCK() not defined for this target type, I2C interrupts disabled"
#ifdef I2C_USE_INTERRUPTS #define ATOMIC_BLOCK(x) // expand to nothing.
//#undef I2C_USE_INTERRUPTS #ifdef I2C_USE_INTERRUPTS
#endif #undef I2C_USE_INTERRUPTS
#define ATOMIC_BLOCK(x) // expand to nothing. #endif
#endif #endif
@ -277,7 +284,7 @@ void I2CManagerClass::loop() {
#if !defined(I2C_USE_INTERRUPTS) #if !defined(I2C_USE_INTERRUPTS)
handleInterrupt(); handleInterrupt();
#endif #endif
// Call function to monitor for stuch I2C operations. // Call function to monitor for stuck I2C operations.
checkForTimeout(); checkForTimeout();
} }