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 
00056 #include <cfg/os.h>
00057 #include <cfg/memory.h>
00058 
00059 #include <sys/event.h>
00060 #include <sys/timer.h>
00061 
00062 #include <stdlib.h>
00063 #include <string.h>
00064 
00065 #include <dev/at49bv.h>
00066 
00069 #ifndef FLASH_CHIP_BASE
00070 #define FLASH_CHIP_BASE  0x10000000
00071 #endif
00072 
00075 #ifndef FLASH_CONF_SECTOR
00076 #define FLASH_CONF_SECTOR  0x6000
00077 #endif
00078 
00086 #ifndef FLASH_CONF_SIZE
00087 #define FLASH_CONF_SIZE         512
00088 #endif
00089 
00090 #ifndef FLASH_ERASE_WAIT
00091 #define FLASH_ERASE_WAIT        3000
00092 #endif
00093 
00094 #ifndef FLASH_CHIP_ERASE_WAIT
00095 #define FLASH_CHIP_ERASE_WAIT   50000
00096 #endif
00097 
00098 #ifndef FLASH_WRITE_POLLS
00099 #define FLASH_WRITE_POLLS       1000
00100 #endif
00101 
00102 
00103 #ifdef FLASH_8BIT
00104 typedef unsigned char flashdat_t;
00105 #else
00106 typedef unsigned short flashdat_t;
00107 #endif
00108 
00109 typedef unsigned long flashadr_t;
00110 typedef volatile flashdat_t *flashptr_t;
00111 
00112 static flashptr_t chip = (flashptr_t) FLASH_CHIP_BASE;
00113 
00114 #define FLASH_UNLOCK(base) { \
00115     base[0x0555] = 0xAA; \
00116     base[0x0AAA] = 0x55; \
00117 }
00118 
00119 #define FLASH_COMMAND(base, cmd) { \
00120     base[0x0555] = cmd; \
00121 }
00122 
00123 #define FLASH_CMD_ERASE         0x80
00124 #define FLASH_CMD_ERASE_CHIP    0x10
00125 #define FLASH_CMD_ERASE_SECTOR  0x30
00126 
00127 #define FLASH_CMD_ENTER_ID      0x90
00128 #define FLASH_CMD_EXIT_ID       0xF0
00129 
00130 #define FLASH_CMD_PROGRAM       0xA0
00131 
00137 static int At49bvWaitReady(flashptr_t addr, flashdat_t data, u_long tmo, int poll)
00138 {
00139     while (*addr != data) {
00140         if (!poll) {
00141             NutSleep(1);
00142         }
00143         if (tmo-- == 0) {
00144             return -1;
00145         }
00146     }
00147     return 0;
00148 }
00149 
00150 /*
00151  * May be later used to retrieve the chip layout.
00152  */
00153 unsigned long At49bvInit(void)
00154 {
00155     unsigned long id;
00156 
00157     FLASH_UNLOCK(chip);
00158     FLASH_COMMAND(chip, FLASH_CMD_ENTER_ID);
00159     id = chip[0];
00160     id <<= 16;
00161     id |= chip[1];
00162     FLASH_UNLOCK(chip);
00163     FLASH_COMMAND(chip, FLASH_CMD_EXIT_ID);
00164 
00165     return id;
00166 }
00167 
00171 int At49bvSectorErase(u_int off)
00172 {
00173     flashptr_t ptr = (flashptr_t) (uptr_t) (FLASH_CHIP_BASE + off);
00174 
00175     FLASH_UNLOCK(chip);
00176     FLASH_COMMAND(chip, FLASH_CMD_ERASE);
00177     FLASH_UNLOCK(chip);
00178     *ptr = FLASH_CMD_ERASE_SECTOR;
00179 
00180     return At49bvWaitReady(ptr, (flashdat_t) - 1, FLASH_ERASE_WAIT, 0);
00181 }
00182 
00186 int At49bvChipErase(void)
00187 {
00188     FLASH_UNLOCK(chip);
00189     FLASH_COMMAND(chip, FLASH_CMD_ERASE);
00190     FLASH_UNLOCK(chip);
00191     FLASH_COMMAND(chip, FLASH_CMD_ERASE_CHIP);
00192 
00193     return At49bvWaitReady(chip, (flashdat_t) - 1, FLASH_CHIP_ERASE_WAIT, 0);
00194 }
00195 
00205 int At49bvSectorRead(u_int off, void *data, u_int len)
00206 {
00207     memcpy(data, (void *) (uptr_t) (FLASH_CHIP_BASE + off), len);
00208 
00209     return 0;
00210 }
00211 
00223 int At49bvSectorWrite(u_int off, CONST void *data, u_int len)
00224 {
00225     int rc = 0;
00226     flashptr_t sp = (flashptr_t) data;
00227     flashptr_t dp = (flashptr_t) (uptr_t) (FLASH_CHIP_BASE + off);
00228     u_int i;
00229 
00230     for (i = 0; i < len; i += sizeof(flashdat_t)) {
00231         /* No need to save values with all bits set. */
00232         if (*sp != (flashdat_t) - 1) {
00233             /* Write to memory location. */
00234             FLASH_UNLOCK(chip);
00235             FLASH_COMMAND(chip, FLASH_CMD_PROGRAM);
00236             *dp = *sp;
00237             if ((rc = At49bvWaitReady(dp, *sp, FLASH_WRITE_POLLS, 1)) != 0) {
00238                 break;
00239             }
00240         }
00241         dp++;
00242         sp++;
00243     }
00244     return rc;
00245 }
00246 
00256 int At49bvParamRead(u_int pos, void *data, u_int len)
00257 {
00258     return At49bvSectorRead(FLASH_CONF_SECTOR + pos, data, len);
00259 }
00260 
00270 int At49bvParamWrite(u_int pos, CONST void *data, u_int len)
00271 {
00272     int rc = -1;
00273     u_char *buff;
00274 
00275     /* Load the complete configuration area. */
00276     if ((buff = malloc(FLASH_CONF_SIZE)) != 0) {
00277         rc = At49bvSectorRead(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
00278         /* Compare old with new contents. */
00279         if (memcmp(buff + pos, data, len)) {
00280             /* New contents differs. Copy it into the sector buffer. */
00281             memcpy(buff + pos, data, len);
00282             /* Erase sector and write new data. */
00283             if ((rc = At49bvSectorErase(FLASH_CONF_SECTOR)) == 0) {
00284                 rc = At49bvSectorWrite(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
00285             }
00286         }
00287         free(buff);
00288     }
00289     return rc;
00290 }

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