You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
4.3 KiB
157 lines
4.3 KiB
/*
|
|
* COPYRIGHT (C) 2011-2023, Real-Thread Information Technology Ltd
|
|
* All rights reserved
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Change Logs:
|
|
* Date Author Notes
|
|
* 2013-04-14 Grissiom initial implementation
|
|
* 2019-12-09 Steven Liu add YMODEM send protocol
|
|
* 2022-08-04 Meco Man move error codes to rym_code to silence warnings
|
|
*
|
|
* Radkil adapted in 2026: 移除 RT-Thread 依赖, 使用 rd_time 抽象
|
|
*/
|
|
|
|
#ifndef __YMODEM_H__
|
|
#define __YMODEM_H__
|
|
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include "common.h"
|
|
#include "rd_time.h"
|
|
#include "com.h"
|
|
|
|
/* The word "RYM" is stand for "Real-YModem". */
|
|
enum rym_code
|
|
{
|
|
RYM_CODE_NONE = 0x00,
|
|
RYM_CODE_SOH = 0x01,
|
|
RYM_CODE_STX = 0x02,
|
|
RYM_CODE_EOT = 0x04,
|
|
RYM_CODE_ACK = 0x06,
|
|
RYM_CODE_NAK = 0x15,
|
|
RYM_CODE_CAN = 0x18,
|
|
RYM_CODE_C = 0x43,
|
|
|
|
/* RYM error code */
|
|
RYM_ERR_TMO = 0x70,
|
|
RYM_ERR_CODE = 0x71,
|
|
RYM_ERR_SEQ = 0x72,
|
|
RYM_ERR_CRC = 0x73,
|
|
RYM_ERR_DSZ = 0x74,
|
|
RYM_ERR_CAN = 0x75,
|
|
RYM_ERR_ACK = 0x76,
|
|
RYM_ERR_FILE = 0x77,
|
|
};
|
|
|
|
/* 超时改为毫秒 */
|
|
#ifndef RYM_WAIT_CHR_MS
|
|
#define RYM_WAIT_CHR_MS 3000
|
|
#endif
|
|
#ifndef RYM_WAIT_PKG_MS
|
|
#define RYM_WAIT_PKG_MS 3000
|
|
#endif
|
|
#ifndef RYM_CHD_INTV_MS
|
|
#define RYM_CHD_INTV_MS 3000
|
|
#endif
|
|
|
|
#ifndef RYM_END_SESSION_SEND_CAN_NUM
|
|
#define RYM_END_SESSION_SEND_CAN_NUM 0x07
|
|
#endif
|
|
|
|
#ifndef RYM_MAX_ERRORS
|
|
#define RYM_MAX_ERRORS ((size_t)5)
|
|
#endif
|
|
|
|
/* 发送方向: 收到 NAK / 等应答超时时, 重发同一包的最大次数.
|
|
* 注意 YMODEM 里 NAK 的语义是"这一包没收好, 请重发", 不是失败退出;
|
|
* 接收端(尤其是刚建完文件/还没就绪时) 头一两次回 NAK 是正常现象. */
|
|
#ifndef RYM_TX_RETRY_MAX
|
|
#define RYM_TX_RETRY_MAX 10
|
|
#endif
|
|
|
|
/* 发送方向数据块的大小选择:
|
|
* 1 = 数据阶段一律用 1K(STX) 块 (标准 YMODEM 发送端行为, lrzsz 的 sz 默认如此).
|
|
* 0 = 按本块实际字节数选择 SOH(128B)/STX(1K).
|
|
* 对接某些终端(如 Xshell)时它们只接受 STX 数据块, 收到 SOH 数据块会一直回 NAK. */
|
|
#ifndef RYM_TX_BLOCK_1K
|
|
#define RYM_TX_BLOCK_1K 1
|
|
#endif
|
|
|
|
enum rym_stage
|
|
{
|
|
RYM_STAGE_NONE = 0,
|
|
RYM_STAGE_ESTABLISHING,
|
|
RYM_STAGE_ESTABLISHED,
|
|
RYM_STAGE_TRANSMITTING,
|
|
RYM_STAGE_FINISHING,
|
|
RYM_STAGE_FINISHED,
|
|
};
|
|
|
|
struct rym_ctx;
|
|
|
|
typedef enum rym_code(*rym_callback)(struct rym_ctx *ctx, uint8_t *buf, size_t len);
|
|
|
|
/*
|
|
* rym_device: 串口设备抽象层
|
|
*
|
|
* 使用者提供 read/write/set_rx_indicate 回调, ymodem 协议层不再依赖
|
|
* 任何具体 OS 或驱动框架.
|
|
*
|
|
* set_rx_indicate(opaque, callback, arg):
|
|
* 注册接收通知回调. 当串口收到数据时, 驱动应调用 callback(arg).
|
|
* callback 可以为 NULL (取消注册).
|
|
*/
|
|
typedef struct
|
|
{
|
|
/* 读串口: 返回实际读到的字节数, 无数据返回 0 */
|
|
size_t (*read)(void *opaque, uint8_t *buf, size_t len);
|
|
/* 写串口: 返回实际写入的字节数 */
|
|
size_t (*write)(void *opaque, const uint8_t *buf, size_t len);
|
|
/* 透传指针 (如 TComCtrl*) */
|
|
void *opaque;
|
|
} rym_device_t;
|
|
|
|
struct rym_ctx
|
|
{
|
|
rym_callback on_data;
|
|
rym_callback on_begin;
|
|
rym_callback on_end;
|
|
enum rym_stage stage;
|
|
uint8_t *buf;
|
|
|
|
rym_device_t dev;
|
|
};
|
|
|
|
int rym_recv_on_device(struct rym_ctx *ctx,
|
|
rym_device_t *dev,
|
|
rym_callback on_begin,
|
|
rym_callback on_data,
|
|
rym_callback on_end,
|
|
int handshake_timeout_sec);
|
|
|
|
int rym_send_on_device(struct rym_ctx *ctx,
|
|
rym_device_t *dev,
|
|
rym_callback on_begin,
|
|
rym_callback on_data,
|
|
rym_callback on_end,
|
|
int handshake_timeout_sec);
|
|
|
|
/**
|
|
* @brief YMODEM 接收文件
|
|
* @param ptCom 串口 TComCtrl (需已创建且 recv 线程已启动)
|
|
* @param file_path 本地保存路径, 如 "C:/fw.bin"
|
|
* @return 0 成功, <0 失败 (参见 enum rym_code)
|
|
*/
|
|
int rym_download_file(TComCtrl *ptCom, const char *file_path);
|
|
|
|
/**
|
|
* @brief YMODEM 发送文件
|
|
* @param ptCom 串口 TComCtrl
|
|
* @param file_path 待发送的本地文件路径
|
|
* @return 0 成功, <0 失败
|
|
*/
|
|
int rym_upload_file(TComCtrl *ptCom, const char *file_path);
|
|
|
|
#endif
|