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 <stdlib.h>
|
||||
#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 */
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user