00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
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
00232 if (*sp != (flashdat_t) - 1) {
00233
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
00276 if ((buff = malloc(FLASH_CONF_SIZE)) != 0) {
00277 rc = At49bvSectorRead(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
00278
00279 if (memcmp(buff + pos, data, len)) {
00280
00281 memcpy(buff + pos, data, len);
00282
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 }