首页 > 其他分享 >Flash均衡读写

Flash均衡读写

时间:2024-06-23 19:20:20浏览次数:24  
标签:addr cfg 读写 Flash pos uint16 均衡 CONFIG page


#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

相关文章

  • 【小沐学GIS】Google的kml文件的读写(C++、Python)
    文章目录1、简介1.1kml简介1.2功能点1.2.1地标1.2.2地面叠加层1.2.3路径1.2.4多边形2、下载和编译3、C++测试4、Python测试4.1安装库4.2测试14.2测试24.3测试3结语1、简介https://developers.google.cn/kml/documentation/kmzarchives?hl=zh-cn1.1kml......
  • Linux平台I2C多字节数据、按页连续读写E2PROM Demo(AT24C16)
    1)Linux平台I2C多字节数据按页连续读写E2PROM之AT24C16小知识,分享给将要学习或者正在学习Linux平台I2C多字节按页连续读写E2PROM开发的同学。2)内容属于原创,若转载,请说明出处。3)提供相关问题有偿答疑和支持。我测试使用的是 E2PROM(AT24C16)芯片,其中内部地址是1010 外部的地......
  • Kuberntes部署MetalLB负载均衡器
    Kuberntes部署MetalLB负载均衡器MetalLB简介MetalLB是一个为基础Kubernetes集群提供负载均衡实现的工具,使用标准路由协议。Kubernetes在基础集群中不提供网络负载均衡器(类型为LoadBalancer的服务)的实现。Kubernetes提供的网络负载平衡器实现都是调用各种IaaS平台(如GCP、AWS、A......
  • STM32通过SPI硬件读写W25Q64
    文章目录1. W25Q642.硬件电路3. 软件/硬件波形对比4.STM32中的SPI外设5.代码实现5.1MyI2C.c5.2 MyI2C.h5.3W25Q64.c5.4 W25Q64.h5.5 W25Q64_Ins.h5.6main.c1. W25Q64对于SPI通信和W25Q64的详细解析可以看下面这篇文章STM32单片机SPI通信详解-CSDN......
  • STM32通过SPI软件读写W25Q64
    文章目录1.W25Q642.硬件电路3. W25Q64框架图4. 软件/硬件波形对比5.代码实现5.1MyI2C.c5.2 MyI2C.h5.3W25Q64.c5.4 W25Q64.h5.5 W25Q64_Ins.h5.6main.c1.W25Q64对于SPI通信和W25Q64的详细解析可以看下面这篇文章STM32单片机SPI通信详解-CSDN博客......
  • LVS负载均衡群集
    一、LVS概述1.工作原理LVS(LinuxVirtualServer)是一个用于构建高可用性和可伸缩性网络服务的开源软件,其工作原理如下:负载均衡器(LoadBalancer):LVS主要功能是作为一个负载均衡器,将来自客户端的请求分发到多个后端服务器,以达到分担负载、提高可用性和性能的目的。四种调度算法:......
  • golang 爬虫修炼02 ---协程、互斥锁、读写锁、waitgroup
    协程程序:为了完成特定任务,使用某种语言编写的一组指令的集合,是一段静态的代码进程:是程序的一次执行过程。正在运行的一个程序,进程作为资源分配的单位,在内存中会为每个进程分配不同的内存区域。进程是动态的,有产生、存在、消亡的过程线程:进程可进一步细分为线程,是一个程序......
  • LVS+KeepAlived高可用负载均衡集群
    1、高可用群集(1)单台服务器(2)keepalived一个合格的群集应该具备的特点:负载均衡:用于提高群集的性能(LVSNqinxHAProxySLBF5)健康检查(探针):针对于调度器和节点服务器(KeepalivedHeartbeat)故障转移:通过VIP漂移实现主备切换健康检查(探针)常用的工作方式:发送心跳消息:vrr......
  • Xilinxddr3 mig ip核:基于AXI接口的ddr3读写控制
    本文完全参考野火的DDR3读写控制设计,原文十分详细,需要的可以去看看。一、AXI4接口详解AXI接口由5个独立的通道构成,分别是读地址、读数据、写地址、写数据、写响应。如下是读传输过程示意图,使用读地址与读数据通道。主机首先在读地址通道给出读地址和控制信号,然后......
  • Flash驱动控制--芯片擦除(SPI协议)
    摘要:本篇博客具体包括SPI协议的基本原理、模式选择以及时序逻辑要求,采用FPGA(EPCE4),通过SPI通信协议,对flash(W25Q16BV)存储的固化程序进行芯片擦除操作。关键词:SPI;VerilogHDL;Flash【SPI协议通信模式】SPI是Motorola公司推出的一种同步串行接口,是一种高速、全双工、同步的通信总......