Contiki 2.5
eeprom.c
Go to the documentation of this file.
1 /**
2  * \file
3  * EEPROM functions.
4  * \author Adam Dunkels <adam@sics.se>
5  */
6 
7 /* Copyright (c) 2004 Swedish Institute of Computer Science.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without modification,
11  * are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright notice,
14  * this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  * 3. The name of the author may not be used to endorse or promote products
19  * derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30  * OF SUCH DAMAGE.
31  *
32  * $Id: eeprom.c,v 1.1 2006/06/18 07:49:33 adamdunkels Exp $
33  *
34  * Author: Adam Dunkels <adam@sics.se>
35  *
36  */
37 
38 /*
39 Copyright 2003/2004, Freie Universitaet Berlin. All rights reserved.
40 
41 These sources were developed at the Freie Universit\x{FFFF}t Berlin, Computer
42 Systems and Telematics group.
43 
44 Redistribution and use in source and binary forms, with or without
45 modification, are permitted provided that the following conditions are
46 met:
47 
48 - Redistributions of source code must retain the above copyright
49 notice, this list of conditions and the following disclaimer.
50 
51 - Redistributions in binary form must reproduce the above copyright
52 notice, this list of conditions and the following disclaimer in the
53 documentation and/or other materials provided with the distribution.
54 
55 - Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
56 contributors may be used to endorse or promote products derived from
57 this software without specific prior written permission.
58 
59 This software is provided by FUB and the contributors on an "as is"
60 basis, without any representations or warranties of any kind, express
61 or implied including, but not limited to, representations or
62 warranties of non-infringement, merchantability or fitness for a
63 particular purpose. In no event shall FUB or contributors be liable
64 for any direct, indirect, incidental, special, exemplary, or
65 consequential damages (including, but not limited to, procurement of
66 substitute goods or services; loss of use, data, or profits; or
67 business interruption) however caused and on any theory of liability,
68 whether in contract, strict liability, or tort (including negligence
69 or otherwise) arising in any way out of the use of this software, even
70 if advised of the possibility of such damage.
71 
72 This implementation was developed by the CST group at the FUB.
73 Contributors: Thomas Pietsch, Bjoern Lichtblau
74 
75 For documentation and questions please use the web site
76 http://www.scatterweb.net and the mailinglist
77 scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
78 Berlin, 2003/2004
79 */
80 
81 #include "contiki.h"
82 /* #include <msp430x14x.h> */
83 
84 #include "dev/eeprom.h"
85 
86 /* Temporary switch for the eeprom address. */
87 #define EEPROMADDRESS (0x00) /* use 8k EEPROM, future versions will have only one 64k eeprom at this address */
88 /*#define EEPROMADDRESS (0x02)*/ /* use 64k EEPROM */
89 
90 /* must be set together with EEPROMADDRESS */
91 /*#define EEPROMPAGEMASK (0x1F) */ /* 8k EEPROM, 32b page writes possible */
92 #define EEPROMPAGEMASK (0x7F) /* 64k EEPROM, 128b page writes possible */
93 
94 
95 
96 /*
97  * Macros for accessing the clock and data lines. Data is on P56 and
98  * clock on P57.
99  */
100 #define SDA_HIGH (P5OUT |= 0x04) /**< EEPROM data line high */
101 #define SDA_LOW (P5OUT &= 0xFB) /**< EEPROM data line low */
102 #define SCL_HIGH (P5OUT |= 0x08) /**< EEPROM clock line high */
103 #define SCL_LOW (P5OUT &= 0xF7) /**< EEPROM clock line low */
104 
105 
106 /*-----------------------------------------------------------------------------------*/
107 /**
108  * \internal \name Basic functions for interfacing the i2c-like EEPROM bus.
109  */
110 /** @{ */
111 
112 /**
113  * \internal
114  * Put start condition on the bus.
115  */
116 static void
117 start(void)
118 {
119  P5DIR |= 0x0C; /* ensure: P52(SDA), P53(SCL) output */
120  SCL_LOW; _NOP(); _NOP();
121  SDA_HIGH; _NOP(); _NOP();
122  SCL_HIGH; _NOP(); _NOP();
123  SDA_LOW; _NOP(); _NOP();
124  SCL_LOW; _NOP(); _NOP();
125 }
126 
127 /*-----------------------------------------------------------------------------------*/
128 /**
129  * \internal
130  * Put stop condition on the bus.
131  */
132 static void
133 stop(void)
134 {
135  //P5DIR |= 0x0C; /* ensure: P52(SDA), P53(SCL) output */
136  SCL_LOW; _NOP(); _NOP();
137  SDA_LOW; _NOP(); _NOP();
138  SCL_HIGH; _NOP(); _NOP();
139  SDA_HIGH; _NOP(); _NOP();
140  SCL_LOW; _NOP(); _NOP();
141  P5DIR &= ~0x0C;
142 }
143 /*-----------------------------------------------------------------------------------*/
144 /**
145  * \internal
146  * Write a byte on the bus, return the acknowledge bit.
147  */
148 static int
149 write_bus(unsigned char byte)
150 {
151  int i, ack;
152 
153  /* Write byte, one bit at a time. Start with the leftmost (most
154  significant) bit and roll in bits from the right. */
155  for(i = 0; i < 8; ++i) {
156  if(byte & 0x80) {
157  SDA_HIGH;
158  } else {
159  SDA_LOW;
160  }
161  _NOP();
162  _NOP();
163  SCL_HIGH;
164  _NOP();
165  _NOP();
166  byte = byte << 1;
167  SCL_LOW;
168  _NOP();
169  _NOP();
170  }
171 
172  /* check ack */
173  P5DIR &= 0xFB; /* P52(SDA) input */
174  SCL_HIGH;
175  _NOP();
176  _NOP();
177  if(P5IN & 0x04) {
178  ack = 0;
179  } else {
180  ack = 1; /* test if ack=0, else error */
181  }
182  SCL_LOW;
183  _NOP();
184  _NOP();
185  P5DIR |= 0x04; /* P52(SDA) output */
186  _NOP();
187  _NOP();
188  _NOP();
189  return ack;
190 }
191 /*-----------------------------------------------------------------------------------*/
192 /**
193  * \internal
194  * Read one byte from the bus.
195  *
196  * \param ack If set, the ackbit after the received byte will be set.
197  */
198 static unsigned char
199 read_bus(unsigned char ack)
200 {
201  int i;
202  unsigned char byte = 0;
203 
204  P5DIR &= 0xFB; /* P52(SDA) input */
205 
206  for(i = 0; i < 8; ++i) {
207  byte = byte << 1;
208  SCL_HIGH;
209  _NOP();
210  _NOP();
211  if(P5IN & 0x04) {
212  byte |= 0x01;
213  } else {
214  byte &= 0xFE;
215  }
216  _NOP();
217  SCL_LOW;
218  _NOP();
219  _NOP();
220  }
221 
222  P5DIR |= 0x04; /* P52(SDA) output */
223  if(ack) {
224  SDA_LOW;
225  } else {
226  SDA_HIGH;
227  }
228  _NOP();
229  SCL_HIGH;
230  _NOP();
231  SCL_LOW;
232  _NOP();
233  return byte;
234 }
235 /** @} */
236 /*-----------------------------------------------------------------------------------*/
237 /**
238  * Read bytes from the EEPROM using sequential read.
239  */
240 void
241 eeprom_read(unsigned short addr, unsigned char *buf, int size)
242 {
243  unsigned int i;
244 
245  if(size <= 0) {
246  return;
247  }
248 
249  do {
250  /* Wait if the writecycle has not finished. */
251  start();
252  /* 1010 control, 000 address, 0=write --- but only inits address */
253  } while(!write_bus(0xa0 | EEPROMADDRESS));
254 
255 
256  /* Write address to bus, low byte first. */
257  write_bus(addr >> 8);
258  write_bus(addr & 0xff);
259  start();
260  /* 1010 control, 000 address, 1=read */
261  write_bus(0xa1 | EEPROMADDRESS);
262 
263  for(i = 0; i < (size - 1); ++i){
264  buf[i] = read_bus(1);
265  }
266  buf[size - 1] = read_bus(0);
267  stop();
268 }
269 /*-----------------------------------------------------------------------------------*/
270 /**
271  * Write bytes to EEPROM using sequencial write.
272  */
273 void
274 eeprom_write(unsigned short addr, unsigned char *buf,
275  int size)
276 {
277  unsigned int i = 0;
278  unsigned int curaddr;
279 
280  if(size <= 0) {
281  return;
282  }
283 
284  /* Disable write protection. */
285  P5OUT &= 0xEF;
286 
287  curaddr = addr;
288  for(i = 0; i < size; ++i) {
289  /* If we are writing the first byte or are on a 128b page boundary
290  we have to start a new write. */
291  if(i == 0 || (curaddr & EEPROMPAGEMASK) == 0) {
292  do {
293  start();
294  /* 1010 control, 000 addresse, 0=write */
295  } while(!write_bus(0xa0 | EEPROMADDRESS));
296 
297  /* Write the new address to the bus. */
298  if(write_bus(curaddr >> 8) == 0) {
299  return;
300  }
301  if(write_bus(curaddr) == 0) {
302  return;
303  }
304  }
305 
306  /* Write byte. */
307  if(write_bus(buf[i]) == 0) {
308  return;
309  }
310 
311  /* If we are writing the last byte totally or of a 128b page
312  generate a stop condition */
313  if(i == size - 1 || (curaddr & EEPROMPAGEMASK) == EEPROMPAGEMASK) {
314  stop();
315  }
316 
317  ++curaddr;
318  }
319 
320  /* Enable write protection. */
321  P5OUT |= 0x10;
322 }
323 
324 /*-----------------------------------------------------------------------------------*/