Skip to content

Commit dc807b6

Browse files
Steven Cartmelladbridge
authored andcommitted
Fix bug allowing I2C::abort_transfer to incorrectly unlock deep sleep mode
- Add flag to I2C class to track if the I2C instance has locked deep sleep mode. - Wrap call to sleep_manager_lock_deep_sleep to only be called if I2C instance hasn't already locked deep sleep. - Wrap call to sleep_manager_unlock_deep_sleep to only be called if I2C has currently locked deep sleep mode.
1 parent 27c5dfc commit dc807b6

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

drivers/I2C.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ SingletonPtr<PlatformMutex> I2C::_mutex;
2828

2929
I2C::I2C(PinName sda, PinName scl) :
3030
#if DEVICE_I2C_ASYNCH
31-
_irq(this), _usage(DMA_USAGE_NEVER),
31+
_irq(this), _usage(DMA_USAGE_NEVER), _deep_sleep_locked(false),
3232
#endif
33-
_i2c(), _hz(100000) {
33+
_i2c(), _hz(100000)
34+
{
3435
// No lock needed in the constructor
3536

3637
// 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
133134
unlock();
134135
return -1; // transaction ongoing
135136
}
136-
sleep_manager_lock_deep_sleep();
137+
lock_deep_sleep();
137138
aquire();
138139

139140
_callback = callback;
@@ -148,7 +149,7 @@ void I2C::abort_transfer(void)
148149
{
149150
lock();
150151
i2c_abort_asynch(&_i2c);
151-
sleep_manager_unlock_deep_sleep();
152+
unlock_deep_sleep();
152153
unlock();
153154
}
154155

@@ -159,11 +160,26 @@ void I2C::irq_handler_asynch(void)
159160
_callback.call(event);
160161
}
161162
if (event) {
162-
sleep_manager_unlock_deep_sleep();
163+
unlock_deep_sleep();
163164
}
164165

165166
}
166167

168+
void I2C::lock_deep_sleep()
169+
{
170+
if (_deep_sleep_locked == false) {
171+
sleep_manager_lock_deep_sleep();
172+
_deep_sleep_locked = true;
173+
}
174+
}
175+
176+
void I2C::unlock_deep_sleep()
177+
{
178+
if (_deep_sleep_locked == true) {
179+
sleep_manager_unlock_deep_sleep();
180+
_deep_sleep_locked = false;
181+
}
182+
}
167183

168184
#endif
169185

drivers/I2C.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,19 @@ class I2C : private NonCopyable<I2C> {
176176
/** Abort the on-going I2C transfer
177177
*/
178178
void abort_transfer();
179-
protected:
179+
180+
protected:
181+
/** Lock deep sleep only if it is not yet locked */
182+
void lock_deep_sleep();
183+
184+
/** Unlock deep sleep only if it has been locked */
185+
void unlock_deep_sleep();
186+
180187
void irq_handler_asynch(void);
181188
event_callback_t _callback;
182189
CThunk<I2C> _irq;
183190
DMAUsage _usage;
191+
bool _deep_sleep_locked;
184192
#endif
185193

186194
protected:

0 commit comments

Comments
 (0)