Contiki 2.6

eeprom.c

Go to the documentation of this file.
00001 /**
00002  * \file
00003  * EEPROM functions.
00004  * \author Adam Dunkels <adam@sics.se> 
00005  */
00006 
00007 /* Copyright (c) 2004 Swedish Institute of Computer Science.
00008  * All rights reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without modification,
00011  * are permitted provided that the following conditions are met:
00012  *
00013  * 1. Redistributions of source code must retain the above copyright notice,
00014  *    this list of conditions and the following disclaimer.
00015  * 2. Redistributions in binary form must reproduce the above copyright notice,
00016  *    this list of conditions and the following disclaimer in the documentation
00017  *    and/or other materials provided with the distribution.
00018  * 3. The name of the author may not be used to endorse or promote products
00019  *    derived from this software without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00022  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00023  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00024  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00026  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00027  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00028  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00029  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00030  * OF SUCH DAMAGE.
00031  *
00032  * $Id: eeprom.c,v 1.1 2006/06/18 07:49:33 adamdunkels Exp $
00033  *
00034  * Author: Adam Dunkels <adam@sics.se>
00035  *
00036  */
00037 
00038 /*
00039 Copyright 2003/2004, Freie Universitaet Berlin. All rights reserved.
00040                                                                                                                                      
00041 These sources were developed at the Freie Universit\x{FFFF}t Berlin, Computer
00042 Systems and Telematics group.
00043                                                                                                                                      
00044 Redistribution and use in source and binary forms, with or without
00045 modification, are permitted provided that the following conditions are
00046 met:
00047                                                                                                                                      
00048 - Redistributions of source code must retain the above copyright
00049 notice, this list of conditions and the following disclaimer.
00050                                                                                                                                      
00051 - Redistributions in binary form must reproduce the above copyright
00052 notice, this list of conditions and the following disclaimer in the
00053 documentation and/or other materials provided with the distribution.
00054                                                                                                                                      
00055 - Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
00056 contributors may be used to endorse or promote products derived from
00057 this software without specific prior written permission.
00058                                                                                                                                      
00059 This software is provided by FUB and the contributors on an "as is"
00060 basis, without any representations or warranties of any kind, express
00061 or implied including, but not limited to, representations or
00062 warranties of non-infringement, merchantability or fitness for a
00063 particular purpose. In no event shall FUB or contributors be liable
00064 for any direct, indirect, incidental, special, exemplary, or
00065 consequential damages (including, but not limited to, procurement of
00066 substitute goods or services; loss of use, data, or profits; or
00067 business interruption) however caused and on any theory of liability,
00068 whether in contract, strict liability, or tort (including negligence
00069 or otherwise) arising in any way out of the use of this software, even
00070 if advised of the possibility of such damage.
00071                                                                                                                                      
00072 This implementation was developed by the CST group at the FUB.
00073 Contributors: Thomas Pietsch, Bjoern Lichtblau
00074                                                                                                                                      
00075 For documentation and questions please use the web site
00076 http://www.scatterweb.net and the mailinglist
00077 scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
00078 Berlin, 2003/2004
00079 */
00080 
00081 #include "contiki.h"
00082 /* #include <msp430x14x.h> */
00083 
00084 #include "dev/eeprom.h"
00085 
00086 /* Temporary switch for the eeprom address. */
00087 #define EEPROMADDRESS (0x00) /* use 8k EEPROM, future versions will have only one 64k eeprom at this address */
00088 /*#define EEPROMADDRESS (0x02)*/   /* use 64k EEPROM */
00089  
00090 /* must be set together with EEPROMADDRESS */
00091 /*#define EEPROMPAGEMASK (0x1F) */ /*  8k EEPROM, 32b page writes possible */
00092 #define EEPROMPAGEMASK (0x7F)   /* 64k EEPROM, 128b page writes possible */
00093  
00094 
00095 
00096 /*
00097  * Macros for accessing the clock and data lines. Data is on P56 and
00098  * clock on P57.
00099  */
00100 #define SDA_HIGH (P5OUT |= 0x04) /**< EEPROM data line high */
00101 #define SDA_LOW (P5OUT &= 0xFB)  /**< EEPROM data line low */
00102 #define SCL_HIGH (P5OUT |= 0x08) /**< EEPROM clock line high */
00103 #define SCL_LOW (P5OUT &= 0xF7)  /**< EEPROM clock line low */
00104  
00105 
00106 /*-----------------------------------------------------------------------------------*/
00107 /**
00108  * \internal \name Basic functions for interfacing the i2c-like EEPROM bus.
00109  */
00110 /** @{ */
00111  
00112 /**
00113  * \internal
00114  * Put start condition on the bus.
00115  */
00116 static void
00117 start(void)
00118 {
00119   P5DIR |= 0x0C; /* ensure: P52(SDA), P53(SCL) output */
00120   SCL_LOW;  _NOP(); _NOP();
00121   SDA_HIGH; _NOP(); _NOP();
00122   SCL_HIGH; _NOP(); _NOP();
00123   SDA_LOW;  _NOP(); _NOP();
00124   SCL_LOW;  _NOP(); _NOP();
00125 }
00126 
00127 /*-----------------------------------------------------------------------------------*/
00128 /**
00129  * \internal
00130  * Put stop condition on the bus.
00131  */
00132 static void
00133 stop(void)
00134 {
00135   //P5DIR |= 0x0C; /* ensure: P52(SDA), P53(SCL) output */
00136   SCL_LOW;  _NOP(); _NOP();
00137   SDA_LOW;  _NOP(); _NOP();
00138   SCL_HIGH; _NOP(); _NOP();
00139   SDA_HIGH; _NOP(); _NOP();
00140   SCL_LOW;  _NOP(); _NOP();
00141   P5DIR &= ~0x0C;
00142 }
00143 /*-----------------------------------------------------------------------------------*/
00144 /**
00145  * \internal
00146  * Write a byte on the bus, return the acknowledge bit.
00147  */
00148 static int
00149 write_bus(unsigned char byte)
00150 {
00151   int i, ack;
00152 
00153   /* Write byte, one bit at a time. Start with the leftmost (most
00154      significant) bit and roll in bits from the right. */
00155   for(i = 0; i < 8; ++i) {
00156     if(byte & 0x80) {
00157       SDA_HIGH;
00158     } else {
00159       SDA_LOW;
00160     }
00161     _NOP();
00162     _NOP();
00163     SCL_HIGH;
00164     _NOP();
00165     _NOP();
00166     byte = byte << 1;
00167     SCL_LOW;
00168     _NOP();
00169     _NOP();
00170   }
00171   
00172   /* check ack */
00173   P5DIR &= 0xFB;                              /* P52(SDA) input */
00174   SCL_HIGH;
00175   _NOP();
00176   _NOP();
00177   if(P5IN & 0x04) {
00178     ack = 0;
00179   } else {
00180     ack = 1;      /* test if ack=0, else error */
00181   }
00182   SCL_LOW;
00183   _NOP();
00184   _NOP();
00185   P5DIR |= 0x04;                              /* P52(SDA) output */
00186   _NOP();
00187   _NOP();
00188   _NOP();
00189   return ack;
00190 }
00191 /*-----------------------------------------------------------------------------------*/                                                                                                                                     
00192 /**
00193  * \internal
00194  * Read one byte from the bus.
00195  *
00196  * \param ack If set, the ackbit after the received byte will be set.
00197  */
00198 static unsigned char
00199 read_bus(unsigned char ack)
00200 {
00201   int i;
00202   unsigned char byte = 0;
00203                                                                                                                                      
00204   P5DIR &= 0xFB;                              /* P52(SDA) input */
00205                                                                                                                                      
00206   for(i = 0; i < 8; ++i) {
00207     byte = byte << 1;
00208     SCL_HIGH;
00209     _NOP();
00210     _NOP();
00211     if(P5IN & 0x04) {
00212       byte |= 0x01;
00213     } else {
00214       byte &= 0xFE;
00215     }
00216     _NOP();
00217     SCL_LOW;
00218     _NOP();
00219     _NOP();
00220   }
00221   
00222   P5DIR |= 0x04;                              /* P52(SDA) output */
00223   if(ack) {
00224     SDA_LOW;
00225   } else {
00226     SDA_HIGH;
00227   }
00228   _NOP();
00229   SCL_HIGH;
00230   _NOP();
00231   SCL_LOW;
00232   _NOP();
00233   return byte;
00234 }
00235 /** @} */
00236 /*-----------------------------------------------------------------------------------*/                                                                                                                                     
00237 /**
00238  * Read bytes from the EEPROM using sequential read.
00239  */
00240 void
00241 eeprom_read(unsigned short addr, unsigned char *buf, int size)
00242 {
00243   unsigned int i;
00244 
00245   if(size <= 0) {
00246     return;
00247   }
00248   
00249   do {
00250     /* Wait if the writecycle has not finished. */
00251     start();
00252     /* 1010 control, 000 address, 0=write  --- but only inits address */
00253   } while(!write_bus(0xa0 | EEPROMADDRESS));
00254            
00255 
00256   /* Write address to bus, low byte first. */
00257   write_bus(addr >> 8);
00258   write_bus(addr & 0xff);
00259   start();
00260   /* 1010 control, 000 address, 1=read */
00261   write_bus(0xa1 | EEPROMADDRESS); 
00262 
00263   for(i = 0; i < (size - 1); ++i){
00264     buf[i] = read_bus(1);
00265   }
00266   buf[size - 1] = read_bus(0);
00267   stop();
00268 }
00269 /*-----------------------------------------------------------------------------------*/                                                                                                                                     
00270 /**
00271  * Write bytes to EEPROM using sequencial write.
00272  */
00273 void
00274 eeprom_write(unsigned short addr, unsigned char *buf,
00275              int size)
00276 {
00277   unsigned int i = 0;
00278   unsigned int curaddr;
00279 
00280   if(size <= 0) {
00281     return;
00282   }
00283   
00284   /* Disable write protection. */
00285   P5OUT &= 0xEF; 
00286 
00287   curaddr = addr;
00288   for(i = 0; i < size; ++i) {
00289     /* If we are writing the first byte or are on a 128b page boundary
00290        we have to start a new write. */
00291     if(i == 0 || (curaddr & EEPROMPAGEMASK) == 0) {
00292       do {
00293         start();
00294         /* 1010 control, 000 addresse, 0=write */
00295       } while(!write_bus(0xa0 | EEPROMADDRESS));
00296 
00297       /* Write the new address to the bus. */
00298       if(write_bus(curaddr >> 8) == 0) {
00299         return;
00300       }
00301       if(write_bus(curaddr) == 0) {
00302         return;
00303       }
00304     }
00305   
00306     /* Write byte. */
00307     if(write_bus(buf[i]) == 0) {
00308       return;
00309     }
00310     
00311     /* If we are writing the last byte totally or of a 128b page
00312        generate a stop condition */
00313     if(i == size - 1 || (curaddr & EEPROMPAGEMASK) == EEPROMPAGEMASK) {
00314       stop();
00315     }
00316     
00317     ++curaddr;
00318   }
00319   
00320   /* Enable write protection. */
00321   P5OUT |= 0x10;                              
00322 }
00323                                                                                                                                      
00324 /*-----------------------------------------------------------------------------------*/