Files
checker_gen1/source/task/handle.c
2025-02-13 23:22:16 +08:00

595 lines
13 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 "handle.h"
#include "buff.h"
#include "bytearray.h"
#include "debug.h"
#include "crc.h"
#include "prot_mcu.h"
#include "mymisc.h"
/**
*
* 批检仪
* BUS1(UART5)->slave 1,2,3,4
* BUS2(UART2)->slave 5,6,7,8
* BUS3(UART3)->slave 9,10,11,12
* BUS4(UART6)->slave 13,14,15,16
* BUS5(UART1)->slave 17,18,19,20
*
* 注码仪
* UART5->1,2,3,4
* UART2->5,6,7,8
* UAER3->9,10
*
**/
#define PORT_MUN 5
typedef struct{
int init;
protm_def *protm[PORT_MUN];
}self_def;
static self_def g_self;
struct _port_mcu{
protm_def *protm;
rt_timer_t timer;
int busy;
uint8_t addr;
handle_def *handle;
};
int port_init(void)
{
self_def *s=&g_self;
if(s->init==0){
s->protm[0]=protm_creat(dev_get("uart5"),(int []){1,2,3,4},4);
s->protm[1]=protm_creat(dev_get("uart2"),(int []){5,6,7,8},4);
s->protm[2]=protm_creat(dev_get("uart3"),(int []){9,10,11,12},4);
s->protm[3]=protm_creat(dev_get("uart6"),(int []){13,14,15,16},4);
s->protm[4]=protm_creat(dev_get("uart1"),(int []){17,18,19,20},4);
s->init=1;
}
return 0;
}
port_mcu *port_creat(uint8_t addr,sig_thread t)
{
self_def *s=&g_self;
if(s->init==0){
DBG_WARN("port not init.");
return 0;
}
port_mcu *p=calloc(1,sizeof(port_mcu));
param_check(p);
p->addr=addr;
for(int i=0;i<PORT_MUN;i++)
{
if(protm_contains(s->protm[i],addr))
{
p->protm=s->protm[i];
connect(p,port_send_signal,t,p->protm,protm_send_call);
connect(p->protm,protm_recv_signal,t,p,port_recv_call);
break;
}
}
return p;
}
void port_delete(port_mcu **p)
{
param_check(p);
param_check(*p);
disconnect_sig(*p);
CHECK_DO((*p)->timer,rt_timer_delete);
CHECK_DO((*p)->handle,(*p)->handle->del);
free(*p);
*p=0;
}
void port_recv_call(port_mcu *obj,uint8_t src,uint8_t cmd,array_def *data,char *err_str)
{
port_mcu *p=obj;
if(src==p->addr)
{
//DBG_LOG("addr=%d,cmd=%d,data=%s.",src,cmd,str_temp(arr_string(data)));
if(p->handle){
p->handle->dolater(p->handle,src,cmd,data,err_str);
}
else{
emit port_end_signal(obj,obj,0,0,"success");
}
}
// else{
// DBG_WARN("err data,addr=%d.",src);
// }
}
static void port_timeout_cb(void *t)
{
port_mcu *p=t;
if(p->handle)
p->handle->timeout(p->handle);
}
// 开始定时器,重复调用会重新开始
void port_timer_start(port_mcu *p)
{
param_check(p);
CHECK_DO(p->timer,rt_timer_start);
}
// 停止定时器
void port_timer_stop(port_mcu *p)
{
param_check(p);
CHECK_DO(p->timer,rt_timer_stop);
}
// 设置忙状态
void port_set_busy(port_mcu *p,int busy)
{
param_check(p);
p->busy=busy?1:0;
}
// 获取忙状态
int port_get_busy(port_mcu *p)
{
param_check(p);
return p->busy;
}
// 获取通信地址
uint8_t port_get_addr(port_mcu *p)
{
return p->addr;
}
// 开始一个通信操作h是此项操作的类
int port_start(port_mcu *p,handle_def *h)
{
param_check(p);
param_check(h);
if(port_get_busy(p)==1){
h->del(h);
DBG_WARN("slave:%d, handle is busy:%s",p->addr, p->handle->name);
return -1;
}
CHECK_DO(p->handle,p->handle->del);
p->handle=h;
p->handle->p=p;
if(p->timer==0)
{
char s1[16]={0};
sprintf(s1,"port_t#%d",p->addr);
p->timer=rt_timer_create(s1,port_timeout_cb,p,
rt_tick_from_millisecond(h->interval),
RT_TIMER_FLAG_PERIODIC|RT_TIMER_FLAG_SOFT_TIMER);
}
else{
rt_tick_t tick=rt_tick_from_millisecond(h->interval);
rt_timer_control(p->timer,RT_TIMER_CTRL_SET_TIME,&tick);
}
rt_timer_start(p->timer);
p->handle->start(p->handle);
return 0;
}
#define MCU_APP_ADDR_BASE 0x8002400
#define MCU_TASKID_ADDR_BASE 0x800f400
typedef struct{
handle_def h;
const uint8_t *data;// 外部地址指针,不需要释放
int size;
int stat;
int sent;
int retry_time;//升级失败重试次数
rt_timer_t timer;// 用于发送命令超时
}updata_def;
static void updata_del(handle_def *h)
{
updata_def *c=(updata_def *)h;
CHECK_DO(c->timer,rt_timer_delete);
free(h);
}
static void updata_start(handle_def *h)
{
updata_def *c=(updata_def *)h;
port_set_busy(h->p,1);
c->stat=1;
c->sent=0;
list_def *l=list_creat_int();
int arr[]={0xf9};
list_appends(l,arr,1);
emit port_send_signal(h->p,((port_mcu *)h->p)->addr,0xf9,list_temp(l),arr_temp(arr_creat()),60,1);
}
// 跳转到bootloader之后需要延时一段时间发送擦除命令
static void updata_earse(void *t)
{
handle_def *h=t;
list_def *l=list_creat_int();
int arr[]={0xfe};
list_appends(l,arr,1);
emit port_send_signal(h->p,((port_mcu *)h->p)->addr,0xfe,list_temp(l),arr_temp(arr_creat()),5500,1);
}
static void updata_dolater(handle_def *h,uint8_t src,uint8_t cmd,array_def *data,char *err_str)
{
updata_def *c=(updata_def *)h;
if(port_get_busy(h->p)==0) return;
port_timer_start(h->p);
if(c->stat==1){
if((arr_length(data)>=2)&&(1==arr_get(data,1)))
{
// 这是重试的流程如果重试时在app状态则升级成功
if(c->retry_time>0){
DBG_LOG("slave:%d mcu updata success.",src);
emit port_end_signal(h->p,h->p,0,0,"ok");
port_set_busy(h->p,0);
port_timer_stop(h->p);
return ;
}
// 如果设备不在bootloader进入这一步
c->stat=2;
DBG_LOG("slave:%d mcu in app mode.",src);
// 设备跳转后不响应此命令,只重发一次
list_def *l=list_creat_int();
int arr[]={0xf8};
list_appends(l,arr,1);
emit port_send_signal(h->p,((port_mcu *)h->p)->addr,0xf8,list_temp(l),arr_temp(arr_creat()),60,3);
}else{
// 都在bootloader模式直接进入下一步
c->stat=3;
DBG_LOG("slave:%d mcu in bootloader mode.",src);
updata_earse(h);
}
}else if(c->stat==2){
c->stat=3;
DBG_LOG("slave:%d mcu turn in bootloader mode.",src);
later_execute(updata_earse,h,1000);
}else if(c->stat==3){
if(c->sent<c->size)
{
int len=c->sent<c->size-240?240:c->size-c->sent;
uint32_t addr=MCU_APP_ADDR_BASE+c->sent;
array_def *temp=arr_creat();
arr_append(temp,addr&0xff);
arr_append(temp,(addr>>8)&0xff);
arr_append(temp,(addr>>16)&0xff);
arr_append(temp,(addr>>24)&0xff);
arr_appends(temp,&c->data[c->sent],len);
c->sent+=len;
list_def *l=list_creat_int();
int arr[]={0xfc};
list_appends(l,arr,1);
emit port_send_signal(h->p,((port_mcu *)h->p)->addr,0xfc,list_temp(l),arr_temp(temp),350,10);
//DBG_LOG("slave addr=%d,rate=%d.",h->p->addr,c->sent*100/c->size);
}else{
c->stat=4;
uint32_t addr;
array_def *temp=arr_creat();
addr=MCU_APP_ADDR_BASE;
arr_append(temp,addr&0xff);
arr_append(temp,(addr>>8)&0xff);
arr_append(temp,(addr>>16)&0xff);
arr_append(temp,(addr>>24)&0xff);
addr=MCU_APP_ADDR_BASE+c->size;
arr_append(temp,addr&0xff);
arr_append(temp,(addr>>8)&0xff);
arr_append(temp,(addr>>16)&0xff);
arr_append(temp,(addr>>24)&0xff);
uint32_t crc=crc_crc32(c->data,c->size);
arr_append(temp,crc&0xff);
arr_append(temp,(crc>>8)&0xff);
arr_append(temp,(crc>>16)&0xff);
arr_append(temp,(crc>>24)&0xff);
//DBG_LOG("updata:crc=%08x",crc);
list_def *l=list_creat_int();
int arr[]={0xfb};
list_appends(l,arr,1);
emit port_send_signal(h->p,((port_mcu *)h->p)->addr,0xfb,list_temp(l),arr_temp(temp),350,10);
DBG_LOG("slave:%d file updata done.",src);
}
}
else if(c->stat==4)
{
DBG_LOG("slave:%d mcu reboot to app.",src);
emit port_end_signal(h->p,h->p,0,0,"ok");
port_set_busy(h->p,0);
port_timer_stop(h->p);
}
}
static void updata_timeout(handle_def *h)
{
updata_def *c=(updata_def *)h;
// 从机没有指定数目时从这里返回
DBG_WARN("slave:%d,%s timeout.",h->p->addr, h->name);
if(c->retry_time>3)
{
port_timer_stop(h->p);
port_set_busy(h->p,0);
DBG_WARN("slave:%d,%s failed.",h->p->addr, h->name);
emit port_end_signal(h->p,h->p,0,-1,"timeout");
}else{
port_timer_start(h->p);
DBG_LOG("slave:%d, updata retry",h->p->addr);
h->start(h);
c->retry_time++;
}
}
handle_def *updata_creat(const uint8_t *data,int size)
{
updata_def *c=calloc(1,sizeof(updata_def));
handle_def *h=(handle_def *)c;
param_check(h);
h->static_=0;// 动态内存这项设置为0
h->start=updata_start;
h->dolater=updata_dolater;
h->del=updata_del;
h->timeout=updata_timeout;
h->interval=15000;// 此项根据方案调整
h->name="updata";
c->data=data;
c->size=size;
return h;
}
typedef struct{
handle_def h;
const uint8_t *data;// 外部地址指针,不需要释放
int size;
int stat;
int sent;
int retry_time;//升级失败重试次数
rt_timer_t timer;// 用于发送命令超时
}updata_scheme_def;
static void updata_scheme_del(handle_def *h)
{
updata_scheme_def *c=(updata_scheme_def *)h;
CHECK_DO(c->timer,rt_timer_delete);
free(h);
}
static void updata_scheme_send_packet(handle_def *h)
{
updata_scheme_def *c=(updata_scheme_def *)h;
if(port_get_busy(h->p)==0) return;
port_timer_start(h->p);
if(c->stat==1){
if(c->sent<c->size)
{
int len=c->sent<c->size-240?240:c->size-c->sent;
uint32_t addr=MCU_TASKID_ADDR_BASE+c->sent;
array_def *temp=arr_creat();
arr_append(temp,addr&0xff);
arr_append(temp,(addr>>8)&0xff);
arr_append(temp,(addr>>16)&0xff);
arr_append(temp,(addr>>24)&0xff);
arr_appends(temp,&c->data[c->sent],len);
c->sent+=len;
list_def *l=list_creat_int();
int arr[]={0x11};
list_appends(l,arr,1);
emit port_send_signal(h->p,((port_mcu *)h->p)->addr,0x11,list_temp(l),arr_temp(temp),350,10);
//DBG_LOG("slave addr=%d,rate=%d.",h->p->addr,c->sent*100/c->size);
}else{
c->stat=0;
uint32_t addr;
array_def *temp=arr_creat();
list_def *l=list_creat_int();
int arr[]={0x15};
list_appends(l,arr,1);
emit port_send_signal(h->p,((port_mcu *)h->p)->addr,0x15,list_temp(l),arr_temp(temp),350,10);
DBG_LOG("slave:%d mcu reboot .",h->p->addr);
emit port_end_signal(h->p,h->p,0,0,"ok");
port_set_busy(h->p,0);
port_timer_stop(h->p);
}
}
}
static void updata_scheme_dolater(handle_def *h,uint8_t src,uint8_t cmd,array_def *data,char *err_str)
{
updata_scheme_send_packet(h);
}
static void updata_scheme_start(handle_def *h)
{
updata_scheme_def *c=(updata_scheme_def *)h;
port_set_busy(h->p,1);
c->stat=1;
c->sent=0;
updata_scheme_send_packet(h);
}
static void updata_scheme_timeout(handle_def *h)
{
updata_scheme_def *c=(updata_scheme_def *)h;
// 从机没有指定数目时从这里返回
DBG_WARN("slave:%d,%s timeout.",h->p->addr, h->name);
if(c->retry_time>3)
{
port_timer_stop(h->p);
port_set_busy(h->p,0);
DBG_WARN("slave:%d,%s failed.",h->p->addr, h->name);
emit port_end_signal(h->p,h->p,0,-1,"timeout");
}else{
port_timer_start(h->p);
DBG_LOG("slave:%d, updata retry",h->p->addr);
h->start(h);
c->retry_time++;
}
}
handle_def *updata_scheme_creat(const uint8_t *data,int size)
{
updata_scheme_def *c=calloc(1,sizeof(updata_scheme_def));
handle_def *h=(handle_def *)c;
param_check(h);
h->static_=0;// 动态内存这项设置为0
h->start=updata_scheme_start;
h->dolater=updata_scheme_dolater;
h->del=updata_scheme_del;
h->timeout=updata_scheme_timeout;
h->interval=15000;// 此项根据方案调整
h->name="updata_scheme";
c->data=data;
c->size=size;
return h;
}
typedef struct{
handle_def h;
int data_length;
uint8_t cmd;
uint8_t data[0];
}usercmd_def;
static void usercmd_start(handle_def *h)
{
usercmd_def *u=(usercmd_def *)h;
port_set_busy(h->p,1);
list_def *l=list_creat_int();
int arr[]={u->cmd};
list_appends(l,arr,1);
emit port_send_signal(h->p,port_get_addr(h->p),u->cmd,list_temp(l),arr_temp(arr_creat()),300,3);
}
static void usercmd_dolater(handle_def *h,uint8_t src,uint8_t cmd,array_def *data,char *err_str)
{
usercmd_def *c=(usercmd_def *)h;
if(port_get_busy(h->p)==0) return;
if(cmd==c->cmd)
{
port_set_busy(h->p,0);
port_timer_stop(h->p);
DBG_LOG("slave:%d, userdata:%s",src,str_temp(arr_string(data)));
// 直接返回原始数据
emit port_end_signal(h->p,h->p,data,0,"ok");
}else
{
port_set_busy(h->p,0);
port_timer_stop(h->p);
DBG_WARN("slave:%d,get usercmd err,%s",src,str_temp(arr_string(data)));
emit port_end_signal(h->p,h->p,0,-1,"get usercmd err");
}
}
static void usercmd_timeout(handle_def *h)
{
// 从机没有指定数目时从这里返回
port_timer_stop(h->p);
port_set_busy(h->p,0);
DBG_WARN("slave:%d,%s timeout.",port_get_addr(h->p), h->name);
emit port_end_signal(h->p,h->p,0,-1,"timeout");
}
static void usercmd_del(handle_def *h)
{
usercmd_def *c=(usercmd_def *)h;
free(h);
}
handle_def *usercmd_creat(uint8_t cmd,array_def *data)
{
int data_len=arr_length(data);
usercmd_def *c=calloc(1,sizeof(usercmd_def)+data_len);
c->cmd=cmd;
c->data_length=data_len;
for(int i=0;i<data_len;i++){c->data[i]=arr_get(data,i);}
handle_def *h=(handle_def *)c;
param_check(h);
h->static_=0;// 动态内存这项设置为0
h->start=usercmd_start;
h->dolater=usercmd_dolater;
h->del=usercmd_del;
h->timeout=usercmd_timeout;
h->interval=5000;
h->name="usercmd";
return h;
}