Files
checker_slave/source/task/transmit.c
2023-11-01 23:51:19 +08:00

492 lines
10 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"
typedef struct _tran_def{
ucport_def *u;
int is_busy;
}tran_def;
static int tran_init(void)
{
sig_thread t=thread_creat(10);
tran_def *tran= tran_creat(t);
app_variable("tran",tran,0);
return 0;
}
app_init_export(tran_init);
void tran_end_slot(tran_def *obj,void *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);
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_end_slot(tran_def *obj,void *src,void *data,int ack,char *err_str)
{
//DBG_LOG("tran end slot");
param_check(obj);
if(strcmp(err_str,"timeout")==0)
{
}else{
}
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;
}
static ucport_item *cmd_find(const char *codec_name,uint8_t cmd)
{
#if defined (__CC_ARM)
extern const int transtruct$$Base;
extern const int transtruct$$Limit;
ucport_item *start=(ucport_item *)&transtruct$$Base;
ucport_item *end=(ucport_item *)&transtruct$$Limit;
#else
extern const int __start_transtruct;
extern const int __stop_transtruct;
ucport_item *start=(ucport_item *)&__start_transtruct;
ucport_item *end=(ucport_item *)&__stop_transtruct;
#endif
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;
}
}
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;
}
static ucport_def *tran_upjwtcode(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_jwtcode();
u->u.p=t;
if(op==1)
{
flash_erase_jwtcode();
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)
transmit_export(ym_checker,0xec,tran_upjwtcode)