Nut/OS  4.10.3
API Reference
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 
00067 #include <cfg/os.h>
00068 #include <cfg/memory.h>
00069 
00070 #include <sys/event.h>
00071 #include <sys/timer.h>
00072 
00073 #include <stdlib.h>
00074 #include <string.h>
00075 
00076 #include <dev/at49bv.h>
00077 
00080 #ifndef FLASH_CHIP_BASE
00081 #define FLASH_CHIP_BASE  0x10000000
00082 #endif
00083 
00086 #ifndef FLASH_CONF_SECTOR
00087 #define FLASH_CONF_SECTOR  0x6000
00088 #endif
00089 
00097 #ifndef FLASH_CONF_SIZE
00098 #define FLASH_CONF_SIZE         512
00099 #endif
00100 
00101 #ifndef FLASH_ERASE_WAIT
00102 #define FLASH_ERASE_WAIT        3000
00103 #endif
00104 
00105 #ifndef FLASH_CHIP_ERASE_WAIT
00106 #define FLASH_CHIP_ERASE_WAIT   50000
00107 #endif
00108 
00109 #ifndef FLASH_WRITE_POLLS
00110 #define FLASH_WRITE_POLLS       1000
00111 #endif
00112 
00113 
00114 #ifdef FLASH_8BIT
00115 typedef unsigned char flashdat_t;
00116 #else
00117 typedef unsigned short flashdat_t;
00118 #endif
00119 
00120 typedef unsigned long flashadr_t;
00121 typedef volatile flashdat_t *flashptr_t;
00122 
00123 static flashptr_t chip = (flashptr_t) FLASH_CHIP_BASE;
00124 
00125 #define FLASH_UNLOCK(base) { \
00126     base[0x0555] = 0xAA; \
00127     base[0x0AAA] = 0x55; \
00128 }
00129 
00130 #define FLASH_COMMAND(base, cmd) { \
00131     base[0x0555] = cmd; \
00132 }
00133 
00134 #define FLASH_CMD_ERASE         0x80
00135 #define FLASH_CMD_ERASE_CHIP    0x10
00136 #define FLASH_CMD_ERASE_SECTOR  0x30
00137 
00138 #define FLASH_CMD_ENTER_ID      0x90
00139 #define FLASH_CMD_EXIT_ID       0xF0
00140 
00141 #define FLASH_CMD_PROGRAM       0xA0
00142 
00148 static int At49bvWaitReady(flashptr_t addr, flashdat_t data, uint32_t tmo, int poll)
00149 {
00150     while (*addr != data) {
00151         if (!poll) {
00152             NutSleep(1);
00153         }
00154         if (tmo-- == 0) {
00155             return -1;
00156         }
00157     }
00158     return 0;
00159 }
00160 
00161 /*
00162  * May be later used to retrieve the chip layout.
00163  */
00164 unsigned long At49bvInit(void)
00165 {
00166     unsigned long id;
00167 
00168     FLASH_UNLOCK(chip);
00169     FLASH_COMMAND(chip, FLASH_CMD_ENTER_ID);
00170     id = chip[0];
00171     id <<= 16;
00172     id |= chip[1];
00173     FLASH_UNLOCK(chip);
00174     FLASH_COMMAND(chip, FLASH_CMD_EXIT_ID);
00175 
00176     return id;
00177 }
00178 
00185 unsigned long long AT49bvReadProtectionRegister(int factory)
00186 {
00187     unsigned long long id;
00188 
00189     FLASH_UNLOCK(chip);
00190     FLASH_COMMAND(chip, FLASH_CMD_ENTER_ID);
00191     if (factory) {
00192         id  = chip[0x81];
00193         id <<= 16;
00194         id |= chip[0x82];
00195         id <<= 16;
00196         id |= chip[0x83];
00197         id <<= 16;
00198         id |= chip[0x84];
00199     } else {
00200         id  = chip[0x85];
00201         id <<= 16;
00202         id |= chip[0x86];
00203         id <<= 16;
00204         id |= chip[0x87];
00205         id <<= 16;
00206         id |= chip[0x88];
00207     }        
00208     FLASH_UNLOCK(chip);
00209     FLASH_COMMAND(chip, FLASH_CMD_EXIT_ID);
00210 
00211     return id;
00212 }
00213 
00217 int At49bvSectorErase(unsigned int off)
00218 {
00219     flashptr_t ptr = (flashptr_t) (uintptr_t) (FLASH_CHIP_BASE + off);
00220 
00221     FLASH_UNLOCK(chip);
00222     FLASH_COMMAND(chip, FLASH_CMD_ERASE);
00223     FLASH_UNLOCK(chip);
00224     *ptr = FLASH_CMD_ERASE_SECTOR;
00225 
00226     return At49bvWaitReady(ptr, (flashdat_t) - 1, FLASH_ERASE_WAIT, 0);
00227 }
00228 
00232 int At49bvChipErase(void)
00233 {
00234     FLASH_UNLOCK(chip);
00235     FLASH_COMMAND(chip, FLASH_CMD_ERASE);
00236     FLASH_UNLOCK(chip);
00237     FLASH_COMMAND(chip, FLASH_CMD_ERASE_CHIP);
00238 
00239     return At49bvWaitReady(chip, (flashdat_t) - 1, FLASH_CHIP_ERASE_WAIT, 0);
00240 }
00241 
00251 int At49bvSectorRead(unsigned int off, void *data, unsigned int len)
00252 {
00253     memcpy(data, (void *) (uintptr_t) (FLASH_CHIP_BASE + off), len);
00254 
00255     return 0;
00256 }
00257 
00269 int At49bvSectorWrite(unsigned int off, CONST void *data, unsigned int len)
00270 {
00271     int rc = 0;
00272     flashptr_t sp = (flashptr_t) data;
00273     flashptr_t dp = (flashptr_t) (uintptr_t) (FLASH_CHIP_BASE + off);
00274     unsigned int i;
00275 
00276     for (i = 0; i < len; i += sizeof(flashdat_t)) {
00277         /* No need to save values with all bits set. */
00278         if (*sp != (flashdat_t) - 1) {
00279             /* Write to memory location. */
00280             FLASH_UNLOCK(chip);
00281             FLASH_COMMAND(chip, FLASH_CMD_PROGRAM);
00282             *dp = *sp;
00283             if ((rc = At49bvWaitReady(dp, *sp, FLASH_WRITE_POLLS, 1)) != 0) {
00284                 break;
00285             }
00286         }
00287         dp++;
00288         sp++;
00289     }
00290     return rc;
00291 }
00292 
00302 int At49bvParamRead(unsigned int pos, void *data, unsigned int len)
00303 {
00304     return At49bvSectorRead(FLASH_CONF_SECTOR + pos, data, len);
00305 }
00306 
00316 int At49bvParamWrite(unsigned int pos, CONST void *data, unsigned int len)
00317 {
00318     int rc = -1;
00319     uint8_t *buff;
00320 
00321     /* Load the complete configuration area. */
00322     if ((buff = malloc(FLASH_CONF_SIZE)) != 0) {
00323         rc = At49bvSectorRead(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
00324         /* Compare old with new contents. */
00325         if (memcmp(buff + pos, data, len)) {
00326             /* New contents differs. Copy it into the sector buffer. */
00327             memcpy(buff + pos, data, len);
00328             /* Erase sector and write new data. */
00329             if ((rc = At49bvSectorErase(FLASH_CONF_SECTOR)) == 0) {
00330                 rc = At49bvSectorWrite(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
00331             }
00332         }
00333         free(buff);
00334     }
00335     return rc;
00336 }