Merge pull request #5721 from scartmell-arm/bug-i2c-abort-deep-sleep

Fix bug allowing I2C::abort_transfer to incorrectly unlock deep sleep mode
pull/5744/merge
Cruz Monrreal 2018-01-11 10:30:53 -06:00 committed by GitHub
commit 31f59b9fb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 6 deletions

View File

@ -28,9 +28,10 @@ SingletonPtr<PlatformMutex> I2C::_mutex;
I2C::I2C(PinName sda, PinName scl) : I2C::I2C(PinName sda, PinName scl) :
#if DEVICE_I2C_ASYNCH #if DEVICE_I2C_ASYNCH
_irq(this), _usage(DMA_USAGE_NEVER), _irq(this), _usage(DMA_USAGE_NEVER), _deep_sleep_locked(false),
#endif #endif
_i2c(), _hz(100000) { _i2c(), _hz(100000)
{
// No lock needed in the constructor // No lock needed in the constructor
// The init function also set the frequency to 100000 // The init function also set the frequency to 100000
@ -133,7 +134,7 @@ int I2C::transfer(int address, const char *tx_buffer, int tx_length, char *rx_bu
unlock(); unlock();
return -1; // transaction ongoing return -1; // transaction ongoing
} }
sleep_manager_lock_deep_sleep(); lock_deep_sleep();
aquire(); aquire();
_callback = callback; _callback = callback;
@ -148,7 +149,7 @@ void I2C::abort_transfer(void)
{ {
lock(); lock();
i2c_abort_asynch(&_i2c); i2c_abort_asynch(&_i2c);
sleep_manager_unlock_deep_sleep(); unlock_deep_sleep();
unlock(); unlock();
} }
@ -159,12 +160,27 @@ void I2C::irq_handler_asynch(void)
_callback.call(event); _callback.call(event);
} }
if (event) { if (event) {
unlock_deep_sleep();
}
}
void I2C::lock_deep_sleep()
{
if (_deep_sleep_locked == false) {
sleep_manager_lock_deep_sleep();
_deep_sleep_locked = true;
}
}
void I2C::unlock_deep_sleep()
{
if (_deep_sleep_locked == true) {
sleep_manager_unlock_deep_sleep(); sleep_manager_unlock_deep_sleep();
_deep_sleep_locked = false;
} }
} }
#endif #endif
} // namespace mbed } // namespace mbed

View File

@ -176,11 +176,19 @@ public:
/** Abort the on-going I2C transfer /** Abort the on-going I2C transfer
*/ */
void abort_transfer(); void abort_transfer();
protected: protected:
/** Lock deep sleep only if it is not yet locked */
void lock_deep_sleep();
/** Unlock deep sleep only if it has been locked */
void unlock_deep_sleep();
void irq_handler_asynch(void); void irq_handler_asynch(void);
event_callback_t _callback; event_callback_t _callback;
CThunk<I2C> _irq; CThunk<I2C> _irq;
DMAUsage _usage; DMAUsage _usage;
bool _deep_sleep_locked;
#endif #endif
protected: protected: