Nut/OS  4.10.3
API Reference
nvmem_at45d.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008-2009 by egnite GmbH
00003  * Copyright (C) 2006 by egnite Software GmbH
00004  *
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  * 3. Neither the name of the copyright holders nor the names of
00017  *    contributors may be used to endorse or promote products derived
00018  *    from this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00027  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00028  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00029  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00030  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  *
00033  * For additional information see http://www.ethernut.de/
00034  */
00035 
00045 #include <cfg/eeprom.h>
00046 #include <cfg/memory.h>
00047 
00048 #include <dev/board.h>
00049 #include <dev/spi_at45d.h>
00050 
00051 #include <sys/nutdebug.h>
00052 
00053 #include <stdlib.h>
00054 #include <string.h>
00055 #include <memdebug.h>
00056 
00057 #include <dev/nvmem_at45d.h>
00058 
00059 static NUTDEVICE *devSysConf;
00060 
00071 static int SpiAt45dConfigDevice(void)
00072 {
00073 #if !defined(DEV_SPIBUS)
00074     return -1;
00075 #else /* DEV_SPIBUS */
00076     if (devSysConf == NULL) {
00077         NUTSPINODE *node;
00078         NUTDEVICE *dev;
00079 #if NUT_CONFIG_AT45D == 0
00080         dev = &devSpiAt45d0;
00081 #elif NUT_CONFIG_AT45D == 1
00082         dev = &devSpiAt45d1;
00083 #elif NUT_CONFIG_AT45D == 2
00084         dev = &devSpiAt45d2;
00085 #elif NUT_CONFIG_AT45D == 3
00086         dev = &devSpiAt45d3;
00087 #else
00088         return -1;
00089 #endif
00090         node = (NUTSPINODE *) dev->dev_icb;
00091         NUTASSERT(node != NULL);
00092         if (node->node_bus == NULL) {
00093             NUTSPIBUS *bus;
00094             bus = &DEV_SPIBUS;
00095             node->node_bus = bus;
00096         }
00097 #ifdef NUT_CONFIG_AT45D_CS
00098         node->node_cs = NUT_CONFIG_AT45D_CS;
00099 #endif
00100         NUTASSERT(node->node_bus->bus_initnode != NULL);
00101         if ((*node->node_bus->bus_initnode) (node)) {
00102             return -1;
00103         }
00104         NutEventPost(&node->node_bus->bus_mutex);
00105         if (SpiAt45dInit(dev)) {
00106             return -1;
00107         }
00108         devSysConf = dev;
00109     }
00110     return 0;
00111 #endif /* DEV_SPIBUS */
00112 }
00113 
00114 static uint32_t SpiAt45dConfigPage(void)
00115 {
00116 #ifdef NUT_CONFIG_AT45D_PAGE
00117     return NUT_CONFIG_AT45D_PAGE;
00118 #else
00119     return SpiAt45dPages(devSysConf) - 1;
00120 #endif
00121 }
00122 
00134 size_t SpiAt45dConfigSize(void)
00135 {
00136     size_t rc = 0;
00137 
00138     if (SpiAt45dConfigDevice() == 0) {
00139 #ifdef NUT_CONFIG_AT45D_SIZE
00140         rc = NUT_CONFIG_AT45D_SIZE;
00141 #else
00142         rc = (size_t) SpiAt45dPageSize(devSysConf);
00143 #endif
00144     }
00145     return rc;
00146 }
00147 
00157 int SpiAt45dConfigRead(size_t pos, void *data, size_t len)
00158 {
00159     int rc = -1;
00160     uint8_t *buff;
00161     int csize = SpiAt45dConfigSize();
00162 
00163     /* Load the complete configuration area. */
00164     if (csize >= pos + len && (buff = malloc(csize)) != NULL) {
00165         uint32_t cpage = SpiAt45dConfigPage();
00166 
00167         if (SpiAt45dPageRead(devSysConf, cpage, buff, csize) == csize) {
00168             /* Copy requested contents to caller's buffer. */
00169             memcpy(data, buff + pos, len);
00170             rc = 0;
00171         }
00172         free(buff);
00173     }
00174     return rc;
00175 }
00176 
00187 int SpiAt45dConfigWrite(size_t pos, CONST void *data, size_t len)
00188 {
00189     int rc = -1;
00190     uint8_t *pbuff;
00191     uint8_t *data_buff = (uint8_t*) data;
00192     int csize = SpiAt45dConfigSize();
00193     int psize = SpiAt45dPageSize(devSysConf);
00194     int page  = SpiAt45dConfigPage();
00195     int offset;
00196     int wsize;
00197     int remaining = len;
00198 
00199     if ((len > 0) && (csize >= pos + len) && (len > 0) && ((pbuff = malloc(psize)) != NULL)) {
00200         page    += pos / psize;
00201         offset   = pos % psize;
00202 
00203         wsize = (offset + len > psize) ? psize - offset : psize;
00204         if (remaining < wsize) {
00205             wsize = remaining;
00206         }
00207 
00208         while (remaining > 0) {
00209             /* Load one full page */
00210             if (SpiAt45dPageRead(devSysConf, page, pbuff, psize) == psize) {
00211                 /* Compare old with new contents. */
00212                 if (memcmp(pbuff + offset, data_buff, wsize)) {
00213                     /* New contents differs. Copy it into the sector buffer. */
00214                     memcpy(pbuff + offset, data_buff, wsize);
00215                     /* Erase sector and write new data. */
00216                     if (SpiAt45dPageWrite(devSysConf, page, pbuff, psize) == psize) {
00217                         rc = 0;
00218                     } else {
00219                         rc = -1;
00220                         break;
00221                     }
00222                 } else {
00223                     rc = 0;
00224                 }
00225             } else {
00226                 rc = -1;
00227                 break;
00228             }
00229         
00230             data_buff += wsize;
00231             remaining -= wsize;
00232             offset = 0;
00233             page ++;
00234 
00235             wsize = (remaining > psize) ? psize : remaining;
00236         }
00237         free(pbuff);
00238     }
00239         
00240     return rc;
00241 }