-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Eight-Bit-Addressing mode to I2CEEBlockDevice. #12446
Changes from all commits
cd34860
8d1978e
52aed22
e850984
267d8cc
76a177f
7c589ae
532f378
3741440
4d0c346
440fa49
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,17 +22,21 @@ using namespace mbed; | |
|
||
I2CEEBlockDevice::I2CEEBlockDevice( | ||
PinName sda, PinName scl, uint8_t addr, | ||
bd_size_t size, bd_size_t block, int freq) | ||
: _i2c_addr(addr), _size(size), _block(block) | ||
bd_size_t size, bd_size_t block, int freq, | ||
bool address_is_eight_bit) | ||
: _i2c_addr(addr), _size(size), _block(block), | ||
_address_is_eight_bit(address_is_eight_bit) | ||
{ | ||
_i2c = new (_i2c_buffer) I2C(sda, scl); | ||
_i2c->frequency(freq); | ||
} | ||
|
||
I2CEEBlockDevice::I2CEEBlockDevice( | ||
I2C *i2c_obj, uint8_t addr, | ||
bd_size_t size, bd_size_t block) | ||
: _i2c_addr(addr), _size(size), _block(block) | ||
bd_size_t size, bd_size_t block, | ||
bool address_is_eight_bit) | ||
: _i2c_addr(addr), _size(size), _block(block), | ||
_address_is_eight_bit(address_is_eight_bit) | ||
{ | ||
_i2c = i2c_obj; | ||
} | ||
|
@@ -58,48 +62,61 @@ int I2CEEBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) | |
// Check the address and size fit onto the chip. | ||
MBED_ASSERT(is_valid_read(addr, size)); | ||
|
||
auto *pBuffer = static_cast<char *>(buffer); | ||
|
||
_i2c->start(); | ||
|
||
if (!_i2c->write(_i2c_addr | 0) || | ||
!_i2c->write((char)(addr >> 8)) || | ||
!_i2c->write((char)(addr & 0xff))) { | ||
if (1 != _i2c->write(get_paged_device_address(addr))) { | ||
return BD_ERROR_DEVICE_ERROR; | ||
} | ||
|
||
_i2c->stop(); | ||
if (!_address_is_eight_bit && 1 != _i2c->write((char)(addr >> 8u))) { | ||
return BD_ERROR_DEVICE_ERROR; | ||
} | ||
|
||
auto err = _sync(); | ||
if (err) { | ||
return err; | ||
if (1 != _i2c->write((char)(addr & 0xffu))) { | ||
return BD_ERROR_DEVICE_ERROR; | ||
} | ||
|
||
if (0 != _i2c->read(_i2c_addr, static_cast<char *>(buffer), size)) { | ||
_i2c->stop(); | ||
|
||
if (0 != _i2c->read(_i2c_addr, pBuffer, size)) { | ||
return BD_ERROR_DEVICE_ERROR; | ||
} | ||
|
||
return 0; | ||
return BD_ERROR_OK; | ||
} | ||
|
||
int I2CEEBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) | ||
{ | ||
// Check the addr and size fit onto the chip. | ||
MBED_ASSERT(is_valid_program(addr, size)); | ||
|
||
const auto *pBuffer = static_cast<const char *>(buffer); | ||
|
||
// While we have some more data to write. | ||
while (size > 0) { | ||
uint32_t off = addr % _block; | ||
uint32_t chunk = (off + size < _block) ? size : (_block - off); | ||
|
||
_i2c->start(); | ||
|
||
if (!_i2c->write(_i2c_addr | 0) || | ||
!_i2c->write((char)(addr >> 8)) || | ||
!_i2c->write((char)(addr & 0xff))) { | ||
if (1 != _i2c->write(get_paged_device_address(addr))) { | ||
return BD_ERROR_DEVICE_ERROR; | ||
} | ||
|
||
if (!_address_is_eight_bit && 1 != _i2c->write((char)(addr >> 8u))) { | ||
return BD_ERROR_DEVICE_ERROR; | ||
} | ||
|
||
if (1 != _i2c->write((char)(addr & 0xffu))) { | ||
return BD_ERROR_DEVICE_ERROR; | ||
} | ||
|
||
for (unsigned i = 0; i < chunk; i++) { | ||
_i2c->write(static_cast<const char *>(buffer)[i]); | ||
if (1 != _i2c->write(pBuffer[i])) { | ||
return BD_ERROR_DEVICE_ERROR; | ||
} | ||
} | ||
|
||
_i2c->stop(); | ||
|
@@ -112,10 +129,10 @@ int I2CEEBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size | |
|
||
addr += chunk; | ||
size -= chunk; | ||
buffer = static_cast<const char *>(buffer) + chunk; | ||
pBuffer += chunk; | ||
} | ||
|
||
return 0; | ||
return BD_ERROR_OK; | ||
} | ||
|
||
int I2CEEBlockDevice::erase(bd_addr_t addr, bd_size_t size) | ||
|
@@ -164,3 +181,15 @@ const char *I2CEEBlockDevice::get_type() const | |
{ | ||
return "I2CEE"; | ||
} | ||
|
||
uint8_t I2CEEBlockDevice::get_paged_device_address(bd_addr_t address) | ||
{ | ||
if (!_address_is_eight_bit) { | ||
return _i2c_addr; | ||
} else { | ||
// Use the three least significant bits of the 2nd byte as the page | ||
// The page will be bits 2-4 of the user defined addresses. | ||
return _i2c_addr | ((address & 0x0700u) >> 7u); | ||
} | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Think you've gone overboard and now have an excess blank line :) (Any Git diff should show both cases in red normally). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops, I didn't know where you wanted the NL. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's possible I'm being misled by GitHub's view, but I think originally you had an unterminated final |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't directly relate to this PR, but this driver should now really have a constructor that takes
const i2c_pinmap_t &
and passes toI2C
to offer the possibility to avoid pulling in pinmap tables.It would be nice to add this, but I guess as a follow-up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think this should be a separate PR as it actually has nothing to do with the 8bit-mode.