X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fdrv%2Feeprom.c;h=599db5c34518fce1fe637431d21ee762d5b4e2b4;hb=9a76f040340e6fd0c42989871173fd0a03ec1f2f;hp=7240fccad00bd4601d109be524553131d7196cd2;hpb=d027b58f316922081fa2f7291dc8e45022910a7e;p=bertos.git diff --git a/bertos/drv/eeprom.c b/bertos/drv/eeprom.c index 7240fcca..599db5c3 100644 --- a/bertos/drv/eeprom.c +++ b/bertos/drv/eeprom.c @@ -26,7 +26,7 @@ * invalidate any other reasons why the executable file might be covered by * the GNU General Public License. * - * Copyright 2003, 2004, 2005 Develer S.r.l. (http://www.develer.com/) + * Copyright 2003, 2004, 2005, 2010 Develer S.r.l. (http://www.develer.com/) * * --> * @@ -38,8 +38,7 @@ #include "eeprom.h" -#warning TODO:Test and complete this module for arm platform. -#if !CPU_ARM +#include "cfg/cfg_i2c.h" #include // MIN() #include @@ -70,6 +69,12 @@ */ static const EepromInfo mem_info[] = { + { + /* 24XX08 */ + .has_dev_addr = false, + .blk_size = 0x10, + .e2_size = 0x400, + }, { /* 24XX16 */ .has_dev_addr = false, @@ -88,12 +93,19 @@ static const EepromInfo mem_info[] = .blk_size = 0x80, .e2_size = 0x10000, }, + { + /* 24XX1024 */ + .has_dev_addr = true, + .blk_size = 0x100, + .e2_size = 0x20000, + }, + /* Add other memories here */ }; STATIC_ASSERT(countof(mem_info) == EEPROM_CNT); - +#if 0//!CONFIG_I2C_DISABLE_OLD_API /** * Copy \a size bytes from buffer \a buf to * eeprom. @@ -111,7 +123,7 @@ static size_t eeprom_writeRaw(struct KFile *_fd, const void *buf, size_t size) STATIC_ASSERT(countof(addr_buf) <= sizeof(e2addr_t)); /* clamp size to memory limit (otherwise may roll back) */ - ASSERT(_fd->seek_pos + size <= (kfile_off_t)_fd->size); + ASSERT(_fd->seek_pos + (kfile_off_t)size <= (kfile_off_t)_fd->size); size = MIN((kfile_off_t)size, _fd->size - _fd->seek_pos); if (mem_info[fd->type].has_dev_addr) @@ -211,7 +223,7 @@ static size_t eeprom_read(struct KFile *_fd, void *_buf, size_t size) STATIC_ASSERT(countof(addr_buf) <= sizeof(e2addr_t)); /* clamp size to memory limit (otherwise may roll back) */ - ASSERT(_fd->seek_pos + size <= (kfile_off_t)_fd->size); + ASSERT(_fd->seek_pos + (kfile_off_t)size <= (kfile_off_t)_fd->size); size = MIN((kfile_off_t)size, _fd->size - _fd->seek_pos); e2dev_addr_t dev_addr; @@ -238,20 +250,11 @@ static size_t eeprom_read(struct KFile *_fd, void *_buf, size_t size) return 0; } - while (size--) - { - /* - * The last byte read does not have an ACK - * to stop communication. - */ - int c = i2c_get(size); - if (c == EOF) - break; - - *buf++ = c; - fd->fd.seek_pos++; - rd_len++; + if (i2c_recv(buf, size)) + { + fd->fd.seek_pos += size; + rd_len += size; } i2c_stop(); @@ -388,4 +391,138 @@ void eeprom_init(Eeprom *fd, EepromType type, e2dev_addr_t addr, bool verify) fd->fd.seek = kfile_genericSeek; } -#endif +#endif /* !CONFIG_I2C_DISABLE_OLD_API */ + +static size_t eeprom_writeDirect(KBlock *b, block_idx_t idx, const void *buf, size_t offset, size_t size) +{ + Eeprom *fd = EEPROM_CAST(b); + e2dev_addr_t dev_addr; + uint8_t addr_buf[2]; + uint8_t addr_len; + uint32_t abs_addr = b->blk_size * idx + offset; + + STATIC_ASSERT(countof(addr_buf) <= sizeof(e2addr_t)); + + + /* clamp size to memory limit (otherwise may roll back) */ + ASSERT(idx <= b->blk_cnt); + size = MIN(size, b->blk_size - offset); + + if (mem_info[fd->type].has_dev_addr) + { + dev_addr = fd->addr; + addr_len = 2; + } + else + { + dev_addr = (e2dev_addr_t)((abs_addr >> 8) & 0x07); + addr_len = 1; + } + + if (mem_info[fd->type].has_dev_addr) + { + addr_buf[0] = (abs_addr >> 8) & 0xFF; + addr_buf[1] = (abs_addr & 0xFF); + } + else + { + dev_addr = (e2dev_addr_t)((abs_addr >> 8) & 0x07); + addr_buf[0] = (abs_addr & 0xFF); + } + + i2c_start_w(fd->i2c, EEPROM_ADDR(dev_addr), addr_len + size, I2C_STOP); + i2c_write(fd->i2c, addr_buf, addr_len); + i2c_write(fd->i2c, buf, size); + + if (i2c_error(fd->i2c)) + return 0; + + return size; +} + + +static size_t eeprom_readDirect(struct KBlock *b, block_idx_t idx, void *_buf, size_t offset, size_t size) +{ + Eeprom *fd = EEPROM_CAST(b); + uint8_t addr_buf[2]; + uint8_t addr_len; + size_t rd_len = 0; + uint8_t *buf = (uint8_t *)_buf; + uint32_t abs_addr = mem_info[fd->type].blk_size * idx + offset; + + STATIC_ASSERT(countof(addr_buf) <= sizeof(e2addr_t)); + + /* clamp size to memory limit (otherwise may roll back) */ + ASSERT(idx <= b->blk_cnt); + size = MIN(size, b->blk_size - offset); + + e2dev_addr_t dev_addr; + if (mem_info[fd->type].has_dev_addr) + { + dev_addr = fd->addr; + addr_len = 2; + addr_buf[0] = (abs_addr >> 8) & 0xFF; + addr_buf[1] = (abs_addr & 0xFF); + } + else + { + dev_addr = (e2dev_addr_t)((abs_addr >> 8) & 0x07); + addr_len = 1; + addr_buf[0] = (abs_addr & 0xFF); + } + + + i2c_start_w(fd->i2c, EEPROM_ADDR(dev_addr), addr_len, I2C_NOSTOP); + i2c_write(fd->i2c, addr_buf, addr_len); + + i2c_start_r(fd->i2c, EEPROM_ADDR(dev_addr), size, I2C_STOP); + i2c_read(fd->i2c, buf, size); + + if (i2c_error(fd->i2c)) + return rd_len; + + rd_len += size; + + return rd_len; +} + +static int kblockEeprom_dummy(UNUSED_ARG(struct KBlock *,b)) +{ + return 0; +} + + +static const KBlockVTable eeprom_unbuffered_vt = +{ + .readDirect = eeprom_readDirect, + .writeDirect = eeprom_writeDirect, + + .error = kblockEeprom_dummy, + .clearerr = (kblock_clearerr_t)kblockEeprom_dummy, +}; + +/** + * Initialize EEPROM module. + * \param b is the Kblock context. + * \param type is the eeprom device we want to initialize (\see EepromType) + * \param i2c context for i2c channel + * \param addr is the i2c devide address (usually pins A0, A1, A2). + */ +void eeprom_init(Eeprom *b, I2c *i2c, EepromType type, e2dev_addr_t addr) +{ + ASSERT(type < EEPROM_CNT); + + memset(b, 0, sizeof(*b)); + DB(b->b.priv.type = KBT_EEPROM); + + b->type = type; + b->addr = addr; + b->i2c = i2c; + + b->b.blk_size = mem_info[type].blk_size; + b->b.blk_cnt = mem_info[type].e2_size / mem_info[type].blk_size; + b->b.priv.flags |= KB_PARTIAL_WRITE; + b->b.priv.vt = &eeprom_unbuffered_vt; +} + +