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
I2CEEBlockDevice.cpp
00001 /* Simple access class for I2C EEPROM chips like Microchip 24LC 00002 * Copyright (c) 2015 Robin Hourahane 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "I2CEEBlockDevice.h" 00017 #include "rtos/ThisThread.h" 00018 using namespace mbed; 00019 00020 #define I2CEE_TIMEOUT 10000 00021 00022 00023 I2CEEBlockDevice::I2CEEBlockDevice( 00024 PinName sda, PinName scl, uint8_t addr, 00025 bd_size_t size, bd_size_t block, int freq) 00026 : _i2c_addr(addr), _size(size), _block(block) 00027 { 00028 _i2c = new (_i2c_buffer) I2C(sda, scl); 00029 _i2c->frequency(freq); 00030 } 00031 00032 I2CEEBlockDevice::I2CEEBlockDevice( 00033 I2C *i2c_obj, uint8_t addr, 00034 bd_size_t size, bd_size_t block) 00035 : _i2c_addr(addr), _size(size), _block(block) 00036 { 00037 _i2c = i2c_obj; 00038 } 00039 I2CEEBlockDevice::~I2CEEBlockDevice() 00040 { 00041 if (_i2c == (I2C *)_i2c_buffer) { 00042 _i2c->~I2C(); 00043 } 00044 } 00045 00046 int I2CEEBlockDevice::init() 00047 { 00048 return _sync(); 00049 } 00050 00051 int I2CEEBlockDevice::deinit() 00052 { 00053 return 0; 00054 } 00055 00056 int I2CEEBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) 00057 { 00058 // Check the address and size fit onto the chip. 00059 MBED_ASSERT(is_valid_read(addr, size)); 00060 00061 _i2c->start(); 00062 00063 if (!_i2c->write(_i2c_addr | 0) || 00064 !_i2c->write((char)(addr >> 8)) || 00065 !_i2c->write((char)(addr & 0xff))) { 00066 return BD_ERROR_DEVICE_ERROR; 00067 } 00068 00069 _i2c->stop(); 00070 00071 if (_i2c->read(_i2c_addr, static_cast<char *>(buffer), size) < 0) { 00072 return BD_ERROR_DEVICE_ERROR; 00073 } 00074 00075 return 0; 00076 } 00077 00078 int I2CEEBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) 00079 { 00080 // Check the addr and size fit onto the chip. 00081 MBED_ASSERT(is_valid_program(addr, size)); 00082 00083 // While we have some more data to write. 00084 while (size > 0) { 00085 uint32_t off = addr % _block; 00086 uint32_t chunk = (off + size < _block) ? size : (_block - off); 00087 00088 _i2c->start(); 00089 00090 if (!_i2c->write(_i2c_addr | 0) || 00091 !_i2c->write((char)(addr >> 8)) || 00092 !_i2c->write((char)(addr & 0xff))) { 00093 return BD_ERROR_DEVICE_ERROR; 00094 } 00095 00096 for (unsigned i = 0; i < chunk; i++) { 00097 _i2c->write(static_cast<const char *>(buffer)[i]); 00098 } 00099 00100 _i2c->stop(); 00101 00102 int err = _sync(); 00103 00104 if (err) { 00105 return err; 00106 } 00107 00108 addr += chunk; 00109 size -= chunk; 00110 buffer = static_cast<const char *>(buffer) + chunk; 00111 } 00112 00113 return 0; 00114 } 00115 00116 int I2CEEBlockDevice::erase(bd_addr_t addr, bd_size_t size) 00117 { 00118 // No erase needed 00119 return 0; 00120 } 00121 00122 int I2CEEBlockDevice::_sync() 00123 { 00124 // The chip doesn't ACK while writing to the actual EEPROM 00125 // so loop trying to do a zero byte write until it is ACKed 00126 // by the chip. 00127 for (int i = 0; i < I2CEE_TIMEOUT; i++) { 00128 if (_i2c->write(_i2c_addr | 0, 0, 0) < 1) { 00129 return 0; 00130 } 00131 00132 rtos::ThisThread::sleep_for(1); 00133 } 00134 00135 return BD_ERROR_DEVICE_ERROR; 00136 } 00137 00138 bd_size_t I2CEEBlockDevice::get_read_size() const 00139 { 00140 return 1; 00141 } 00142 00143 bd_size_t I2CEEBlockDevice::get_program_size() const 00144 { 00145 return 1; 00146 } 00147 00148 bd_size_t I2CEEBlockDevice::get_erase_size() const 00149 { 00150 return 1; 00151 } 00152 00153 bd_size_t I2CEEBlockDevice::size() const 00154 { 00155 return _size; 00156 } 00157 00158 const char *I2CEEBlockDevice::get_type() const 00159 { 00160 return "I2CEE"; 00161 }
Generated on Tue Jul 12 2022 13:54:24 by
