Skip to content

Commit 532f378

Browse files
committedFeb 18, 2020
Remove overcomplicated code from I2CEEBlockDevice
1 parent 7c589ae commit 532f378

File tree

2 files changed

+51
-130
lines changed

2 files changed

+51
-130
lines changed
 

‎components/storage/blockdevice/COMPONENT_I2CEE/I2CEEBlockDevice.cpp

+49-111
Original file line numberDiff line numberDiff line change
@@ -62,99 +62,92 @@ int I2CEEBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
6262
// Check the address and size fit onto the chip.
6363
MBED_ASSERT(is_valid_read(addr, size));
6464

65-
auto *charBuffer = reinterpret_cast<char *>(buffer);
65+
auto *pBuffer = reinterpret_cast<char *>(buffer);
66+
67+
while (size > 0) {
68+
uint32_t off = addr % _block;
69+
uint32_t chunk = (off + size < _block) ? size : (_block - off);
6670

67-
auto const handler = [&](const bd_addr_t &pagedStart, const bd_size_t &pagedLength, const uint8_t &pagedDeviceAddress) -> int {
6871
_i2c->start();
6972

70-
if (1 != _i2c->write(pagedDeviceAddress))
71-
{
73+
if (1 != _i2c->write(get_paged_device_address(addr))) {
7274
return BD_ERROR_DEVICE_ERROR;
7375
}
7476

75-
if (!_address_is_eight_bit && 1 != _i2c->write((char)(pagedStart >> 8u)))
76-
{
77+
if (!_address_is_eight_bit && 1 != _i2c->write((char)(addr >> 8u))) {
7778
return BD_ERROR_DEVICE_ERROR;
7879
}
7980

80-
if (1 != _i2c->write((char)(pagedStart & 0xffu)))
81-
{
81+
if (1 != _i2c->write((char)(addr & 0xffu))) {
8282
return BD_ERROR_DEVICE_ERROR;
8383
}
8484

8585
_i2c->stop();
8686

8787
auto err = _sync();
88-
if (err)
89-
{
88+
89+
if (err) {
9090
return err;
9191
}
9292

93-
if (0 != _i2c->read(_i2c_addr, charBuffer, pagedLength))
94-
{
93+
if (0 != _i2c->read(_i2c_addr, pBuffer, chunk)) {
9594
return BD_ERROR_DEVICE_ERROR;
9695
}
9796

98-
charBuffer += size;
99-
100-
return BD_ERROR_OK;
101-
};
97+
addr += chunk;
98+
size -= chunk;
99+
pBuffer += chunk;
100+
}
102101

103-
return do_paged(addr, size, handler);
102+
return BD_ERROR_OK;
104103
}
105104

106105
int I2CEEBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
107106
{
108107
// Check the addr and size fit onto the chip.
109108
MBED_ASSERT(is_valid_program(addr, size));
110109

111-
auto const *charBuffer = reinterpret_cast<char const *>(buffer);
110+
auto const *pBuffer = reinterpret_cast<char const *>(buffer);
112111

113-
auto const handler = [&](const bd_addr_t &pagedStart, const bd_size_t &pagedLength, const uint8_t &pagedDeviceAddress) -> int {
114-
// While we have some more data to write.
115-
while (size > 0)
116-
{
117-
uint32_t off = addr % _block;
118-
uint32_t chunk = (off + size < _block) ? size : (_block - off);
112+
// While we have some more data to write.
113+
while (size > 0) {
114+
uint32_t off = addr % _block;
115+
uint32_t chunk = (off + size < _block) ? size : (_block - off);
119116

120-
_i2c->start();
117+
_i2c->start();
121118

122-
if (1 != _i2c->write(pagedDeviceAddress)) {
123-
return BD_ERROR_DEVICE_ERROR;
124-
}
119+
if (1 != _i2c->write(get_paged_device_address(addr))) {
120+
return BD_ERROR_DEVICE_ERROR;
121+
}
125122

126-
if (!_address_is_eight_bit && 1 != _i2c->write((char)(pagedStart >> 8u))) {
127-
return BD_ERROR_DEVICE_ERROR;
128-
}
123+
if (!_address_is_eight_bit && 1 != _i2c->write((char)(addr >> 8u))) {
124+
return BD_ERROR_DEVICE_ERROR;
125+
}
129126

130-
if (1 != _i2c->write((char)(addr & 0xffu))) {
131-
return BD_ERROR_DEVICE_ERROR;
132-
}
127+
if (1 != _i2c->write((char)(addr & 0xffu))) {
128+
return BD_ERROR_DEVICE_ERROR;
129+
}
133130

134-
for (unsigned i = 0; i < chunk; i++) {
135-
if (1 != _i2c->write(charBuffer[i])) {
136-
return BD_ERROR_DEVICE_ERROR;
137-
}
131+
for (unsigned i = 0; i < chunk; i++) {
132+
if (1 != _i2c->write(pBuffer[i])) {
133+
return BD_ERROR_DEVICE_ERROR;
138134
}
135+
}
139136

140-
_i2c->stop();
141-
142-
int err = _sync();
137+
_i2c->stop();
143138

144-
if (err) {
145-
return err;
146-
}
139+
int err = _sync();
147140

148-
addr += chunk;
149-
size -= chunk;
150-
charBuffer += chunk;
141+
if (err) {
142+
return err;
151143
}
152144

153-
return BD_ERROR_OK;
154-
};
145+
addr += chunk;
146+
size -= chunk;
147+
pBuffer += chunk;
148+
}
155149

156-
auto const originalSize = size;
157-
return do_paged(addr, originalSize, handler);
150+
return BD_ERROR_OK;
158151
}
159152

160153
int I2CEEBlockDevice::erase(bd_addr_t addr, bd_size_t size)
@@ -204,68 +197,13 @@ const char *I2CEEBlockDevice::get_type() const
204197
return "I2CEE";
205198
}
206199

207-
int I2CEEBlockDevice::do_paged(const bd_addr_t &startAddress,
208-
const bd_size_t &length,
209-
const paged_handler &handler)
210-
{
211-
// This helper is only used for eight bit mode.
212-
if (!this->_address_is_eight_bit) {
213-
return handler(startAddress, length, get_paged_device_address(0));
214-
}
215-
216-
auto currentStartAddress = startAddress;
217-
218-
auto const pageSize = 256;
219-
bd_size_t lengthDone = 0;
220-
while (lengthDone != length) {
221-
/* Integer division => Round down */
222-
uint8_t const currentPage = currentStartAddress / pageSize;
223-
bd_addr_t const nextPageBegin = (currentPage + 1) * pageSize;
224-
bd_addr_t const currentReadEndAddressExclusive = std::min(nextPageBegin, startAddress + length);
225-
bd_size_t const currentLength = currentReadEndAddressExclusive - currentStartAddress;
226-
bd_addr_t const pagedBegin = currentStartAddress - (currentPage * pageSize);
227-
uint8_t const pagedDeviceAddress = get_paged_device_address(currentPage);
228-
229-
auto const handlerReturn = handler(pagedBegin, currentLength, pagedDeviceAddress);
230-
if (handlerReturn != BD_ERROR_OK) {
231-
return handlerReturn;
232-
}
233-
234-
currentStartAddress = currentReadEndAddressExclusive;
235-
lengthDone += currentLength;
236-
}
237-
238-
return BD_ERROR_OK;
239-
}
240-
241-
uint8_t I2CEEBlockDevice::get_paged_device_address(const uint8_t &page)
200+
uint8_t I2CEEBlockDevice::get_paged_device_address(const bd_addr_t &address)
242201
{
243202
if (!this->_address_is_eight_bit) {
244203
return this->_i2c_addr;
245204
} else {
246-
// This method uses a dynamically created bit mask for the page given.
247-
// This ensures compatibility with all sizes of ICs.
248-
// E. g. the 512K variants have two user address bits and one page bit.
249-
// We don't want to forcefully override the two user address bits.
250-
251-
// Create a mask to cover all bits required to set page
252-
// i starts at one because the LSB is used for R/W in I2C
253-
uint8_t i = 1;
254-
uint8_t addressMask = 0;
255-
auto p = page;
256-
while (p != 0u) {
257-
addressMask |= (1u << i);
258-
p >>= 1u;
259-
i++;
260-
}
261-
262-
uint8_t pagedDeviceAddress = this->_i2c_addr & static_cast<uint8_t>(~addressMask);
263-
// Assert page < 0b111, because we don't have
264-
// more bits for page encoding
265-
// Don't actually write 0b111, this is a nonstandard extension.
266-
MBED_ASSERT(page < 0x7);
267-
pagedDeviceAddress |= static_cast<uint8_t>(page << 1u);
268-
269-
return pagedDeviceAddress;
205+
// Use the three least significant bits of the 2nd byte as the page
206+
// The page will be bits 2-4 of the user defined addresses.
207+
return this->_i2c_addr | ((address & 0x0700u) >> 7u);
270208
}
271-
}
209+
}

‎components/storage/blockdevice/COMPONENT_I2CEE/I2CEEBlockDevice.h

+2-19
Original file line numberDiff line numberDiff line change
@@ -181,32 +181,15 @@ class I2CEEBlockDevice : public BlockDevice {
181181

182182
int _sync();
183183

184-
using paged_handler = std::function<int(const bd_addr_t &address, const bd_size_t &length, const uint8_t &deviceAddress)>;
185-
186-
/**
187-
* Executes a handler across page boundaries for eight bit mode.
188-
* When eight bit mode is disabled, the function does not do paging at all.
189-
* When eight bit mode is enabled, this function splits the requested
190-
* address space into multiple pages when needed.
191-
* This is required when a read or write must be done across multiple pages.
192-
*
193-
* @param startAddress The address to start
194-
* @param length The requested length of the operation
195-
* @param handler The handler to execute
196-
* @return Returns 0 when all calls to handler() return 0. Otherwise the
197-
* error code from the first non-zero handler() call.
198-
*/
199-
int do_paged(const bd_addr_t &startAddress, const bd_size_t &length, const paged_handler &handler);
200-
201184
/**
202185
* Gets the device's I2C address with respect to the requested page.
203186
* When eight bit mode is disabled, this function is a noop.
204187
* When eight bit mode is enabled, it sets the bits required for this bit
205188
* in the devices address. Other bits remain unchained.
206-
* @param page The requested page
189+
* @param address An address in the requested page.
207190
* @return The device's I2C address for that page
208191
*/
209-
uint8_t get_paged_device_address(const uint8_t &page);
192+
uint8_t get_paged_device_address(const bd_addr_t &address);
210193
};
211194

212195

0 commit comments

Comments
 (0)
Please sign in to comment.