📄 flash.c
字号:
#include <hardware.h>#include <stdio.h>#include <string.h>#include <time.h>#include <setup.h>#include <command.h>#include <io.h>#define READ_ARRAY (0x00FF00FF)#define READ_IDCODE (0x00900090)#define READ_QUERY (0x00980098)#define STATUS_READ (0x00700070)#define STATUS_CLEAR (0x00500050)#define WRITE_BUF (0x00E800E8)#define WRITE_BUF_COMFIRM (0x00D000D0)#define PGM_SETUP (0x00400040)#define ERASE_SETUP (0x00200020)#define ERASE_CONFIRM (0x00D000D0)#define ERASE_PROGRAM_SUSPEND (0x00B000B0)#define ERASE_PROGRAM_RESUME (0x00D000D0)#define FLASH_CFG (0x00B800B8)#define FLASH_SETUP (0x00600060)#define SET_READ_CFG (0x00030003)#define BLOCK_LOCK_BIT_SET (0x00010001)#define BLOCK_LOCK_BIT_CLEAR (0x00D000D0)#define PROTECTION_PROGRAM (0x00C000C0)/* Status bits */#define STATUS_BUSY (0x00800080)#define STATUS_ERR_FILTER (0x007E007E)#define STATUS_LOCK_DETECT (0x00020002)#define STATUS_VOLT_RANG_ERR (0x00080008)#define STATUS_CMD_SEQ_ERR (0x00300030)#define STATUS_PGM_ERR (0x00100010)#define STATUS_LOCK_ERR (0x00100010)#define STATUS_ERASE_ERR (0x00200020)#define STATUS_UNLOCK_ERR (0x00200020)#define STATUS_LOCK_ERR_FILTER (0x00380038)#define report(fmt, args...) printf(fmt, ##args)#define detail(fmt, args...) //printf(fmt, ##args)#define assert(fmt, args...) printf(fmt, ##args)#define failed(fmt, args...) //printf(fmt, ##args)struct iflash { ulong base; ulong size; ulong blksize; ulong blocks; uint flashcnt; uint buswidth; ushort buff_size; ushort erase_time;};enum action { ACT_PGM, ACT_ERASE, ACT_LOCK, ACT_UNLOCK, ACT_WRITE_BUF };extern bool iflash_init(void);static bool do_flash(int argc, char **argv);static void flash_usage(void);static bool do_erase(int argc, char **argv);static void erase_usage(void);static bool do_lock(int argc, char **argv);static void lock_usage(void);static bool do_unlock(int argc, char **argv);static void unlock_usage(void);static bool iflash_write_block(void *dest, const void *src);static bool iflash_erase_block(void *addr);static bool iflash_lock_block(void *addr);static bool iflash_unlock_block(void *addr);bool flash_write(void *dest, const void *src, uint cnt);//static ulong iflash_read(void *addr, int buswidth);static void iflash_write_cmd(void *addr, int buswidth, int c);static bool iflash_status_check(void *addr, enum action which);static void wait_while_busy(void *addr);static struct iflash _flash, *flash=&_flash;struct command_t cmd_flash = { .name = "flash", .run = do_flash, .usage = flash_usage};struct command_t cmd_erase = { .name = "erase", .run = do_erase, .usage = erase_usage};struct command_t cmd_lock = { .name = "lock", .run = do_lock, .usage = lock_usage};struct command_t cmd_unlock = { .name = "unlock", .run = do_unlock, .usage = unlock_usage};extern bool iflash_init(void){ int bit_mode; int buswidth, flashcnt; int blocks, blksize; ulong base; /* check query and find buswidth */ iflash_write_cmd((void *)flash->base, 1, READ_QUERY); for (buswidth=1; buswidth <= 8; buswidth <<= 1){ if ( *(uint8 *)(flash->base + (0x10 * buswidth)) == 'Q' && *(uint8 *)(flash->base + (0x11 * buswidth)) == 'R' && *(uint8 *)(flash->base + (0x12 * buswidth)) == 'Y' ) break; } iflash_write_cmd((void *)flash->base, 1, READ_ARRAY); if (buswidth > 8) return false; /* find number of flash */ base = flash->base; iflash_write_cmd((void *)base, buswidth, READ_QUERY); for (bit_mode=1; bit_mode < buswidth; bit_mode <<= 1){ int ch = *(uint8 *)(base + (0x10 * buswidth) + bit_mode); if (ch == 'Q' || ch == 'R') break; } flashcnt = buswidth / bit_mode; /* get flash information from query */ flash->size = (1 << *(uint8 *)(base + (0x27 * buswidth))) * flashcnt; blocks = *(uint8 *)(base + 0x2E*buswidth) << 8 | *(uint8 *)(base + 0x2D*buswidth); flash->blocks = (blocks | (blocks>>2)) + 1; blksize = *(uint8 *)(base + 0x30*buswidth) << 8 | *(uint8 *)(base + 0x2F*buswidth); flash->blksize = blksize * 256 * flashcnt; if (flash->size != flash->blksize * flash->blocks){ blocks = *(uint8 *)(base + 0x32*buswidth) << 8 | *(uint8 *)(base + 0x31*buswidth); flash->blocks = (blocks | (blocks>>2)) + 1; blksize = *(uint8 *)(base + 0x34*buswidth) << 8 | *(uint8 *)(base + 0x33*buswidth); flash->blksize = blksize * 256 * flashcnt; } flash->flashcnt = flashcnt; flash->buswidth = buswidth; flash->buff_size = (1 << *(uint8 *)(flash->base + (0x2A * buswidth))) * flashcnt; flash->erase_time = (1 << *(uint8 *)(flash->base + (0x25 * buswidth))); detail(" strata flash\n"); detail(" base base : 0x%08lX\n", flash->base); detail(" size : 0x%08lX\n", flash->size); detail(" blk size : 0x%08lX\n", flash->blksize); detail(" blocks : 0x%08lX\n", flash->blocks); detail(" buff size : 0x%08X\n", flash->buff_size); detail(" erase time: 0x%08X\n", flash->erase_time); detail(" flash cnt : 0x%08X\n", flash->flashcnt); detail(" bit width : 0x%08X\n", flash->buswidth); report(" flash : base=0x%08lX, size=0x%08lX\n", flash->base, flash->size); iflash_write_cmd((void *)flash->base, buswidth, READ_ARRAY); //iflash_unlock_all(); return true;}static bool do_flash_by_map(int argc, char **argv){ bool res; uint n, len; uchar *to, *from; void *dest, *src; struct map *mp; if (argc != 2) goto invalid; mp = find_map(argv[1]); if (!mp) goto invalid; dest = (void *)mp->sramb; src = (void *)mp->dramb; if (!mp->drams) goto fail1; /* erase */ to = dest; len = mp->maxs; if (len) do { report("\r erase at 0x%p~0x%p : at 0x%p", dest, dest + mp->maxs-1, to); res = iflash_erase_block(to); if (!res){ failed("\n error : failed to erase.\n"); goto fail2; } to += flash->blksize; len -= flash->blksize; } while (len); report("\r erase at 0x%p~0x%p : done. \n", dest, dest + mp->maxs-1); /* write */ to = dest; from = src; len = mp->drams; if (len) do { n = flash->blksize - ((ulong)to & (flash->blksize-1)); n = len < n ? len : n; report("\r write at 0x%p~0x%p with 0x%p : at 0x%p", dest, dest + mp->drams-1, src, to); res = flash_write(to, from, n); if (!res){ failed("write failed"); report("\n"); goto fail2; } to += n; from += n; len -= n; } while (len); report("\r write at 0x%p~0x%p with 0x%p : done. \n", dest, dest + mp->drams-1, src); mp->srams = mp->drams; save_setup(); return true;fail1 : printf(" error : image is not exists in dynamic memory.\n"); return false;fail2 : mp->srams = 0; save_setup(); return false;invalid : flash_usage(); return false;}static bool do_flash_by_addr(int argc, char **argv){ bool res; uint n, size, remain; ulong tmp; void *dest, *src; uchar *to, *from; /* get information */ if (argc != 4) goto invalid; res = strtoul(argv[1], &tmp, 16); if (!res) goto invalid; dest = (void *)tmp; res = strtoul(argv[2], &tmp, 16); if (!res) goto invalid; src = (void *)tmp; res = strtoul(argv[3], &tmp, 0); if (!res) goto invalid; size = tmp; /* write */ to = dest; from = src; remain = size; if (remain) do { n = flash->blksize - ((ulong)to & (flash->blksize-1)); n = remain < n ? remain : n; report("\r write at 0x%p~0x%p with 0x%p : at 0x%p", dest, (char *)dest + size-1, src, to); res = flash_write(to, from, n); if (!res){ failed("write failed"); report("\n"); return false; } to += n; from += n; remain -= n; } while (remain); report("\r write at 0x%p~0x%p with 0x%p : done. \n", dest, dest + size-1, src); return true;invalid : flash_usage(); return false;}static bool do_flash(int argc, char **argv){ if (argc == 2) return do_flash_by_map(argc, argv); else if (argc == 4) return do_flash_by_addr(argc, argv); flash_usage(); return false;}static void flash_usage(void){ usage_format("flash {loader/kernel/root/ramdisk}", "copy to flash from sdram of area"); //usage_format("flash dest src size", "copy to flash from src to dest"); return;}static bool do_erase(int argc, char **argv){ bool res; ulong addr, size, tmp; /* get information */ if (argc == 2){ struct map *mp; mp = find_map(argv[1]); if (mp){ /* erase {loader/kernel/ramdisk/root} */ addr = mp->sramb; size = mp->maxs; } else if (strtoul(argv[1], &tmp, 16)){ /* erase addr */ addr = tmp; size = flash->blksize; } else goto invalid; } else if (argc == 3){ /* erase addr size */ res = strtoul(argv[1], &tmp, 16); if (!res) goto invalid; addr = tmp; res = strtoul(argv[2], &tmp, 16); if (!res) goto invalid; size = tmp; } else goto invalid; /* check address and size */ if (addr % flash->blksize){ failed(" error : addr is not flash block base.(blksize=%lx)\n", flash->blksize); return false; } if (size % flash->blksize){ failed(" error : size is not multifly of block size.(blksize=%lx)\n", flash->blksize); return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -