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 
00060 #include <cfg/os.h>
00061 #include <cfg/memory.h>
00062 
00063 #include <sys/event.h>
00064 #include <sys/timer.h>
00065 
00066 #include <stdlib.h>
00067 #include <string.h>
00068 
00069 #include <dev/at49bv.h>
00070 
00073 #ifndef FLASH_CHIP_BASE
00074 #define FLASH_CHIP_BASE  0x10000000
00075 #endif
00076 
00079 #ifndef FLASH_CONF_SECTOR
00080 #define FLASH_CONF_SECTOR  0x6000
00081 #endif
00082 
00090 #ifndef FLASH_CONF_SIZE
00091 #define FLASH_CONF_SIZE         512
00092 #endif
00093 
00094 #ifndef FLASH_ERASE_WAIT
00095 #define FLASH_ERASE_WAIT        3000
00096 #endif
00097 
00098 #ifndef FLASH_CHIP_ERASE_WAIT
00099 #define FLASH_CHIP_ERASE_WAIT   50000
00100 #endif
00101 
00102 #ifndef FLASH_WRITE_POLLS
00103 #define FLASH_WRITE_POLLS       1000
00104 #endif
00105 
00106 
00107 #ifdef FLASH_8BIT
00108 typedef unsigned char flashdat_t;
00109 #else
00110 typedef unsigned short flashdat_t;
00111 #endif
00112 
00113 typedef unsigned long flashadr_t;
00114 typedef volatile flashdat_t *flashptr_t;
00115 
00116 static flashptr_t chip = (flashptr_t) FLASH_CHIP_BASE;
00117 
00118 #define FLASH_UNLOCK(base) { \
00119     base[0x0555] = 0xAA; \
00120     base[0x0AAA] = 0x55; \
00121 }
00122 
00123 #define FLASH_COMMAND(base, cmd) { \
00124     base[0x0555] = cmd; \
00125 }
00126 
00127 #define FLASH_CMD_ERASE         0x80
00128 #define FLASH_CMD_ERASE_CHIP    0x10
00129 #define FLASH_CMD_ERASE_SECTOR  0x30
00130 
00131 #define FLASH_CMD_ENTER_ID      0x90
00132 #define FLASH_CMD_EXIT_ID       0xF0
00133 
00134 #define FLASH_CMD_PROGRAM       0xA0
00135 
00141 static int At49bvWaitReady(flashptr_t addr, flashdat_t data, u_long tmo, int poll)
00142 {
00143     while (*addr != data) {
00144         if (!poll) {
00145             NutSleep(1);
00146         }
00147         if (tmo-- == 0) {
00148             return -1;
00149         }
00150     }
00151     return 0;
00152 }
00153 
00154 /*
00155  * May be later used to retrieve the chip layout.
00156  */
00157 unsigned long At49bvInit(void)
00158 {
00159     unsigned long id;
00160 
00161     FLASH_UNLOCK(chip);
00162     FLASH_COMMAND(chip, FLASH_CMD_ENTER_ID);
00163     id = chip[0];
00164     id <<= 16;
00165     id |= chip[1];
00166     FLASH_UNLOCK(chip);
00167     FLASH_COMMAND(chip, FLASH_CMD_EXIT_ID);
00168 
00169     return id;
00170 }
00171 
00178 unsigned long long AT49bvReadProtectionRegister(int factory)
00179 {
00180     unsigned long long id;
00181 
00182     FLASH_UNLOCK(chip);
00183     FLASH_COMMAND(chip, FLASH_CMD_ENTER_ID);
00184     if (factory) {
00185         id  = chip[0x81];
00186         id <<= 16;
00187         id |= chip[0x82];
00188         id <<= 16;
00189         id |= chip[0x83];
00190         id <<= 16;
00191         id |= chip[0x84];
00192     } else {
00193         id  = chip[0x85];
00194         id <<= 16;
00195         id |= chip[0x86];
00196         id <<= 16;
00197         id |= chip[0x87];
00198         id <<= 16;
00199         id |= chip[0x88];
00200     }        
00201     FLASH_UNLOCK(chip);
00202     FLASH_COMMAND(chip, FLASH_CMD_EXIT_ID);
00203 
00204     return id;
00205 }
00206 
00210 int At49bvSectorErase(u_int off)
00211 {
00212     flashptr_t ptr = (flashptr_t) (uptr_t) (FLASH_CHIP_BASE + off);
00213 
00214     FLASH_UNLOCK(chip);
00215     FLASH_COMMAND(chip, FLASH_CMD_ERASE);
00216     FLASH_UNLOCK(chip);
00217     *ptr = FLASH_CMD_ERASE_SECTOR;
00218 
00219     return At49bvWaitReady(ptr, (flashdat_t) - 1, FLASH_ERASE_WAIT, 0);
00220 }
00221 
00225 int At49bvChipErase(void)
00226 {
00227     FLASH_UNLOCK(chip);
00228     FLASH_COMMAND(chip, FLASH_CMD_ERASE);
00229     FLASH_UNLOCK(chip);
00230     FLASH_COMMAND(chip, FLASH_CMD_ERASE_CHIP);
00231 
00232     return At49bvWaitReady(chip, (flashdat_t) - 1, FLASH_CHIP_ERASE_WAIT, 0);
00233 }
00234 
00244 int At49bvSectorRead(u_int off, void *data, u_int len)
00245 {
00246     memcpy(data, (void *) (uptr_t) (FLASH_CHIP_BASE + off), len);
00247 
00248     return 0;
00249 }
00250 
00262 int At49bvSectorWrite(u_int off, CONST void *data, u_int len)
00263 {
00264     int rc = 0;
00265     flashptr_t sp = (flashptr_t) data;
00266     flashptr_t dp = (flashptr_t) (uptr_t) (FLASH_CHIP_BASE + off);
00267     u_int i;
00268 
00269     for (i = 0; i < len; i += sizeof(flashdat_t)) {
00270         /* No need to save values with all bits set. */
00271         if (*sp != (flashdat_t) - 1) {
00272             /* Write to memory location. */
00273             FLASH_UNLOCK(chip);
00274             FLASH_COMMAND(chip, FLASH_CMD_PROGRAM);
00275             *dp = *sp;
00276             if ((rc = At49bvWaitReady(dp, *sp, FLASH_WRITE_POLLS, 1)) != 0) {
00277                 break;
00278             }
00279         }
00280         dp++;
00281         sp++;
00282     }
00283     return rc;
00284 }
00285 
00295 int At49bvParamRead(u_int pos, void *data, u_int len)
00296 {
00297     return At49bvSectorRead(FLASH_CONF_SECTOR + pos, data, len);
00298 }
00299 
00309 int At49bvParamWrite(u_int pos, CONST void *data, u_int len)
00310 {
00311     int rc = -1;
00312     u_char *buff;
00313 
00314     /* Load the complete configuration area. */
00315     if ((buff = malloc(FLASH_CONF_SIZE)) != 0) {
00316         rc = At49bvSectorRead(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
00317         /* Compare old with new contents. */
00318         if (memcmp(buff + pos, data, len)) {
00319             /* New contents differs. Copy it into the sector buffer. */
00320             memcpy(buff + pos, data, len);
00321             /* Erase sector and write new data. */
00322             if ((rc = At49bvSectorErase(FLASH_CONF_SECTOR)) == 0) {
00323                 rc = At49bvSectorWrite(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
00324             }
00325         }
00326         free(buff);
00327     }
00328     return rc;
00329 }

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