4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2003, 2004, 2005 Develer S.r.l. (http://www.develer.com/)
33 * \brief Driver for the 24xx16 and 24xx256 I2C EEPROMS (implementation)
35 * \author Stefano Fedrigo <aleph@develer.com>
36 * \author Bernie Innocenti <bernie@codewiz.org>
41 #warning TODO:Test and complete this module for arm platform.
44 #include <cfg/macros.h> // MIN()
45 #include <cfg/debug.h>
46 #include <cfg/module.h> // MOD_CHECK()
53 #include <cpu/byteorder.h> // cpu_to_be16()
55 #include <string.h> // memset()
60 #define EEPROM_ID 0xA0
63 * This macros form the correct slave address for EEPROMs
65 #define EEPROM_ADDR(x) (EEPROM_ID | (((uint8_t)((x) & 0x07)) << 1))
69 * Array used to describe EEPROM memory devices currently supported.
71 static const EepromInfo mem_info[] =
75 .has_dev_addr = false,
81 .has_dev_addr = false,
97 /* Add other memories here */
100 STATIC_ASSERT(countof(mem_info) == EEPROM_CNT);
104 * Copy \a size bytes from buffer \a buf to
107 static size_t eeprom_writeRaw(struct KFile *_fd, const void *buf, size_t size)
109 Eeprom *fd = EEPROM_CAST(_fd);
110 e2dev_addr_t dev_addr;
115 e2blk_size_t blk_size = mem_info[fd->type].blk_size;
117 STATIC_ASSERT(countof(addr_buf) <= sizeof(e2addr_t));
119 /* clamp size to memory limit (otherwise may roll back) */
120 ASSERT(_fd->seek_pos + size <= (kfile_off_t)_fd->size);
121 size = MIN((kfile_off_t)size, _fd->size - _fd->seek_pos);
123 if (mem_info[fd->type].has_dev_addr)
130 dev_addr = (e2dev_addr_t)((fd->fd.seek_pos >> 8) & 0x07);
137 * Split write in multiple sequential mode operations that
138 * don't cross page boundaries.
140 size_t count = MIN(size, (size_t)(blk_size - (fd->fd.seek_pos & (blk_size - 1))));
142 if (mem_info[fd->type].has_dev_addr)
144 addr_buf[0] = (fd->fd.seek_pos >> 8) & 0xFF;
145 addr_buf[1] = (fd->fd.seek_pos & 0xFF);
149 dev_addr = (e2dev_addr_t)((fd->fd.seek_pos >> 8) & 0x07);
150 addr_buf[0] = (fd->fd.seek_pos & 0xFF);
154 if (!(i2c_start_w(EEPROM_ADDR(dev_addr))
155 && i2c_send(addr_buf, addr_len)
156 && i2c_send(buf, count)))
164 /* Update count and addr for next operation */
166 fd->fd.seek_pos += count;
167 buf = ((const char *)buf) + count;
175 * Copy \a size bytes from buffer \a _buf to
177 * \note Writes are verified and if buffer content
178 * is not matching we retry 5 times max.
180 static size_t eeprom_writeVerify(struct KFile *_fd, const void *_buf, size_t size)
182 Eeprom *fd = EEPROM_CAST(_fd);
188 wr_len = eeprom_writeRaw(_fd, _buf, size);
189 /* rewind to verify what we have just written */
190 kfile_seek(_fd, -(kfile_off_t)wr_len, KSM_SEEK_CUR);
192 && eeprom_verify(fd, _buf, wr_len))
194 /* Forward to go after what we have written*/
195 kfile_seek(_fd, wr_len, KSM_SEEK_CUR);
205 * from eeprom to RAM to buffer \a _buf.
207 * \return the number of bytes read.
209 static size_t eeprom_read(struct KFile *_fd, void *_buf, size_t size)
211 Eeprom *fd = EEPROM_CAST(_fd);
215 uint8_t *buf = (uint8_t *)_buf;
217 STATIC_ASSERT(countof(addr_buf) <= sizeof(e2addr_t));
219 /* clamp size to memory limit (otherwise may roll back) */
220 ASSERT(_fd->seek_pos + size <= (kfile_off_t)_fd->size);
221 size = MIN((kfile_off_t)size, _fd->size - _fd->seek_pos);
223 e2dev_addr_t dev_addr;
224 if (mem_info[fd->type].has_dev_addr)
228 addr_buf[0] = (fd->fd.seek_pos >> 8) & 0xFF;
229 addr_buf[1] = (fd->fd.seek_pos & 0xFF);
233 dev_addr = (e2dev_addr_t)((fd->fd.seek_pos >> 8) & 0x07);
235 addr_buf[0] = (fd->fd.seek_pos & 0xFF);
239 if (!(i2c_start_w(EEPROM_ADDR(dev_addr))
240 && i2c_send(addr_buf, addr_len)
241 && i2c_start_r(EEPROM_ADDR(dev_addr))))
250 * The last byte read does not have an ACK
251 * to stop communication.
253 int c = i2c_get(size);
268 * Check that the contents of an EEPROM range
269 * match with a provided data buffer.
271 * \return true on success.
272 * \note Seek position of \a fd will not change.
274 bool eeprom_verify(Eeprom *fd, const void *buf, size_t count)
276 uint8_t verify_buf[16];
279 /* Save seek position */
280 kfile_off_t prev_seek = fd->fd.seek_pos;
282 while (count && result)
284 /* Split read in smaller pieces */
285 size_t size = MIN(count, sizeof verify_buf);
287 /* Read back buffer */
288 if (eeprom_read(&fd->fd, verify_buf, size))
290 if (memcmp(buf, verify_buf, size) != 0)
292 TRACEMSG("Data mismatch!");
298 TRACEMSG("Read error!");
302 /* Update count and addr for next operation */
304 buf = ((const char *)buf) + size;
307 /* Restore previous seek position */
308 fd->fd.seek_pos = prev_seek;
313 * Erase specified part of eeprom, writing 0xFF.
315 * \a addr starting address
316 * \a count length of block to erase
317 * \note Seek position is unchanged.
318 * \return true if ok, false otherwise.
320 bool eeprom_erase(Eeprom *fd, e2addr_t addr, e2_size_t count)
322 e2blk_size_t blk_size = mem_info[fd->type].blk_size;
323 uint8_t buf[blk_size];
324 kfile_off_t prev_off = fd->fd.seek_pos;
328 memset(buf, 0xFF, blk_size);
331 kfile_seek(&fd->fd, addr, KSM_SEEK_SET);
334 * Optimization: this first write id used to realign
335 * current address to block boundaries.
339 size = MIN(count, (e2_size_t)(blk_size - (addr & (blk_size - 1))));
340 if (kfile_write(&fd->fd, buf, size) != size)
342 fd->fd.seek_pos = prev_off;
350 /* Long operation, reset watchdog */
353 size = MIN(count, (e2_size_t)sizeof buf);
354 if (kfile_write(&fd->fd, buf, size) != size)
362 fd->fd.seek_pos = prev_off;
368 * Initialize EEPROM module.
369 * \a fd is the Kfile context.
370 * \a type is the eeprom device we want to initialize (\see EepromType)
371 * \a addr is the i2c devide address (usually pins A0, A1, A2).
372 * \a verify is true if you want that every write operation will be verified.
374 void eeprom_init(Eeprom *fd, EepromType type, e2dev_addr_t addr, bool verify)
377 ASSERT(type < EEPROM_CNT);
379 memset(fd, 0, sizeof(*fd));
380 DB(fd->fd._type = KFT_EEPROM);
384 fd->fd.size = mem_info[fd->type].e2_size;
386 // Setup eeprom programming functions.
387 fd->fd.read = eeprom_read;
389 fd->fd.write = eeprom_writeVerify;
391 fd->fd.write = eeprom_writeRaw;
392 fd->fd.close = kfile_genericClose;
394 fd->fd.seek = kfile_genericSeek;