Skip to content

Commit 51dd443

Browse files
committed
Add 'components/storage/blockdevice/COMPONENT_I2CEE/' from commit 'd92806c11e0e05280c08db0b3ed6459b2d8dea2c'
git-subtree-dir: components/storage/blockdevice/COMPONENT_I2CEE git-subtree-mainline: 9cc1caa git-subtree-split: d92806c
2 parents 9cc1caa + d92806c commit 51dd443

File tree

6 files changed

+767
-0
lines changed

6 files changed

+767
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
dist: xenial
2+
language: python
3+
python: 2.7
4+
5+
install:
6+
# Get arm-none-eabi-gcc
7+
- sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa
8+
- sudo apt-get update -qq
9+
- sudo apt-get install -qq gcc-arm-embedded
10+
# Get dependencies
11+
- git clone https://github.com/armmbed/mbed-os.git
12+
# Install python dependencies
13+
# - python -m pip install --upgrade pip==18.1
14+
# - python -m pip install --upgrade setuptools==40.4.3
15+
- pip install -r mbed-os/requirements.txt
16+
17+
script:
18+
# Check that examples compile
19+
- sed -n '/``` cpp/,${/```$/q;/```/d;p}' README.md > main.cpp &&
20+
PYTHONPATH=mbed-os python mbed-os/tools/make.py -t GCC_ARM -m K82F
21+
--source=. --build=BUILD/K82F/GCC_ARM -j0 &&
22+
rm main.cpp
23+
- sed -n '/@code/,${/@endcode/q;/@/d;s/^ \*//;p}' I2CEEBlockDevice.h > main.cpp &&
24+
PYTHONPATH=mbed-os python mbed-os/tools/make.py -t GCC_ARM -m K82F
25+
--source=. --build=BUILD/K82F/GCC_ARM -j0 &&
26+
rm main.cpp
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/* Simple access class for I2C EEPROM chips like Microchip 24LC
2+
* Copyright (c) 2015 Robin Hourahane
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "I2CEEBlockDevice.h"
17+
18+
#define I2CEE_TIMEOUT 10000
19+
20+
21+
I2CEEBlockDevice::I2CEEBlockDevice(
22+
PinName sda, PinName scl, uint8_t addr,
23+
bd_size_t size, bd_size_t block, int freq)
24+
: _i2c_addr(addr), _size(size), _block(block)
25+
{
26+
_i2c = new (_i2c_buffer) I2C(sda, scl);
27+
_i2c->frequency(freq);
28+
}
29+
30+
I2CEEBlockDevice::I2CEEBlockDevice(
31+
I2C * i2c_obj, uint8_t addr,
32+
bd_size_t size, bd_size_t block)
33+
: _i2c_addr(addr), _size(size), _block(block)
34+
{
35+
_i2c = i2c_obj;
36+
}
37+
I2CEEBlockDevice::~I2CEEBlockDevice()
38+
{
39+
if (_i2c == (I2C*)_i2c_buffer) {
40+
_i2c->~I2C();
41+
}
42+
}
43+
44+
int I2CEEBlockDevice::init()
45+
{
46+
return _sync();
47+
}
48+
49+
int I2CEEBlockDevice::deinit()
50+
{
51+
return 0;
52+
}
53+
54+
int I2CEEBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
55+
{
56+
// Check the address and size fit onto the chip.
57+
MBED_ASSERT(is_valid_read(addr, size));
58+
59+
_i2c->start();
60+
if (!_i2c->write(_i2c_addr | 0) ||
61+
!_i2c->write((char)(addr >> 8)) ||
62+
!_i2c->write((char)(addr & 0xff))) {
63+
return BD_ERROR_DEVICE_ERROR;
64+
}
65+
_i2c->stop();
66+
67+
if (_i2c->read(_i2c_addr, static_cast<char*>(buffer), size) < 0) {
68+
return BD_ERROR_DEVICE_ERROR;
69+
}
70+
71+
return 0;
72+
}
73+
74+
int I2CEEBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
75+
{
76+
// Check the addr and size fit onto the chip.
77+
MBED_ASSERT(is_valid_program(addr, size));
78+
79+
// While we have some more data to write.
80+
while (size > 0) {
81+
uint32_t off = addr % _block;
82+
uint32_t chunk = (off + size < _block) ? size : (_block - off);
83+
84+
_i2c->start();
85+
if (!_i2c->write(_i2c_addr | 0) ||
86+
!_i2c->write((char)(addr >> 8)) ||
87+
!_i2c->write((char)(addr & 0xff))) {
88+
return BD_ERROR_DEVICE_ERROR;
89+
}
90+
91+
for (unsigned i = 0; i < chunk; i++) {
92+
_i2c->write(static_cast<const char*>(buffer)[i]);
93+
}
94+
_i2c->stop();
95+
96+
int err = _sync();
97+
if (err) {
98+
return err;
99+
}
100+
101+
addr += chunk;
102+
size -= chunk;
103+
buffer = static_cast<const char*>(buffer) + chunk;
104+
}
105+
106+
return 0;
107+
}
108+
109+
int I2CEEBlockDevice::erase(bd_addr_t addr, bd_size_t size)
110+
{
111+
// No erase needed
112+
return 0;
113+
}
114+
115+
int I2CEEBlockDevice::_sync()
116+
{
117+
// The chip doesn't ACK while writing to the actual EEPROM
118+
// so loop trying to do a zero byte write until it is ACKed
119+
// by the chip.
120+
for (int i = 0; i < I2CEE_TIMEOUT; i++) {
121+
if (_i2c->write(_i2c_addr | 0, 0, 0) < 1) {
122+
return 0;
123+
}
124+
125+
wait_ms(1);
126+
}
127+
128+
return BD_ERROR_DEVICE_ERROR;
129+
}
130+
131+
bd_size_t I2CEEBlockDevice::get_read_size() const
132+
{
133+
return 1;
134+
}
135+
136+
bd_size_t I2CEEBlockDevice::get_program_size() const
137+
{
138+
return 1;
139+
}
140+
141+
bd_size_t I2CEEBlockDevice::get_erase_size() const
142+
{
143+
return 1;
144+
}
145+
146+
bd_size_t I2CEEBlockDevice::size() const
147+
{
148+
return _size;
149+
}
150+
151+
const char *I2CEEBlockDevice::get_type() const
152+
{
153+
return "I2CEE";
154+
}
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/* Simple access class for I2C EEPROM chips like Microchip 24LC
2+
* Copyright (c) 2015 Robin Hourahane
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#ifndef MBED_I2CEEPROM_BLOCK_DEVICE_H
17+
#define MBED_I2CEEPROM_BLOCK_DEVICE_H
18+
19+
#include "mbed.h"
20+
#include "BlockDevice.h"
21+
22+
23+
/** BlockDevice for I2C based flash device such as
24+
* Microchip's 24LC or ATMEL's AT24C ranges
25+
*
26+
* @code
27+
* // Here's an example using a 24LC256 on a GR PEACH
28+
* #include "mbed.h"
29+
* #include "I2CEEBlockDevice.h"
30+
*
31+
* // Create EEPROM device on I2C bus with 32kbytes of memory
32+
* I2CEEBlockDevice i2cee(D14, D15, 0xa0, 32*1024);
33+
*
34+
* int main() {
35+
* printf("i2cee test\n");
36+
*
37+
* // Initialize the device and print the memory layout
38+
* i2cee.init();
39+
* printf("i2cee size: %llu\n", i2cee.size());
40+
* printf("i2cee read size: %llu\n", i2cee.get_read_size());
41+
* printf("i2cee program size: %llu\n", i2cee.get_program_size());
42+
* printf("i2cee erase size: %llu\n", i2cee.get_erase_size());
43+
*
44+
* // Write "Hello World!" to the first block
45+
* char *buffer = (char*)malloc(i2cee.get_erase_size());
46+
* sprintf(buffer, "Hello World!\n");
47+
* i2cee.erase(0, i2cee.get_erase_size());
48+
* i2cee.program(buffer, 0, i2cee.get_erase_size());
49+
*
50+
* // Read back what was stored
51+
* i2cee.read(buffer, 0, i2cee.get_erase_size());
52+
* printf("%s", buffer);
53+
*
54+
* // Deinitialize the device
55+
* i2cee.deinit();
56+
* }
57+
* @endcode
58+
*/
59+
class I2CEEBlockDevice : public BlockDevice {
60+
public:
61+
/** Constructor to create an I2CEEBlockDevice on I2C pins
62+
*
63+
* @param sda The pin name for the sda line of the I2C bus.
64+
* @param scl The pin name for the scl line of the I2C bus.
65+
* @param addr The 8bit I2C address of the chip, common range 0xa0 - 0xae.
66+
* @param size The size of the device in bytes
67+
* @param block The page size of the device in bytes, defaults to 32bytes
68+
* @param freq The frequency of the I2C bus, defaults to 400K.
69+
*/
70+
I2CEEBlockDevice(
71+
PinName sda, PinName scl, uint8_t address,
72+
bd_size_t size, bd_size_t block=32,
73+
int bus_speed=400000);
74+
75+
/** Constructor to create an I2CEEBlockDevice on I2C pins
76+
*
77+
* @param i2c The I2C instance pointer
78+
* @param addr The 8bit I2C address of the chip, common range 0xa0 - 0xae.
79+
* @param size The size of the device in bytes
80+
* @param block The page size of the device in bytes, defaults to 32bytes
81+
* @param freq The frequency of the I2C bus, defaults to 400K.
82+
*/
83+
I2CEEBlockDevice(
84+
I2C * i2c_obj, uint8_t address,
85+
bd_size_t size, bd_size_t block=32);
86+
87+
/** Destructor of I2CEEBlockDevice
88+
*/
89+
90+
virtual ~I2CEEBlockDevice();
91+
92+
/** Initialize a block device
93+
*
94+
* @return 0 on success or a negative error code on failure
95+
*/
96+
virtual int init();
97+
98+
/** Deinitialize a block device
99+
*
100+
* @return 0 on success or a negative error code on failure
101+
*/
102+
virtual int deinit();
103+
104+
/** Read blocks from a block device
105+
*
106+
* @param buffer Buffer to write blocks to
107+
* @param addr Address of block to begin reading from
108+
* @param size Size to read in bytes, must be a multiple of read block size
109+
* @return 0 on success, negative error code on failure
110+
*/
111+
virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
112+
113+
/** Program blocks to a block device
114+
*
115+
* The blocks must have been erased prior to being programmed
116+
*
117+
* @param buffer Buffer of data to write to blocks
118+
* @param addr Address of block to begin writing to
119+
* @param size Size to write in bytes, must be a multiple of program block size
120+
* @return 0 on success, negative error code on failure
121+
*/
122+
virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
123+
124+
/** Erase blocks on a block device
125+
*
126+
* The state of an erased block is undefined until it has been programmed
127+
*
128+
* @param addr Address of block to begin erasing
129+
* @param size Size to erase in bytes, must be a multiple of erase block size
130+
* @return 0 on success, negative error code on failure
131+
*/
132+
virtual int erase(bd_addr_t addr, bd_size_t size);
133+
134+
/** Get the size of a readable block
135+
*
136+
* @return Size of a readable block in bytes
137+
*/
138+
virtual bd_size_t get_read_size() const;
139+
140+
/** Get the size of a programable block
141+
*
142+
* @return Size of a programable block in bytes
143+
* @note Must be a multiple of the read size
144+
*/
145+
virtual bd_size_t get_program_size() const;
146+
147+
/** Get the size of a eraseable block
148+
*
149+
* @return Size of a eraseable block in bytes
150+
* @note Must be a multiple of the program size
151+
*/
152+
virtual bd_size_t get_erase_size() const;
153+
154+
/** Get the total size of the underlying device
155+
*
156+
* @return Size of the underlying device in bytes
157+
*/
158+
virtual bd_size_t size() const;
159+
160+
/** Get the BlockDevice class type.
161+
*
162+
* @return A string representation of the BlockDevice class type.
163+
*/
164+
virtual const char *get_type() const;
165+
166+
private:
167+
I2C * _i2c;
168+
uint32_t _i2c_buffer[sizeof(I2C) / sizeof(uint32_t)];
169+
uint8_t _i2c_addr;
170+
uint32_t _size;
171+
uint32_t _block;
172+
173+
int _sync();
174+
};
175+
176+
177+
#endif /* MBED_SD_BLOCK_DEVICE_H */

0 commit comments

Comments
 (0)