📄 flash_v3.c
字号:
void cfi_cmdset_0002(cfi_info_t *pcfi){ switch (CFIDEV_DEVTYPE) { case 1 : pcfi->addr_unlock1 = 0x555; pcfi->addr_unlock2 = 0x2aa; break; case 2 : pcfi->addr_unlock1 = 0xaaa; pcfi->addr_unlock2 = 0x555; break; case 4 : pcfi->addr_unlock1 = 0x1555; pcfi->addr_unlock2 = 0xaaa; break; }}//// init & basic//int flash_found(void){ return g_flash_chips;}int flash_addr_found(unsigned long addr){ return (find_cfi(addr) != NULL) ? 1 : 0;}int flash_probe(unsigned int base, int force, int verbose){ int i, ret; cfi_info_t *pcfi = NULL; if (!g_flash_inited) { for (i = 0; i < FLASH_MAX_CHIPSET; ++i) g_cfi[i].chip_state = FLSTATE_READY; g_flash_inited = 1; } if ((pcfi = find_cfi(base)) != NULL && !force) return 0; if (pcfi == NULL) if ((pcfi = get_free_cfi()) == NULL) return 0; pcfi->base = base; if ((ret = cfi_probe_chip(pcfi)) != 0) { uart_printf("Flash does not exist at 0x%08x\n", pcfi->base); return ret; } if (verbose) flash_list(pcfi); return 0;}unsigned int flash_getsize(void){ int i; unsigned int size; for (i = 0, size = 0; i < FLASH_MAX_CHIPSET; ++i) { if (g_cfi[i].exist) size += g_cfi[i].size; } return size;}//// erasing//#ifdef FLASH_USE_DQXstatic void dqx_wait(unsigned long addr, unsigned int datum, unsigned int wait){ unsigned int dq6, dq5; unsigned int status, oldstatus, res; dq6 = cfi_build_cmd(1<<6); dq5 = cfi_build_cmd(1<<5); if (flash_wait_div <= 1) { if (wait > 1000) { unsigned_divide(wait, 1000, &res, NULL); em86xx_msleep(res); } else { em86xx_usleep(wait); } flash_wait_div = 1; } oldstatus = cfi_read(addr); status = cfi_read(addr); while ((status != datum) || (((status & dq6) != (oldstatus & dq6)) && ((status & dq5) != dq5))) { if (wait > 1000) { unsigned_divide(wait, 1000 * flash_wait_div, &res, NULL); em86xx_msleep(res); } else { unsigned_divide(wait, flash_wait_div, &res, NULL); em86xx_msleep(res); } oldstatus = cfi_read(addr); status = cfi_read(addr); }}#endifint flash_erase_all(void){ int i, nchips, cnt = 0; cfi_info_t *pcfi; for (i = 0, nchips = 0; i < FLASH_MAX_CHIPSET; ++i) { pcfi = &g_cfi[i]; if (!pcfi->exist) continue; if (pcfi->chip_state != FLSTATE_READY) return FLASH_NOTREADY; pcfi->chip_state = FLSTATE_ERASING; cfi_send_cmd(0xaa, pcfi->addr_unlock1, pcfi->base); cfi_send_cmd(0x55, pcfi->addr_unlock2, pcfi->base); cfi_send_cmd(0x80, pcfi->addr_unlock1, pcfi->base); cfi_send_cmd(0xaa, pcfi->addr_unlock1, pcfi->base); cfi_send_cmd(0x55, pcfi->addr_unlock2, pcfi->base); cfi_send_cmd(0x10, pcfi->addr_unlock1, pcfi->base);#ifdef FLASH_USE_DQX dqx_wait(pcfi->base, 0xff, 1000*(1<<pcfi->ident.timeout_chip_erase));#else for (cnt = 0; cnt < FLASH_ERR_CNT; cnt++) { uart_putc('.'); if (pcfi->ident.timeout_chip_erase != 0) em86xx_msleep(1<<pcfi->ident.timeout_chip_erase); else em86xx_msleep(100); if ((cfi_read(pcfi->base) & 0xff) == 0xff) break; } if (cnt >= FLASH_ERR_CNT) break;#endif pcfi->chip_state = FLSTATE_READY; ++nchips; } if (cnt >= FLASH_ERR_CNT) return FLASH_VERIFY_FAIL; return (nchips == 0) ? FLASH_NOTEXIST : FLASH_OK;}int flash_erase_oneblock(unsigned long addr){ int cnt = 0; cfi_info_t *pcfi = find_cfi(addr); if (pcfi == NULL) return FLASH_NOTEXIST; if (pcfi->chip_state != FLSTATE_READY) return FLASH_NOTREADY; pcfi->chip_state = FLSTATE_ERASING; cfi_send_cmd(0xaa, pcfi->addr_unlock1, pcfi->base); cfi_send_cmd(0x55, pcfi->addr_unlock2, pcfi->base); cfi_send_cmd(0x80, pcfi->addr_unlock1, pcfi->base); cfi_send_cmd(0xaa, pcfi->addr_unlock1, pcfi->base); cfi_send_cmd(0x55, pcfi->addr_unlock2, pcfi->base); cfi_send_cmd(0x30, addr - pcfi->base, pcfi->base);#ifdef FLASH_USE_DQX dqx_wait(addr, 0xff, 1000*(1<<pcfi->ident.timeout_block_erase));#else for (cnt = 0; cnt < FLASH_ERR_CNT; cnt++) { em86xx_msleep(1 << pcfi->ident.timeout_block_erase); if ((cfi_read(addr) & 0xff) == 0xff) break; }#endif pcfi->chip_state = FLSTATE_READY; return (cnt >= FLASH_ERR_CNT) ? FLASH_VERIFY_FAIL : FLASH_OK;}int flash_erase_region(unsigned long addr, unsigned int len){ unsigned int start, blocksize; cfi_info_t *pcfi = find_cfi(addr); if (len == 0) return FLASH_OK; if (pcfi == NULL) return FLASH_NOTEXIST; if (pcfi->chip_state != FLSTATE_READY) return FLASH_NOTREADY; if (flash_calcblock(addr, &start, &blocksize) < 0) return FLASH_NOTEXIST; do { uart_putc('.'); flash_erase_oneblock(start); start += blocksize; if (flash_calcblock(start, &start, &blocksize) < 0) break; } while (start < addr + len); return FLASH_OK;}//// read / writing//// suppose 16 bits writing//int flash_read_data(unsigned long addr, void *data, int len){ memcpy(data, (void *) addr, len); return FLASH_OK;}int flash_writable(unsigned long addr, int len){ int i; for (i = 0; i < len; ++i) { if (((unsigned char *) (addr))[i] != 0xff) return 0; } return 1;}int flash_write_onebyte(unsigned long addr, unsigned int data){ int cnt = 0; unsigned int curdata; unsigned int olddata, newaddr, newdata; cfi_info_t *pcfi = find_cfi(addr);#if (CFIDEV_BUSWIDTH != 1 && CFIDEV_BUSWIDTH != 2)#error "Current code doesn't support other than 8-bits and 16-bits writing"#endif if (pcfi == NULL) return FLASH_NOTEXIST; if (pcfi->chip_state != FLSTATE_READY) return FLASH_NOTREADY; #if CFIDEV_BUSWIDTH == 1 newaddr = addr; olddata = curdata = cfi_read(newaddr); newdata = data;#elif CFIDEV_BUSWIDTH == 2 newaddr = addr & ~0x01; curdata = cfi_read(newaddr); if (addr & 0x01) { olddata = (curdata & 0xff00) >> 8; newdata = (curdata & 0x00ff) | ((data & 0xff) << 8); } else { olddata = (curdata & 0x00ff); newdata = (curdata & 0xff00) | (data & 0xff); }#endif if (~olddata & data) return FLASH_WRITE_FAULT; pcfi->chip_state = FLSTATE_WRITING; cfi_send_cmd(0xaa, pcfi->addr_unlock1, pcfi->base); cfi_send_cmd(0x55, pcfi->addr_unlock2, pcfi->base); cfi_send_cmd(0xa0, pcfi->addr_unlock1, pcfi->base); cfi_write(newdata, newaddr);#ifdef FLASH_USE_DQX dqx_wait(newaddr, newdata, 1<<pcfi->ident.timeout_single_write);#else for (cnt = 0; cnt < FLASH_ERR_CNT; cnt++) { em86xx_usleep(1 << pcfi->ident.timeout_single_write); if (cfi_read(newaddr) == newdata) break; }#endif pcfi->chip_state = FLSTATE_READY; return (cnt >= FLASH_ERR_CNT) ? FLASH_WRITE_FAULT : FLASH_OK;}int flash_write_oneword(unsigned long addr, unsigned int data){#if (CFIDEV_BUSWIDTH != 1 && CFIDEV_BUSWIDTH != 2)#error "Current code doesn't support other than 8-bits and 16-bits writing"#endif#if CFIDEV_BUSWIDTH == 1 int ret; if ((ret = flash_write_onebyte(addr, data & 0xff)) == FLASH_OK) ret = flash_write_onebyte(addr + 1, (data >> 8) & 0xff); return ret;#elif CFIDEV_BUSWIDTH == 2 int ret; int cnt = 0; unsigned int olddata, newaddr; cfi_info_t *pcfi = find_cfi(addr); // if the address is not aligned if ((addr & 0x01) != 0) { if ((ret = flash_write_onebyte(addr, data & 0xff)) == FLASH_OK) ret = flash_write_onebyte(addr + 1, (data >> 8) & 0xff); return ret; } if (pcfi == NULL) return FLASH_NOTEXIST; if (pcfi->chip_state != FLSTATE_READY) return FLASH_NOTREADY; newaddr = addr & ~0x01; olddata = cfi_read(newaddr); if (~olddata & data) return FLASH_WRITE_FAULT; pcfi->chip_state = FLSTATE_WRITING; cfi_send_cmd(0xaa, pcfi->addr_unlock1, pcfi->base); cfi_send_cmd(0x55, pcfi->addr_unlock2, pcfi->base); cfi_send_cmd(0xa0, pcfi->addr_unlock1, pcfi->base); cfi_write(data, newaddr);#ifdef FLASH_USE_DQX dqx_wait(newaddr, data, 1<<pcfi->ident.timeout_single_write);#else for (cnt = 0; cnt < FLASH_ERR_CNT; cnt++) { em86xx_usleep(1 << pcfi->ident.timeout_single_write); if (cfi_read(newaddr) == data) break; }#endif pcfi->chip_state = FLSTATE_READY; return (cnt >= FLASH_ERR_CNT) ? FLASH_WRITE_FAULT : FLASH_OK;#endif}int do_write_buffer(cfi_info_t *pcfi, unsigned long adr, const unsigned char *buf, int len){ int wbufsize, z,ret=0, cnt=0; unsigned char datum=0; unsigned int dq1,dq7, dq5; unsigned int status, oldstatus, res; unsigned int wait = 1<<pcfi->ident.timeout_single_write; wbufsize = CFIDEV_INTERLEAVE << 5; //cfi->cfiq->MaxBufWriteSize=0x5 adr += 0; //chip->start=0x0; /* write buffers algorithm taken from S29GL064M90 manual */ cfi_send_cmd(0xAA, pcfi->addr_unlock1, pcfi->base); cfi_send_cmd(0x55, pcfi->addr_unlock2, pcfi->base); cfi_write(0x25, adr); cfi_write((len/CFIDEV_BUSWIDTH-1), adr); /* word count */ /* Write data */ for (z = 0; z < len; z += CFIDEV_BUSWIDTH) { cfi_write( datum=*((unsigned char*)buf)++, adr+z); } /* start program */ cfi_write(0x29, adr); //zxh+ /* use data polling algorithm */ dq1 = cfi_build_cmd(1<<1); dq5 = cfi_build_cmd(1<<5); dq7 = cfi_build_cmd(1<<7); z -= CFIDEV_BUSWIDTH; /* go to last written address */ do { status = cfi_read(adr+z); if( (dq7 & status) == (dq7 & datum) ) break; if( ((dq5 & status) == dq5) || ((dq1 & status) == dq1) ) { status = cfi_read( adr+z ); if( (dq7 & status) != (dq7 & datum) ) { ret = 1; break; } else break; } cnt++; } while( cnt<1000 ); if( !ret && !(cnt<1000) ) { uart_puts("Waiting for write to complete timed out in do_write_buffer.\n"); ret = 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -