|
@@ -0,0 +1,290 @@
|
|
|
+/*
|
|
|
+ * Copyright (c) 2025 Wingcool Technology Co., Ltd
|
|
|
+ *
|
|
|
+ * SPDX-License-Identifier: Apache-2.0
|
|
|
+ */
|
|
|
+#include <soc.h>
|
|
|
+#include <board.h>
|
|
|
+#include <device.h>
|
|
|
+#include <drivers/uart.h>
|
|
|
+#include <aem_core_if.h>
|
|
|
+#include <logging/log.h>
|
|
|
+//#include <gps/gps.h>
|
|
|
+
|
|
|
+LOG_MODULE_REGISTER(uart2_rec, LOG_LEVEL_INF);
|
|
|
+#define CONFIG_UART2_REC_DEV_NAME "uart2_rec"
|
|
|
+#define UART2_REC_DEV_NAME CONFIG_UART_2_NAME
|
|
|
+
|
|
|
+#define UART_FIFO_MAX 256
|
|
|
+#define REC_DATA_BUFFER_SIZE 256
|
|
|
+#define PRODUCT_INFO_SIZE 64
|
|
|
+#define WRITE_KEY_SIZE 160
|
|
|
+
|
|
|
+// 定义命令
|
|
|
+#define DEVICE_ID_CMD 0xB1
|
|
|
+#define PROJECT_ID_CMD 0xB2
|
|
|
+#define WRITE_KEY_CMD 0xB3
|
|
|
+#define IS_KEY_INSIDE_CMD 0xB4
|
|
|
+#define SET_TIME_CMD 0xC1
|
|
|
+// 定义帧头和帧尾
|
|
|
+#define FRAME_HEADER1 0xAA
|
|
|
+#define FRAME_HEADER2 0x55
|
|
|
+#define FRAME_TAIL1 0x55
|
|
|
+#define FRAME_TAIL2 0xAA
|
|
|
+
|
|
|
+struct uart2_rec_data {
|
|
|
+ const struct device *uart_gpio_dev;
|
|
|
+ uint8_t rec_data[REC_DATA_BUFFER_SIZE];
|
|
|
+ //gps_notify_t notify;
|
|
|
+};
|
|
|
+
|
|
|
+static struct uart2_rec_data uart2_rec_data;
|
|
|
+uint8_t bySetTimeStep = 0;
|
|
|
+
|
|
|
+extern uint8_t bySetHour;
|
|
|
+extern uint8_t bySetMinute;
|
|
|
+extern uint8_t bySetWeekday;
|
|
|
+extern uint16_t wSetYear;
|
|
|
+extern uint8_t bySetMonth;
|
|
|
+extern uint8_t bySetDay;
|
|
|
+
|
|
|
+extern void uart2_poll_out_ch(int c); // UART2发送一个字节
|
|
|
+extern bool aem_read_aem_key_record(aem_key_w_record_t *record); // 读取AEM KEY记录
|
|
|
+extern bool aem_defender_factory_write_key(uint8_t * data, uint16_t len); // 写入KEY
|
|
|
+extern uint16_t aem_factory_get_product_info(uint8_t *data, uint16_t in_len); // 获取产品信息
|
|
|
+
|
|
|
+// 计算累加和校验值
|
|
|
+//1 字节,对命令码、数据长度和数据内容的所有字节进行累加求和,取低8位作为校验值,用于检测数据在传输过程中是否出错
|
|
|
+uint8_t calculate_checksum(uint8_t cmd, uint8_t *data, uint8_t data_len)
|
|
|
+{
|
|
|
+ uint8_t checksum = cmd + data_len;
|
|
|
+ for (uint8_t i = 0; i < data_len; i++) {
|
|
|
+ checksum += data[i];
|
|
|
+ }
|
|
|
+ return checksum;
|
|
|
+}
|
|
|
+
|
|
|
+// 发送一帧数据
|
|
|
+void send_frame(uint8_t cmd, uint8_t *data, uint8_t data_len)
|
|
|
+{
|
|
|
+ uint8_t checksum = calculate_checksum(cmd, data, data_len);
|
|
|
+ // 发送帧头
|
|
|
+ uart2_poll_out_ch(FRAME_HEADER1);
|
|
|
+ uart2_poll_out_ch(FRAME_HEADER2);
|
|
|
+ // 发送命令码
|
|
|
+ uart2_poll_out_ch(cmd);
|
|
|
+ // 发送数据长度
|
|
|
+ uart2_poll_out_ch(data_len);
|
|
|
+ // 发送数据内容
|
|
|
+ for (uint8_t i = 0; i < data_len; i++) {
|
|
|
+ uart2_poll_out_ch(data[i]);
|
|
|
+ }
|
|
|
+ // 发送累加和校验值
|
|
|
+ uart2_poll_out_ch(checksum);
|
|
|
+ // 发送帧尾
|
|
|
+ uart2_poll_out_ch(FRAME_TAIL1);
|
|
|
+ uart2_poll_out_ch(FRAME_TAIL2);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// 检查一帧数据是否正确
|
|
|
+bool check_receive_frame(uint8_t *data)
|
|
|
+{
|
|
|
+ uint8_t calculated_checksum;
|
|
|
+ uint8_t data_len = data[3];
|
|
|
+
|
|
|
+ // 帧头
|
|
|
+ if (data[0] != FRAME_HEADER1)
|
|
|
+ {
|
|
|
+ return false; // 帧头错误
|
|
|
+ }
|
|
|
+ if (data[1] != FRAME_HEADER2)
|
|
|
+ {
|
|
|
+ return false; // 帧头错误
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算本地累加和校验值
|
|
|
+ calculated_checksum = calculate_checksum(data[2], data + 4, data_len);
|
|
|
+
|
|
|
+ if (data[data_len + 4] != calculated_checksum) {
|
|
|
+ return false; // 累加和校验错误
|
|
|
+ }
|
|
|
+ // 读取帧尾
|
|
|
+ if (data[data_len + 5] != FRAME_TAIL1 || data[data_len + 6] != FRAME_TAIL2) {
|
|
|
+ return false; // 帧尾错误
|
|
|
+ }
|
|
|
+ return true; // 接收成功
|
|
|
+}
|
|
|
+
|
|
|
+static uint8_t byAACnt = 2;
|
|
|
+static bool bReceiveFrameDone = false;
|
|
|
+static void uart_fifo_callback(const struct device *dev, void *user_data)
|
|
|
+{
|
|
|
+ uint8_t rx_buff[UART_FIFO_MAX];
|
|
|
+ uint8_t tx_buff[UART_FIFO_MAX];
|
|
|
+ int read_size;
|
|
|
+ static uint8_t cnt;
|
|
|
+ aem_key_w_record_t *key_record = NULL;
|
|
|
+
|
|
|
+ printk("uart_fifo_callback start\n");
|
|
|
+
|
|
|
+ uart_irq_update(dev);
|
|
|
+ if (uart_irq_rx_ready(dev)) {
|
|
|
+ read_size = uart_fifo_read(dev, rx_buff, UART_FIFO_MAX);
|
|
|
+ printk("read_size: %d\n", read_size);
|
|
|
+ if (read_size == UART_FIFO_MAX)
|
|
|
+ printk("uart fifo buffer overflow\n");
|
|
|
+
|
|
|
+ for (int i = 0; i < read_size; i++)
|
|
|
+ {
|
|
|
+ switch (rx_buff[i]) {
|
|
|
+ case FRAME_HEADER1:
|
|
|
+ byAACnt++;
|
|
|
+ if (byAACnt > 2)
|
|
|
+ {
|
|
|
+ byAACnt = 1;
|
|
|
+ cnt = 0;
|
|
|
+ bReceiveFrameDone = false;
|
|
|
+ }
|
|
|
+ else if (byAACnt == 2)
|
|
|
+ {
|
|
|
+ bReceiveFrameDone = true;
|
|
|
+ }
|
|
|
+ uart2_rec_data.rec_data[cnt++] = rx_buff[i];
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ uart2_rec_data.rec_data[cnt++] = rx_buff[i];
|
|
|
+
|
|
|
+ /* protection data cannot exceed boundary */
|
|
|
+ if (cnt >= REC_DATA_BUFFER_SIZE)
|
|
|
+ cnt--;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bReceiveFrameDone && check_receive_frame(uart2_rec_data.rec_data))
|
|
|
+ {
|
|
|
+ printk("receive frame success\n");
|
|
|
+
|
|
|
+ switch (uart2_rec_data.rec_data[2])
|
|
|
+ {
|
|
|
+ case DEVICE_ID_CMD:
|
|
|
+ aem_factory_get_product_info(tx_buff, PRODUCT_INFO_SIZE);
|
|
|
+ send_frame(PROJECT_ID_CMD, tx_buff, PRODUCT_INFO_SIZE);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PROJECT_ID_CMD:
|
|
|
+ tx_buff[0] = 0x0F;
|
|
|
+ tx_buff[1] = 0x6B;
|
|
|
+ tx_buff[2] = 0x3B;
|
|
|
+ tx_buff[3] = 0xD8;
|
|
|
+ send_frame(PROJECT_ID_CMD, tx_buff, 4);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case WRITE_KEY_CMD:
|
|
|
+ //uart_fifo_fill(dev,rx_buff,read_size);
|
|
|
+
|
|
|
+ tx_buff[0] = 0;
|
|
|
+ if (aem_defender_factory_write_key(uart2_rec_data.rec_data, WRITE_KEY_SIZE))
|
|
|
+ {
|
|
|
+ tx_buff[0] = 0xAA;
|
|
|
+ }
|
|
|
+
|
|
|
+ send_frame(WRITE_KEY_CMD, tx_buff, 1);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case IS_KEY_INSIDE_CMD:
|
|
|
+ tx_buff[0] = 0;
|
|
|
+ aem_read_aem_key_record(key_record);
|
|
|
+ if (key_record != NULL)
|
|
|
+ {
|
|
|
+ if (key_record->is_pass)
|
|
|
+ tx_buff[0] = 0xAA;
|
|
|
+ }
|
|
|
+
|
|
|
+ send_frame(IS_KEY_INSIDE_CMD, tx_buff, 1);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SET_TIME_CMD:
|
|
|
+ bySetMinute = uart2_rec_data.rec_data[4];
|
|
|
+ bySetHour = uart2_rec_data.rec_data[5];
|
|
|
+ bySetDay = uart2_rec_data.rec_data[6];
|
|
|
+ bySetWeekday = uart2_rec_data.rec_data[7];
|
|
|
+ bySetMonth = uart2_rec_data.rec_data[8];
|
|
|
+ wSetYear = uart2_rec_data.rec_data[9];
|
|
|
+ bySetTimeStep = 1;
|
|
|
+ send_frame(SET_TIME_CMD, tx_buff, 0);
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+static void uart2_rec_enable(const struct device *dev)
|
|
|
+{
|
|
|
+ struct uart2_rec_data *data = (struct uart2_rec_data *)dev->data;
|
|
|
+
|
|
|
+ printk("uart2_rec_enable\n");
|
|
|
+
|
|
|
+ uart_irq_rx_enable(data->uart_gpio_dev);
|
|
|
+}
|
|
|
+
|
|
|
+static void uart2_rec_disable(const struct device *dev)
|
|
|
+{
|
|
|
+ struct uart2_rec_data *data = (struct uart2_rec_data *)dev->data;
|
|
|
+
|
|
|
+ printk("uart2_rec_disable\n");
|
|
|
+ uart_irq_rx_disable(data->uart_gpio_dev);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+static void uart2_rec_register_notify(const struct device *dev, gps_notify_t notify)
|
|
|
+{
|
|
|
+ printk("uart2_rec_register_notify\n");
|
|
|
+ struct uart2_rec_data *data = (struct uart2_rec_data *)dev->data;
|
|
|
+
|
|
|
+ data->notify = notify;
|
|
|
+}
|
|
|
+
|
|
|
+static void uart2_rec_unregister_notify(const struct device *dev, gps_notify_t notify)
|
|
|
+{
|
|
|
+ struct uart2_rec_data *data = (struct uart2_rec_data *)dev->data;
|
|
|
+
|
|
|
+ data->notify = NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static const struct gps_dev_driver_api uart2_rec_api = {
|
|
|
+ .enable = uart2_rec_enable,
|
|
|
+ .disable = uart2_rec_disable,
|
|
|
+ .inquiry = NULL,
|
|
|
+ .register_notify = uart2_rec_register_notify,
|
|
|
+ .unregister_notify = uart2_rec_unregister_notify,
|
|
|
+};
|
|
|
+*/
|
|
|
+static int uart2_rec_init(const struct device *dev)
|
|
|
+{
|
|
|
+ struct uart2_rec_data *data = (struct uart2_rec_data *)dev->data;
|
|
|
+
|
|
|
+ printk("uart2_rec_init\n");
|
|
|
+
|
|
|
+ data->uart_gpio_dev = device_get_binding(UART2_REC_DEV_NAME);
|
|
|
+ if (data->uart_gpio_dev == NULL) {
|
|
|
+ printk("Couldn't find uart2\n");
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
+ uart_irq_callback_set(data->uart_gpio_dev, uart_fifo_callback);
|
|
|
+
|
|
|
+ uart_irq_rx_enable(data->uart_gpio_dev);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+#if IS_ENABLED(CONFIG_UART_ACTS)
|
|
|
+DEVICE_DEFINE(uart2_rec, CONFIG_UART2_REC_DEV_NAME, &uart2_rec_init, NULL, &uart2_rec_data, NULL, POST_KERNEL, 60, NULL);
|
|
|
+#endif
|