at49bv.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005-2006 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00063 #include <cfg/os.h>
00064 #include <cfg/memory.h>
00065 
00066 #include <sys/event.h>
00067 #include <sys/timer.h>
00068 
00069 #include <stdlib.h>
00070 #include <string.h>
00071 
00072 #include <dev/at49bv.h>
00073 
00076 #ifndef FLASH_CHIP_BASE
00077 #define FLASH_CHIP_BASE  0x10000000
00078 #endif
00079 
00082 #ifndef FLASH_CONF_SECTOR
00083 #define FLASH_CONF_SECTOR  0x6000
00084 #endif
00085 
00093 #ifndef FLASH_CONF_SIZE
00094 #define FLASH_CONF_SIZE         512
00095 #endif
00096 
00097 #ifndef FLASH_ERASE_WAIT
00098 #define FLASH_ERASE_WAIT        3000
00099 #endif
00100 
00101 #ifndef FLASH_CHIP_ERASE_WAIT
00102 #define FLASH_CHIP_ERASE_WAIT   50000
00103 #endif
00104 
00105 #ifndef FLASH_WRITE_POLLS
00106 #define FLASH_WRITE_POLLS       1000
00107 #endif
00108 
00109 
00110 #ifdef FLASH_8BIT
00111 typedef unsigned char flashdat_t;
00112 #else
00113 typedef unsigned short flashdat_t;
00114 #endif
00115 
00116 typedef unsigned long flashadr_t;
00117 typedef volatile flashdat_t *flashptr_t;
00118 
00119 static flashptr_t chip = (flashptr_t) FLASH_CHIP_BASE;
00120 
00121 #define FLASH_UNLOCK(base) { \
00122     base[0x0555] = 0xAA; \
00123     base[0x0AAA] = 0x55; \
00124 }
00125 
00126 #define FLASH_COMMAND(base, cmd) { \
00127     base[0x0555] = cmd; \
00128 }
00129 
00130 #define FLASH_CMD_ERASE         0x80
00131 #define FLASH_CMD_ERASE_CHIP    0x10
00132 #define FLASH_CMD_ERASE_SECTOR  0x30
00133 
00134 #define FLASH_CMD_ENTER_ID      0x90
00135 #define FLASH_CMD_EXIT_ID       0xF0
00136 
00137 #define FLASH_CMD_PROGRAM       0xA0
00138 
00144 static int At49bvWaitReady(flashptr_t addr, flashdat_t data, uint32_t tmo, int poll)
00145 {
00146     while (*addr != data) {
00147         if (!poll) {
00148             NutSleep(1);
00149         }
00150         if (tmo-- == 0) {
00151             return -1;
00152         }
00153     }
00154     return 0;
00155 }
00156 
00157 /*
00158  * May be later used to retrieve the chip layout.
00159  */
00160 unsigned long At49bvInit(void)
00161 {
00162     unsigned long id;
00163 
00164     FLASH_UNLOCK(chip);
00165     FLASH_COMMAND(chip, FLASH_CMD_ENTER_ID);
00166     id = chip[0];
00167     id <<= 16;
00168     id |= chip[1];
00169     FLASH_UNLOCK(chip);
00170     FLASH_COMMAND(chip, FLASH_CMD_EXIT_ID);
00171 
00172     return id;
00173 }
00174 
00181 unsigned long long AT49bvReadProtectionRegister(int factory)
00182 {
00183     unsigned long long id;
00184 
00185     FLASH_UNLOCK(chip);
00186     FLASH_COMMAND(chip, FLASH_CMD_ENTER_ID);
00187     if (factory) {
00188         id  = chip[0x81];
00189         id <<= 16;
00190         id |= chip[0x82];
00191         id <<= 16;
00192         id |= chip[0x83];
00193         id <<= 16;
00194         id |= chip[0x84];
00195     } else {
00196         id  = chip[0x85];
00197         id <<= 16;
00198         id |= chip[0x86];
00199         id <<= 16;
00200         id |= chip[0x87];
00201         id <<= 16;
00202         id |= chip[0x88];
00203     }        
00204     FLASH_UNLOCK(chip);
00205     FLASH_COMMAND(chip, FLASH_CMD_EXIT_ID);
00206 
00207     return id;
00208 }
00209 
00213 int At49bvSectorErase(u_int off)
00214 {
00215     flashptr_t ptr = (flashptr_t) (uptr_t) (FLASH_CHIP_BASE + off);
00216 
00217     FLASH_UNLOCK(chip);
00218     FLASH_COMMAND(chip, FLASH_CMD_ERASE);
00219     FLASH_UNLOCK(chip);
00220     *ptr = FLASH_CMD_ERASE_SECTOR;
00221 
00222     return At49bvWaitReady(ptr, (flashdat_t) - 1, FLASH_ERASE_WAIT, 0);
00223 }
00224 
00228 int At49bvChipErase(void)
00229 {
00230     FLASH_UNLOCK(chip);
00231     FLASH_COMMAND(chip, FLASH_CMD_ERASE);
00232     FLASH_UNLOCK(chip);
00233     FLASH_COMMAND(chip, FLASH_CMD_ERASE_CHIP);
00234 
00235     return At49bvWaitReady(chip, (flashdat_t) - 1, FLASH_CHIP_ERASE_WAIT, 0);
00236 }
00237 
00247 int At49bvSectorRead(u_int off, void *data, u_int len)
00248 {
00249     memcpy(data, (void *) (uptr_t) (FLASH_CHIP_BASE + off), len);
00250 
00251     return 0;
00252 }
00253 
00265 int At49bvSectorWrite(u_int off, CONST void *data, u_int len)
00266 {
00267     int rc = 0;
00268     flashptr_t sp = (flashptr_t) data;
00269     flashptr_t dp = (flashptr_t) (uptr_t) (FLASH_CHIP_BASE + off);
00270     u_int i;
00271 
00272     for (i = 0; i < len; i += sizeof(flashdat_t)) {
00273         /* No need to save values with all bits set. */
00274         if (*sp != (flashdat_t) - 1) {
00275             /* Write to memory location. */
00276             FLASH_UNLOCK(chip);
00277             FLASH_COMMAND(chip, FLASH_CMD_PROGRAM);
00278             *dp = *sp;
00279             if ((rc = At49bvWaitReady(dp, *sp, FLASH_WRITE_POLLS, 1)) != 0) {
00280                 break;
00281             }
00282         }
00283         dp++;
00284         sp++;
00285     }
00286     return rc;
00287 }
00288 
00298 int At49bvParamRead(u_int pos, void *data, u_int len)
00299 {
00300     return At49bvSectorRead(FLASH_CONF_SECTOR + pos, data, len);
00301 }
00302 
00312 int At49bvParamWrite(u_int pos, CONST void *data, u_int len)
00313 {
00314     int rc = -1;
00315     uint8_t *buff;
00316 
00317     /* Load the complete configuration area. */
00318     if ((buff = malloc(FLASH_CONF_SIZE)) != 0) {
00319         rc = At49bvSectorRead(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
00320         /* Compare old with new contents. */
00321         if (memcmp(buff + pos, data, len)) {
00322             /* New contents differs. Copy it into the sector buffer. */
00323             memcpy(buff + pos, data, len);
00324             /* Erase sector and write new data. */
00325             if ((rc = At49bvSectorErase(FLASH_CONF_SECTOR)) == 0) {
00326                 rc = At49bvSectorWrite(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
00327             }
00328         }
00329         free(buff);
00330     }
00331     return rc;
00332 }

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