

#ifdef RT_THREAD


#include "stdio.h"
#include "rtthread.h"
#include "board.h"
#include "mystdlib.h"
#include "list.h"
#include "mystring.h"
#include "signal.h"
#include "prot_mcu.h"
#include "debug.h"
#include "prot_uc.h"
#include "transmit.h"
#include "commend.h"
#include "dev_flash.h"
#include "mymisc.h"
#include "dev_backup.h"
#include "compiler_info.h"
#include "elec_det.h"

static const uint8_t ALIGN(4) g_bootcode[]={
  #include "bootcode.txt"
};

// 升级bootloader
static void boot_updata(void)
{
  if(sizeof(g_bootcode)==0)
    return;
  if(bk_check_magic_num())
  {
    flash_updata_boot((uint8_t *)g_bootcode,sizeof(g_bootcode));
    bk_reboot_app();
  }
}



int main()
{
  boot_updata();
  debug_init();
  elec_init();
  app_init();
  
  protu_def *protu=app_variable("protu",0,0);
  protu_def *protu2=app_variable("protu2",0,0);
  tran_def *tran=app_variable("tran",0,0);
  void *cmd=app_variable("cmd",0,0);
  
  connect(protu,protu_recv_signal,0,tran,tran_recv_slot);
  connect(tran,tran_reply_signal,0,protu,protu_reply_call);
  connect(tran,tran_send_signal,0,protu,protu_send_call);

  connect(protu2,protu_recv_signal,0,cmd,cmd_recv_slot);
  connect(cmd,cmd_reply_signal,0,protu2,protu_send_call);
  
  timer_def *timer=dev_get("timer");
  timer->init(timer);
//  rt_thread_mdelay(5000);
//  timer->write(timer,0);
  while(1)
  {
    elec_led2_power(1);
    rt_thread_mdelay(300);
    elec_led2_power(0);
    rt_thread_mdelay(300);
  }
}



int init_wdog(void)
{
  if(bk_wdog_fun())
  {
    rt_thread_idle_sethook((void (*)(void))bk_wdog_fun());
  }
  return 0;
}

app_init_export(init_wdog)





static int test(list_def *argv)
{
  if(list_length(argv)<2){
    cmd_print("param num too less.");
    return -1;
  }
  float num=str_atof(list_get_str(argv,1));
  cmd_print("test num=%f",num);
  return 0;
}
//commend_export(test,test,"cmd test")





static int scheme_info(list_def *argv)
{
  const scheme_def *s=check_scheme();
  const scheme_task_def *t;
  if(s->plan_id==0xffffffff){
    cmd_print("scheme is empty.");
    return -1;
  }
  cmd_print("plan id:       %d",s->plan_id);
  cmd_print("timeout_m:     %d",s->timeout_m);
  cmd_print("task num:      %d",s->task_num);
  for(int i=0;i<s->task_num;i++)
  {
    t=&s->task[i];
    cmd_print("  task:%02d  id:%02d  err:%02x",t->taskindex,t->taskid,t->err);
    for(int j=0;j<t->item_num;j++)
    {
      cmd_print("    max:%5d, min:%5d err:%02x    %s",t->range[j].max,t->range[j].min,
      t->err,
      t->range[j].max<t->range[j].min?"err":"ok");
    }
  }
  return 0;
}
commend_export(scheme,scheme_info,"print scheme info")













static int memused(list_def *argv)
{
  uint32_t used,total,max_used;
  rt_memory_info(&total,&used,&max_used);
  cmd_print("mem total=%d,used=%d,max_used=%d",total,used,max_used);
  used=mem_perused();
  cmd_print("mem used=%d.",used);
  return 0;
}


commend_export(memused,memused,"print the mem use info")



static int reboot(list_def *argv)
{
  cmd_print("mcu will reboot later");  
  later_execute((void (*)(void *))bk_reboot_app,0,50);
  return 0;
}


commend_export(reboot,reboot,"reboot mcu")









static void print_sys_param(const sys_param_def *par)
{
  cmd_print(" - - - - - - - - - - - - - - ");
  cmd_print("pack time:         %s",par->pack_time);
  cmd_print("host if:           %s",par->host_if);
  cmd_print("device type:       %s",par->device_type);
  cmd_print("mac addr:          %02x.%02x.%02x.%02x.%02x.%02x",
    par->mac[0],par->mac[1],par->mac[2],par->mac[3],par->mac[4],par->mac[5]);
  cmd_print("local id:          %d",par->local_id);
  cmd_print("uart bsp:          %d",par->uartbsp);
}


static int sysinfo(list_def *argv)
{
  const sys_param_def *par=sys_param();
  cmd_print("build time:      %s",BUILD_DATE);
  cmd_print("soft version:    %s",SOFT_VERSION);
  cmd_print("run time:        %d",rt_tick_get()/1000);
  cmd_print("startup:         %s",bk_get_currtype());
  cmd_print("watch dog:       %s",bk_wdog_fun()?"on":"off");
  cmd_print("reboot times:    %d",bk_reboot_times());
  cmd_print("bootloader:      %s",(bk_check_magic_num()==0)?"ok":"err");
  #ifdef DEBUG
  cmd_print("debug:           %s","yes");
  #else
  cmd_print("debug:           %s","no");
  #endif
  print_sys_param(par);
  return 0;
}

commend_export(sysinfo,sysinfo,"print the software info")





static void print_sys_help(void)
{
  cmd_print("example for how to set system params:");
  cmd_print("set hostif                 can/uart1/host");
  cmd_print("set devicetype             checker/coder");
  cmd_print("set localid                1");
  cmd_print("set uartbsp                57600");
  cmd_print("set save");
}

static int sys_set(list_def *argv)
{
  static sys_param_def *spar=0;
  if(spar==0){
    spar=calloc(1,sizeof(sys_param_def));
    memcpy(spar,sys_param(),sizeof(sys_param_def));
  }
  if(list_length(argv)<2){
    cmd_print(" - - - -SET TEMP- - - - ");
    print_sys_param(spar);
    return 0;
  }
  if(strcmp(list_get_str(argv,1),"help")==0)
  {
    print_sys_help();
    return 0;
  }
  else if(strcmp(list_get_str(argv,1),"save")==0)
  {
    cmd_print(" - - - -SET TEMP- - - - ");
    print_sys_param(spar);
    flash_save_param(spar);
    cmd_print("param saved,device will reboot later.");
    later_execute((void (*)(void *))bk_reboot_app,0,100);
    return 0;
  }else{
    if(list_length(argv)<3){
      cmd_print("param num too less.");
      print_sys_help();
      return -1;
    }
  }
  if(strcmp(list_get_str(argv,1),"hostif")==0)
  {
    char *str=list_get_str(argv,2);
    memcpy(spar->host_if,str,strlen(str)+1);
    cmd_print("host if: %s",spar->host_if);
  }
  else if(strcmp(list_get_str(argv,1),"devicetype")==0)
  {
    char *str=list_get_str(argv,2);
    memcpy(spar->device_type,str,strlen(str)+1);
    cmd_print("device type: %s",spar->device_type);
  }
  else if(strcmp(list_get_str(argv,1),"localid")==0)
  {
    char *str=list_get_str(argv,2);
    spar->local_id=str_atoi(str);
    cmd_print("local id:        %d",spar->local_id);
  }
  else if(strcmp(list_get_str(argv,1),"uartbsp")==0)
  {
    char *str=list_get_str(argv,2);
    spar->uartbsp=str_atoi(str);
    cmd_print("uart bsp:        %d",spar->uartbsp);
  }
  else{
    cmd_print("unknown cmd for sysset.");
    print_sys_help();
    return -1;
  }
  return 0;
}

//commend_export(set,sys_set,"set the system params")



#else


#include "board.h"
#include "dev_flash.h"
#include "dev_backup.h"
#include "crc.h"
#include "dev_watchdog.h"
#include "string.h"

#define APP_ADDR 0x08004000

void __set_msp(uint32_t addr);
typedef void (*app)(void);
void app_run(void)
{
  app app_fun;
  if(((*(volatile uint32_t*)APP_ADDR)&0x2FFE0000)==0x20000000)
  {
//    wdog_start();
//    bk_set_wdog_fun(wdog_refresh);
    app_fun=(app)*(volatile uint32_t*)(APP_ADDR+4);
    __set_msp(*(volatile uint32_t*)APP_ADDR);
    app_fun();
  }
}


void param_init(rom_head *h);
void app_updata(void);
int main()
{
  uint32_t boot_type=bk_get_boottype();
  bk_init();
  switch(boot_type){
    // 重启并升级
    case REBOOT_APP_TO_BOOT:
    {
      uint8_t *rom;
      rom_head *head;
      rom=flash_get_rom(&head);
      if(strcmp(head->device_type,"slave")!=0){
        // 如果不是小板的固件，本次不升级
        bk_reboot_guide();
      }
      param_init(head);
      if(rom)
      {
        if(head->crc==crc_crc32(rom,head->size))
        {
          flash_updata_app(rom,head->size);
        }
      }
      bk_reboot_guide();
      break;
    }
    // 重新运行boot
    case REBOOT_BOOT_TO_BOOT:
      break;
    // 重启app
    case REBOOT_APP_TO_APP:
    // 引导至app
    case REBOOT_BOOT_TO_APP:
    // 断言失败重启
    case REBOOT_PARAM_ERR:
    // 硬件错误重启
    case REBOOT_HARD_ERR:
    // 看门狗重启
    case REBOOT_INIT:
    // 上电启动
    default:
      param_init(0);
      app_run();
      break;
  }
  while(1)
  {
  }
}


// 初始化mac地址
void mac_init(uint8_t *mac)
{
  const uint8_t *mcu_id=(const uint8_t *)0x1FFF7A10;
  for(int i=0;i<6;i++)
  {
    mac[i]=0;
  }
}





// 参数初始化
void param_init(rom_head *h)
{
  static sys_param_def pars={0};
  memcpy(&pars,sys_param(),sizeof(sys_param_def));
  if(h){
    memcpy(pars.pack_time,h->pack_time,20);
    if(pars.local_id==0xffffffff){
      memcpy(pars.host_if,h->host_if,8);
      memcpy(pars.device_type,"slave",6);
      mac_init(pars.mac);
      pars.local_id=0;
    }
    flash_save_param(&pars);
  }
  else{
    // 填充默认配置
    if(pars.local_id==0xffffffff){
      memcpy(pars.pack_time,"initial app",12);
      memcpy(pars.host_if,"host",5);
      memcpy(pars.device_type,"slave",6);
      mac_init(pars.mac);
      pars.local_id=0;
      flash_save_param(&pars);
    }
  }
}






#endif




