at24c.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 by egnite Software GmbH. All rights reserved.
00003  * Copyright (C) 2008 by egnite GmbH. All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the copyright holders nor the names of
00015  *    contributors may be used to endorse or promote products derived
00016  *    from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00022  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00025  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00026  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00028  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * For additional information see http://www.ethernut.de/
00032  *
00033  */
00034 
00035 
00036 #include <cfg/os.h>
00037 #include <cfg/memory.h>
00038 
00039 #include <sys/timer.h>
00040 
00041 #include <stdlib.h>
00042 
00043 #include <dev/twif.h>
00044 #include <dev/at24c.h>
00045 
00046 #define AT24C_AT91
00047 
00048 #define AT24C_DEBUG
00049 
00050 #ifdef AT24C_DEBUG
00051 #include <stdio.h>
00052 #endif
00053 
00064 static int lld_at24_write( struct at24c *at24cs, uint8_t *buffer, uint32_t len, uint32_t addr)
00065 {
00066     uint8_t retry = at24cs->Timeout;
00067     int tme;
00068 
00069     do {
00070         TwMasterRegWrite( at24cs->SlaveAddress, addr, at24cs->IAddrW, buffer, len, 500 );
00071         /* there was an error */
00072         tme = TwMasterError();
00073         if( tme == TWERR_OK)
00074             return 0;
00075 
00076 #ifdef AT24C_DEBUG
00077         printf("MRW %lu: TME:%d t:%d\n", len, tme, TwMasterIndexes( 0));
00078 #endif
00079         if( tme >= TWERR_SLA_NACK) {
00080             /* slave might be busy so we retry (ACK-Polling) */
00081             --retry;
00082 //          NutSleep(1);
00083 #ifdef AT24C_DEBUG
00084             printf("RW %u\n", retry);
00085 #else
00086             NutSleep(1);
00087 #endif
00088         }
00089         else {
00090             /* it was something else than a NACK */
00091             return -1;
00092         }
00093     }
00094     while( retry);
00095 
00096     return -2;  // we get here if we ran out of delays for ACK of slave address
00097 }
00098 
00109 static int lld_at24_read( struct at24c *at24cs, uint8_t *buffer, uint32_t len, uint32_t addr)
00110 {
00111     uint8_t retry = at24cs->Timeout;
00112     int tme;
00113 
00114     do {
00115         TwMasterRegRead( at24cs->SlaveAddress, addr, at24cs->IAddrW, buffer, len, 500 );
00116         tme = TwMasterError();
00117 #ifdef AT24C_DEBUG
00118         printf("MRD l=%lu: TME %d, mt %u, mr %u\n", len, tme, TwMasterIndexes( 0), TwMasterIndexes(1));
00119 #endif
00120         /* there was an error */
00121         if( tme == TWERR_SLA_NACK) {
00122             --retry;
00123 #ifdef AT24C_DEBUG
00124             printf("RR %u\n", retry);
00125 #else
00126             NutSleep(1);
00127 #endif
00128         }
00129         else return -2;
00130 
00131     } while( retry);
00132 
00133     return -1;
00134 }
00135 
00146 /****************************************************************************/
00147 int At24cRead( struct at24c *at24cs, uint8_t *buffer, uint32_t len, uint32_t addr )
00148 /****************************************************************************/
00149 {
00150     /* No, on read we definately do not have to wait for internal programming finished! */
00151     return lld_at24_read( at24cs, buffer, len, addr);
00152 }
00153 
00164 /****************************************************************************/
00165 int At24cWrite( struct at24c *at24cs, uint8_t *buffer, uint32_t len, uint32_t addr)
00166 /****************************************************************************/
00167 {
00168     int rc = 0;
00169     uint8_t *ptr = buffer;
00170     uint32_t bulk;
00171     /* get first bulk of data till page end */
00172     while( (len>0) && (rc>=0))
00173     {
00174         bulk = at24cs->PageSize-(addr%at24cs->PageSize);
00175         if( bulk > len) bulk = len;
00176         rc = lld_at24_write( at24cs, ptr, bulk, addr );
00177         ptr+=bulk; addr+=bulk; len-=bulk;
00178     }
00179     return rc;
00180 }
00181 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/