Nut/OS  4.10.3
API Reference
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 
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         if( tme == TWERR_OK)
00121             return 0;           
00122 
00123         /* there was an error */
00124                 if( tme == TWERR_SLA_NACK) {
00125                         --retry;
00126 
00127 #ifdef AT24C_DEBUG
00128                         printf("RR %u\n", retry);
00129 #else
00130                         NutSleep(1);
00131 #endif
00132                 }
00133         else
00134             return -2;
00135 
00136         } while( retry);
00137 
00138         return -1;
00139 }
00140 
00151 /****************************************************************************/
00152 int At24cRead( struct at24c *at24cs, uint8_t *buffer, uint32_t len, uint32_t addr )
00153 /****************************************************************************/
00154 {
00155         /* No, on read we definately do not have to wait for internal programming finished! */
00156         return lld_at24_read( at24cs, buffer, len, addr);
00157 }
00158 
00169 /****************************************************************************/
00170 int At24cWrite( struct at24c *at24cs, uint8_t *buffer, uint32_t len, uint32_t addr)
00171 /****************************************************************************/
00172 {
00173     int rc = 0;
00174         uint8_t *ptr = buffer;
00175         uint32_t bulk;
00176         /* get first bulk of data till page end */
00177         while( (len>0) && (rc>=0))
00178         {
00179                 bulk = at24cs->PageSize-(addr%at24cs->PageSize);
00180                 if( bulk > len) bulk = len;
00181                 rc = lld_at24_write( at24cs, ptr, bulk, addr );
00182                 ptr+=bulk; addr+=bulk; len-=bulk;
00183         }
00184         return rc;
00185 }
00186