update: 增加帧尾

This commit is contained in:
2025-02-19 21:54:47 +08:00
parent c242c118f2
commit 33b804785b

View File

@@ -1,6 +1,5 @@
#define PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@@ -11,35 +10,34 @@
#include <pthread.h> // 引入 pthread 库 #include <pthread.h> // 引入 pthread 库
// 宏定义 // 宏定义
// #define USE_FEC
#ifdef USE_FEC #ifdef USE_FEC
#define FEC_SIZE 32 // 前向纠错冗余数据大小 #define FEC_SIZE 32 // 前向纠错冗余数据大小
#else #else
#define FEC_SIZE 0 // 前向纠错冗余数据大小 #define FEC_SIZE 0 // 前向纠错冗余数据大小
#endif #endif
#define FRAME_HEADER 0xAA55 // 帧头 #define FRAME_HEADER 0xAA55 // 帧头
#define FRAME_TAIL 0x0D7E // 帧尾
#define FRAME_SIZE (240) // 每帧大小 #define FRAME_SIZE (240) // 每帧大小
#define HEADER_SIZE (4) // 帧头 + 帧序号 + 数据长度 #define HEADER_SIZE (4) // 帧头 + 帧序号 + 数据长度
#define TAIL_SIZE (2) // 帧尾
#define CHECKSUM_SIZE (4) // CRC32 校验和大小4 字节) #define CHECKSUM_SIZE (4) // CRC32 校验和大小4 字节)
#define DATA_SIZE (FRAME_SIZE - HEADER_SIZE - CHECKSUM_SIZE - FEC_SIZE) // 数据段大小 #define DATA_SIZE (FRAME_SIZE - HEADER_SIZE - CHECKSUM_SIZE - FEC_SIZE - TAIL_SIZE) // 数据段大小
#define RING_BUFFER_SIZE (1024 * 10) // 环形缓冲区大小 - default 10KB #define RING_BUFFER_SIZE (1024 * 10) // 环形缓冲区大小 - default 10KB
#define QUEUE_MAX_SIZE 1024 // 队列最大容量 #define QUEUE_MAX_SIZE 1024 // 队列最大容量
// 全局变量 // 全局变量
static by_serial_t serial_port; static by_serial_t serial_port;
static by_ringbuf_t ring_buffer; static by_ringbuf_t ring_buffer;
static uint8_t send_buffer[FRAME_SIZE]; static unsigned char send_buffer[FRAME_SIZE];
static uint8_t frame_counter = 0; static unsigned char frame_counter = 0;
static uint8_t data_len = 0; static unsigned char data_len = 0;
unsigned char output_data[8192];
uint8_t output_data[8192];
static int output_len = 0; static int output_len = 0;
// 定义队列结构体 // 定义队列结构体
typedef struct typedef struct
{ {
uint8_t *data; unsigned char *data;
int length; int length;
} FrameData; } FrameData;
@@ -48,71 +46,82 @@ static FrameData frame_queue[QUEUE_MAX_SIZE]; // 存储接收
static int queue_head = 0; // 队列头指针 static int queue_head = 0; // 队列头指针
static int queue_tail = 0; // 队列尾指针 static int queue_tail = 0; // 队列尾指针
static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER; // 保护队列的互斥锁 static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER; // 保护队列的互斥锁
static bool stop_receiving = false; // 控制接收线程停止的标志 static int stop_receiving = false; // 控制接收线程停止的标志
// 前向声明 // 前向声明
void *receive_thread_func(void *arg); void *receive_thread_func(void *arg);
// 计算 CRC32 校验和 // 计算 CRC32 校验和
uint32_t calculate_crc32(const uint8_t *data, size_t length) unsigned long calculate_crc32(const unsigned char *data, size_t length)
{ {
return crc32(0, data, length); return crc32(0, data, length);
} }
// 解析一帧数据 // 解析一帧数据
int parse_frame(by_ringbuf_t *ringbuf, uint8_t *output_data, int *output_len) int parse_frame(by_ringbuf_t *ringbuf, unsigned char *output_data, int *output_len)
{ {
uint8_t frame[FRAME_SIZE]; unsigned char frame[FRAME_SIZE];
unsigned char buffer[FRAME_SIZE * 3];
int available_data = by_ringbuf_available_data(ringbuf); int available_data = by_ringbuf_available_data(ringbuf);
while (by_ringbuf_available_data(ringbuf) < FRAME_SIZE)
{
int ret = by_serial_read(&serial_port, buffer, FRAME_SIZE);
if (ret > 0)
{
by_ringbuf_append(&ring_buffer, buffer, ret);
}
}
// TODO 有无必要
// 检查是否有足够的数据解析一帧 // 检查是否有足够的数据解析一帧
if (available_data < HEADER_SIZE + CHECKSUM_SIZE + FEC_SIZE) if (available_data < FRAME_SIZE)
{ {
return -1; // 数据不足,无法解析 return -1; // 数据不足,无法解析
} }
// 查找帧头 // 查找帧头
uint16_t header = FRAME_HEADER; unsigned short header = FRAME_HEADER;
int header_pos = by_ringbuf_find(ringbuf, (uint8_t *)&header, 2); unsigned short tail = FRAME_TAIL;
int header_pos = by_ringbuf_find(ringbuf, (unsigned char *)&header, 2);
if (header_pos < 0) if (header_pos < 0)
{ {
return -1; // 没有找到帧头 return -1; // 没有找到帧头
} }
// 弹出帧头之前的数据 // 弹出帧头之前的数据
by_ringbuf_pop(ringbuf, frame, header_pos); by_ringbuf_pop(ringbuf, frame, header_pos);
// 检查是否有足够的数据解析一帧 // 检查是否有足够的数据解析一帧
if (by_ringbuf_available_data(ringbuf) < FRAME_SIZE) if (by_ringbuf_available_data(ringbuf) < FRAME_SIZE)
{ {
return -1; // 数据不足,无法解析 return -1; // 数据不足,无法解析
} }
// 读取帧数据 // 读取帧数据
by_ringbuf_pop(ringbuf, frame, FRAME_SIZE); by_ringbuf_pop(ringbuf, frame, HEADER_SIZE);
int tail_pos = by_ringbuf_find(ringbuf, (unsigned char *)&tail, 2);
if (tail_pos < FRAME_SIZE - HEADER_SIZE - TAIL_SIZE - 1)
{
printf(" fail, next frame header pos: %d\n", header_pos);
return -2; // 下一帧帧头小于 FRAME_SIZE丢弃该帧
}
else
{
by_ringbuf_pop(ringbuf, frame + HEADER_SIZE, tail_pos + TAIL_SIZE);
}
// 解析帧序号、有效数据长度、数据段和 CRC32 // 解析帧序号、有效数据长度、数据段和 CRC32
uint8_t seq = frame[2]; unsigned char seq = frame[2];
uint8_t valid_data_len = frame[2 + 1]; unsigned char valid_data_len = frame[2 + 1];
uint8_t *data_segment = &frame[2 + 1 + 1]; unsigned char *data_segment = &frame[2 + 1 + 1];
uint32_t received_crc = *(uint32_t *)&frame[2 + 1 + 1 + DATA_SIZE]; unsigned int received_crc = *(unsigned long *)&frame[HEADER_SIZE + DATA_SIZE];
// 计算 CRC32 校验 // 计算 CRC32 校验
uint32_t calculated_crc = calculate_crc32(frame, HEADER_SIZE + DATA_SIZE + FEC_SIZE); unsigned int calculated_crc = calculate_crc32(frame, HEADER_SIZE + DATA_SIZE + FEC_SIZE);
if (received_crc != calculated_crc) if (received_crc != calculated_crc)
{ {
printf("CRC mismatch! Expected: %08X, Received: %08X\n", calculated_crc, received_crc); printf("CRC mismatch! Expected: %08X, Received: %08X\n", calculated_crc, received_crc);
return -1; // CRC 校验失败,丢弃该帧 return -2; // CRC 校验失败,丢弃该帧,严重错误
} }
// 将有效数据拼接到输出缓冲区 // 将有效数据拼接到输出缓冲区
memcpy(&output_data[*output_len], data_segment, valid_data_len); memcpy(&output_data[*output_len], data_segment, valid_data_len);
*output_len += valid_data_len; *output_len += valid_data_len;
printf("output len: %d\n", *output_len); printf("output len: %d\n", *output_len);
printf("Received frame: seq=%d, len=%d\r\n", seq, valid_data_len); printf("Received frame: seq=%d, len=%d\r\n", seq, valid_data_len);
// 判断是否为最后一帧 // 判断是否为最后一帧
if (valid_data_len < DATA_SIZE) if (valid_data_len < DATA_SIZE)
{ {
@@ -125,19 +134,8 @@ int parse_frame(by_ringbuf_t *ringbuf, uint8_t *output_data, int *output_len)
// 接收线程函数 // 接收线程函数
void *receive_thread_func(void *arg) void *receive_thread_func(void *arg)
{ {
while (!stop_receiving) while (!stop_receiving)
{ {
// 从串口读取数据到环形缓冲区
uint8_t buffer[FRAME_SIZE];
int ret = by_serial_read(&serial_port, buffer, FRAME_SIZE);
if (ret > 0)
{
by_ringbuf_append(&ring_buffer, buffer, ret);
}
// 尝试解析环形缓冲区中的数据
while (1) while (1)
{ {
int parse_result = parse_frame(&ring_buffer, output_data, &output_len); int parse_result = parse_frame(&ring_buffer, output_data, &output_len);
@@ -166,12 +164,12 @@ void *receive_thread_func(void *arg)
printf("Parsed data length: %d\n", output_len); printf("Parsed data length: %d\n", output_len);
break; // 数据不足或解析失败,退出循环 break; // 数据不足或解析失败,退出循环
} }
else if (parse_result == -1) else if (parse_result == -2)
{ {
output_len = 0;
break; // 数据不足或解析失败,退出循环 break; // 数据不足或解析失败,退出循环
} }
} }
usleep(1000); // 避免占用过多 CPU usleep(1000); // 避免占用过多 CPU
} }
return NULL; return NULL;
@@ -185,20 +183,17 @@ static PyObject *serial_init(PyObject *self, PyObject *args)
{ {
return NULL; return NULL;
} }
if (by_serial_init(&serial_port, dev_name) != 0) if (by_serial_init(&serial_port, dev_name) != 0)
{ {
PyErr_SetString(PyExc_IOError, "Failed to initialize serial port"); PyErr_SetString(PyExc_IOError, "Failed to initialize serial port");
return NULL; return NULL;
} }
// 初始化环形缓冲区 // 初始化环形缓冲区
if (by_ringbuf_init(&ring_buffer, RING_BUFFER_SIZE) != 0) if (by_ringbuf_init(&ring_buffer, RING_BUFFER_SIZE) != 0)
{ {
PyErr_SetString(PyExc_IOError, "Failed to initialize ring buffer"); PyErr_SetString(PyExc_IOError, "Failed to initialize ring buffer");
return NULL; return NULL;
} }
// 启动接收线程 // 启动接收线程
pthread_t receive_thread; pthread_t receive_thread;
stop_receiving = false; stop_receiving = false;
@@ -207,7 +202,6 @@ static PyObject *serial_init(PyObject *self, PyObject *args)
PyErr_SetString(PyExc_RuntimeError, "Failed to start receive thread"); PyErr_SetString(PyExc_RuntimeError, "Failed to start receive thread");
return NULL; return NULL;
} }
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@@ -220,16 +214,13 @@ static PyObject *serial_send(PyObject *self, PyObject *args)
{ {
return NULL; return NULL;
} }
size_t offset = 0; size_t offset = 0;
while (offset < length) while (offset < length)
{ {
memset(send_buffer, 0, FRAME_SIZE); memset(send_buffer, 0, FRAME_SIZE);
// 构造帧头 // 构造帧头
uint16_t header = FRAME_HEADER; unsigned short header = FRAME_HEADER;
memcpy(send_buffer, &header, 2); memcpy(send_buffer, &header, 2);
// 构造帧序号和数据长度 // 构造帧序号和数据长度
memcpy(send_buffer + 2, &frame_counter, 1); memcpy(send_buffer + 2, &frame_counter, 1);
if (length - offset > DATA_SIZE) if (length - offset > DATA_SIZE)
@@ -241,28 +232,24 @@ static PyObject *serial_send(PyObject *self, PyObject *args)
data_len = length - offset; data_len = length - offset;
} }
memcpy(send_buffer + 3, &data_len, 1); memcpy(send_buffer + 3, &data_len, 1);
// 拷贝该帧对应数据段 // 拷贝该帧对应数据段
memcpy(send_buffer + HEADER_SIZE, data + offset, data_len); memcpy(send_buffer + HEADER_SIZE, data + offset, data_len);
printf("Received frame: seq=%d, len=%d\r\n", frame_counter, data_len); printf("Received frame: seq=%d, len=%d\r\n", frame_counter, data_len);
// 计算 CRC32 校验和 // 计算 CRC32 校验和
uint32_t crc = calculate_crc32(send_buffer, HEADER_SIZE + DATA_SIZE + FEC_SIZE); unsigned long crc = calculate_crc32(send_buffer, HEADER_SIZE + DATA_SIZE + FEC_SIZE);
memcpy(send_buffer + HEADER_SIZE + DATA_SIZE + FEC_SIZE, &crc, CHECKSUM_SIZE); memcpy(send_buffer + HEADER_SIZE + DATA_SIZE + FEC_SIZE, &crc, CHECKSUM_SIZE);
unsigned short tail = FRAME_TAIL;
memcpy(send_buffer + HEADER_SIZE + DATA_SIZE + FEC_SIZE + CHECKSUM_SIZE, &tail, TAIL_SIZE);
// 发送帧 // 发送帧
if (by_serial_write(&serial_port, (const char *)send_buffer, FRAME_SIZE) != 0) if (by_serial_write(&serial_port, (const char *)send_buffer, FRAME_SIZE) != 0)
{ {
PyErr_SetString(PyExc_IOError, "Failed to send data over serial port"); PyErr_SetString(PyExc_IOError, "Failed to send data over serial port");
return NULL; return NULL;
} }
offset += DATA_SIZE; offset += DATA_SIZE;
frame_counter++; frame_counter++;
usleep(80000); usleep(80000);
} }
frame_counter = 0; frame_counter = 0;
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@@ -277,12 +264,10 @@ static PyObject *serial_receive(PyObject *self, PyObject *args)
PyErr_SetString(PyExc_IOError, "No data available in the queue"); PyErr_SetString(PyExc_IOError, "No data available in the queue");
return NULL; return NULL;
} }
// 获取队列中最早的数据包 // 获取队列中最早的数据包
FrameData frame = frame_queue[queue_head]; FrameData frame = frame_queue[queue_head];
queue_head = (queue_head + 1) % QUEUE_MAX_SIZE; queue_head = (queue_head + 1) % QUEUE_MAX_SIZE;
pthread_mutex_unlock(&queue_mutex); pthread_mutex_unlock(&queue_mutex);
// 返回解析后的数据 // 返回解析后的数据
PyObject *result = Py_BuildValue("y#", frame.data, frame.length); PyObject *result = Py_BuildValue("y#", frame.data, frame.length);
free(frame.data); // 释放内存 free(frame.data); // 释放内存