📄 flash.c
字号:
}int cfi_chip_setup(cfi_info_t *pcfi){ int i; int num_erase_regions = cfi_read(pcfi->base + cfi_build_cmd_addr(0x2c)); unsigned int start; if (num_erase_regions == 0) return FLASH_NOREGION; for (i = 0; i < (sizeof pcfi->ident) - (sizeof pcfi->ident.erase_region_info) + (num_erase_regions * 4); ++i) ((unsigned char *) &pcfi->ident)[i] = cfi_read(pcfi->base + cfi_build_cmd_addr(0x10 + i)); if (pcfi->ident.primary_id != 0x2) /* Not using command set 0002 */ uart_puts("Warning: not using command set 0002\n"); for (i = 0, start = 0; i < num_erase_regions; ++i) { pcfi->erase_regions[i].start = start; pcfi->erase_regions[i].size = 0x100 * ((pcfi->ident.erase_region_info[i] >> 16) & 0xffff); pcfi->erase_regions[i].blocks = (pcfi->ident.erase_region_info[i] & 0xffff) + 1; start += pcfi->erase_regions[i].size * pcfi->erase_regions[i].blocks; } pcfi->size = 1 << pcfi->ident.device_size; return FLASH_OK;}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); #ifdef SET_SERVER_IP_FOR_DOWNLOAD unsigned long show=0;#endif 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_printf(" 0x%08x be erased\n",start); uart_printf(" 0x%08x blocksize\n",blocksize); #ifdef SET_SERVER_IP_FOR_DOWNLOAD if(show%2){ fip_display_character(10, '|'); } else{ fip_display_character(10, '-'); } show++; #endif 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -