Skip to content

Commit a02cf8c

Browse files
committed
bd: Added I2CEeprom as backend for block device
Forked from https://developer.mbed.org/users/rhourahane/code/I2CEeprom/
1 parent eed9b2a commit a02cf8c

File tree

3 files changed

+423
-0
lines changed

3 files changed

+423
-0
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
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(sda, scl), _i2c_addr(addr), _size(size), _block(block)
25+
{
26+
_i2c.frequency(freq);
27+
}
28+
29+
bd_error_t I2CEEBlockDevice::init()
30+
{
31+
return _sync();
32+
}
33+
34+
bd_error_t I2CEEBlockDevice::deinit()
35+
{
36+
return 0;
37+
}
38+
39+
bd_error_t I2CEEBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
40+
{
41+
// Check the address and size fit onto the chip.
42+
if (!is_valid_read(addr, size)) {
43+
return BD_ERROR_PARAMETER;
44+
}
45+
46+
_i2c.start();
47+
if (!_i2c.write(_i2c_addr | 0) ||
48+
!_i2c.write((char)(addr >> 8)) ||
49+
!_i2c.write((char)(addr & 0xff))) {
50+
return BD_ERROR_DEVICE_ERROR;
51+
}
52+
_i2c.stop();
53+
54+
if (_i2c.read(_i2c_addr, static_cast<char*>(buffer), size) < 0) {
55+
return BD_ERROR_DEVICE_ERROR;
56+
}
57+
58+
return 0;
59+
}
60+
61+
bd_error_t I2CEEBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
62+
{
63+
// Check the addr and size fit onto the chip.
64+
if (!is_valid_program(addr, size)) {
65+
return BD_ERROR_PARAMETER;
66+
}
67+
68+
// While we have some more data to write.
69+
while (size > 0) {
70+
_i2c.start();
71+
if (!_i2c.write(_i2c_addr | 0) ||
72+
!_i2c.write((char)(addr >> 8)) ||
73+
!_i2c.write((char)(addr & 0xff))) {
74+
return BD_ERROR_DEVICE_ERROR;
75+
}
76+
77+
for (unsigned i = 0; i < _block; i++) {
78+
_i2c.write(static_cast<const char*>(buffer)[i]);
79+
}
80+
_i2c.stop();
81+
82+
bd_error_t err = _sync();
83+
if (err) {
84+
return err;
85+
}
86+
87+
addr += _block;
88+
size -= _block;
89+
buffer = static_cast<const char*>(buffer) + _block;
90+
}
91+
92+
return 0;
93+
}
94+
95+
bd_error_t I2CEEBlockDevice::erase(bd_addr_t addr, bd_size_t size)
96+
{
97+
// No erase needed
98+
return 0;
99+
}
100+
101+
bd_error_t I2CEEBlockDevice::_sync()
102+
{
103+
// The chip doesn't ACK while writing to the actual EEPROM
104+
// so loop trying to do a zero byte write until it is ACKed
105+
// by the chip.
106+
for (int i = 0; i < I2CEE_TIMEOUT; i++) {
107+
if (_i2c.write(_i2c_addr | 0, 0, 0) < 1) {
108+
return 0;
109+
}
110+
111+
wait_ms(1);
112+
}
113+
114+
return BD_ERROR_DEVICE_ERROR;
115+
}
116+
117+
bd_size_t I2CEEBlockDevice::get_read_size()
118+
{
119+
return 1;
120+
}
121+
122+
bd_size_t I2CEEBlockDevice::get_program_size()
123+
{
124+
return _block;
125+
}
126+
127+
bd_size_t I2CEEBlockDevice::get_erase_size()
128+
{
129+
return _block;
130+
}
131+
132+
bd_size_t I2CEEBlockDevice::size()
133+
{
134+
return _size;
135+
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
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+
/* If the target has no I2C support then I2CEEPROM is not supported */
20+
#ifdef DEVICE_I2C
21+
22+
#include <mbed.h>
23+
#include "BlockDevice.h"
24+
25+
26+
/** BlockDevice for I2C based flash device such as
27+
* Microchip's 24LC or ATMEL's AT24C ranges
28+
*
29+
* @code
30+
* #include "mbed.h"
31+
* #include "I2CEEBlockDevice.h"
32+
*
33+
* // Create 24LC device with 32Kbytes of memory
34+
* I2CEEBlockDevice flash(D14, D15, 0xa0, 32*1024);
35+
*
36+
* int main() {
37+
* printf("flash test\n");
38+
* mx52r.init();
39+
* printf("flash size: %llu\n", flash.size());
40+
* printf("flash read size: %llu\n", flash.get_read_size());
41+
* printf("flash program size: %llu\n", flash.get_program_size());
42+
* printf("flash erase size: %llu\n", flash.get_erase_size());
43+
*
44+
* uint8_t *buffer = malloc(flash.get_erase_size());
45+
* sprintf(buffer, "Hello World!\n");
46+
* flash.erase(0, flash.get_erase_size());
47+
* flash.write(buffer, 0, flash.get_erase_size());
48+
* flash.read(buffer, 0, flash.get_erase_size());
49+
* printf("%s", buffer);
50+
*
51+
* flash.deinit();
52+
* }
53+
*/
54+
class I2CEEBlockDevice : public BlockDevice {
55+
public:
56+
/** Constructor to create an I2CEEBlockDevice on I2C pins
57+
*
58+
* @param sda The pin name for the sda line of the I2C bus.
59+
* @param scl The pin name for the scl line of the I2C bus.
60+
* @param addr The 8bit I2C address of the chip, common range 0xa0 - 0xae.
61+
* @param size The size of the device in bytes
62+
* @param block The block size of the device in bytes, defaults to 32bytes
63+
* @param freq The frequency of the I2C bus, defaults to 400K.
64+
*/
65+
I2CEEBlockDevice(
66+
PinName sda, PinName scl, uint8_t address,
67+
bd_size_t size, bd_size_t block=32,
68+
int bus_speed=400000);
69+
70+
/** Initialize a block device
71+
*
72+
* @return 0 on success or a negative error code on failure
73+
*/
74+
virtual bd_error_t init();
75+
76+
/** Deinitialize a block device
77+
*
78+
* @return 0 on success or a negative error code on failure
79+
*/
80+
virtual bd_error_t deinit();
81+
82+
/** Read blocks from a block device
83+
*
84+
* @param buffer Buffer to write blocks to
85+
* @param addr Address of block to begin reading from
86+
* @param size Size to read in bytes, must be a multiple of read block size
87+
* @return 0 on success, negative error code on failure
88+
*/
89+
virtual bd_error_t read(void *buffer, bd_addr_t addr, bd_size_t size);
90+
91+
/** Program blocks to a block device
92+
*
93+
* The blocks must have been erased prior to being programmed
94+
*
95+
* @param buffer Buffer of data to write to blocks
96+
* @param addr Address of block to begin writing to
97+
* @param size Size to write in bytes, must be a multiple of program block size
98+
* @return 0 on success, negative error code on failure
99+
*/
100+
virtual bd_error_t program(const void *buffer, bd_addr_t addr, bd_size_t size);
101+
102+
/** Erase blocks on a block device
103+
*
104+
* The state of an erased block is undefined until it has been programmed
105+
*
106+
* @param addr Address of block to begin erasing
107+
* @param size Size to erase in bytes, must be a multiple of erase block size
108+
* @return 0 on success, negative error code on failure
109+
*/
110+
virtual bd_error_t erase(bd_addr_t addr, bd_size_t size);
111+
112+
/** Get the size of a readable block
113+
*
114+
* @return Size of a readable block in bytes
115+
*/
116+
virtual bd_size_t get_read_size();
117+
118+
/** Get the size of a programable block
119+
*
120+
* @return Size of a programable block in bytes
121+
* @note Must be a multiple of the read size
122+
*/
123+
virtual bd_size_t get_program_size();
124+
125+
/** Get the size of a eraseable block
126+
*
127+
* @return Size of a eraseable block in bytes
128+
* @note Must be a multiple of the program size
129+
*/
130+
virtual bd_size_t get_erase_size();
131+
132+
/** Get the total size of the underlying device
133+
*
134+
* @return Size of the underlying device in bytes
135+
*/
136+
virtual bd_size_t size();
137+
138+
private:
139+
I2C _i2c;
140+
uint8_t _i2c_addr;
141+
uint32_t _size;
142+
uint32_t _block;
143+
144+
bd_error_t _sync();
145+
};
146+
147+
#endif /* DEVICE_SPI */
148+
149+
#endif /* MBED_SD_BLOCK_DEVICE_H */

0 commit comments

Comments
 (0)