📄 flash.c
字号:
prot = 0; for (sect = s_first; sect <= s_last; ++sect) { if (info->protect[sect]) { prot++; } } if (prot) printf("- Warning: %d protected sectors will not be erased!\n", prot); else printf("\n"); start = get_timer(0); last = start; /* Start erase on unprotected sectors */ for (sect = s_first; sect <= s_last; sect++) { if (info->protect[sect] == 0) { /* not protected */ FPWV *addr = (FPWV *) (info->start[sect]); int min = 0; printf("."); /* arm simple, non interrupt dependent timer */ start = get_timer(0); if (intel) { *addr = (FPW) INTEL_READID; min = addr[INTEL_CFI_TERB] & 0xff; min = 1 << min; /* ms */ min = (min / info->sector_count) * 1000; /* start erase block */ *addr = (FPW) INTEL_CLEAR; /* clear status register */ *addr = (FPW) INTEL_ERASE; /* erase setup */ *addr = (FPW) INTEL_CONFIRM; /* erase confirm */ while ((*addr & (FPW) INTEL_FINISHED) != (FPW) INTEL_FINISHED) { if (get_timer(start) > CFG_FLASH_ERASE_TOUT) { printf("Timeout\n"); *addr = (FPW) INTEL_SUSERASE; /* suspend erase */ *addr = (FPW) INTEL_RESET; /* reset to read mode */ rcode = 1; break; } } *addr = (FPW) INTEL_RESET; /* resest to read mode */ } else { FPWV *base; /* first address in bank */ FPWV *atmeladdr; flag = disable_interrupts(); atmeladdr = (FPWV *) addr; /* concatenate to 8 bit */ base = (FPWV *) (CFG_ATMEL_BASE); /* First sector */ base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */ base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */ base[FLASH_CYCLE1] = (u8) 0x00800080; /* erase mode */ base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */ base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */ *atmeladdr = (u8) 0x00300030; /* erase sector */ if (flag) enable_interrupts(); while ((*atmeladdr & (u8) 0x00800080) != (u8) 0x00800080) { if (get_timer(start) > CFG_FLASH_ERASE_TOUT) { printf("Timeout\n"); *atmeladdr = (u8) 0x00F000F0; /* reset to read mode */ rcode = 1; break; } } *atmeladdr = (u8) 0x00F000F0; /* reset to read mode */ } /* Atmel or Intel */ } } printf(" done\n"); return rcode;}int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt){ if (info->flash_id == FLASH_UNKNOWN) return 4; switch (info->flash_id & FLASH_VENDMASK) { case FLASH_MAN_ATM: { u16 data = 0; int bytes; /* number of bytes to program in current word */ int left; /* number of bytes left to program */ int i, res; for (left = cnt, res = 0; left > 0 && res == 0; addr += sizeof(data), left -= sizeof(data) - bytes) { bytes = addr & (sizeof(data) - 1); addr &= ~(sizeof(data) - 1); /* combine source and destination data so can program * an entire word of 16 or 32 bits */ for (i = 0; i < sizeof(data); i++) { data <<= 8; if (i < bytes || i - bytes >= left) data += *((uchar *) addr + i); else data += *src++; } data = (data >> 8) | (data << 8); res = write_word_atm(info, (FPWV *) addr, data); } return res; } /* case FLASH_MAN_ATM */ case FLASH_MAN_INTEL: { ulong cp, wp; u16 data; int count, i, l, rc, port_width; /* get lower word aligned address */ wp = addr; port_width = sizeof(FPW); /* * handle unaligned start bytes */ if ((l = addr - wp) != 0) { data = 0; for (i = 0, cp = wp; i < l; ++i, ++cp) { data = (data << 8) | (*(uchar *) cp); } for (; i < port_width && cnt > 0; ++i) { data = (data << 8) | *src++; --cnt; ++cp; } for (; cnt == 0 && i < port_width; ++i, ++cp) data = (data << 8) | (*(uchar *) cp); if ((rc = write_data(info, wp, data)) != 0) return (rc); wp += port_width; } if (cnt > WR_BLOCK) { /* * handle word aligned part */ count = 0; while (cnt >= WR_BLOCK) { if ((rc = write_data_block(info, (ulong) src, wp)) != 0) return (rc); wp += WR_BLOCK; src += WR_BLOCK; cnt -= WR_BLOCK; if (count++ > 0x800) { spin_wheel(); count = 0; } } } /* handle word aligned part */ if (cnt < WR_BLOCK) { /* * handle word aligned part */ count = 0; while (cnt >= port_width) { data = 0; for (i = 0; i < port_width; ++i) data = (data << 8) | *src++; if ((rc = write_data(info, (ulong) ((FPWV *) wp), (FPW) (data))) != 0) return (rc); wp += port_width; cnt -= port_width; if (count++ > 0x800) { spin_wheel(); count = 0; } } } if (cnt == 0) return ERR_OK; /* * handle unaligned tail bytes */ data = 0; for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) { data = (data << 8) | (*src++); --cnt; } for (; i < port_width; ++i, ++cp) { data = (data << 8) | (*(uchar *) cp); } return write_data(info, (ulong) ((FPWV *) wp), (FPW) data); } /* case FLASH_MAN_INTEL */ } /* switch */ return ERR_OK;}/*----------------------------------------------------------------------- * Write a word or halfword to Flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased */int write_data_block(flash_info_t * info, ulong src, ulong dest){ FPWV *srcaddr = (FPWV *) src; FPWV *dstaddr = (FPWV *) dest; ulong start; int flag, i; /* Check if Flash is (sufficiently) erased */ for (i = 0; i < WR_BLOCK; i++) if ((*dstaddr++ & 0xff) != 0xff) { printf("not erased at %08lx (%lx)\n", (ulong) dstaddr, *dstaddr); return (2); } dstaddr = (FPWV *) dest; /* Disable interrupts which might cause a timeout here */ flag = disable_interrupts(); *dstaddr = (FPW) INTEL_WRBLK; /* write block setup */ if (flag) enable_interrupts(); /* arm simple, non interrupt dependent timer */ start = get_timer(0); /* wait while polling the status register */ while ((*dstaddr & (FPW) INTEL_FINISHED) != (FPW) INTEL_OK) { if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { *dstaddr = (FPW) INTEL_RESET; /* restore read mode */ return (1); } } *dstaddr = (FPW) WR_BLOCK - 1; /* write 32 to buffer */ for (i = 0; i < WR_BLOCK; i++) *dstaddr++ = *srcaddr++; dstaddr -= 1; *dstaddr = (FPW) INTEL_CONFIRM; /* write 32 to buffer */ /* arm simple, non interrupt dependent timer */ start = get_timer(0); /* wait while polling the status register */ while ((*dstaddr & (FPW) INTEL_FINISHED) != (FPW) INTEL_OK) { if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { *dstaddr = (FPW) INTEL_RESET; /* restore read mode */ return (1); } } *dstaddr = (FPW) INTEL_RESET; /* restore read mode */ return (0);}/*----------------------------------------------------------------------- * Write a word or halfword to Flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased */int write_data(flash_info_t * info, ulong dest, FPW data){ FPWV *addr = (FPWV *) dest; ulong start; int flag; /* Check if Flash is (sufficiently) erased */ if ((*addr & data) != data) { printf("not erased at %08lx (%lx)\n", (ulong) addr, (ulong) * addr); return (2); } /* Disable interrupts which might cause a timeout here */ flag = (int)disable_interrupts(); *addr = (FPW) INTEL_CLEAR; *addr = (FPW) INTEL_RESET; *addr = (FPW) INTEL_WRSETUP; /* write setup */ *addr = data; if (flag) enable_interrupts(); /* arm simple, non interrupt dependent timer */ start = get_timer(0); /* wait while polling the status register */ while ((*addr & (FPW) INTEL_OK) != (FPW) INTEL_OK) { if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { *addr = (FPW) INTEL_SUSERASE; /* suspend mode */ *addr = (FPW) INTEL_CLEAR; /* clear status */ *addr = (FPW) INTEL_RESET; /* reset */ return (1); } } *addr = (FPW) INTEL_CLEAR; /* clear status */ *addr = (FPW) INTEL_RESET; /* restore read mode */ return (0);}/*----------------------------------------------------------------------- * Write a word to Flash for ATMEL FLASH * A word is 16 bits, whichever the bus width of the flash bank * (not an individual chip) is. * * returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased */int write_word_atm(flash_info_t * info, volatile u8 * dest, u16 data){ ulong start; int flag, i; int res = 0; /* result, assume success */ FPWV *base; /* first address in flash bank */ /* Check if Flash is (sufficiently) erased */ if ((*((volatile u16 *)dest) & data) != data) { return (2); } base = (FPWV *) (CFG_ATMEL_BASE); for (i = 0; i < sizeof(u16); i++) { /* Disable interrupts which might cause a timeout here */ flag = disable_interrupts(); base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */ base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */ base[FLASH_CYCLE1] = (u8) 0x00A000A0; /* selects program mode */ *dest = data; /* start programming the data */ /* re-enable interrupts if necessary */ if (flag) enable_interrupts(); start = get_timer(0); /* data polling for D7 */ while (res == 0 && (*dest & (u8) 0x00800080) != (data & (u8) 0x00800080)) { if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { *dest = (u8) 0x00F000F0; /* reset bank */ res = 1; } } *dest++ = (u8) 0x00F000F0; /* reset bank */ data >>= 8; } return (res);}void inline spin_wheel(void){ static int p = 0; static char w[] = "\\/-"; printf("\010%c", w[p]); (++p == 3) ? (p = 0) : 0;}#ifdef CFG_FLASH_PROTECTION/*----------------------------------------------------------------------- */int flash_real_protect(flash_info_t * info, long sector, int prot){ int rcode = 0; /* assume success */ FPWV *addr; /* address of sector */ FPW value; addr = (FPWV *) (info->start[sector]); switch (info->flash_id & FLASH_TYPEMASK) { case FLASH_28F160C3B: case FLASH_28F160C3T: case FLASH_28F320C3B: case FLASH_28F320C3T: case FLASH_28F640C3B: case FLASH_28F640C3T: *addr = (FPW) INTEL_RESET; /* make sure in read mode */ *addr = (FPW) INTEL_LOCKBIT; /* lock command setup */ if (prot) *addr = (FPW) INTEL_PROTECT; /* lock sector */ else *addr = (FPW) INTEL_CONFIRM; /* unlock sector */ /* now see if it really is locked/unlocked as requested */ *addr = (FPW) INTEL_READID; /* read sector protection at sector address, (A7 .. A0) = 0x02. * D0 = 1 for each device if protected. * If at least one device is protected the sector is marked * protected, but return failure. Mixed protected and * unprotected devices within a sector should never happen. */ value = addr[2] & (FPW) INTEL_PROTECT; if (value == 0) info->protect[sector] = 0; else if (value == (FPW) INTEL_PROTECT) info->protect[sector] = 1; else { /* error, mixed protected and unprotected */ rcode = 1; info->protect[sector] = 1; } if (info->protect[sector] != prot) rcode = 1; /* failed to protect/unprotect as requested */ /* reload all protection bits from hardware for now */ flash_sync_real_protect(info); break; default: /* no hardware protect that we support */ info->protect[sector] = prot; break; } return rcode;}#endif#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -