
#include "main.h"

#if USE_LFS_RECORD==1
#define USE_MID_LFS_FLASH
#endif

#ifdef USE_MID_LFS_FLASH

#include <stdio.h>
#include "obj_spi_w25qxx.h"
#include "obj_hal_w25qxx.h"
#include "func_spi_w25qxx.h"
#include "mid_littlefs_flash.h"

// lfs for W25Q128 *********************************************************/
//The W25Q128BV array is organized into 65,536 programmable pages of 256-bytes each.
//128Mbit ==> 16Mbyte ==> 16*1024*1024 ==> 4*1024*block==>
//-------------------------------------------------------------------------//
lfs_t lfs; 
lfs_file_t lfs_file;

// configuration of the filesystem is provided by this struct
#pragma pack(4) /*4字节对齐*/
typedef struct lfs_sys_bufffer
{
	uint32_t read[LFS_CACH_SIZE/4];
	uint32_t prog[LFS_CACH_SIZE/4];
	uint32_t lookahead[LFS_CACH_SIZE/4/8];
}lfs_sys_buff;

lfs_sys_buff lfs_sys_buf = {0};


/* lfs for STM32Flash ********************************************************/
lfs_t lfs_flash; 
lfs_file_t file_flash;
#pragma pack()/*还原默认对齐*/
/* Private function prototypes -----------------------------------------------*/
int flash_block_read(const struct lfs_config *c, lfs_block_t block,
            lfs_off_t off, void *buffer, lfs_size_t size);
int flash_block_prog(const struct lfs_config *c, lfs_block_t block,
            lfs_off_t off, const void *buffer, lfs_size_t size);
int flash_block_erase(const struct lfs_config *c, lfs_block_t block);
int flash_block_sync(const struct lfs_config *c);

int lfs_file_open_user(lfs_t *lfs, lfs_file_t *file, const char *path, int flags) ;

// configuration of the filesystem is provided by this struct
const struct lfs_config cfg_flash = {
    // block device operations
    .read  = flash_block_read,
    .prog  = flash_block_prog,
    .erase = flash_block_erase,
    .sync  = flash_block_sync,

    // block device configuration
    .read_size = LFS_SECT_SIZE,
    .prog_size = LFS_SECT_SIZE,
	
    .block_size = LFS_BLOCK_SIZE,
    .block_count = LFS_BLOCK_CNT,
	
    .cache_size = LFS_CACH_SIZE,
	
    .lookahead_size = LFS_CACH_SIZE/8,
	
    .block_cycles = 500,
		
		.read_buffer = lfs_sys_buf.read,	
	  .prog_buffer = lfs_sys_buf.prog,	
	
		.lookahead_buffer = lfs_sys_buf.lookahead,	
};

void mid_lfs_flash_init(void)
{
	int err = -1;	
	int erase_flag = 0;	
	
	err = lfs_mount(&lfs_flash, &cfg_flash);	
	
	while( err != LFS_ERR_OK )
	{ 
		
		if(erase_flag)
		{
			W25QXX_Erase_Chip();
			lfs_format(&lfs_flash, &cfg_flash);
			err = lfs_mount(&lfs_flash, &cfg_flash);
			erase_flag = 0;
		}

		osDelay(1000);
	}		
	return;
}

int mid_lfs_flash_get_free(void)
{
	return 0xffffff;
}




int mid_lfs_flash_bootcnt(void)
{
	
	//while(1)
	{		
		uint32_t boot_count = 0;
		lfs_file_open_static(&lfs_flash, &file_flash, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
		lfs_file_read(&lfs_flash, &file_flash, &boot_count, sizeof(boot_count));

		
		// update boot count
		boot_count += 1;
		lfs_file_rewind(&lfs_flash, &file_flash);  // seek the file to begin
		lfs_file_write(&lfs_flash, &file_flash, &boot_count, sizeof(boot_count));

		// remember the storage is not updated until the file is closed successfully
		lfs_file_close(&lfs_flash, &file_flash);

//	// release any resources we were using


		// print the boot count
		printf("boot_count: %d\n", boot_count);
	};
	return 0;
}

int mid_lfs_flash_boot_step(void)
{
	
	//while(1)
	{		
		uint32_t boot_count = 0;
		lfs_file_open_static(&lfs_flash, &file_flash, "boot_step", LFS_O_RDWR | LFS_O_CREAT);
		lfs_file_read(&lfs_flash, &file_flash, &boot_count, sizeof(boot_count));

		
		// update boot count
		boot_count += 1;
		lfs_file_rewind(&lfs_flash, &file_flash);  // seek the file to begin
		lfs_file_write(&lfs_flash, &file_flash, &boot_count, sizeof(boot_count));

		// remember the storage is not updated until the file is closed successfully
		lfs_file_close(&lfs_flash, &file_flash);

//	// release any resources we were using


		// print the boot count
		printf("boot_count: %d\n", boot_count);
	};
	return 0;
}

int flash_block_read(const struct lfs_config *c, lfs_block_t block,
            lfs_off_t off, void *buffer, lfs_size_t size)
{

		W25QXX_Read((uint8_t*)buffer, (uint32_t)((block * LFS_BLOCK_SIZE) + off),  (uint16_t)size);
    return 0;
}            

int flash_block_prog(const struct lfs_config *c, lfs_block_t block,
            lfs_off_t off, const void *buffer, lfs_size_t size)
{
	
    //W25QXX_Write((uint8_t*)buffer, block * LFS_BLOCK_SIZE + off,  size);
		W25QXX_Write_NoCheck((uint8_t*)buffer, block * LFS_BLOCK_SIZE + off,  size);
    return 0;
}

int flash_block_erase(const struct lfs_config *c, lfs_block_t block)
{
	  W25QXX_Erase_Sector(block);
    return 0;
}

int flash_block_sync(const struct lfs_config *c)
{
    return 0;
}
#if 0
#pragma pack(4) /*4字节对齐*/
//uint32_t file_buffer[LFS_CACH_SIZE/4];
#pragma pack()/*还原默认对齐*/
#else
static uint8_t file_buffer[LFS_CACH_SIZE] __attribute__((aligned(4)));
#endif

struct lfs_file_config file_cfg = {.attr_count = 0, .attrs = 0, .buffer = file_buffer};

int lfs_file_open_static(lfs_t *lfs, lfs_file_t *file, const char *path, int flags) 
{
	memset(&file_cfg,0x00,sizeof(struct lfs_file_config));
	file_cfg.buffer = file_buffer;		
	memset(file_buffer,0x00,sizeof(file_buffer));
	memset(file,0x00,sizeof(lfs_file_t));
	return lfs_file_opencfg(lfs, file, path, flags, &file_cfg);
}



#endif //---------------USE_MID_LFS_FLASH---------------------//

//------------------------the end of file-------------------------//
