530 lines
11 KiB
C
530 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.");
|
||
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;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)
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|