

#include "rtthread.h"
#include "stm32f10x.h"
#include "board.h"
#include "dev_flash.h"
#include "debug.h"
#include "stdlib.h"
#include "string.h"

#ifndef RT_THREAD

#define rt_interrupt_enter()
#define rt_interrupt_leave()
#define rt_mutex_create(...) 0
#define rt_mutex_delete(...)
#define rt_mutex_take(...)
#define rt_mutex_release(...)

#endif





/*

bootloader 0~7
app 8~57
buff 58~107
params 108
scheme 109~110

*/
#define FLASH_SECTOR_SIZE         2048
#define FLASH_BOOT_SECTOR         (0)
#define FLASH_BOOT_SECTOR_NUM     (8)
#define FLASH_APP_SECTOR          (8)
#define FLASH_APP_SECTOR_NUM      (50)
#define FLASH_BUFF_SECTOR         (58)
#define FLASH_BUFF_SECTOR_NUM     (50)
#define FLASH_PARAM_SECTOR        (108)
#define FLASH_PARAM_SECTOR_NUM    (1)
#define FLASH_JWTCODE_SECTOR      (109)
#define FLASH_JWTCODE_SECTOR_NUM  (9)
#define FLASH_SCHEME_SECTOR       (118)
#define FLASH_SCHEME_SECTOR_NUM   (6)









typedef struct{
  void *mutex;
}self_def;

static self_def g_self;



typedef struct{
  uint32_t *addr;
  uint32_t sector;
}flash_item;







#define FLASH_CLEAR_FLAG()  \
  FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); 






// 擦除指定扇区，返回0成功，-1失败
static int flash_erase(uint32_t sector)
{
  self_def *s=&g_self;
  FLASH_Status ret;
  if(s->mutex==0){
    s->mutex=rt_mutex_create("flash_mutex",RT_IPC_FLAG_FIFO);
  }
  rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
  //irq_disable();
  FLASH_Unlock();
  FLASH_CLEAR_FLAG();
  // 对于f103 2048byte为一个扇区，这里把扇区地址转化为flash地址
  ret=FLASH_ErasePage(FLASH_BASE+ sector*2048);
  //FLASH_Lock(); 	
  //irq_enable();
  rt_mutex_release(s->mutex);
  if(ret!=FLASH_COMPLETE)
  {
    DBG_WARN("flash earse failed.ret=%d",ret);
    return -1;
  }else{
    DBG_LOG("flash earse success.ret=%d",ret);
    return 0;
  }
}

// 擦除指定地址
int flash_erase_addr(uint32_t addr)
{
  addr=addr-FLASH_BASE;
  return flash_erase(addr/2048);
}

// 操作开始
int flash_operate_start(void)
{
  FLASH_Status state;
  int ret=0;
  self_def *s=&g_self;
  #ifdef RT_THREAD
  param_check(s->mutex);
  #endif
  rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
  FLASH_Unlock();
  FLASH_CLEAR_FLAG();
  rt_mutex_release(s->mutex);
  return 0;
}


// 操作结束
int flash_operate_end(void)
{
  FLASH_Status state;
  int ret=0;
  self_def *s=&g_self;
  #ifdef RT_THREAD
  param_check(s->mutex);
  #endif
  rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
  FLASH_Lock();
  rt_mutex_release(s->mutex);
  return 0;
}

// boot区
int flash_erase_boot(void)
{
  int ret;
  for(int i=0;i<FLASH_BOOT_SECTOR_NUM;i++){
    ret=flash_erase(FLASH_BOOT_SECTOR+i);
    if(ret!=0) return -1;
  }
  return 0;
}

// 参数区2K
int flash_erase_param(void)
{
  int ret;
  for(int i=0;i<FLASH_PARAM_SECTOR_NUM;i++){
    ret=flash_erase(FLASH_PARAM_SECTOR+i);
    if(ret!=0) return -1;
  }
  return 0;
}
//程序区1 100K
int flash_erase_app1(void)
{
  int ret;
  for(int i=0;i<FLASH_APP_SECTOR_NUM;i++){
    ret=flash_erase(FLASH_APP_SECTOR+i);
    if(ret!=0) return -1;
  }
  return 0;
}
//程序区2 100K 对于f103 程序区2与小板程序区相同
int flash_erase_app2(void)
{
  int ret;
  for(int i=0;i<FLASH_BUFF_SECTOR_NUM;i++){
    ret=flash_erase(FLASH_BUFF_SECTOR+i);
    if(ret!=0) return -1;
  }
  return 0;
}
//小板程序区 100K
int flash_erase_slave(void)
{
  int ret;
  for(int i=0;i<FLASH_BUFF_SECTOR_NUM;i++){
    ret=flash_erase(FLASH_BUFF_SECTOR+i);
    if(ret!=0) return -1;
  }
  return 0;
}
//方案区 6K
int flash_erase_scheme(void)
{
  int ret;
  for(int i=0;i<FLASH_SCHEME_SECTOR_NUM;i++){
    ret=flash_erase(FLASH_SCHEME_SECTOR+i);
    if(ret!=0) return -1;
  }
  return 0;
}
//脚本区 
int flash_erase_lua(void)
{
  int ret;
  return -1;
}

// 模块程序区 16K
int flash_erase_jwtcode(void)
{
  int ret;
  for(int i=0;i<FLASH_JWTCODE_SECTOR_NUM;i++){
    ret=flash_erase(FLASH_JWTCODE_SECTOR+i);
    if(ret!=0) return -1;
  }
  return 0;
}


uint32_t *flash_get_param(void)
{
  return (void *)(FLASH_BASE+FLASH_SECTOR_SIZE*FLASH_PARAM_SECTOR);
}

//uint32_t *flash_get_app1(void)
//{
//  return (void *)0x08020000;
//}

uint32_t *flash_get_app2(void)
{
  return (void *)(FLASH_BASE+FLASH_SECTOR_SIZE*FLASH_BUFF_SECTOR);
}

uint32_t *flash_get_slave(void)
{
  return (void *)(FLASH_BASE+FLASH_SECTOR_SIZE*FLASH_BUFF_SECTOR);
}

uint32_t *flash_get_scheme(void)
{
  return (void *)(FLASH_BASE+FLASH_SECTOR_SIZE*FLASH_SCHEME_SECTOR);
}
uint32_t *flash_get_jwtcode(void)
{
  return (void *)(FLASH_BASE+FLASH_SECTOR_SIZE*FLASH_JWTCODE_SECTOR);
}

uint32_t *flash_get_lua(void)
{
  return (void *)0;
}



int flash_write(uint8_t *addr,const uint8_t *data,int len)
{
  FLASH_Status state;
  int ret=0;
  self_def *s=&g_self;
  if((uint32_t)data%4)
  {
    DBG_WARN("write addr err.");
    return 1;
  }
  uint32_t *t=(uint32_t *)data;
  uint32_t flash_addr=(uint32_t)addr;
  #ifdef RT_THREAD
  param_check(s->mutex);
  #endif
  rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
  
  //DBG_LOG("write flash addr=%08x",flash_addr);
  len+=3;// len不是4字节对齐时强行增加到4字节
  //FLASH_Unlock();
  for(int i=0;i<len/4;i++)
  {
    //irq_disable();
    //state=FLASH_ProgramByte((uint32_t)addr,data[i]);
    state=FLASH_ProgramWord(flash_addr,t[i]);
    //FLASH_CLEAR_FLAG();
    //irq_enable();
    if(state!=FLASH_COMPLETE)
    {
      DBG_WARN("flash write failed.ret=%d",state);
      DBG_WARN("addr=%08X",flash_addr);
      ret=2;
      break;
    }
    flash_addr+=4;
  }
  //FLASH_Lock(); 
  if(memcmp(addr,data,(len/4)*4)!=0)
  {
    DBG_WARN("addr=%08x write/read data not equate.",addr);
    ret=3;
  }
  rt_mutex_release(s->mutex);
  return ret;
}


// 写数据自动擦除
int flash_write_with_erase(uint8_t *addr,const uint8_t *data,int len)
{
  int ret=0;
  uint32_t addr_u32=(uint32_t)addr;
  if((addr_u32%FLASH_SECTOR_SIZE)==0){
    ret=flash_erase(addr_u32/FLASH_SECTOR_SIZE);
    flash_operate_end();
    if(ret!=0) return -1;
  }else{
    flash_operate_start();
  }
  ret=flash_write(addr,data,len);
  flash_operate_end();
  if(ret!=0) return -1;
  return 0;
}



uint8_t *flash_get_rom(rom_head **head)
{
  uint8_t *src=(uint8_t *)flash_get_app2();
  flash_file *file=(flash_file *)flash_get_app2();
  rom_head *h=(rom_head *)(src+FLASH_FILE_HEAD_SIZE);
  uint8_t *rom=src+ROM_HEAD_SIZE+FLASH_FILE_HEAD_SIZE;
  if(file->file_size==0xffffffff){
    return 0;
  }
  if(head) *head=h;
  return rom;
}

int flash_updata_app(uint8_t *rom,uint32_t size)
{
  uint8_t *dst=(uint8_t *)0x08004000;
  flash_erase_app1();
  return flash_write(dst,rom,size);
}


int flash_updata_boot(uint8_t *rom,uint32_t size)
{
  uint8_t *dst=(uint8_t *)0x08000000;
  flash_erase_boot();
  return flash_write(dst,rom,size);
}


// 保存参数
int flash_save_param(sys_param_def *par)
{
  uint8_t *dst=(uint8_t *)flash_get_param();
  uint8_t *src=(uint8_t *)par;
  int size=sizeof(sys_param_def);
  flash_erase_param();
  return flash_write(dst,src,size);
}


const sys_param_def *sys_param(void)
{
  return (sys_param_def *)flash_get_param();
}



const scheme_def *check_scheme(void)
{
  uint8_t *d=(uint8_t *)flash_get_scheme();
  return (scheme_def *)(d+FLASH_FILE_HEAD_SIZE);
}




