mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #5721 from scartmell-arm/bug-i2c-abort-deep-sleep
Fix bug allowing I2C::abort_transfer to incorrectly unlock deep sleep modepull/5744/merge
						commit
						31f59b9fb4
					
				| 
						 | 
					@ -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,11 +160,26 @@ void I2C::irq_handler_asynch(void)
 | 
				
			||||||
        _callback.call(event);
 | 
					        _callback.call(event);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (event) {
 | 
					    if (event) {
 | 
				
			||||||
        sleep_manager_unlock_deep_sleep();
 | 
					        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();
 | 
				
			||||||
 | 
					        _deep_sleep_locked = false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue