Files
checker_gen1/source/task/transmit.c
2023-07-03 18:27:10 +08:00

533 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}
DBG_LOG("memused:%d",mem_perused());
rt_thread_mdelay(100);
DBG_LOG("memused:%d",mem_perused());
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)