Skip to content

Commit cd34860

Browse files
committed
Add Eight-Bit-Adressing mode to I2CEEBlockDevice.
When dealing with EEPROMs without a 16 bit adressing, the current implementation does not work, as it writes a 16 bit address to the chip. This may cause undefined behaviour. This change adds a new constructor argument to enable this new eight-bit mode. It defaults to false to not break existing code. This constructor argument should actually never be necessary to manually set, except when dealing with cheap devices.
1 parent 3d038e5 commit cd34860

File tree

2 files changed

+51
-25
lines changed

2 files changed

+51
-25
lines changed

components/storage/blockdevice/COMPONENT_I2CEE/I2CEEBlockDevice.cpp

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,21 @@ using namespace mbed;
2222

2323
I2CEEBlockDevice::I2CEEBlockDevice(
2424
PinName sda, PinName scl, uint8_t addr,
25-
bd_size_t size, bd_size_t block, int freq)
26-
: _i2c_addr(addr), _size(size), _block(block)
25+
bd_size_t size, bd_size_t block, int freq,
26+
bool address_is_eight_bit)
27+
: _i2c_addr(addr), _size(size), _block(block),
28+
_address_is_eight_bit(address_is_eight_bit)
2729
{
2830
_i2c = new (_i2c_buffer) I2C(sda, scl);
2931
_i2c->frequency(freq);
3032
}
3133

3234
I2CEEBlockDevice::I2CEEBlockDevice(
3335
I2C *i2c_obj, uint8_t addr,
34-
bd_size_t size, bd_size_t block)
35-
: _i2c_addr(addr), _size(size), _block(block)
36+
bd_size_t size, bd_size_t block,
37+
bool address_is_eight_bit)
38+
: _i2c_addr(addr), _size(size), _block(block),
39+
_address_is_eight_bit(address_is_eight_bit)
3640
{
3741
_i2c = i2c_obj;
3842
}
@@ -60,9 +64,15 @@ int I2CEEBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
6064

6165
_i2c->start();
6266

63-
if (!_i2c->write(_i2c_addr | 0) ||
64-
!_i2c->write((char)(addr >> 8)) ||
65-
!_i2c->write((char)(addr & 0xff))) {
67+
if (!_i2c->write(_i2c_addr | 0)) {
68+
return BD_ERROR_DEVICE_ERROR;
69+
}
70+
71+
if (!_address_is_eight_bit && !_i2c->write((char)(addr >> 8))) {
72+
return BD_ERROR_DEVICE_ERROR;
73+
}
74+
75+
if (!_i2c->write((char)(addr & 0xff))) {
6676
return BD_ERROR_DEVICE_ERROR;
6777
}
6878

@@ -92,9 +102,15 @@ int I2CEEBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size
92102

93103
_i2c->start();
94104

95-
if (!_i2c->write(_i2c_addr | 0) ||
96-
!_i2c->write((char)(addr >> 8)) ||
97-
!_i2c->write((char)(addr & 0xff))) {
105+
if (!_i2c->write(_i2c_addr | 0)) {
106+
return BD_ERROR_DEVICE_ERROR;
107+
}
108+
109+
if (!_address_is_eight_bit && !_i2c->write((char)(addr >> 8))) {
110+
return BD_ERROR_DEVICE_ERROR;
111+
}
112+
113+
if (!_i2c->write((char)(addr & 0xff))) {
98114
return BD_ERROR_DEVICE_ERROR;
99115
}
100116

components/storage/blockdevice/COMPONENT_I2CEE/I2CEEBlockDevice.h

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,29 +59,37 @@ class I2CEEBlockDevice : public BlockDevice {
5959
public:
6060
/** Constructor to create an I2CEEBlockDevice on I2C pins
6161
*
62-
* @param sda The pin name for the sda line of the I2C bus.
63-
* @param scl The pin name for the scl line of the I2C bus.
64-
* @param addr The 8bit I2C address of the chip, common range 0xa0 - 0xae.
65-
* @param size The size of the device in bytes
66-
* @param block The page size of the device in bytes, defaults to 32bytes
67-
* @param freq The frequency of the I2C bus, defaults to 400K.
62+
* @param sda The pin name for the sda line of the I2C bus.
63+
* @param scl The pin name for the scl line of the I2C bus.
64+
* @param addr The 8bit I2C address of the chip, common range 0xa0 - 0xae.
65+
* @param size The size of the device in bytes
66+
* @param block The page size of the device in bytes, defaults to 32bytes
67+
* @param freq The frequency of the I2C bus, defaults to 400K.
68+
* @param address_is_eight_bit Specifies whether the EEPROM device is using eight bit
69+
* addresses instead of 16 bit addresses. This should not be needed
70+
* unless dealing with very cheap devices.
6871
*/
6972
I2CEEBlockDevice(
7073
PinName sda, PinName scl, uint8_t address,
7174
bd_size_t size, bd_size_t block = 32,
72-
int bus_speed = 400000);
75+
int bus_speed = 400000,
76+
bool address_is_eight_bit = false);
7377

7478
/** Constructor to create an I2CEEBlockDevice on I2C pins
75-
*
76-
* @param i2c The I2C instance pointer
77-
* @param addr The 8bit I2C address of the chip, common range 0xa0 - 0xae.
78-
* @param size The size of the device in bytes
79-
* @param block The page size of the device in bytes, defaults to 32bytes
80-
* @param freq The frequency of the I2C bus, defaults to 400K.
81-
*/
79+
*
80+
* @param i2c The I2C instance pointer
81+
* @param addr The 8bit I2C address of the chip, common range 0xa0 - 0xae.
82+
* @param size The size of the device in bytes
83+
* @param block The page size of the device in bytes, defaults to 32bytes
84+
* @param freq The frequency of the I2C bus, defaults to 400K.
85+
* @param address_is_eight_bit Specifies whether the EEPROM device is using eight bit
86+
* addresses instead of 16 bit addresses. This should not be needed
87+
* unless dealing with very cheap devices.
88+
*/
8289
I2CEEBlockDevice(
8390
mbed::I2C *i2c_obj, uint8_t address,
84-
bd_size_t size, bd_size_t block = 32);
91+
bd_size_t size, bd_size_t block = 32,
92+
bool address_is_eight_bit = false);
8593

8694
/** Destructor of I2CEEBlockDevice
8795
*/
@@ -169,6 +177,8 @@ class I2CEEBlockDevice : public BlockDevice {
169177
uint32_t _size;
170178
uint32_t _block;
171179

180+
bool _address_is_eight_bit;
181+
172182
int _sync();
173183
};
174184

0 commit comments

Comments
 (0)