#include "sr_flash.h"

#include "luat_flash.h"
#include "mem_map_716s.h"


//返回实际读取的大小
int BspFlashRead(srSize_t offset, uint8_t *buf, srSize_t size)
{
	int ret = -1;
	SR_ASSERT((buf!=SR_NULL)&&(size>0)&&(offset<BS_FLASH_RD_ADDR_MAX)&&(offset+size<BS_FLASH_RD_ADDR_MAX));

	// hezhou:int <= 0错误 >0实际写入的大小
	ret = luat_flash_read(buf, offset, size);

	return (ret <= 0) ? SR_FAIL : ret;
}



int BspFlashErase(srSize_t offset, srSize_t num)
{
	int ret = -1;
	SR_ASSERT((num>0)&&(offset<BS_FLASH_WR_ADDR_MAX)&&((num*BSP_FLASH_SECTOR_SIZE+offset)<BS_FLASH_WR_ADDR_MAX));
	if (offset % BSP_FLASH_SECTOR_SIZE != 0) return SR_INVALID;

	// hezhou:int != 0错误 =0 正常 
	ret = luat_flash_erase(offset, num * BSP_FLASH_SECTOR_SIZE);

	return (ret == 0) ? SR_OK : SR_FAIL;
}


//写FLASH  
//在指定地址开始写入指定长度的数据
//该函数带擦除操作!
//buf:数据存储区
//offset:开始写入的地址(32bit)						
//size:要写入的字节数(最大65535)   
//返回实际读取的大小或负值错误码
int BspFlashWrite(srSize_t offset, uint8_t *buf, srSize_t size)
{ 
	uint32_t secpos;
	uint16_t i,secoff,secremain;   
	uint8_t tempBuf[BSP_FLASH_SECTOR_SIZE];	  
	int ret = 0;	
	uint32_t tempSize =size;

	SR_ASSERT((buf!=SR_NULL)&&(size>0)&&(offset<BS_FLASH_WR_ADDR_MAX)&&(offset+size<BS_FLASH_WR_ADDR_MAX));
	
 	secpos=offset/BSP_FLASH_SECTOR_SIZE;//扇区地址  
	secoff=offset%BSP_FLASH_SECTOR_SIZE;//在扇区内的偏移
	secremain=BSP_FLASH_SECTOR_SIZE-secoff;//扇区剩余空间大小   
 	//printf("ad:%X,nb:%X\r\n",offset,size);//测试用
	
 	if(size<=secremain)secremain=size;//不大于BSP_FLASH_SECTOR_SIZE个字节
	while(1) 
	{	
		//_Read(dev,tempBuf,secpos*BSP_FLASH_SECTOR_SIZE,BSP_FLASH_SECTOR_SIZE);
		BspFlashRead(secpos*BSP_FLASH_SECTOR_SIZE, tempBuf, BSP_FLASH_SECTOR_SIZE); //读出整个扇区的内容
		for(i=0;i<secremain;i++)//校验数据
		{
			if(tempBuf[secoff+i]!=0XFF)break;//需要擦除  	  
		}
		if(i<secremain)//需要擦除
		{
			//_Erase_Sector(dev,secpos);//擦除这个扇区
			ret = BspFlashErase(secpos*BSP_FLASH_SECTOR_SIZE, 1);
			if(ret!=SR_OK) return SR_FAIL;
			
			for(i=0;i<secremain;i++)	   //复制
			{
				tempBuf[i+secoff]=buf[i];	  
			}

			// hezhou:int <= 0错误 >0实际写入的大小  
            ret = luat_flash_write(tempBuf, secpos*BSP_FLASH_SECTOR_SIZE, BSP_FLASH_SECTOR_SIZE);	//写入整个扇区	
            if(ret<=0) return SR_FAIL;
			

		}
		else {
		
		    // hezhou:int <= 0错误 >0实际写入的大小 
            ret = luat_flash_write(buf, offset, secremain);		//写已经擦除了的,直接写入扇区剩余区间.	
			if(ret<=0) return SR_FAIL;
			
		}
		if(size==secremain)  break;//写入结束了
		else//写入未结束
		{
			secpos++;//扇区地址增1
			secoff=0;//偏移位置为0 	 

		    buf+=secremain;    //指针偏移
			offset+=secremain; //写地址偏移	   
		    size-=secremain;	 //字节数递减
			if(size>BSP_FLASH_SECTOR_SIZE)secremain=BSP_FLASH_SECTOR_SIZE;	//下一个扇区还是写不完
			else secremain=size;			//下一个扇区可以写完了
		}	 
	};	

	return tempSize;
}

#if  0
int BspFlashWrite(srSize_t offset, uint8_t *buf, srSize_t size)
{
	int ret = -1;

	// hezhou:int <= 0错误 >0实际写入的大小
	ret = luat_flash_write(buf, offset, size);

	return (ret <= 0) ? SR_FAIL : ret;
}
#endif


#include "fal_part.h"

static int _FalRead(fal_flash_t *flash, uint32_t offset, uint8_t *buf, uint32_t size)
{
  uint32_t addr = flash->addr + offset;

  return  BspFlashRead(addr, buf, size);
  
}

static int _FalWrite(fal_flash_t *flash, uint32_t offset, uint8_t *buf, uint32_t size)
{
  uint32_t addr = flash->addr + offset;

  return  BspFlashWrite(addr, buf, size);

}
static int _FalEraseBlock(fal_flash_t *flash, uint32_t offset, uint32_t num)
{

   uint32_t addr = flash->addr + offset;

   return BspFlashErase(addr, num);
}



fal_flash_t hzOnflash;

static int BspFalOnflashInit(void)
{


    hzOnflash.name=BSP_FAL_ONCHIP_NAME;

    hzOnflash.addr = BSP_FLASH_USER_START;
    hzOnflash.len   = 12*1024;
    hzOnflash.blk_size = BSP_FLASH_SECTOR_SIZE;
    //hzOnflash.page_size  = ;

    hzOnflash.ops.read  = _FalRead ;
    hzOnflash.ops.write  = _FalWrite;
    hzOnflash.ops.erase_block = _FalEraseBlock;

    //hzOnflash.priv = SR_NULL;

    return fal_flash_register(&hzOnflash);
}
SR_INIT_BSP_EXPORT(BspFalOnflashInit,SR_PRIORITY_1);



/*合宙flash布局:详见mem_map_716s.h
AP/CP flash layout, toatl 2MB
flash raw address: 0x00000000---0x00200000
flash xip address(from ap/cp view): 0x00800000---0x00a00000


0x00000000          |---------------------------------|
                    |      header1 4KB                |
0x00001000          |---------------------------------|
                    |      header2 4KB                |
0x00002000          |---------------------------------|
                    |      fuse mirror 4KB            |
0x00003000          |---------------------------------|
                    |      BL 72KB                    |
0x00015000          |---------------------------------|
                    |      rel (factory) 20KB         |----compress
#if (defined MID_FEATURE_MODE) || (defined GCF_FEATURE_MODE)
0x0001a000          |---------------------------------|
                    |      cp img 360KB               |
0x00074000          |---------------------------------|
                    |      ap img 1224KB              |

#elif defined  FEATURE_MORERAM_ENABLE
0x0001a000          |---------------------------------|
                    |      cp img 376KB               |
0x00078000          |---------------------------------|
                    |      ap img 1208KB              |
#elif defined FEATURE_LESSLOG_ENABLE &&FEATURE_MOREROM_ENABLE
0x0001a000          |---------------------------------|
                    |      cp img 336KB               |
0x00072000          |---------------------------------|
                    |      ap img 1248KB              |
#else
0x0001a000          |---------------------------------|
                    |      cp img 352KB               |
0x00072000          |---------------------------------|
                    |      ap img 1232KB              |
#endif

#if (defined MID_FEATURE_MODE) || (FEATURE_MOREROM_ENABLE)
0x001a6000          |---------------------------------|
                    |      hib backup 96KB            |
0x001be000          |---------------------------------|
                    |      lfs 48KB                   |
0x001ca000          |---------------------------------|
                    |      fota 160KB                 |
#else
0x001a6000          |---------------------------------|
                    |      lfs 48KB                   |
0x001b2000          |---------------------------------|
                    |      fota 256KB                 |
#endif
0x001f2000          |---------------------------------|
                    |      rel 52KB                   |
0x001ff000          |---------------------------------|
                    |      plat config 4KB            |---- read-modify-write
0x00200000          |---------------------------------|


*/

