2025-09-09 18:16:48 +08:00
|
|
|
|
#include "resend_protl.h"
|
|
|
|
|
|
|
|
|
|
|
|
void resend_init(resend_device_t *resend_device, int (*send)(void* data, uint16_t len, int timeout), int (*recv)(void* data, uint16_t len, int timeout), int (*get_length )(void), void (*resend_user_parse)(void *resend_device))
|
|
|
|
|
|
{
|
|
|
|
|
|
resend_device->send = send;
|
|
|
|
|
|
resend_device->recv = recv;
|
|
|
|
|
|
resend_device->get_length = get_length;
|
|
|
|
|
|
resend_device->resend_user_parse = resend_user_parse;
|
|
|
|
|
|
|
|
|
|
|
|
resend_device->status.c_state = RESEND_IDLE;
|
|
|
|
|
|
|
|
|
|
|
|
resend_device->tx_frame.header_0 = RESEND_HEADER_0;
|
|
|
|
|
|
resend_device->tx_frame.header_1 = RESEND_HEADER_1;
|
|
|
|
|
|
resend_device->tx_frame.seq = 0;
|
|
|
|
|
|
resend_device->tx_frame.cmd = 0;
|
|
|
|
|
|
resend_device->tx_frame.retry_cnt = 0;
|
|
|
|
|
|
resend_device->tx_frame.len = 0;
|
|
|
|
|
|
resend_device->tx_frame.crc = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
void resend_set(resend_device_t *resend_device)
|
|
|
|
|
|
{
|
|
|
|
|
|
resend_device->tx_frame.seq = resend_device->rx_frame.seq;
|
|
|
|
|
|
}
|
|
|
|
|
|
int resend_encode(resend_device_t *resend_device, void *out, uint8_t cmd, void* data, uint16_t len)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(!out ) return -1;
|
|
|
|
|
|
uint8_t* c = (uint8_t*)out;
|
|
|
|
|
|
// header
|
|
|
|
|
|
c[0] = resend_device->tx_frame.header_0;
|
|
|
|
|
|
c[1] = resend_device->tx_frame.header_1;
|
|
|
|
|
|
// seq
|
|
|
|
|
|
if(cmd != RESEND_CMD_DATA && cmd != RESEND_CMD_ACK && resend_device->tx_frame.retry_cnt == 0)
|
|
|
|
|
|
resend_device->tx_frame.seq++;
|
|
|
|
|
|
|
|
|
|
|
|
c[2] = resend_device->tx_frame.seq;
|
|
|
|
|
|
// cmd
|
|
|
|
|
|
c[3] = resend_device->tx_frame.cmd = cmd;
|
|
|
|
|
|
// retry_cnt
|
|
|
|
|
|
c[4] = resend_device->tx_frame.retry_cnt;
|
|
|
|
|
|
// len big endian
|
2025-09-18 16:49:25 +08:00
|
|
|
|
c[5] = (uint8_t)((len) & 0xFF);
|
|
|
|
|
|
c[6] = (uint8_t)((len >> 8) & 0xFF);
|
2025-09-09 18:16:48 +08:00
|
|
|
|
// payload
|
|
|
|
|
|
if (len > 0 && data) memcpy(&c[7], data, len);
|
|
|
|
|
|
// compute crc over seq..payload (i.e. bytes p+1 .. p+5+len)
|
|
|
|
|
|
uint16_t crc = fmav_crc_calculate(&c[2], 5 + len);
|
2025-09-18 16:49:25 +08:00
|
|
|
|
c[7 + len] = (uint8_t)(crc & 0xFF);
|
|
|
|
|
|
c[7 + len + 1] = (uint8_t)((crc >> 8) & 0xFF);
|
2025-09-09 18:16:48 +08:00
|
|
|
|
|
|
|
|
|
|
return (int)(len + RESEND_MAX_PAYLOAD);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int resend_decode(resend_device_t *resend_device, uint8_t c)
|
|
|
|
|
|
{
|
|
|
|
|
|
static uint16_t frame_crc = 0;
|
|
|
|
|
|
switch(resend_device->status.c_state)
|
|
|
|
|
|
{
|
|
|
|
|
|
case RESEND_IDLE:
|
|
|
|
|
|
if (c == RESEND_HEADER_0) {
|
|
|
|
|
|
resend_device->status.c_state = RESEND_HDR;
|
|
|
|
|
|
}
|
|
|
|
|
|
else{
|
|
|
|
|
|
resend_device->status.c_state = RESEND_IDLE;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_HDR:
|
|
|
|
|
|
if (c == RESEND_HEADER_1) {
|
|
|
|
|
|
resend_device->status.c_state = RESEND_SEQ;
|
|
|
|
|
|
fmav_crc_init(&frame_crc);
|
|
|
|
|
|
}else{
|
|
|
|
|
|
resend_device->status.c_state = RESEND_IDLE;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_SEQ:
|
|
|
|
|
|
resend_device->rx_frame.seq = c;
|
|
|
|
|
|
fmav_crc_accumulate(&frame_crc, c);
|
|
|
|
|
|
resend_device->status.c_state = RESEND_CMD;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_CMD:
|
|
|
|
|
|
resend_device->rx_frame.cmd = c;
|
|
|
|
|
|
fmav_crc_accumulate(&frame_crc, c);
|
|
|
|
|
|
resend_device->status.c_state = RESEND_RETRY_CNT;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_RETRY_CNT:
|
|
|
|
|
|
resend_device->rx_frame.retry_cnt = c;
|
2025-09-10 14:09:03 +08:00
|
|
|
|
//超过最大允许重传次数
|
|
|
|
|
|
if(resend_device->rx_frame.retry_cnt > RESEND_MAX_RETRY_CNT)
|
|
|
|
|
|
resend_device->status.c_state = RESEND_IDLE;
|
2025-09-09 18:16:48 +08:00
|
|
|
|
fmav_crc_accumulate(&frame_crc, c);
|
|
|
|
|
|
resend_device->status.c_state = RESEND_LEN_1;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_LEN_1:
|
|
|
|
|
|
resend_device->rx_frame.len = 0;
|
2025-09-18 16:49:25 +08:00
|
|
|
|
resend_device->rx_frame.len |= c;
|
2025-09-09 18:16:48 +08:00
|
|
|
|
fmav_crc_accumulate(&frame_crc, c);
|
|
|
|
|
|
resend_device->status.c_state = RESEND_LEN_2;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_LEN_2:
|
2025-09-18 16:49:25 +08:00
|
|
|
|
resend_device->rx_frame.len |= (uint16_t)(c << 8);;
|
2025-09-09 18:16:48 +08:00
|
|
|
|
fmav_crc_accumulate(&frame_crc, c);
|
|
|
|
|
|
if(resend_device->rx_frame.len > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
resend_device->status.data_offset = 0;
|
|
|
|
|
|
resend_device->status.c_state = RESEND_DATA;
|
2025-09-10 14:09:03 +08:00
|
|
|
|
//超过允许的字节数
|
|
|
|
|
|
if(resend_device->rx_frame.len > RESEND_DATA_SIZE)
|
|
|
|
|
|
resend_device->status.c_state = RESEND_IDLE;
|
2025-09-09 18:16:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
resend_device->status.c_state = RESEND_CRC_1;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_DATA:
|
|
|
|
|
|
resend_device->rx_frame.payload[resend_device->status.data_offset ++] = c;
|
|
|
|
|
|
fmav_crc_accumulate(&frame_crc, c);
|
|
|
|
|
|
if(resend_device->rx_frame.len == resend_device->status.data_offset){
|
|
|
|
|
|
resend_device->status.data_offset = 0;
|
|
|
|
|
|
resend_device->status.c_state = RESEND_CRC_1;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_CRC_1:
|
2025-09-18 16:49:25 +08:00
|
|
|
|
if((uint8_t)(frame_crc) == c){
|
2025-09-09 18:16:48 +08:00
|
|
|
|
resend_device->status.c_state = RESEND_CRC_2;
|
|
|
|
|
|
}else{
|
|
|
|
|
|
resend_device->status.c_state = RESEND_IDLE;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_CRC_2:
|
2025-09-18 16:49:25 +08:00
|
|
|
|
if((uint8_t)(frame_crc >> 8 & 0xFF) == c){
|
2025-09-09 18:16:48 +08:00
|
|
|
|
resend_device->status.c_state = RESEND_IDLE;
|
|
|
|
|
|
resend_device->rx_frame.crc = frame_crc;
|
|
|
|
|
|
if(resend_device->rx_frame.cmd != RESEND_CMD_DATA && resend_device->rx_frame.cmd != RESEND_CMD_ACK && resend_device->rx_frame.retry_cnt == 0)
|
|
|
|
|
|
resend_device->tx_frame.seq++;
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}else{
|
|
|
|
|
|
resend_device->status.c_state = RESEND_IDLE;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int resend_recv_data(resend_device_t *resend_device, int timeout)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t data[RESEND_FRAME_SIZE];
|
|
|
|
|
|
int ret = resend_device->recv(data, RESEND_FRAME_SIZE, timeout);
|
|
|
|
|
|
if(ret <= 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
int ret_later = ret;
|
|
|
|
|
|
static uint8_t seq_lat = 0;
|
|
|
|
|
|
while(ret_later --)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(!resend_decode(resend_device, data[ret - ret_later - 1]))
|
|
|
|
|
|
{
|
|
|
|
|
|
printf("tx_req %d rx_req %d retry_cnt %d cmd %d\r\n", resend_device->tx_frame.seq, resend_device->rx_frame.seq, resend_device->rx_frame.retry_cnt, resend_device->rx_frame.cmd);
|
|
|
|
|
|
|
|
|
|
|
|
if(seq_lat == resend_device->rx_frame.seq){
|
|
|
|
|
|
resend_device->status.resend_flag = 1;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
resend_device->status.resend_flag = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
resend_device->resend_user_parse(resend_device);
|
|
|
|
|
|
resend_parse_data(resend_device);
|
|
|
|
|
|
|
|
|
|
|
|
seq_lat = resend_device->rx_frame.seq;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int resend_send_cmd(resend_device_t *resend_device, uint8_t cmd, int timeout)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t out[RESEND_MAX_PAYLOAD];
|
|
|
|
|
|
int ret = resend_encode(resend_device, out, cmd, NULL, 0);
|
|
|
|
|
|
if (ret <= 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
return resend_device->send(out, ret, timeout);
|
|
|
|
|
|
}
|
|
|
|
|
|
int resend_send_data(resend_device_t *resend_device, uint8_t cmd, void* data, uint16_t len, int timeout)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t out[RESEND_MAX_PAYLOAD + len];
|
|
|
|
|
|
memcpy(resend_device->tx_frame.payload, data, len);
|
|
|
|
|
|
|
|
|
|
|
|
resend_device->tx_frame.retry_cnt = 0;
|
|
|
|
|
|
|
|
|
|
|
|
int ret = resend_encode(resend_device, out, cmd, data, len);
|
|
|
|
|
|
if (ret <= 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
// 初始化ack应答标志位,需等待应答
|
|
|
|
|
|
resend_device->status.ack_flag = 1;
|
|
|
|
|
|
|
|
|
|
|
|
while(resend_device->status.ack_flag)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(resend_device->tx_frame.retry_cnt)
|
|
|
|
|
|
{
|
|
|
|
|
|
//进行重发 , 重新编码
|
|
|
|
|
|
ret = resend_encode(resend_device, out, cmd, data, len);
|
|
|
|
|
|
if (ret <= 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
printf("data retry cnt %d\n", resend_device->tx_frame.retry_cnt);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ret = resend_device->send(out, ret, 0);
|
|
|
|
|
|
if(ret < RESEND_MAX_PAYLOAD)
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
|
|
// 特殊命令以及应答信号不需要等待
|
|
|
|
|
|
if(cmd == RESEND_CMD_DATA || cmd == RESEND_CMD_ACK)
|
|
|
|
|
|
resend_device->status.ack_flag = 0;
|
|
|
|
|
|
|
|
|
|
|
|
resend_device->tx_frame.retry_cnt ++;
|
|
|
|
|
|
|
|
|
|
|
|
// 接收数据
|
|
|
|
|
|
resend_recv_data(resend_device, timeout);
|
|
|
|
|
|
// 超过允许的等待次数
|
|
|
|
|
|
if(resend_device->tx_frame.retry_cnt > RESEND_MAX_RETRY_CNT)
|
|
|
|
|
|
{
|
|
|
|
|
|
printf("timeout cnt max\n");
|
|
|
|
|
|
resend_device->tx_frame.retry_cnt = 0;
|
|
|
|
|
|
resend_device->status.ack_flag = 0;
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
// return resend_device->send(out, resend_frame_encode(resend_device, out, data, len), timeout);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int resend_parse_data(resend_device_t *resend_device)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch(resend_device->rx_frame.cmd){
|
|
|
|
|
|
case RESEND_CMD_DATA:
|
|
|
|
|
|
for (size_t i = 0; i < resend_device->rx_frame.len; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
printf("%02X ", resend_device->rx_frame.payload[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
printf("\r\n");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_CMD_ACK:
|
|
|
|
|
|
printf("ACK\n");
|
|
|
|
|
|
resend_device->status.ack_flag = 0;
|
|
|
|
|
|
break;
|
2025-09-18 16:49:25 +08:00
|
|
|
|
case RESEND_CMD_GET_STATUS:
|
|
|
|
|
|
resend_send_cmd(resend_device, RESEND_CMD_ACK, 0);
|
|
|
|
|
|
resend_device->handle_flag = RESEND_CMD_GET_STATUS;
|
|
|
|
|
|
break;
|
2025-09-09 18:16:48 +08:00
|
|
|
|
case RESEND_CMD_STATUS:
|
|
|
|
|
|
resend_set(resend_device);
|
|
|
|
|
|
resend_send_cmd(resend_device, RESEND_CMD_ACK, 0);
|
|
|
|
|
|
break;
|
2025-09-18 16:49:25 +08:00
|
|
|
|
case RESEND_CMD_SET_STATUS:
|
|
|
|
|
|
resend_send_cmd(resend_device, RESEND_CMD_ACK, 0);
|
|
|
|
|
|
break;
|
2025-09-09 18:16:48 +08:00
|
|
|
|
case RESEND_CMD_DATA_ACK:
|
|
|
|
|
|
for (size_t i = 0; i < resend_device->rx_frame.len; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
printf("%02X ", resend_device->rx_frame.payload[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
printf("\r\n");
|
|
|
|
|
|
resend_send_cmd(resend_device, RESEND_CMD_ACK, 0);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_CMD_OTA_START:
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_CMD_OTA_DATA:
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RESEND_CMD_OTA_END:
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|