update
This commit is contained in:
parent
d1b240abd0
commit
05752eae3b
66
MultiTimer.c
Normal file
66
MultiTimer.c
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include "MultiTimer.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
83
MultiTimer.h
Normal file
83
MultiTimer.h
Normal file
@ -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 <stdint.h>
|
||||||
|
|
||||||
|
#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
|
122
tcl.c
122
tcl.c
@ -3,6 +3,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "MultiTimer.h"
|
#include "MultiTimer.h"
|
||||||
|
#include "lwrb/lwrb.h"
|
||||||
|
|
||||||
#define CMD_TRA_MODE 0xA1
|
#define CMD_TRA_MODE 0xA1
|
||||||
#define CMD_REC_MODE 0xA2
|
#define CMD_REC_MODE 0xA2
|
||||||
@ -11,32 +12,48 @@
|
|||||||
#define CMD_ACK_OK 0xAB
|
#define CMD_ACK_OK 0xAB
|
||||||
#define CMD_ACK_NOK 0xAF
|
#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 HOST_RETRY_PERIOD_MS (MIN_TR_PERIOD_MS + 1000) // 主机重试时间间隔
|
||||||
#define CLIENT_RETRY_PERIOD_MS (MIN_TR_PERIOD_MS + 1000 * 10) // 客户端重试时间间隔
|
#define CLIENT_RETRY_PERIOD_MS (MIN_TR_PERIOD_MS + 1000 * 10) // 客户端重试时间间隔
|
||||||
|
|
||||||
static int devMode = HOST_MODE;
|
#define RING_BUFFER_SIZE (1024 * 3)
|
||||||
static int curMode = R_MODE;
|
#define FRAME_SIZE_MAX (200)
|
||||||
static int tarMode = R_MODE;
|
|
||||||
static int trySwt = 0; // 是否尝试切换到发送模式
|
|
||||||
static int tarDevMode = R_MODE; // 目标端工作模式
|
|
||||||
static MultiTimer retryTimer, timeoutTimer; // 重试定时器、超时定时器
|
|
||||||
|
|
||||||
/// @brief 主从模式,主机拥有更高优先级
|
/// @brief 主从模式,主机拥有更高优先级
|
||||||
enum
|
typedef enum
|
||||||
{
|
{
|
||||||
HOST_MODE = 0,
|
HOST_MODE = 0,
|
||||||
CLIENT_MODE
|
CLIENT_MODE
|
||||||
};
|
} devmode_t;
|
||||||
|
|
||||||
/// @brief 工作模式,收、发、休眠、唤醒
|
/// @brief 工作模式,收、发、休眠、唤醒
|
||||||
enum
|
typedef enum
|
||||||
{
|
{
|
||||||
T_MODE = 0,
|
T_MODE = 0,
|
||||||
R_MODE,
|
R_MODE,
|
||||||
SLEEP_MODE,
|
SLEEP_MODE,
|
||||||
WORK_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电平
|
// 设置GPIO电平
|
||||||
void setGpioLevel(int gpio, int level)
|
void setGpioLevel(int gpio, int level)
|
||||||
@ -46,7 +63,7 @@ void setGpioLevel(int gpio, int level)
|
|||||||
|
|
||||||
/// @brief 初始化工作模式,仅设置对应GPIO电平
|
/// @brief 初始化工作模式,仅设置对应GPIO电平
|
||||||
/// @param cfg
|
/// @param cfg
|
||||||
void initWorkMode(int cfg)
|
void initWorkStatus(devstatus_t cfg)
|
||||||
{
|
{
|
||||||
switch (cfg)
|
switch (cfg)
|
||||||
{
|
{
|
||||||
@ -73,12 +90,20 @@ void initWorkMode(int cfg)
|
|||||||
void lineTransmitData(uint8_t *data, uint8_t len)
|
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 通过用户串口发送数据
|
/// @brief 通过用户串口发送数据
|
||||||
/// @param data 待发送数据
|
/// @param data 待发送数据
|
||||||
@ -144,8 +169,8 @@ void retryTimerCallback(MultiTimer *timer, void *userData)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 计算异或XOR校验
|
/// @brief 计算异或XOR校验
|
||||||
/// @param data
|
/// @param data 待校验数据
|
||||||
/// @param len
|
/// @param len 数据长度
|
||||||
/// @return 校验结果
|
/// @return 校验结果
|
||||||
uint8_t bccCRC(uint8_t *data, uint8_t len)
|
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 data 待校验数据
|
||||||
/// @param len 数据长度
|
/// @param len 数据长度
|
||||||
/// @return 0->有效 1->帧头无效 2->帧尾无效 3->校验位无效
|
/// @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) // 帧头校验
|
if (data[0] != 0x5A || data[1] != 0xA5) // 帧头校验
|
||||||
{
|
{
|
||||||
return 1;
|
return ERR_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data[len - 1] != 0xED) // 帧尾校验
|
if (data[len - 1] != 0xED) // 帧尾校验
|
||||||
{
|
{
|
||||||
return 2;
|
return ERR_TAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bccCRC(data + 2, len - 4) != data[len - 2]) // 校验位校验
|
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 用户接口接收数据回调
|
/// @brief 用户接口接收数据回调
|
||||||
@ -218,10 +252,12 @@ void userRecDataCallback(uint8_t *data, uint8_t len)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (chkDataValid(data, len))
|
// 需要透传的数据
|
||||||
{
|
updateDataQueue(data, len);
|
||||||
lineTransmitData(data, len);
|
// if (chkDataValid(data, len))
|
||||||
}
|
// {
|
||||||
|
// lineTransmitData(data, len);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,10 +294,33 @@ void lineRecCallback(uint8_t *data, uint8_t len)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (chkDataValid(data, len))
|
if (chkDataValid(data, len) == ERR_OK)
|
||||||
{
|
{
|
||||||
|
lineTransmitData(CMD_ACK_OK, 1);
|
||||||
userTransmitData(data, len);
|
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
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
multiTimerYield();
|
multiTimerYield();
|
||||||
@ -295,6 +360,11 @@ void handleTR()
|
|||||||
switchToTraMode();
|
switchToTraMode();
|
||||||
multiTimerStart(&retryTimer, retryTime, retryTimerCallback, NULL); // always restart timer
|
multiTimerStart(&retryTimer, retryTime, retryTimerCallback, NULL); // always restart timer
|
||||||
}
|
}
|
||||||
|
if (lwrb)
|
||||||
|
{
|
||||||
|
/* code */
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user