| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699 |
- #include "little_flash.h"
- #include "little_flash_table.h"
- extern lf_err_t little_flash_port_init(little_flash_t *lf);
- static const little_flash_chipinfo_t little_flash_table[] = LITTLE_FLASH_CHIP_TABLE;
- lf_err_t little_flash_write_status(const little_flash_t *lf, uint8_t address, uint8_t status){
- lf_err_t result = LF_ERR_OK;
- uint8_t cmd_data[3]={0};
- cmd_data[0]=LF_CMD_WRITE_STATUS_REGISTER;
- if (address){
- cmd_data[1]=address;
- cmd_data[2]=status;
- }else{
- cmd_data[1]=status;
- }
- result = lf->spi.transfer(lf,cmd_data, address?3:2,LF_NULL,0);
- return result;
- }
- lf_err_t little_flash_read_status(const little_flash_t *lf, uint8_t address, uint8_t *status){
- lf_err_t result = LF_ERR_OK;
- uint8_t cmd_data[2]={0};
- cmd_data[0]=LF_CMD_READ_STATUS_REGISTER;
- if (address){
- cmd_data[1]=address;
- }
- result = lf->spi.transfer(lf,cmd_data, address?2:1,status,1);
- return result;
- }
- static lf_err_t little_flash_wait_busy(const little_flash_t *lf, uint32_t timeout) {
- lf_err_t result = LF_ERR_OK;
- size_t retry_times = lf->chip_info.retry_times;
- uint32_t timeout_us = timeout;
- volatile uint8_t status;
- do{
- timeout_us = timeout;
- do{
- if (lf->chip_info.type==LF_DRIVER_NOR_FLASH){
- result = little_flash_read_status(lf, 0, &status);
- }else{
- result = little_flash_read_status(lf, LF_NANDFLASH_STATUS_REGISTER3, &status);
- }
- // LF_DEBUG("status 0x%02x",status);
- if (result==LF_ERR_OK && (status&LF_STATUS_REGISTER_BUSY)==0){
- return LF_ERR_OK;
- }
- if (timeout>1000){
- lf->wait_ms(1);
- timeout_us -= 1000;
- }else{
- lf->wait_10us(1);
- timeout_us -= 10;
- }
- } while (timeout_us>0);
- retry_times--;
- } while (retry_times>0);
- LF_ERROR("Error: Wait busy timeout.");
- return LF_ERR_TIMEOUT;
- }
- /*
- reset device
- */
- static lf_err_t little_flash_reset(little_flash_t *lf){
- lf_err_t result = LF_ERR_OK;
- result |= little_flash_wait_busy(lf,1000);
- if(lf->chip_info.type==LF_DRIVER_NOR_FLASH){
- result |= lf->spi.transfer(lf,(uint8_t[]){LF_CMD_ENABLE_RESET}, 1,LF_NULL,0);
- result |= lf->spi.transfer(lf,(uint8_t[]){LF_CMD_NORFLASH_RESET}, 1,LF_NULL,0);
- }else{
- // nand flash
- result |= lf->spi.transfer(lf,(uint8_t[]){LF_CMD_NANDFLASH_RESET}, 1,LF_NULL,0);
- }
- lf->wait_ms(50);
- result |= little_flash_wait_busy(lf,1000);
- if (result) return result;
- if(lf->chip_info.type==LF_DRIVER_NOR_FLASH){
- if(lf->chip_info.prog_size==0) lf->chip_info.prog_size = LF_NORFLASH_PAGE_ZISE;
- if(lf->chip_info.read_size==0) lf->chip_info.read_size = LF_NORFLASH_PAGE_ZISE;
- if(lf->chip_info.erase_times==0) lf->chip_info.erase_times = LF_NORFLASH_ERASE_TIMES;
- // 以下需要根据型号进行适配
- result |= little_flash_write_status(lf,0,0x00);
- }else{
- if(lf->chip_info.prog_size==0) lf->chip_info.prog_size = LF_NANDFLASH_PAGE_ZISE;
- if(lf->chip_info.read_size==0) lf->chip_info.read_size = LF_NANDFLASH_PAGE_ZISE;
- if(lf->chip_info.erase_times==0) lf->chip_info.erase_times = LF_NANDFLASH_ERASE_TIMES;
- // 以下需要根据型号进行适配
- result |= little_flash_write_status(lf,LF_NANDFLASH_STATUS_REGISTER1,0x00);
- // ECC-E = 1, BUF = 1
- result |= little_flash_write_status(lf,LF_NANDFLASH_STATUS_REGISTER2,(1 << 4) | (1 << 3));
- }
- if(lf->chip_info.retry_times==0) lf->chip_info.retry_times = LF_RETRY_TIMES;
- lf->wait_10us(5);
- return result;
- }
- static lf_err_t little_flash_write_enabled(const little_flash_t *lf, uint8_t enable){
- lf_err_t result = LF_ERR_OK;
- uint8_t status;
- lf->spi.transfer(lf,enable?(uint8_t[]){LF_CMD_WRITE_ENABLE}:(uint8_t[]){LF_CMD_WRITE_DISABLE}, 1,LF_NULL,0);
- result = little_flash_wait_busy(lf,1);
- if (result) {
- LF_ERROR("Error: Write enabled timeout.");
- return result;
- }
- if (lf->chip_info.type==LF_DRIVER_NOR_FLASH){
- result |= little_flash_read_status(lf, 0, &status);
- }else{
- result |= little_flash_read_status(lf, LF_NANDFLASH_STATUS_REGISTER3, &status);
- }
- if (result) return result;
- if (enable && (status & LF_STATUS_REGISTER_WEL) == 0) {
- LF_ERROR("Error: Can't enable write status.");
- result = LF_ERR_WRITE;
- } else if (!enable && (status & LF_STATUS_REGISTER_WEL) != 0) {
- LF_ERROR("Error: Can't disable write status.");
- result = LF_ERR_WRITE;
- }
- return result;
- }
- lf_err_t little_flash_init(void){
- LF_INFO("Welcome to use little flash V%s .", LF_SW_VERSION);
- LF_INFO("Github Repositories https://github.com/Dozingfiretruck/little_flash .");
- LF_INFO("Gitee Repositories https://gitee.com/Dozingfiretruck/little_flash .");
- return LF_ERR_OK;
- }
- #ifdef LF_USE_SFDP
- static inline lf_err_t little_flash_sfdp_read(const little_flash_t *lf, uint32_t offset, uint8_t *data, size_t size){
- lf_err_t result = LF_ERR_OK;
- uint8_t cmd_data[]={LF_CMD_SFDP_REGISTER,(uint8_t)(offset>>16),(uint8_t)(offset>>8),(uint8_t)(offset),0XFF};
- result = lf->spi.transfer(lf,cmd_data, sizeof(cmd_data), data, size);
- return result;
- }
- lf_err_t little_flash_sfdp_probe(little_flash_t *lf){
- lf_err_t result = LF_ERR_OK;
- little_flash_sfdp_t sfdp;
- uint8_t recv_data[8]={0};
- little_flash_sfdp_read(lf, LF_CMD_SFDP_HEADER, recv_data, sizeof(recv_data));
- if (recv_data[0]!='S' || recv_data[1]!='F' || recv_data[2]!='D' || recv_data[3]!='P'){
- LF_DEBUG("SFDP header not found.");
- return LF_ERR_SFDP_HEADER;
- }
- sfdp.minor_rev=recv_data[4];
- sfdp.major_rev=recv_data[5];
- sfdp.nph=recv_data[6];
- sfdp.access_protocol=recv_data[7];
- if (sfdp.access_protocol == 0xFA || (sfdp.access_protocol >= 0xFC && sfdp.access_protocol <= 0xFF)){
- lf->chip_info.type |= LF_DRIVER_NOR_FLASH;
- }else if((sfdp.access_protocol >= 0xF1 && sfdp.access_protocol <= 0xF7)){
- lf->chip_info.type |= LF_DRIVER_NAND_FLASH;
- }else{
- LF_ERROR("Error: Access protocol 0x%02X is not supported.", sfdp.access_protocol);
- return LF_ERR_SFDP_PARAMETER;
- }
- if (sfdp.major_rev>LF_SFDP_MAJOR_REV || sfdp.minor_rev>LF_SFDP_MINOR_REV){
- LF_ERROR("Error: SFDP version %d.%d is not supported.", sfdp.major_rev, sfdp.minor_rev);
- return LF_ERR_SFDP_PARAMETER;
- }
-
- LF_DEBUG("Found SFDP Header. The Revision is V%d.%d, NPN is %d, Access Protocol is 0x%X.",
- sfdp.major_rev, sfdp.minor_rev, sfdp.nph, sfdp.access_protocol);
- little_flash_sfdp_read(lf, LF_CMD_SFDP_PARAMETER_HEADER1, recv_data, sizeof(recv_data));
- sfdp.parameter_id = (uint16_t)recv_data[0] | (uint16_t)recv_data[7] << 8;
- sfdp.parameter_minor_rev = recv_data[1];
- sfdp.parameter_major_rev = recv_data[2];
- sfdp.parameter_length = recv_data[3];
- sfdp.parameter_pointer = (uint32_t)recv_data[4] | (uint32_t)recv_data[5] << 8 | (uint32_t)recv_data[6] << 16;
- if (sfdp.parameter_id!=0xFF00){
- LF_ERROR("Error: SFDP Parameter ID 0x%04X.",sfdp.parameter_id);
- return LF_ERR_SFDP_PARAMETER;
- }
- if (sfdp.parameter_major_rev > LF_SFDP_MAJOR_REV) {
- LF_ERROR("Error: SFDP Parameter Table Revision %d.%d is not supported.", sfdp.parameter_major_rev, sfdp.parameter_minor_rev);
- return LF_ERR_SFDP_PARAMETER;
- }
- if (sfdp.parameter_length < 9) {
- LF_DEBUG("Error: The Parameter Table Length is %d.", sfdp.parameter_length);
- return LF_ERR_SFDP_PARAMETER;
- }
- LF_DEBUG("Parameter Header is OK. The Parameter ID is 0x%04X, Revision is V%d.%d, Length is %d,Parameter Table Pointer is 0x%06lX.",
- sfdp.parameter_id, recv_data[1],recv_data[2],sfdp.parameter_length, sfdp.parameter_pointer);
- if (sfdp.parameter_length * 4 > sizeof(little_flash_sfdp_pt_t)){
- LF_WARNING("Table Revision %d.%d parameter_length is too long", sfdp.parameter_major_rev, sfdp.parameter_minor_rev);
- sfdp.parameter_length = sizeof(little_flash_sfdp_pt_t) / 4;
- }
- uint8_t parameter_table[sfdp.parameter_length * 4];
- little_flash_sfdp_read(lf, sfdp.parameter_pointer, parameter_table, sfdp.parameter_length);
- // [1] = 0xE5 0x20 0xF1 0xFF
- // [2] = 0xFF 0xFF 0xFF 0x07
- // [3] = 0x44 0xD3 0x8B 0x00
- // [4] = 0xAB 0x13 0x9A 0x00
- // [5] = 0xA7 0xD3 0x8B 0x00
- // [6] = 0x00 0xFF 0x00 0x00
- // [7] = 0x00 0x00 0x00 0x00
- // [8] = 0x01 0x00 0x00 0x00
- // [9] = 0x09 0x00 0x00 0x00
- memcpy(&sfdp.pt, parameter_table, sfdp.parameter_length*4);
- // LF_DEBUG("sfdp.pt Flash_Memory_Density 0x%08X",sfdp.pt.Flash_Memory_Density);
- if (sfdp.pt.Flash_Memory_Density & 0x80000000){
- lf->chip_info.capacity = sfdp.pt.Flash_Memory_Density;
- lf->chip_info.capacity &= 0x7FFFFFFF;
- lf->chip_info.capacity = 1L << (lf->chip_info.capacity - 3);
- }else{
- lf->chip_info.capacity = (sfdp.pt.Flash_Memory_Density+1)>>3;
- }
-
- if (sfdp.pt.Erase_Sizes==1 && sfdp.pt.Erase_4k){
- lf->chip_info.erase_cmd = sfdp.pt.Erase_4k;
- lf->chip_info.erase_size = 4096;
- }
-
- if (sfdp.pt.Write_Granularity){
- lf->chip_info.prog_size = 256;
- }else{
- lf->chip_info.prog_size = 1;
- }
- // Address Bytes
- if (sfdp.pt.Address_Bytes == 0){
- lf->chip_info.addr_bytes |= LF_ADDR_BYTES_3;
- }else if (sfdp.pt.Address_Bytes == 1){
- lf->chip_info.addr_bytes |= LF_ADDR_BYTES_3;
- lf->chip_info.addr_bytes |= LF_ADDR_BYTES_4;
- }else if (sfdp.pt.Address_Bytes == 2){
- lf->chip_info.addr_bytes |= LF_ADDR_BYTES_4;
- }
- // LF_DEBUG("capacity: %d bytes",lf->chip_info.capacity);
- // LF_DEBUG("erase_size: %d bytes",lf->chip_info.erase_size);
- // LF_DEBUG("prog_size: %d bytes",lf->chip_info.prog_size);
- // LF_DEBUG("erase_cmd 0x%02X",lf->chip_info.erase_cmd);
- // LF_DEBUG("addr_bytes 0x%02X",lf->chip_info.addr_bytes);
- LF_DEBUG("Found a flash chip. Size is %d bytes.",lf->chip_info.capacity);
- return result;
- }
- #endif /* LF_USE_SFDP */
- lf_err_t little_flash_device_init(little_flash_t *lf){
- lf_err_t result = LF_ERR_OK;
- uint8_t manufacturer_id = 0;
- uint16_t device_id = 0;
- little_flash_port_init(lf);
- LF_ASSERT(lf->wait_10us);
- LF_ASSERT(lf->wait_ms);
- LF_ASSERT(lf->spi.transfer);
- #ifdef LF_USE_HEAP
- LF_ASSERT(lf->malloc);
- LF_ASSERT(lf->free);
- #endif
- #ifdef LF_USE_SFDP
- result = little_flash_sfdp_probe(lf);
- if (result == LF_ERR_OK){
- return little_flash_reset(lf);
- }
- #endif
- uint8_t recv_data[4]={0};
- result = lf->spi.transfer(lf,(uint8_t[]){LF_CMD_JEDEC_ID}, 1, recv_data, sizeof(recv_data));
- if(result) return result;
- // LF_DEBUG("recv_data [0]:0x%02X [1]:0x%02X [2]:0x%02X [3]:0x%02X",recv_data[0],recv_data[1],recv_data[2],recv_data[3]);
- // nor flash?
- manufacturer_id = recv_data[0];
- device_id = recv_data[1]<<8|recv_data[2];
- for (size_t i = 0; i < sizeof(little_flash_table)/sizeof(little_flash_table[0]); i++){
- if (manufacturer_id==little_flash_table[i].manufacturer_id && device_id ==little_flash_table[i].device_id){
- memcpy(&lf->chip_info.name,&little_flash_table[i],sizeof(little_flash_chipinfo_t));
- LF_DEBUG("JEDEC ID: manufacturer_id:0x%02X device_id:0x%04X ",little_flash_table[i].manufacturer_id,little_flash_table[i].device_id);
- LF_DEBUG("little flash fonud flash %s",lf->chip_info.name);
- result = little_flash_reset(lf);
- return result;
- }
- }
- // nand flash?
- manufacturer_id = recv_data[1];
- device_id = recv_data[2]<<8|recv_data[3];
- for (size_t i = 0; i < sizeof(little_flash_table)/sizeof(little_flash_table[0]); i++){
- if (manufacturer_id==little_flash_table[i].manufacturer_id && device_id ==little_flash_table[i].device_id){
- memcpy(&lf->chip_info.name,&little_flash_table[i],sizeof(little_flash_chipinfo_t));
- LF_DEBUG("JEDEC ID: manufacturer_id:0x%02X device_id:0x%04X ",little_flash_table[i].manufacturer_id,little_flash_table[i].device_id);
- LF_DEBUG("little flash fonud flash %s",lf->chip_info.name);
- result = little_flash_reset(lf);
- return result;
- }
- }
- // all not found
- LF_DEBUG("NOT fonud flash");
- return LF_ERR_NO_FLASH;
- }
- lf_err_t little_flash_device_deinit(little_flash_t *lf){
- return LF_ERR_OK;
- }
- lf_err_t little_flash_deinit(void){
- return LF_ERR_OK;
- }
- static lf_err_t little_flash_cheak_erase(const little_flash_t *lf){
- lf_err_t result = LF_ERR_OK;
- uint8_t status;
- result |= little_flash_wait_busy(lf,4000);
- if (result) {
- LF_ERROR("Error: Cheak erase timeout.");
- return result;
- }
- if(lf->chip_info.type==LF_DRIVER_NAND_FLASH){
- result |= little_flash_read_status(lf, LF_NANDFLASH_STATUS_REGISTER3, &status);
- if (result || (status&0x04)){
- return LF_ERR_ERASE;
- }
- }
- return result;
- }
- static lf_err_t little_flash_cheak_write(const little_flash_t *lf){
- lf_err_t result = LF_ERR_OK;
- uint8_t status;
- result |= little_flash_wait_busy(lf,700);
- if (result) {
- LF_ERROR("Error: Cheak write timeout.");
- return result;
- }
- if(lf->chip_info.type==LF_DRIVER_NAND_FLASH){
- result |= little_flash_read_status(lf, LF_NANDFLASH_STATUS_REGISTER3, &status);
- if (result||(status&0x08)){
- return LF_ERR_WRITE;
- }
- }
- return result;
- }
- static lf_err_t little_flash_cheak_read(const little_flash_t *lf){
- lf_err_t result = LF_ERR_OK;
- uint8_t status;
- result |= little_flash_wait_busy(lf,60);
- if (result) {
- LF_ERROR("Error: Cheak read timeout.");
- return result;
- }
- if(lf->chip_info.type==LF_DRIVER_NAND_FLASH){
- result |= little_flash_read_status(lf, LF_NANDFLASH_STATUS_REGISTER3, &status);
- // 以下也是要根据不同型号移植的
- uint8_t ecc = (status & 0x30) >> 4;
- if (result==0 && ecc<2){
- return LF_ERR_OK;
- }
- }
- return result;
- }
- lf_err_t little_flash_chip_erase(const little_flash_t *lf){
- lf_err_t result = LF_ERR_OK;
- uint32_t addr = 0;
- uint8_t cmd_data[4];
- if (lf->lock) {
- lf->lock(lf);
- }
- if(little_flash_write_enabled(lf, LF_ENABLE)) goto error;
- if(lf->chip_info.type==LF_DRIVER_NOR_FLASH){
- result |= lf->spi.transfer(lf,(uint8_t[]){LF_CMD_ERASE_CHIP}, 1,LF_NULL,0);
- lf->wait_ms(lf->chip_info.capacity / lf->chip_info.erase_size * lf->chip_info.erase_times);
- result |= little_flash_cheak_erase(lf);
- }else{
- cmd_data[0] = lf->chip_info.erase_cmd;
- while (true){
- uint32_t page_addr = addr/lf->chip_info.prog_size;
- cmd_data[1] = page_addr >> 16;
- cmd_data[2] = page_addr >> 8;
- cmd_data[3] = page_addr;
- result |= lf->spi.transfer(lf,cmd_data, 4,LF_NULL,0);
- if(result) goto error;
- lf->wait_ms(lf->chip_info.erase_times);
- result |= little_flash_cheak_erase(lf);
- if(result) goto error;
- addr += lf->chip_info.erase_size;
- if (addr>=lf->chip_info.capacity){
- break;
- }
- }
- }
- if (little_flash_write_enabled(lf, LF_DISABLE)) goto error;
- if (lf->unlock) {
- lf->unlock(lf);
- }
- return LF_ERR_OK;
- error:
- LF_ERROR("Error: Chip erase failed.");
- little_flash_write_enabled(lf, LF_DISABLE);
- if (lf->unlock) {
- lf->unlock(lf);
- }
- return LF_ERR_ERASE;
- }
- lf_err_t little_flash_erase(const little_flash_t *lf, uint32_t addr, uint32_t len){
- uint8_t cmd_data[4]={0};
- if (addr + len > lf->chip_info.capacity) {
- LF_ERROR("Error: Flash address is out of bound.");
- return LF_ERR_BAD_ADDRESS;
- }
- if (addr == 0 && len == lf->chip_info.capacity) {
- return little_flash_chip_erase(lf);
- }
- if (lf->lock) {
- lf->lock(lf);
- }
- if(little_flash_write_enabled(lf, LF_ENABLE)) goto error;
- cmd_data[0] = lf->chip_info.erase_cmd;
- uint32_t erase_off = addr % lf->chip_info.erase_size;
- uint32_t erase_addr = addr / lf->chip_info.erase_size * lf->chip_info.erase_size;
- uint32_t erase_len = len - erase_off;
- while (erase_off || erase_len){
- cmd_data[1] = erase_addr >> 16;
- cmd_data[2] = erase_addr >> 8;
- cmd_data[3] = erase_addr;
- lf->spi.transfer(lf,cmd_data, 4,LF_NULL,0);
- lf->wait_ms(lf->chip_info.erase_times);
- if(little_flash_cheak_erase(lf)) goto error;
- if (erase_len == 0){
- break;
- }
-
- erase_addr += lf->chip_info.erase_size;
- if (erase_len<=lf->chip_info.erase_size){
- erase_len = 0;
- }else{
- erase_len -= lf->chip_info.erase_size;
- }
- }
- if (little_flash_write_enabled(lf, LF_DISABLE)) goto error;
- if (lf->unlock) {
- lf->unlock(lf);
- }
- return LF_ERR_OK;
- error:
- LF_ERROR("Error: Erase failed.");
- little_flash_write_enabled(lf, LF_DISABLE);
- if (lf->unlock) {
- lf->unlock(lf);
- }
- return LF_ERR_ERASE;
- }
- lf_err_t little_flash_write(const little_flash_t *lf, uint32_t addr, const uint8_t *data, uint32_t len){
- #ifdef LF_USE_HEAP
- uint8_t* cmd_data = (uint8_t*)lf->malloc(4+lf->chip_info.prog_size);
- if (!cmd_data){
- LF_ERROR("Error: malloc failed.");
- return LF_ERR_NO_MEM;
- }
- #else
- uint8_t cmd_data[4+lf->chip_info.prog_size];
- #endif /* LF_USE_HEAP */
- uint32_t base_addr = addr;
-
- if (lf->lock) {
- lf->lock(lf);
- }
- if(little_flash_write_enabled(lf, LF_ENABLE)){
- goto error;
- }
- while (len){
- if (little_flash_wait_busy(lf,100)){
- goto error;
- }
-
- if (lf->chip_info.type==LF_DRIVER_NOR_FLASH){
- cmd_data[0] = LF_CMD_PROG_DATA;
- cmd_data[1] = addr >> 16;
- cmd_data[2] = addr >> 8;
- cmd_data[3] = addr;
- uint16_t column_addr = addr%lf->chip_info.prog_size;
- if (column_addr){
- if ((column_addr+len)<=lf->chip_info.prog_size){
- memcpy(&cmd_data[4],&data[addr-base_addr],len);
- lf->spi.transfer(lf,cmd_data, 4+len,LF_NULL,0);
- break;
- }else{
- memcpy(&cmd_data[4],&data[addr-base_addr],lf->chip_info.prog_size-column_addr);
- lf->spi.transfer(lf,cmd_data, 4+lf->chip_info.prog_size-column_addr,LF_NULL,0);
- len -= (lf->chip_info.prog_size-column_addr);
- addr += (lf->chip_info.prog_size-column_addr);
- }
- }else{
- if (len<=lf->chip_info.prog_size){
- memcpy(&cmd_data[4],&data[addr-base_addr],len);
- lf->spi.transfer(lf,cmd_data, 4+len,LF_NULL,0);
- break;
- }else{
- memcpy(&cmd_data[4],&data[addr-base_addr],lf->chip_info.prog_size);
- lf->spi.transfer(lf,cmd_data, 4+lf->chip_info.prog_size,LF_NULL,0);
- len -= lf->chip_info.prog_size;
- addr += lf->chip_info.prog_size;
- }
- }
- }else{
- uint32_t page_addr = addr/lf->chip_info.prog_size;
- uint16_t column_addr = addr%lf->chip_info.prog_size;
- cmd_data[0] = LF_CMD_PROG_DATA;
- cmd_data[1] = column_addr >> 8;
- cmd_data[2] = column_addr;
- if (column_addr){
- if ((column_addr+len)<=lf->chip_info.prog_size){
- memcpy(&cmd_data[3],&data[addr-base_addr],len);
- lf->spi.transfer(lf,cmd_data, 3+len,LF_NULL,0);
- little_flash_wait_busy(lf,100);
- cmd_data[0] = LF_NANDFLASH_PAGE_PROG_EXEC;
- cmd_data[1] = page_addr >> 16;
- cmd_data[2] = page_addr >> 8;
- cmd_data[3] = page_addr;
- lf->spi.transfer(lf,cmd_data, 4,LF_NULL,0);
- little_flash_cheak_write(lf);
- break;
- }else{
- memcpy(&cmd_data[3],&data[addr-base_addr],lf->chip_info.prog_size-column_addr);
- lf->spi.transfer(lf,cmd_data, 3+lf->chip_info.prog_size-column_addr,LF_NULL,0);
- len -= (lf->chip_info.prog_size-column_addr);
- addr += (lf->chip_info.prog_size-column_addr);
- }
- }else{
- if (len<=lf->chip_info.prog_size){
- memcpy(&cmd_data[3],&data[addr-base_addr],len);
- lf->spi.transfer(lf,cmd_data, 3+len,LF_NULL,0);
- little_flash_wait_busy(lf,100);
- cmd_data[0] = LF_NANDFLASH_PAGE_PROG_EXEC;
- cmd_data[1] = page_addr >> 16;
- cmd_data[2] = page_addr >> 8;
- cmd_data[3] = page_addr;
- lf->spi.transfer(lf,cmd_data, 4,LF_NULL,0);
- little_flash_cheak_write(lf);
- break;
- }else{
- memcpy(&cmd_data[3],&data[addr-base_addr],lf->chip_info.prog_size);
- lf->spi.transfer(lf,cmd_data, 3+lf->chip_info.prog_size,LF_NULL,0);
- len -= lf->chip_info.prog_size;
- addr += lf->chip_info.prog_size;
- }
- }
- little_flash_wait_busy(lf,100);
- cmd_data[0] = LF_NANDFLASH_PAGE_PROG_EXEC;
- cmd_data[1] = page_addr >> 16;
- cmd_data[2] = page_addr >> 8;
- cmd_data[3] = page_addr;
- lf->spi.transfer(lf,cmd_data, 4,LF_NULL,0);
- little_flash_cheak_write(lf);
- }
- }
- if (little_flash_write_enabled(lf, LF_DISABLE)) goto error;
- #ifdef LF_USE_HEAP
- lf->free(cmd_data);
- #endif /* LF_USE_HEAP */
- if (lf->unlock) {
- lf->unlock(lf);
- }
- return LF_ERR_OK;
- error:
- LF_ERROR("Error: Write failed.");
- if (lf->unlock) {
- lf->unlock(lf);
- }
- return LF_ERR_WRITE;
- }
- lf_err_t little_flash_erase_write(const little_flash_t *lf, uint32_t addr, const uint8_t *data, uint32_t len){
- lf_err_t result = LF_ERR_OK;
- result = little_flash_erase(lf, addr, len);
- if (result == LF_ERR_OK) {
- result = little_flash_write(lf, addr, data, len);
- }
- return result;
- }
- lf_err_t little_flash_read(const little_flash_t *lf, uint32_t addr, uint8_t *data, uint32_t len){
- uint8_t cmd_data[4];
- uint32_t base_addr = addr;
- if (lf->lock) {
- lf->lock(lf);
- }
- if (lf->chip_info.type==LF_DRIVER_NOR_FLASH){
- cmd_data[0] = LF_CMD_READ_DATA;
- cmd_data[1] = addr >> 16;
- cmd_data[2] = addr >> 8;
- cmd_data[3] = addr;
- lf->spi.transfer(lf,cmd_data, 4,data,len);
- if (little_flash_cheak_read(lf)){
- goto error;
- }
- }else{
- while (len){
- uint32_t page_addr = addr/lf->chip_info.read_size;
- uint16_t column_addr = addr%lf->chip_info.read_size;
- cmd_data[0] = LF_NANDFLASH_PAGE_DATA_READ;
- cmd_data[1] = page_addr >> 16;
- cmd_data[2] = page_addr >> 8;
- cmd_data[3] = page_addr;
- lf->spi.transfer(lf,cmd_data, 4,LF_NULL,0);
- if (little_flash_cheak_read(lf)){
- goto error;
- }
- cmd_data[0] = LF_CMD_READ_DATA;
- cmd_data[1] = column_addr >> 8;
- cmd_data[2] = column_addr;
- cmd_data[3] = 0;
- if (column_addr){
- if ((column_addr+len)<=lf->chip_info.read_size){
- lf->spi.transfer(lf,cmd_data, 4,&data[addr-base_addr],len);
- break;
- }else{
- lf->spi.transfer(lf,cmd_data, 4,&data[addr-base_addr],lf->chip_info.read_size-column_addr);
- len -= (lf->chip_info.read_size-column_addr);
- addr += (lf->chip_info.read_size-column_addr);
- }
- }else{
- if (len<=lf->chip_info.read_size){
- lf->spi.transfer(lf,cmd_data, 4,&data[addr-base_addr],len);
- break;
- }else{
- lf->spi.transfer(lf,cmd_data, 4,&data[addr-base_addr],lf->chip_info.read_size);
- len -= lf->chip_info.read_size;
- addr += lf->chip_info.read_size;
- }
- }
- }
- }
- if (lf->unlock) {
- lf->unlock(lf);
- }
- return LF_ERR_OK;
- error:
- LF_ERROR("Error: Read failed.");
- if (lf->unlock) {
- lf->unlock(lf);
- }
- return LF_ERR_READ;
- }
|