Skip to content

Commit b396c79

Browse files
committed
hal_ee24xx.c: support 1 byte address
1 parent 3a2bcc9 commit b396c79

File tree

1 file changed

+88
-17
lines changed

1 file changed

+88
-17
lines changed

os/hal/src/hal_ee24xx.c

Lines changed: 88 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -120,19 +120,37 @@ static msg_t eeprom_read(const I2CEepromFileConfig *eepcfg,
120120
uint32_t offset, uint8_t *data, size_t len) {
121121

122122
msg_t status = MSG_RESET;
123-
systime_t tmo = calc_timeout(eepcfg->i2cp, 2, len);
123+
/* Determine addressing mode based on device size. Devices up to 16 Kbit (2 KB)
124+
use a 1-byte word address with block select bits in the I2C address. Larger
125+
devices use 2-byte word addresses. */
126+
const bool one_byte_addr = (eepcfg->size <= 2048U);
127+
const uint32_t eff_off = offset + eepcfg->barrier_low;
128+
const size_t addr_bytes = one_byte_addr ? 1U : 2U;
129+
systime_t tmo = calc_timeout(eepcfg->i2cp, addr_bytes, len);
124130

125131
osalDbgAssert(((len <= eepcfg->size) && ((offset + len) <= eepcfg->size)),
126132
"out of device bounds");
127133

128-
eeprom_split_addr(eepcfg->write_buf, (offset + eepcfg->barrier_low));
134+
/* Prepare address buffer */
135+
if (one_byte_addr) {
136+
eepcfg->write_buf[0] = (uint8_t)(eff_off & 0xFFU);
137+
} else {
138+
eeprom_split_addr(eepcfg->write_buf, eff_off);
139+
}
140+
141+
/* Compute 7-bit I2C address, adding block select bits for small-density parts. */
142+
i2caddr_t i2c_addr = eepcfg->addr;
143+
if (one_byte_addr) {
144+
/* Up to 8 blocks (24C16) use bits [10:8]; for 24C08 only [9:8] are used. */
145+
i2c_addr = (i2caddr_t)(eepcfg->addr | ((eff_off >> 8U) & 0x07U));
146+
}
129147

130148
#if I2C_USE_MUTUAL_EXCLUSION
131149
i2cAcquireBus(eepcfg->i2cp);
132150
#endif
133151

134-
status = i2cMasterTransmitTimeout(eepcfg->i2cp, eepcfg->addr,
135-
eepcfg->write_buf, 2, data, len, tmo);
152+
status = i2cMasterTransmitTimeout(eepcfg->i2cp, i2c_addr,
153+
eepcfg->write_buf, addr_bytes, data, len, tmo);
136154

137155
#if I2C_USE_MUTUAL_EXCLUSION
138156
i2cReleaseBus(eepcfg->i2cp);
@@ -154,7 +172,10 @@ static msg_t eeprom_read(const I2CEepromFileConfig *eepcfg,
154172
static msg_t eeprom_write(const I2CEepromFileConfig *eepcfg, uint32_t offset,
155173
const uint8_t *data, size_t len) {
156174
msg_t status = MSG_RESET;
157-
systime_t tmo = calc_timeout(eepcfg->i2cp, (len + 2), 0);
175+
const bool one_byte_addr = (eepcfg->size <= 2048U);
176+
const uint32_t eff_off = offset + eepcfg->barrier_low;
177+
const size_t addr_bytes = one_byte_addr ? 1U : 2U;
178+
systime_t tmo = calc_timeout(eepcfg->i2cp, (len + addr_bytes), 0);
158179

159180
osalDbgAssert(((len <= eepcfg->size) && ((offset + len) <= eepcfg->size)),
160181
"out of device bounds");
@@ -163,16 +184,26 @@ static msg_t eeprom_write(const I2CEepromFileConfig *eepcfg, uint32_t offset,
163184
"data can not be fitted in single page");
164185

165186
/* write address bytes */
166-
eeprom_split_addr(eepcfg->write_buf, (offset + eepcfg->barrier_low));
187+
if (one_byte_addr) {
188+
eepcfg->write_buf[0] = (uint8_t)(eff_off & 0xFFU);
189+
} else {
190+
eeprom_split_addr(eepcfg->write_buf, eff_off);
191+
}
167192
/* write data bytes */
168-
memcpy(&(eepcfg->write_buf[2]), data, len);
193+
memcpy(&(eepcfg->write_buf[addr_bytes]), data, len);
194+
195+
/* Compute 7-bit I2C address, adding block select bits for small-density parts. */
196+
i2caddr_t i2c_addr = eepcfg->addr;
197+
if (one_byte_addr) {
198+
i2c_addr = (i2caddr_t)(eepcfg->addr | ((eff_off >> 8U) & 0x07U));
199+
}
169200

170201
#if I2C_USE_MUTUAL_EXCLUSION
171202
i2cAcquireBus(eepcfg->i2cp);
172203
#endif
173204

174-
status = i2cMasterTransmitTimeout(eepcfg->i2cp, eepcfg->addr,
175-
eepcfg->write_buf, (len + 2), NULL, 0, tmo);
205+
status = i2cMasterTransmitTimeout(eepcfg->i2cp, i2c_addr,
206+
eepcfg->write_buf, (len + addr_bytes), NULL, 0, tmo);
176207

177208
#if I2C_USE_MUTUAL_EXCLUSION
178209
i2cReleaseBus(eepcfg->i2cp);
@@ -228,6 +259,7 @@ static size_t write(void *ip, const uint8_t *bp, size_t n) {
228259
uint16_t pagesize;
229260
uint32_t firstpage;
230261
uint32_t lastpage;
262+
bool one_byte_addr;
231263

232264
osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
233265

@@ -239,6 +271,7 @@ static size_t write(void *ip, const uint8_t *bp, size_t n) {
239271
return 0;
240272

241273
pagesize = ((EepromFileStream *)ip)->cfg->pagesize;
274+
one_byte_addr = (((EepromFileStream *)ip)->cfg->size <= 2048U);
242275
firstpage = (((EepromFileStream *)ip)->cfg->barrier_low +
243276
eepfs_getposition(ip, NULL)) / pagesize;
244277
lastpage = (((EepromFileStream *)ip)->cfg->barrier_low +
@@ -247,6 +280,13 @@ static size_t write(void *ip, const uint8_t *bp, size_t n) {
247280
/* data fits in single page */
248281
if (firstpage == lastpage) {
249282
len = n;
283+
if (one_byte_addr) {
284+
/* Do not cross 256-byte block address boundary in one transaction */
285+
uint32_t pos = eepfs_getposition(ip, NULL);
286+
uint32_t eff_pos = ((EepromFileStream *)ip)->cfg->barrier_low + pos;
287+
size_t block_rem = 256U - (eff_pos & 0xFFU);
288+
if (len > block_rem) len = block_rem;
289+
}
250290
__fitted_write(ip, bp, len, &written);
251291
return written;
252292
}
@@ -255,13 +295,25 @@ static size_t write(void *ip, const uint8_t *bp, size_t n) {
255295
/* write first piece of data to first page boundary */
256296
len = ((firstpage + 1) * pagesize) - eepfs_getposition(ip, NULL);
257297
len -= ((EepromFileStream *)ip)->cfg->barrier_low;
298+
if (one_byte_addr) {
299+
uint32_t pos = eepfs_getposition(ip, NULL);
300+
uint32_t eff_pos = ((EepromFileStream *)ip)->cfg->barrier_low + pos;
301+
size_t block_rem = 256U - (eff_pos & 0xFFU);
302+
if (len > block_rem) len = block_rem;
303+
}
258304
if (__fitted_write(ip, bp, len, &written) != MSG_OK)
259305
return written;
260306
bp += len;
261307

262308
/* now write page sized blocks (zero or more) */
263309
while ((n - written) > pagesize) {
264310
len = pagesize;
311+
if (one_byte_addr) {
312+
uint32_t pos = eepfs_getposition(ip, NULL);
313+
uint32_t eff_pos = ((EepromFileStream *)ip)->cfg->barrier_low + pos;
314+
size_t block_rem = 256U - (eff_pos & 0xFFU);
315+
if (len > block_rem) len = block_rem;
316+
}
265317
if (__fitted_write(ip, bp, len, &written) != MSG_OK)
266318
return written;
267319
bp += len;
@@ -272,6 +324,12 @@ static size_t write(void *ip, const uint8_t *bp, size_t n) {
272324
if (len == 0)
273325
return written;
274326
else {
327+
if (one_byte_addr) {
328+
uint32_t pos = eepfs_getposition(ip, NULL);
329+
uint32_t eff_pos = ((EepromFileStream *)ip)->cfg->barrier_low + pos;
330+
size_t block_rem = 256U - (eff_pos & 0xFFU);
331+
if (len > block_rem) len = block_rem;
332+
}
275333
__fitted_write(ip, bp, len, &written);
276334
}
277335
}
@@ -324,15 +382,28 @@ static size_t read(void *ip, uint8_t *bp, size_t n) {
324382
}
325383
#endif /* defined(STM32F1XX_I2C) */
326384

327-
/* call low level function */
328-
status = eeprom_read(((I2CEepromFileStream *)ip)->cfg,
329-
eepfs_getposition(ip, NULL), bp, n);
330-
if (status != MSG_OK)
331-
return 0;
332-
else {
333-
eepfs_lseek(ip, (eepfs_getposition(ip, NULL) + n));
334-
return n;
385+
/* Perform reads, splitting at 256-byte block boundaries for small devices. */
386+
size_t read_total = 0;
387+
const bool one_byte_addr = (((I2CEepromFileStream *)ip)->cfg->size <= 2048U);
388+
while (n > 0) {
389+
size_t chunk = n;
390+
if (one_byte_addr) {
391+
uint32_t pos = eepfs_getposition(ip, NULL);
392+
uint32_t eff_pos = ((I2CEepromFileStream *)ip)->cfg->barrier_low + pos;
393+
size_t block_rem = 256U - (eff_pos & 0xFFU);
394+
if (chunk > block_rem) chunk = block_rem;
395+
}
396+
status = eeprom_read(((I2CEepromFileStream *)ip)->cfg,
397+
eepfs_getposition(ip, NULL), bp, chunk);
398+
if (status != MSG_OK) {
399+
return read_total; /* return bytes read so far */
400+
}
401+
eepfs_lseek(ip, (eepfs_getposition(ip, NULL) + chunk));
402+
bp += chunk;
403+
n -= chunk;
404+
read_total += chunk;
335405
}
406+
return read_total;
336407
}
337408

338409
static const struct EepromFileStreamVMT vmt = {

0 commit comments

Comments
 (0)