527 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			527 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | #include "stdio.h"
 | |||
|  | #include "rtthread.h"
 | |||
|  | #include "board.h"
 | |||
|  | #include "mystdlib.h"
 | |||
|  | #include "list.h"
 | |||
|  | #include "mystring.h"
 | |||
|  | #include "signal.h"
 | |||
|  | #include "transmit.h"
 | |||
|  | #include "buff.h"
 | |||
|  | #include "bytearray.h"
 | |||
|  | #include "debug.h"
 | |||
|  | #include "crc.h"
 | |||
|  | #include "dev_flash.h"
 | |||
|  | #include "mymisc.h"
 | |||
|  | #include "dev_backup.h"
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | #define PORT_NUM    20
 | |||
|  | 
 | |||
|  | 
 | |||
|  | typedef struct _tran_def{ | |||
|  |   ucport_def *u; | |||
|  |   port_mcu *port[PORT_NUM]; | |||
|  |   uint32_t slave_online;// 对应位为1则从机在线
 | |||
|  |   int is_busy; | |||
|  | }tran_def; | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | // 打印从机状态
 | |||
|  | static void tran_print_slave_stat(void *t) | |||
|  | { | |||
|  |   list_def *l=list_creat_int(); | |||
|  |   uint32_t a=tran_get_slave_online(t); | |||
|  |   for(int i=0;i<PORT_NUM;i++) | |||
|  |   { | |||
|  |     if(a&(1<<i)){ | |||
|  |       list_append_int(l,i+1); | |||
|  |     } | |||
|  |   } | |||
|  |   DBG_LOG("slave online stat:%s",str_temp(list_string(l))); | |||
|  |   //DBG_LOG("slave online stat:%08x",a);
 | |||
|  |   list_delete(l); | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | // 扫描从机
 | |||
|  | static void tran_scan_slave(void *t) | |||
|  | { | |||
|  |   for(int i=0;i<PORT_NUM;i++) | |||
|  |   { | |||
|  |     // 只给在线设备升级方案
 | |||
|  |     port_mcu *mcu=tran_get_portm(t,i); | |||
|  |     if(mcu&&(tran_get_slave_online(t)&(1<<i))){ | |||
|  |       // f9用于获取运行状态,失败则设备不在线
 | |||
|  |       port_start(mcu,usercmd_creat(0xf9,arr_temp(arr_creat()))); | |||
|  |     } | |||
|  |   } | |||
|  |   later_execute(tran_print_slave_stat,t,5500); | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | static int tran_init(void) | |||
|  | { | |||
|  |   sig_thread t=thread_creat(10); | |||
|  |   tran_def *tran= tran_creat(t); | |||
|  |   tran->slave_online=0xfffff; | |||
|  |   app_variable("tran",tran,0); | |||
|  |   later_execute(tran_scan_slave,tran,500); | |||
|  |   return 0; | |||
|  | } | |||
|  | app_init_export(tran_init); | |||
|  | 
 | |||
|  | 
 | |||
|  | void tran_end_slot(tran_def *obj,port_mcu *src,void *data,int ack,char *err_str); | |||
|  | 
 | |||
|  | tran_def *tran_creat(sig_thread t) | |||
|  | { | |||
|  |   tran_def *tr=calloc(1,sizeof(tran_def)); | |||
|  |   param_check(tr); | |||
|  |   port_init(); | |||
|  |   for(int i=0;i<PORT_NUM;i++) | |||
|  |   { | |||
|  |     tr->port[i]=port_creat(i+1,t); | |||
|  |     // 连接操作结束信号
 | |||
|  |     connect(tr->port[i],port_end_signal,0,tr,tran_end_slot); | |||
|  |   } | |||
|  |   return tr; | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | static ucport_def *ucport_creat(tran_def *t,const char *codec_name,uint8_t cmd,array_def *data); | |||
|  | 
 | |||
|  | void tran_recv_slot(tran_def *t,const char *codec_name,uint8_t cmd,array_def *data,char *err_str) | |||
|  | { | |||
|  |   if((strcmp("ok",err_str)!=0)||(cmd==0)) | |||
|  |   { | |||
|  |     return; | |||
|  |   } | |||
|  |   //DBG_LOG("tran recv:%s",str_temp(arr_string(data)));
 | |||
|  |   tran_def *tr=t; | |||
|  |   if((tr->u)&&(cmd==tr->u->cmd)) | |||
|  |   { | |||
|  |     if(tr->u->dolater==0||(tr->u->dolater(tr->u,cmd,data,err_str)<0)) | |||
|  |       goto init; | |||
|  |   }else | |||
|  |   { | |||
|  |     init: | |||
|  |     DBG_LOG("tran init"); | |||
|  |     if(tran_get_busy(tr)){ | |||
|  |       DBG_WARN("ucport is busy."); | |||
|  |       return; | |||
|  |     } | |||
|  |     CHECK_DO(tr->u,tr->u->del); | |||
|  |     tr->u=ucport_creat(t,codec_name,cmd,data); | |||
|  |     if(tr->u==0){ | |||
|  |       DBG_LOG("recv data but handle is none.cmd=%02x",cmd); | |||
|  |     }else{ | |||
|  |       tr->u->p=tr; | |||
|  |       if(tr->u->del==0) | |||
|  |         tr->u->del=(void (*)(ucport_def *))free; | |||
|  |     } | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | void tran_set_slave_online(tran_def *t,uint8_t addr,int stat) | |||
|  | { | |||
|  |   param_check(t); | |||
|  |   uint32_t a=0; | |||
|  |   a=1<<(addr-1); | |||
|  |   if(stat) | |||
|  |     t->slave_online|=a; | |||
|  |   else{ | |||
|  |     t->slave_online&=(~a); | |||
|  |     //DBG_LOG("a=%08x",a);
 | |||
|  |   } | |||
|  | } | |||
|  | uint32_t tran_get_slave_online(tran_def *t) | |||
|  | { | |||
|  |   param_check(t); | |||
|  |   return t->slave_online; | |||
|  | } | |||
|  | 
 | |||
|  | void tran_end_slot(tran_def *obj,port_mcu *src,void *data,int ack,char *err_str) | |||
|  | { | |||
|  |   //DBG_LOG("tran end slot");
 | |||
|  |   param_check(obj); | |||
|  |   if(strcmp(err_str,"timeout")==0) | |||
|  |   { | |||
|  |     tran_set_slave_online(obj,port_get_addr(src),0); | |||
|  |   }else{ | |||
|  |     tran_set_slave_online(obj,port_get_addr(src),1); | |||
|  |   } | |||
|  |   if((obj->u)&&obj->u->doend) | |||
|  |     obj->u->doend(obj->u,src,data,ack,err_str); | |||
|  | } | |||
|  | 
 | |||
|  | void tran_set_busy(tran_def *t,int busy) | |||
|  | { | |||
|  |   t->is_busy=busy; | |||
|  | } | |||
|  | int tran_get_busy(tran_def *t) | |||
|  | { | |||
|  |   return t->is_busy; | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | // 获取指定通道
 | |||
|  | port_mcu *tran_get_portm(tran_def *t,int index) | |||
|  | { | |||
|  |   if(index<0||index>=PORT_NUM) | |||
|  |     return 0; | |||
|  |   return t->port[index]; | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | static ucport_item *cmd_find(const char *codec_name,uint8_t cmd) | |||
|  | { | |||
|  |   extern const int transtruct$$Base; | |||
|  |   extern const int transtruct$$Limit; | |||
|  |   ucport_item *start=(ucport_item *)&transtruct$$Base; | |||
|  |   ucport_item *end=(ucport_item *)&transtruct$$Limit; | |||
|  |   for(ucport_item *t=start;t<end;t++) | |||
|  |   { | |||
|  |     if((t->cmd==cmd)&&(strcmp(t->codec_name,codec_name)==0)) | |||
|  |     { | |||
|  |       return t; | |||
|  |     } | |||
|  |   } | |||
|  |   return 0; | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | static ucport_def *ucport_creat(tran_def *t,const char *codec_name,uint8_t cmd,array_def *data) | |||
|  | { | |||
|  |   ucport_item *item=cmd_find(codec_name,cmd); | |||
|  |   if(item){ | |||
|  |     return item->creat(t,cmd,data); | |||
|  |   } | |||
|  |   return 0; | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | typedef struct{ | |||
|  |   ucport_def u; | |||
|  |   uint8_t *addr; | |||
|  |   int recved_bytes; | |||
|  |   int all_bytes; | |||
|  |   int packet_now; | |||
|  |   int packet_all; | |||
|  |   void (*doexert)(ucport_def *u); | |||
|  | }updata_def; | |||
|  | 
 | |||
|  | // [0,1]是当前包数,[2,3]是总包数,剩下的是文件数据
 | |||
|  | // 当前包数从1开始
 | |||
|  | static int updata_write_dolater(ucport_def *u,uint8_t cmd,array_def *data,char *err_str) | |||
|  | { | |||
|  |   if(arr_get(data,0)!=2) | |||
|  |   { | |||
|  |     DBG_WARN("cmd=%02x,not a data packet.",cmd); | |||
|  |     u->cmd=0; | |||
|  |     return -1; | |||
|  |   } | |||
|  |   arr_remove(data,0,1); | |||
|  |   updata_def *uu=(updata_def *)u; | |||
|  |   uu->packet_now++; | |||
|  |   int len; | |||
|  |   int packet_now=arr_get(data,0)|(arr_get(data,1)<<8); | |||
|  |   if(packet_now==uu->packet_now) | |||
|  |   { | |||
|  |     //DBG_LOG("write flash addr=%08x",uu->addr);
 | |||
|  |     len=arr_length(data)-4; | |||
|  |     flash_write(uu->addr,&arr_data(data)[4],len); | |||
|  |     uu->recved_bytes+=len; | |||
|  |     uu->addr+=len; | |||
|  |     array_def *a=arr_creat(); | |||
|  |     arr_append(a,0); | |||
|  |     emit tran_reply_signal(u->p,arr_temp(a)); | |||
|  |   } | |||
|  |   else | |||
|  |   { | |||
|  |     DBG_WARN("packet err."); | |||
|  |     uu->u.cmd=0; | |||
|  |   } | |||
|  |   if(uu->all_bytes==uu->recved_bytes) | |||
|  |   { | |||
|  |     flash_operate_end(); | |||
|  |     DBG_LOG("updata success."); | |||
|  |     if(uu->doexert) | |||
|  |     { | |||
|  |       // 做额外的处理
 | |||
|  |       uu->doexert(u); | |||
|  |     } | |||
|  |     uu->u.cmd=0; | |||
|  |   } | |||
|  |   return 0; | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | static int updata_read_dolater(ucport_def *u,uint8_t cmd,array_def *data,char *err_str) | |||
|  | { | |||
|  |   if(arr_get(data,0)!=2) | |||
|  |   { | |||
|  |     DBG_WARN("cmd=%02x,not a data packet.",cmd); | |||
|  |     u->cmd=0; | |||
|  |     return -1; | |||
|  |   } | |||
|  |   updata_def *uu=(updata_def *)u; | |||
|  |   int len=200; | |||
|  |   if(uu->all_bytes<uu->recved_bytes+len) | |||
|  |     len=uu->all_bytes-uu->recved_bytes; | |||
|  |   uu->packet_now++; | |||
|  |   array_def *a=arr_creat(); | |||
|  |   arr_append(a,uu->packet_now&0xff); | |||
|  |   arr_append(a,(uu->packet_now>>8)&0xff); | |||
|  |   arr_append(a,uu->packet_all&0xff); | |||
|  |   arr_append(a,(uu->packet_all>>8)&0xff); | |||
|  |   arr_appends(a,uu->addr,len); | |||
|  |   emit tran_reply_signal(u->p,arr_temp(a)); | |||
|  |   uu->addr+=len; | |||
|  |   uu->recved_bytes+=len; | |||
|  |   if(uu->all_bytes==uu->recved_bytes) | |||
|  |   { | |||
|  |     DBG_LOG("upload success."); | |||
|  |     uu->u.cmd=0; | |||
|  |     return 0; | |||
|  |   } | |||
|  |   return 0; | |||
|  | } | |||
|  | 
 | |||
|  | // 初始化写函数
 | |||
|  | static void updata_prepar_write(updata_def *u,uint8_t cmd,array_def *data) | |||
|  | { | |||
|  |   ucport_def *uu=(ucport_def *)u; | |||
|  |   u->all_bytes=arr_get(data,0)|(arr_get(data,1)<<8)|(arr_get(data,2)<<16)|(arr_get(data,3)<<24); | |||
|  |   uu->cmd=cmd; | |||
|  |   uu->dolater=updata_write_dolater; | |||
|  |   uu->del=(void (*)(ucport_def *))free; | |||
|  |   uint8_t *td=calloc(FLASH_FILE_HEAD_SIZE,sizeof(uint8_t)); | |||
|  |   // 文件大小和文件名
 | |||
|  |   memcpy(td,arr_data(data),arr_length(data)); | |||
|  |   // used字段
 | |||
|  |   ((flash_file *)td)->used=0xffffffff; | |||
|  |   flash_write(u->addr,td,FLASH_FILE_HEAD_SIZE); | |||
|  |   free(td); | |||
|  |   u->addr+=FLASH_FILE_HEAD_SIZE; | |||
|  |    | |||
|  |   // 回复上位机
 | |||
|  |   array_def *a=arr_creat(); | |||
|  |   arr_append(a,0); | |||
|  |   emit tran_reply_signal(uu->p,arr_temp(a)); | |||
|  | } | |||
|  | 
 | |||
|  | // 初始化读函数
 | |||
|  | static void updata_prepar_read(updata_def *u,uint8_t cmd,array_def *data) | |||
|  | { | |||
|  |   ucport_def *uu=(ucport_def *)u; | |||
|  |   int len=0; | |||
|  |   if(u->addr[4]!=0xff){ | |||
|  |     u->all_bytes=u->addr[0]|(u->addr[1]<<8)|(u->addr[2]<<16)|(u->addr[3]<<24); | |||
|  |     u->packet_all=(u->all_bytes+199)/200; | |||
|  |     uu->cmd=cmd; | |||
|  |     uu->dolater=updata_read_dolater; | |||
|  |     uu->del=(void (*)(ucport_def *))free; | |||
|  |     len=strlen((char *)&u->addr[4]); | |||
|  |     len+=4; | |||
|  |    | |||
|  |     // 回复上位机
 | |||
|  |     array_def *a=arr_creat(); | |||
|  |     arr_append(a,0); | |||
|  |     arr_appends(a,u->addr,len); | |||
|  |     emit tran_reply_signal(uu->p,arr_temp(a)); | |||
|  |     u->addr+=FLASH_FILE_HEAD_SIZE; | |||
|  |   }else{ | |||
|  |     // 本机没有相应数据
 | |||
|  |     uu->del=(void (*)(ucport_def *))free; | |||
|  |     array_def *a=arr_creat(); | |||
|  |     arr_append(a,0xff); | |||
|  |     emit tran_reply_signal(uu->p,arr_temp(a)); | |||
|  |     uu->cmd=0; | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | static void when_scheme_done(ucport_def *u) | |||
|  | { | |||
|  |   tran_def *tran=app_variable("tran",0,0); | |||
|  |   if(tran==0){ | |||
|  |     DBG_WARN("can not fond variable \"tran\""); | |||
|  |     return; | |||
|  |   } | |||
|  |   for(int i=0;i<PORT_NUM;i++) | |||
|  |   { | |||
|  |     // 只给在线设备升级方案
 | |||
|  |     port_mcu *mcu=tran_get_portm(tran,i); | |||
|  |     if(mcu&&(tran_get_slave_online(tran)&(1<<i))) | |||
|  |       port_start(mcu,updata_scheme_creat(check_scheme()->slave_data,2048)); | |||
|  |   } | |||
|  | } | |||
|  | static ucport_def *tran_scheme(tran_def *t, uint8_t cmd,array_def *data) | |||
|  | { | |||
|  |   if(arr_length(data)<1){ | |||
|  |     DBG_WARN("cmd format err."); | |||
|  |     return 0; | |||
|  |   } | |||
|  |   uint8_t op=arr_get(data,0); | |||
|  |   updata_def *u=calloc(1,sizeof(updata_def)); | |||
|  |   arr_remove(data,0,1); | |||
|  |   u->recved_bytes=0; | |||
|  |   u->addr=(uint8_t *)flash_get_scheme(); | |||
|  |   u->u.p=t; | |||
|  |   if(op==1) | |||
|  |   { | |||
|  |     u->doexert=when_scheme_done; | |||
|  |     flash_erase_scheme(); | |||
|  |     updata_prepar_write(u,cmd,data); | |||
|  |   }else if(op==0) | |||
|  |   { | |||
|  |     updata_prepar_read(u,cmd,data); | |||
|  |   } | |||
|  |   else{ | |||
|  |     DBG_WARN("cmd=%02x err,op!=0 or 1 .",cmd); | |||
|  |     free(u); | |||
|  |     return 0; | |||
|  |   } | |||
|  |   return (ucport_def *)u; | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | // data[0]==0读;data[0]==1写
 | |||
|  | // 最前4个字节是文件长度,然后是文件名
 | |||
|  | static ucport_def *tran_judge(tran_def *t,uint8_t cmd,array_def *data) | |||
|  | { | |||
|  |   if(arr_length(data)<1){ | |||
|  |     DBG_WARN("cmd format err."); | |||
|  |     return 0; | |||
|  |   } | |||
|  |   uint8_t op=arr_get(data,0); | |||
|  |   updata_def *u=calloc(1,sizeof(updata_def)); | |||
|  |   arr_remove(data,0,1); | |||
|  |   u->recved_bytes=0; | |||
|  |   u->addr=(uint8_t *)flash_get_lua(); | |||
|  |   u->u.p=t; | |||
|  |   if(op==1) | |||
|  |   { | |||
|  |     flash_erase_lua(); | |||
|  |     updata_prepar_write(u,cmd,data); | |||
|  |   }else if(op==0) | |||
|  |   { | |||
|  |     updata_prepar_read(u,cmd,data); | |||
|  |   } | |||
|  |   else{ | |||
|  |     DBG_WARN("cmd=%02x err,op!=0 or 1 .",cmd); | |||
|  |     free(u); | |||
|  |     return 0; | |||
|  |   } | |||
|  |   DBG_LOG("u->cmd=%d",u->u.cmd); | |||
|  |   return (ucport_def *)u; | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | static void when_upself_done(ucport_def *u) | |||
|  | { | |||
|  |   // 升级完成后延时50ms重启
 | |||
|  |   later_execute((void (*)(void *))bk_reboot_updata,0,50); | |||
|  | } | |||
|  | 
 | |||
|  | static ucport_def *tran_upself(tran_def *t,uint8_t cmd,array_def *data) | |||
|  | { | |||
|  |   if(arr_length(data)<1){ | |||
|  |     DBG_WARN("cmd format err."); | |||
|  |     return 0; | |||
|  |   } | |||
|  |   uint8_t op=arr_get(data,0); | |||
|  |   updata_def *u=calloc(1,sizeof(updata_def)); | |||
|  |   arr_remove(data,0,1); | |||
|  |   u->recved_bytes=0; | |||
|  |   u->addr=(uint8_t *)flash_get_app2(); | |||
|  |   u->u.p=t; | |||
|  |   if(op==1) | |||
|  |   { | |||
|  |     // 升级完成后重启
 | |||
|  |     u->doexert =when_upself_done; | |||
|  |     flash_erase_app2(); | |||
|  |     updata_prepar_write(u,cmd,data); | |||
|  |   }else if(op==0) | |||
|  |   { | |||
|  |     updata_prepar_read(u,cmd,data); | |||
|  |   } | |||
|  |   else{ | |||
|  |     DBG_WARN("cmd=%02x err,op!=0 or 1 .",cmd); | |||
|  |     free(u); | |||
|  |     return 0; | |||
|  |   } | |||
|  |   return (ucport_def *)u; | |||
|  | } | |||
|  | static ucport_def *tran_upslave(tran_def *t,uint8_t cmd,array_def *data) | |||
|  | { | |||
|  |   if(arr_length(data)<1){ | |||
|  |     DBG_WARN("cmd format err."); | |||
|  |     return 0; | |||
|  |   } | |||
|  |   uint8_t op=arr_get(data,0); | |||
|  |   updata_def *u=calloc(1,sizeof(updata_def)); | |||
|  |   arr_remove(data,0,1); | |||
|  |   u->recved_bytes=0; | |||
|  |   u->addr=(uint8_t *)flash_get_slave(); | |||
|  |   u->u.p=t; | |||
|  |   if(op==1) | |||
|  |   { | |||
|  |     flash_erase_slave(); | |||
|  |     updata_prepar_write(u,cmd,data); | |||
|  |   }else if(op==0) | |||
|  |   { | |||
|  |     updata_prepar_read(u,cmd,data); | |||
|  |   } | |||
|  |   else{ | |||
|  |     DBG_WARN("cmd=%02x err,op!=0 or 1 .",cmd); | |||
|  |     free(u); | |||
|  |     return 0; | |||
|  |   } | |||
|  |   return (ucport_def *)u; | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | transmit_export(ym_checker,0x32,tran_scheme) | |||
|  | transmit_export(ym_checker,0x36,tran_judge) | |||
|  | transmit_export(ym_checker,0xed,tran_upself) | |||
|  | transmit_export(ym_checker,0xee,tran_upslave) | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 |