#define FLASH_INITIAL_BYTE 0xff
#define PAGE_NUM_PER_CONFIG 2
#define CONFIG_FLASH_PAGE_START 508
#define CONFIG_BUF_SIZE sizeof(CFG_CHARGE_ST)/2 #define CONFIG_FLASH_ADDRESS_START (FLASH_START_ADDR + PAGE_SIZE * CONFIG_FLASH_PAGE_START) static void _config_default_get(CFG_CHARGE_ST *p_cfg) { memset((uint8_t*)p_cfg, 0, sizeof(CFG_CHARGE_ST)); p_cfg->valid = CONFIG_VALID_FLAG; p_cfg->charge_curr = DEFAULT_CHARGE_CURRENT_MAX; return; } //read backward ,last page, last row, iterate until get the first valid flag //parameter of len is measure in word, while pos is measure in byte ,so when calculate pos, // should multiply 2 to get the right pos. static uint8_t flash_page_read(uint32_t page_start_addr, uint16_t *p_data, uint16_t len, uint16_t page_leftover){ uint16_t cnt = (PAGE_SIZE - page_leftover) / len; uint16_t i = 0; uint32_t pos = 0; uint8_t page = 0; uint32_t page_addr = 0; uint8_t *p_read_byte = NULL; cnt /= 2; for(page = PAGE_NUM_PER_CONFIG; page > 0; page--){ page_addr = page_start_addr + (page - 1) * PAGE_SIZE; for(i = cnt; i > 0; i--){ pos = page_addr + (i - 1) * len * 2 + page_leftover; flash_read(pos, p_data, len); p_read_byte = (uint8_t*)p_data; if (p_read_byte[0] == CONFIG_VALID_FLAG){ //cm_printf("flash read 0x%x, p %02x, %d\n", pos, page_addr, i); return true; } } } return false; } //write forward, from the first page, first row ,iterate until get the first initial byte // if not found ,earse the two page, and write from the very beginning static void flash_page_write(uint32_t page_start_addr, uint16_t *p_data, uint16_t len, uint16_t page_leftover){ uint16_t cnt = (PAGE_SIZE - page_leftover) / len; uint8_t page = 0; uint32_t page_addr = 0; uint32_t pos = 0; uint16_t i = 0; uint8_t read_buf[2] = {0}; cnt /= 2; for(page = 0; page < PAGE_NUM_PER_CONFIG; page++){ page_addr = page_start_addr + page * PAGE_SIZE; for(i = 0; i < cnt; i++){ pos = page_addr + i * len * 2; pos += page_leftover; //cm_printf("pos %02x, leftover %02x\n", pos, page_leftover); flash_read(pos, (uint16_t*)read_buf, 1); if (read_buf[0] == FLASH_INITIAL_BYTE && read_buf[1] == FLASH_INITIAL_BYTE){ FLASH_Write_in_ISR(pos, p_data, len); return; } } } FLASH_Page_Erase_direct(page_start_addr); FLASH_Page_Erase_direct(page_start_addr + PAGE_SIZE * 1); FLASH_Write_in_ISR(page_start_addr + page_leftover, p_data, len); } static void config_init(void){ CFG_CHARGE_ST cfg_st; CFG_CHARGE_ST *p_cfg; uint16_t ps_buf[CONFIG_BUF_SIZE] = {0}; flash_page_read(CONFIG_FLASH_ADDRESS_START, ps_buf, CONFIG_BUF_SIZE, 0); p_cfg = (CFG_CHARGE_ST*)ps_buf; if (p_cfg->valid != CONFIG_VALID_FLAG){ _config_default_get(&cfg_st); p_cfg = &cfg_st; } memcpy(&g_config_st, p_cfg, sizeof(CFG_CHARGE_ST)); return; } static void config_save_act(void){ CFG_CHARGE_ST *p_cfg; uint16_t page_leftover = PAGE_SIZE % (sizeof(CFG_CHARGE_ST)); p_cfg = &g_config_st; flash_page_write(CONFIG_FLASH_ADDRESS_START, (uint16_t*)p_cfg, CONFIG_BUF_SIZE, page_leftover); return; }
Flash均衡读写,每次写配置时,从页面的开始地址,找到一个空的位置写入,当整个页面都已写完时,再擦除一次页面,
从页面最开始地址写入。读取配置时,从页面的最后面的地址开始向前查找有效标识位。
此外,flash执行写入操作时,除了unlock/lock,还需要__disable_irq() , __enable_irq(); 关闭中断,写完后再开启中断。
标签:addr,cfg,读写,Flash,pos,uint16,均衡,CONFIG,page From: https://www.cnblogs.com/wallywl/p/18263812