Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
I2C.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2019 ARM Limited 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "drivers/I2C.h" 00019 #include "drivers/DigitalInOut.h" 00020 #include "platform/mbed_wait_api.h" 00021 00022 #if DEVICE_I2C 00023 00024 #if DEVICE_I2C_ASYNCH 00025 #include "platform/mbed_power_mgmt.h" 00026 #endif 00027 00028 namespace mbed { 00029 00030 I2C *I2C::_owner = NULL; 00031 SingletonPtr<PlatformMutex> I2C::_mutex; 00032 00033 I2C::I2C(PinName sda, PinName scl) : 00034 #if DEVICE_I2C_ASYNCH 00035 _irq(this), _usage(DMA_USAGE_NEVER), _deep_sleep_locked(false), 00036 #endif 00037 _i2c(), _hz(100000) 00038 { 00039 lock(); 00040 // The init function also set the frequency to 100000 00041 _sda = sda; 00042 _scl = scl; 00043 recover(sda, scl); 00044 i2c_init(&_i2c, _sda, _scl); 00045 // Used to avoid unnecessary frequency updates 00046 _owner = this; 00047 unlock(); 00048 } 00049 00050 I2C::I2C(const i2c_pinmap_t &static_pinmap) : 00051 #if DEVICE_I2C_ASYNCH 00052 _irq(this), _usage(DMA_USAGE_NEVER), _deep_sleep_locked(false), 00053 #endif 00054 _i2c(), _hz(100000) 00055 { 00056 lock(); 00057 // The init function also set the frequency to 100000 00058 _sda = static_pinmap.sda_pin; 00059 _scl = static_pinmap.scl_pin; 00060 recover(static_pinmap.sda_pin, static_pinmap.scl_pin); 00061 i2c_init_direct(&_i2c, &static_pinmap); 00062 // Used to avoid unnecessary frequency updates 00063 _owner = this; 00064 unlock(); 00065 } 00066 00067 void I2C::frequency(int hz) 00068 { 00069 lock(); 00070 _hz = hz; 00071 00072 // We want to update the frequency even if we are already the bus owners 00073 i2c_frequency(&_i2c, _hz); 00074 00075 // Updating the frequency of the bus we become the owners of it 00076 _owner = this; 00077 unlock(); 00078 } 00079 00080 void I2C::aquire() 00081 { 00082 lock(); 00083 if (_owner != this) { 00084 i2c_frequency(&_i2c, _hz); 00085 _owner = this; 00086 } 00087 unlock(); 00088 } 00089 00090 // write - Master Transmitter Mode 00091 int I2C::write(int address, const char *data, int length, bool repeated) 00092 { 00093 lock(); 00094 aquire(); 00095 00096 int stop = (repeated) ? 0 : 1; 00097 int written = i2c_write(&_i2c, address, data, length, stop); 00098 00099 unlock(); 00100 return length != written; 00101 } 00102 00103 int I2C::write(int data) 00104 { 00105 lock(); 00106 int ret = i2c_byte_write(&_i2c, data); 00107 unlock(); 00108 return ret; 00109 } 00110 00111 // read - Master Receiver Mode 00112 int I2C::read(int address, char *data, int length, bool repeated) 00113 { 00114 lock(); 00115 aquire(); 00116 00117 int stop = (repeated) ? 0 : 1; 00118 int read = i2c_read(&_i2c, address, data, length, stop); 00119 00120 unlock(); 00121 return length != read; 00122 } 00123 00124 int I2C::read(int ack) 00125 { 00126 lock(); 00127 int ret; 00128 if (ack) { 00129 ret = i2c_byte_read(&_i2c, 0); 00130 } else { 00131 ret = i2c_byte_read(&_i2c, 1); 00132 } 00133 unlock(); 00134 return ret; 00135 } 00136 00137 void I2C::start(void) 00138 { 00139 lock(); 00140 i2c_start(&_i2c); 00141 unlock(); 00142 } 00143 00144 void I2C::stop(void) 00145 { 00146 lock(); 00147 i2c_stop(&_i2c); 00148 unlock(); 00149 } 00150 00151 void I2C::lock() 00152 { 00153 _mutex->lock(); 00154 } 00155 00156 void I2C::unlock() 00157 { 00158 _mutex->unlock(); 00159 } 00160 00161 int I2C::recover(PinName sda, PinName scl) 00162 { 00163 DigitalInOut pin_sda(sda, PIN_INPUT, PullNone, 1); 00164 DigitalInOut pin_scl(scl, PIN_INPUT, PullNone, 1); 00165 00166 // Return as SCL is low and no access to become master. 00167 if (pin_scl == 0) { 00168 return I2C_ERROR_BUS_BUSY; 00169 } 00170 00171 // Return successfully as SDA and SCL is high 00172 if (pin_sda == 1) { 00173 return 0; 00174 } 00175 00176 // Send clock pulses, for device to recover 9 00177 pin_scl.mode(PullNone); 00178 pin_scl.output(); 00179 for (int count = 0; count < 10; count++) { 00180 pin_scl.mode(PullNone); 00181 pin_scl = 0; 00182 wait_us(5); 00183 pin_scl.mode(PullUp); 00184 pin_scl = 1; 00185 wait_us(5); 00186 } 00187 00188 // Send Stop 00189 pin_sda.output(); 00190 pin_sda = 0; 00191 wait_us(5); 00192 pin_scl = 1; 00193 wait_us(5); 00194 pin_sda = 1; 00195 wait_us(5); 00196 00197 pin_sda.input(); 00198 pin_scl.input(); 00199 if ((pin_scl == 0) || (pin_sda == 0)) { 00200 // Return as SCL is low and no access to become master. 00201 return I2C_ERROR_BUS_BUSY; 00202 } 00203 00204 return 0; 00205 } 00206 00207 #if DEVICE_I2C_ASYNCH 00208 00209 int I2C::transfer(int address, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, const event_callback_t &callback, int event, bool repeated) 00210 { 00211 lock(); 00212 if (i2c_active(&_i2c)) { 00213 unlock(); 00214 return -1; // transaction ongoing 00215 } 00216 lock_deep_sleep(); 00217 aquire(); 00218 00219 _callback = callback; 00220 int stop = (repeated) ? 0 : 1; 00221 _irq.callback(&I2C::irq_handler_asynch); 00222 i2c_transfer_asynch(&_i2c, (void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length, address, stop, _irq.entry(), event, _usage); 00223 unlock(); 00224 return 0; 00225 } 00226 00227 void I2C::abort_transfer(void) 00228 { 00229 lock(); 00230 i2c_abort_asynch(&_i2c); 00231 unlock_deep_sleep(); 00232 unlock(); 00233 } 00234 00235 void I2C::irq_handler_asynch(void) 00236 { 00237 int event = i2c_irq_handler_asynch(&_i2c); 00238 if (_callback && event) { 00239 _callback.call(event); 00240 } 00241 00242 if (event) { 00243 unlock_deep_sleep(); 00244 } 00245 } 00246 00247 void I2C::lock_deep_sleep() 00248 { 00249 if (_deep_sleep_locked == false) { 00250 sleep_manager_lock_deep_sleep(); 00251 _deep_sleep_locked = true; 00252 } 00253 } 00254 00255 void I2C::unlock_deep_sleep() 00256 { 00257 if (_deep_sleep_locked == true) { 00258 sleep_manager_unlock_deep_sleep(); 00259 _deep_sleep_locked = false; 00260 } 00261 } 00262 00263 #endif 00264 00265 } // namespace mbed 00266 00267 #endif
Generated on Tue Jul 12 2022 13:54:24 by
