📄 flash.c
字号:
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 */#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI) case FLASH_MAN_STM: { ulong wp; u8 *data = (u8 *) src; int left; /* number of bytes left to program */ wp = addr; /* page align, each page is 256 bytes */ if ((wp % 0x100) != 0) { left = (0x100 - (wp & 0xFF)); write_ser_data(info, wp, data, left); cnt -= left; wp += left; data += left; } /* page program - 256 bytes at a time */ if (cnt > 255) { count = 0; while (cnt >= 0x100) { write_ser_data(info, wp, data, 0x100); cnt -= 0x100; wp += 0x100; data += 0x100; if (count++ > 0x400) { spin_wheel(); count = 0; } } } /* remainint bytes */ if (cnt && (cnt < 256)) { write_ser_data(info, wp, data, cnt); wp += cnt; data += cnt; cnt -= cnt; } printf("\b."); }#endif } /* 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);}#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)int write_ser_data(flash_info_t * info, ulong dest, uchar * data, ulong cnt){ ulong start; int status, i; u8 flashdata; /* Check if Flash is (sufficiently) erased */ dspi_tx(ser_flash_cs, 0x80, SER_READ); dspi_tx(ser_flash_cs, 0x80, (dest >> 16) & 0xFF); dspi_tx(ser_flash_cs, 0x80, (dest >> 8) & 0xFF); dspi_tx(ser_flash_cs, 0x80, dest & 0xFF); dspi_rx(); dspi_rx(); dspi_rx(); dspi_rx(); dspi_tx(ser_flash_cs, 0x80, 0); flashdata = dspi_rx(); dspi_tx(ser_flash_cs, 0x00, 0); dspi_rx(); if ((flashdata & *data) != *data) { printf("not erased at %08lx (%lx)\n", (ulong) dest, (ulong) flashdata); return (2); } dspi_tx(ser_flash_cs, 0x00, SER_WREN); dspi_rx(); status = serial_flash_read_status(ser_flash_cs); if (((status & 0x9C) != 0) && ((status & 0x02) != 0x02)) { printf("Error Programming\n"); return 1; } start = get_timer(0); dspi_tx(ser_flash_cs, 0x80, SER_PAGE_PROG); dspi_tx(ser_flash_cs, 0x80, ((dest & 0xFF0000) >> 16)); dspi_tx(ser_flash_cs, 0x80, ((dest & 0xFF00) >> 8)); dspi_tx(ser_flash_cs, 0x80, (dest & 0xFF)); dspi_rx(); dspi_rx(); dspi_rx(); dspi_rx(); for (i = 0; i < (cnt - 1); i++) { dspi_tx(ser_flash_cs, 0x80, *data); dspi_rx(); data++; } dspi_tx(ser_flash_cs, 0x00, *data); dspi_rx(); do { status = serial_flash_read_status(ser_flash_cs); if (get_timer(start) > CFG_FLASH_ERASE_TOUT) { printf("Timeout\n"); return 1; } } while (status & 0x01); return (0);}#endif/*----------------------------------------------------------------------- * 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 + -