#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 2 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;islave_online=0xfffff; app_variable("tran",tran,0); later_execute(tran_scan_slave,tran,2000); 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;iport[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."); array_def *d=arr_creat(); arr_append(d,TRAN_ERR_BUSY); emit tran_send_signal(tr,cmd,arr_temp(d)); 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;tcmd==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_bytesrecved_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; } DBG_LOG("memused:%d",mem_perused()); rt_thread_mdelay(100); DBG_LOG("memused:%d",mem_perused()); for(int i=0;islave_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)