From 05752eae3bc32624acaf6a4a4348a75e83d2fb1f Mon Sep 17 00:00:00 2001 From: "CSSC-WORK\\murmur" Date: Sun, 29 Sep 2024 09:45:34 +0800 Subject: [PATCH] update --- MultiTimer.c | 66 ++++++++++++++++++++++++++++ MultiTimer.h | 83 +++++++++++++++++++++++++++++++++++ tcl.c | 122 ++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 245 insertions(+), 26 deletions(-) create mode 100644 MultiTimer.c create mode 100644 MultiTimer.h diff --git a/MultiTimer.c b/MultiTimer.c new file mode 100644 index 0000000..e90a912 --- /dev/null +++ b/MultiTimer.c @@ -0,0 +1,66 @@ +#include "MultiTimer.h" +#include + +static MultiTimer* timerList = NULL; +static PlatformTicksFunction_t platformTicksFunction = NULL; + +int multiTimerInstall(PlatformTicksFunction_t ticksFunc) { + if (ticksFunc == NULL) { + return -1; // Indicate error if ticksFunc is NULL + } + platformTicksFunction = ticksFunc; + return 0; +} + +static void removeTimer(MultiTimer* timer) { + MultiTimer** current = &timerList; + while (*current) { + if (*current == timer) { + *current = timer->next; + break; + } + current = &(*current)->next; + } +} + +int multiTimerStart(MultiTimer* timer, uint64_t timing, MultiTimerCallback_t callback, void* userData) { + if (!timer || !callback || platformTicksFunction == NULL) { + return -1; // Return error if any parameter is invalid + } + + removeTimer(timer); // Centralize removal logic + + timer->deadline = platformTicksFunction() + timing; + timer->callback = callback; + timer->userData = userData; + + MultiTimer** current = &timerList; + while (*current && ((*current)->deadline < timer->deadline)) { + current = &(*current)->next; + } + timer->next = *current; + *current = timer; + + return 0; +} + +int multiTimerStop(MultiTimer* timer) { + removeTimer(timer); // Use centralized removal function + return 0; +} + +int multiTimerYield(void) { + if (platformTicksFunction == NULL) { + return -1; // Indicate error if platformTicksFunction is NULL + } + uint64_t currentTicks = platformTicksFunction(); + while (timerList && (currentTicks >= timerList->deadline)) { + MultiTimer* timer = timerList; + timerList = timer->next; // Remove expired timer + + if (timer->callback) { + timer->callback(timer, timer->userData); // Execute callback + } + } + return timerList ? (int)(timerList->deadline - currentTicks) : 0; +} diff --git a/MultiTimer.h b/MultiTimer.h new file mode 100644 index 0000000..e1b2030 --- /dev/null +++ b/MultiTimer.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021 0x1abin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _MULTI_TIMER_H_ +#define _MULTI_TIMER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint64_t (*PlatformTicksFunction_t)(void); + +typedef struct MultiTimerHandle MultiTimer; + +typedef void (*MultiTimerCallback_t)(MultiTimer* timer, void* userData); + +struct MultiTimerHandle { + MultiTimer* next; + uint64_t deadline; + MultiTimerCallback_t callback; + void* userData; +}; + +/** + * @brief Platform ticks function. + * + * @param ticksFunc ticks function. + * @return int 0 on success, -1 on error. + */ +int multiTimerInstall(PlatformTicksFunction_t ticksFunc); + +/** + * @brief Start the timer work, add the handle into work list. + * + * @param timer target handle strcut. + * @param timing Set the start time. + * @param callback deadline callback. + * @param userData user data. + * @return int 0: success, -1: fail. + */ +int multiTimerStart(MultiTimer* timer, uint64_t timing, MultiTimerCallback_t callback, void* userData); + +/** + * @brief Stop the timer work, remove the handle off work list. + * + * @param timer target handle strcut. + * @return int 0: success, -1: fail. + */ +int multiTimerStop(MultiTimer* timer); + +/** + * @brief Check the timer expried and call callback. + * + * @return int The next timer expires. + */ +int multiTimerYield(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tcl.c b/tcl.c index aa0b880..d78536b 100644 --- a/tcl.c +++ b/tcl.c @@ -3,6 +3,7 @@ #include #include #include "MultiTimer.h" +#include "lwrb/lwrb.h" #define CMD_TRA_MODE 0xA1 #define CMD_REC_MODE 0xA2 @@ -11,32 +12,48 @@ #define CMD_ACK_OK 0xAB #define CMD_ACK_NOK 0xAF -#define MIN_TR_PERIOD_MS 1000 * 5 // 单字节最小传输时间 +#define MIN_TR_PERIOD_MS (1000 * 5) // 单字节最小传输时间 #define HOST_RETRY_PERIOD_MS (MIN_TR_PERIOD_MS + 1000) // 主机重试时间间隔 #define CLIENT_RETRY_PERIOD_MS (MIN_TR_PERIOD_MS + 1000 * 10) // 客户端重试时间间隔 -static int devMode = HOST_MODE; -static int curMode = R_MODE; -static int tarMode = R_MODE; -static int trySwt = 0; // 是否尝试切换到发送模式 -static int tarDevMode = R_MODE; // 目标端工作模式 -static MultiTimer retryTimer, timeoutTimer; // 重试定时器、超时定时器 +#define RING_BUFFER_SIZE (1024 * 3) +#define FRAME_SIZE_MAX (200) /// @brief 主从模式,主机拥有更高优先级 -enum +typedef enum { HOST_MODE = 0, CLIENT_MODE -}; +} devmode_t; /// @brief 工作模式,收、发、休眠、唤醒 -enum +typedef enum { T_MODE = 0, R_MODE, SLEEP_MODE, WORK_MODE -}; +} devstatus_t; + +typedef enum +{ + ERR_OK = 0, + ERR_HEADER, + ERR_TAIL, + ERR_CRC +} err_t; + +static devmode_t devMode = HOST_MODE; +static devstatus_t curMode = R_MODE; +static devstatus_t tarMode = R_MODE; +volatile int trySwt = 0; // 是否尝试切换到发送模式 +static devstatus_t tarDevMode = R_MODE; // 目标端工作模式 +static MultiTimer retryTimer, timeoutTimer; // 重试定时器、超时定时器 + lwrb_t traBuff,frameLenBuff;// 环形缓冲区 + uint8_t ringBuffer[RING_BUFFER_SIZE]; + uint8_t buffer[FRAME_SIZE_MAX];// 单次待发数据缓冲区 + uint8_t frameLen[15];//缓存区数据帧对应长度 + // 设置GPIO电平 void setGpioLevel(int gpio, int level) @@ -46,7 +63,7 @@ void setGpioLevel(int gpio, int level) /// @brief 初始化工作模式,仅设置对应GPIO电平 /// @param cfg -void initWorkMode(int cfg) +void initWorkStatus(devstatus_t cfg) { switch (cfg) { @@ -73,12 +90,20 @@ void initWorkMode(int cfg) void lineTransmitData(uint8_t *data, uint8_t len) { // 发送数据前后需初始化为发送模式 - initWorkMode(T_MODE); + initWorkStatus(T_MODE); // 发送数据 // 发送完毕后需恢复为接收模式 - initWorkMode(R_MODE); + initWorkStatus(R_MODE); } +// 透传缆发送逻辑 +// 0. 用户串口接收待发送数据,放入缓存队列。帧长度对应保存。 +// 1. 通过透传缆串口发送数据 +// 2. 发送完成后切换为接收模式 +// 3. 通过透传缆串口接收回复的ACK +// 4. ACK正常则发送成功,否则发送失败 +// 5. 发送成功则准备发送缓存队列中下一帧数据 +// 6. 发送失败则重发当前帧 /// @brief 通过用户串口发送数据 /// @param data 待发送数据 @@ -144,8 +169,8 @@ void retryTimerCallback(MultiTimer *timer, void *userData) } /// @brief 计算异或XOR校验 -/// @param data -/// @param len +/// @param data 待校验数据 +/// @param len 数据长度 /// @return 校验结果 uint8_t bccCRC(uint8_t *data, uint8_t len) { @@ -161,26 +186,35 @@ uint8_t bccCRC(uint8_t *data, uint8_t len) /// @param data 待校验数据 /// @param len 数据长度 /// @return 0->有效 1->帧头无效 2->帧尾无效 3->校验位无效 -int chkDataValid(uint8_t *data, uint8_t len) +err_t chkDataValid(uint8_t *data, uint8_t len) { // 按帧发送数据 // 判断帧的完整性及校验位 if (data[0] != 0x5A || data[1] != 0xA5) // 帧头校验 { - return 1; + return ERR_HEADER; } if (data[len - 1] != 0xED) // 帧尾校验 { - return 2; + return ERR_TAIL; } if (bccCRC(data + 2, len - 4) != data[len - 2]) // 校验位校验 { - return 3; + return ERR_CRC; } - return 0; + return ERR_OK; +} + +// 创建长度为3k的队列 + +// 更新缓存队列 +void updateDataQueue(uint8_t *data, uint8_t len) +{ + lwrb_write(&traBuff, data, len); + lwrb_write(&frameLenBuff, len, 1); } /// @brief 用户接口接收数据回调 @@ -218,10 +252,12 @@ void userRecDataCallback(uint8_t *data, uint8_t len) } else { - if (chkDataValid(data, len)) - { - lineTransmitData(data, len); - } + // 需要透传的数据 + updateDataQueue(data, len); + // if (chkDataValid(data, len)) + // { + // lineTransmitData(data, len); + // } } } @@ -258,10 +294,33 @@ void lineRecCallback(uint8_t *data, uint8_t len) } else { - if (chkDataValid(data, len)) + if (chkDataValid(data, len) == ERR_OK) { + lineTransmitData(CMD_ACK_OK, 1); userTransmitData(data, len); } + else + { + lineTransmitData(CMD_ACK_NOK, 1); + } + } +} + +void transmitDataCallback(lwrb_t *buff, lwrb_evt_type_t type, size_t len) +{ + switch (type) + { + case LWRB_EVT_RESET: + printf("[EVT] Buffer reset event!\r\n"); + break; + case LWRB_EVT_READ: + printf("[EVT] Buffer read event: %d byte(s)!\r\n", (int)len); + break; + case LWRB_EVT_WRITE: + printf("[EVT] Buffer write event: %d byte(s)!\r\n", (int)len); + break; + default: + break; } } @@ -286,6 +345,12 @@ void handleTR() // 定时器始终开启 multiTimerStart(&retryTimer, retryTime, retryTimerCallback, NULL); // Start timer + // + + lwrb_init(&traBuff, ringBuffer, RING_BUFFER_SIZE); + lwrb_init(&frameLenBuff,frameLen,sizeof(frameLen)); + lwrb_set_evt_fn(&traBuff, transmitDataCallback); + while (1) { multiTimerYield(); @@ -295,6 +360,11 @@ void handleTR() switchToTraMode(); multiTimerStart(&retryTimer, retryTime, retryTimerCallback, NULL); // always restart timer } + if (lwrb) + { + /* code */ + } + } }