@@ -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
106105int 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
160153int 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+ }
0 commit comments