#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/uart.h>
#include "GVL.h"
#define LOG_MODULE_NAME rs485_thread
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
// 获取设备树节点
#define ZEPHYR_USER_NODE DT_PATH(zephyr_user)
// 声明设备
static const struct device *const rs485_uart = DEVICE_DT_GET(DT_ALIAS(myuart));
static const struct gpio_dt_spec direct_pin = GPIO_DT_SPEC_GET(ZEPHYR_USER_NODE, rs485_gpios);
// 延时工作
static struct k_work_delayable uart_work;
// RS485接收状态机
enum rx_state {
STATE_IDLE,
STATE_GOT_AA,
STATE_RECEIVING
};
static struct {
enum rx_state state;
uint8_t buffer[sizeof(rs485_raw_data_t) + 3]; // AA + BB + payload + CRC
size_t index;
} rx_state_machine;
static struct k_spinlock data_spinlock;
// CRC校验函数
static uint8_t calculate_crc(const uint8_t *data, size_t len)
{
uint8_t crc = 0;
for (size_t i = 0; i < len; i++) {
crc ^= data[i];
}
return crc;
}
// 统一数据结构处理
static void process_rs485_packet(uint8_t *packet, size_t len)
{
// CRC校验 (最后1字节是CRC)
if (calculate_crc(packet, len - 1) != packet[len - 1]) {
LOG_WRN("Invalid RS485 packet CRC");
return;
}
// 解析原始RS485数据
rs485_raw_data_t raw_data;
memcpy(&raw_data, packet + 2, sizeof(raw_data)); // 跳过包头
// 转换为统一数据结构
unified_data_point_t data_point = {
.timestamp = k_uptime_get_32(),
.acc_x = raw_data.acc_x,
.acc_y = raw_data.acc_y,
.acc_z = raw_data.acc_z,
.gyro_x = raw_data.gyro_x,
.gyro_y = raw_data.gyro_y,
.gyro_z = raw_data.gyro_z,
.data_source = 2 // 标记为RS485设备数据
};
// 添加到批处理
k_spinlock_key_t key = k_spin_lock(&batch_lock);
batch_container_t *batch = &data_batches[active_batch_index];
if (batch->count < BATCH_SIZE) {
batch->data[batch->count++] = data_point;
// 批次满或超时处理
if (batch->count >= BATCH_SIZE ||
(batch->count > 0 && (k_uptime_get() - batch->start_timestamp) > MAX_BATCH_TIMEOUT_MS)) {
batch->ready = true;
batch->start_timestamp = k_uptime_get();
// 切换到备用缓冲区
active_batch_index = (active_batch_index + 1) % 2;
data_batches[active_batch_index].count = 0;
data_batches[active_batch_index].ready = false;
// 通知BLE线程
k_sem_give(&ble_data_ready_sem);
}
} else {
LOG_WRN("Batch buffer overflow");
}
k_spin_unlock(&batch_lock, key);
}
static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{
static size_t aborted_len;
struct uart_data_t *buf;
static uint8_t *aborted_buf;
static bool disable_req;
k_spinlock_key_t key;
switch (evt->type) {
case UART_TX_DONE:
LOG_DBG("UART_TX_DONE");
// 设置方向为接收模式
gpio_pin_set_dt(&direct_pin, 0);
if ((evt->data.tx.len == 0) || (!evt->data.tx.buf)) {
return;
}
if (aborted_buf) {
buf = CONTAINER_OF(aborted_buf, struct uart_data_t, data[0]);
aborted_buf = NULL;
aborted_len = 0;
k_free(buf);
} else {
buf = CONTAINER_OF(evt->data.tx.buf, struct uart_data_t, data[0]);
k_free(buf);
}
// 发送下一个数据包
buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
if (buf) {
// 设置方向为发送模式
gpio_pin_set_dt(&direct_pin, 1);
k_busy_wait(RS485_DIR_PIN_DELAY_US);
if (uart_tx(rs485_uart, buf->data, buf->len, SYS_FOREVER_MS)) {
LOG_WRN("Failed to send data over UART");
gpio_pin_set_dt(&direct_pin, 0); // 确保切换回接收模式
k_free(buf);
}
}
break;
case UART_RX_RDY:
const uint8_t *data = evt->data.rx.buf;
size_t len = evt->data.rx.len;
for (size_t i = 0; i < len; i++) {
uint8_t byte = data[i];
switch (rx_state_machine.state) {
case STATE_IDLE:
if (byte == 0xAA) {
rx_state_machine.state = STATE_GOT_AA;
}
break;
case STATE_GOT_AA:
if (byte == 0xBB) {
rx_state_machine.state = STATE_RECEIVING;
rx_state_machine.index = 0;
rx_state_machine.buffer[rx_state_machine.index++] = 0xAA;
rx_state_machine.buffer[rx_state_machine.index++] = 0xBB;
} else {
rx_state_machine.state = (byte == 0xAA) ? STATE_GOT_AA : STATE_IDLE;
}
break;
case STATE_RECEIVING:
rx_state_machine.buffer[rx_state_machine.index++] = byte;
// 检查完整数据包 (AA + BB + payload + CRC)
if (rx_state_machine.index >= sizeof(rx_state_machine.buffer)) {
process_rs485_packet(rx_state_machine.buffer, rx_state_machine.index);
rx_state_machine.state = STATE_IDLE;
}
break;
}
}
break;
case UART_RX_DISABLED:
LOG_DBG("UART_RX_DISABLED");
disable_req = false;
buf = k_malloc(sizeof(*buf));
if (buf) {
buf->len = 0;
uart_rx_enable(rs485_uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT_MS);
} else {
LOG_WRN("Not able to allocate UART receive buffer");
k_work_reschedule(&uart_work, K_MSEC(UART_WAIT_FOR_RX));
}
break;
case UART_RX_BUF_REQUEST:
LOG_DBG("UART_RX_BUF_REQUEST");
buf = k_malloc(sizeof(*buf));
if (buf) {
buf->len = 0;
uart_rx_buf_rsp(rs485_uart, buf->data, sizeof(buf->data));
} else {
LOG_WRN("Not able to allocate UART receive buffer");
}
break;
case UART_RX_BUF_RELEASED:
LOG_DBG("UART_RX_BUF_RELEASED");
buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t, data[0]);
k_free(buf);
break;
case UART_TX_ABORTED:
LOG_DBG("UART_TX_ABORTED");
gpio_pin_set_dt(&direct_pin, 0); // 确保切换回接收模式
if (!aborted_buf) {
aborted_buf = (uint8_t *)evt->data.tx.buf;
aborted_len = evt->data.tx.len;
}
struct uart_data_t *tx_buf = CONTAINER_OF(aborted_buf, struct uart_data_t, data);
size_t remaining = tx_buf->len - aborted_len;
if (remaining > 0) {
gpio_pin_set_dt(&direct_pin, 1);
k_busy_wait(RS485_DIR_PIN_DELAY_US);
uart_tx(rs485_uart, &tx_buf->data[aborted_len], remaining, SYS_FOREVER_MS);
}
break;
default:
break;
}
}
static void uart_work_handler(struct k_work *item)
{
struct uart_data_t *buf = k_malloc(sizeof(*buf));
if (buf) {
buf->len = 0;
uart_rx_enable(rs485_uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT_MS);
} else {
LOG_WRN("Not able to allocate UART receive buffer");
k_work_reschedule(&uart_work, K_MSEC(UART_WAIT_FOR_RX));
}
}
static int rs485_init(void)
{
int err;
if (!device_is_ready(rs485_uart)) {
LOG_ERR("UART device not ready");
return -ENODEV;
}
// 初始化方向控制引脚
if (!device_is_ready(direct_pin.port)) {
LOG_ERR("GPIO device not ready");
return -ENODEV;
}
err = gpio_pin_configure_dt(&direct_pin, GPIO_OUTPUT_INACTIVE);
if (err) {
LOG_ERR("GPIO config error: %d", err);
return err;
}
// 初始化引脚为接收
gpio_pin_set_dt(&direct_pin, 0);
// 初始化接收状态机
rx_state_machine.state = STATE_IDLE;
rx_state_machine.index = 0;
// 初始化UART
k_work_init_delayable(&uart_work, uart_work_handler);
err = uart_callback_set(rs485_uart, uart_cb, NULL);
if (err) {
LOG_ERR("Cannot set UART callback: %d", err);
return err;
}
// 启动接收
k_work_schedule(&uart_work, K_NO_WAIT);
return 0;
}
void rs485_send(const uint8_t *data, size_t len)
{
struct uart_data_t *tx = k_malloc(sizeof(*tx) + len);
if (!tx) {
LOG_ERR("Not enough memory for UART send");
return;
}
memcpy(tx->data, data, len);
tx->len = len;
// 如果发送队列为空,直接发送,否则加入队列
if (k_fifo_is_empty(&fifo_uart_tx_data)) {
// 设置方向为发送模式
gpio_pin_set_dt(&direct_pin, 1);
k_busy_wait(RS485_DIR_PIN_DELAY_US);
if (uart_tx(rs485_uart, tx->data, tx->len, SYS_FOREVER_MS)) {
LOG_WRN("Failed to start UART send");
gpio_pin_set_dt(&direct_pin, 0); // 切换回接收模式
k_free(tx);
}
} else {
k_fifo_put(&fifo_uart_tx_data, tx);
}
}
void rs485_thread(void)
{
if (rs485_init() != 0) {
LOG_ERR("RS485 initialization failed");
return;
}
LOG_INF("RS485 thread started");
// 初始化自旋锁
k_spinlock_init(&data_spinlock);
// 线程主循环
while (1) {
k_sleep(K_FOREVER);
}
}
K_THREAD_DEFINE(rs485_thread_id, 2048, rs485_thread, NULL, NULL, NULL, 5, 0, 0);