» 下一篇:
 

ymodem源码

基于类串口通信的文件传输协议,ymodem应用非常广泛,比如在MCU IAP中,常用的就是这种协议。ymodem是xmodem的改进版协议,具有传输快速稳定的优点。它可以一次传输1024字节的信息块,同时还支持传输多个文件。

本文ymodem源码基于C语言,采用回调机制,设计为独立的C库,包含了发送端和接收端的实现。

YMODEM协议简介

YMODEM文件传输过程,参考文章:https://blog.csdn.net/lcmsir/article/details/80550821

YMODEM源码简介

/*
 * ymodem.h
 *
 * COPYRIGHT (C) 2019. All rights reserved.
 *
 *  Created on: 2019-06-05
 *      Author: gyr
 *
 * \brief	YMODEM协议库实现
 *
 * YMODEM文件传输过程:
 *
 * 发送端                                                                                                        接收端
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   C
 * SOH 00 FF [filename 00] [filesize 00] [NUL..] CRCH CRCL >>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   C
 * SOH 00 FF [filename 00] [filesize 00] [NUL..] CRCH CRCL >>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   ACK
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   C
 * STX 01 FE data[1024] CRC CRC>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   ACK
 * STX 02 FD data[1024] CRC CRC>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   ACK
 * STX 03 FC data[1024] CRC CRC>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   ACK
 * STX 04 FB data[1024] CRC CRC>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   ACK
 * SOH 05 FA data[100]  1A[28] CRC CRC>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   ACK
 * EOT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   NAK
 * EOT>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   ACK
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   C
 * SOH 00 FF NUL[128] CRC CRC >>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   ACK
 *
 * 上述中:
 * filename:	字符串
 * filesize:	文件大小,字符串格式
 * NUL:			填充为0x00
 * CRC:			先传CRC高字节,再传低字节
 */

#ifndef YMODEM_H_
#define YMODEM_H_

/**
 * Make sure we can call this stuff from C++.
 */
#ifdef __cplusplus
extern "C" {
#endif

/**
 * Provide the ability to override linkage features of the interface.
 */
#ifndef YMODEM_EXTERN
# define YMODEM_EXTERN extern
#endif
#ifndef YMODEM_API
# define YMODEM_API
#endif

/**
 * Ensure these symbols were not defined by some previous header file.
 */
#ifdef YMODEM_VERSION
# undef YMODEM_VERSION
#endif
#ifdef YMODEM_VERSION_NUMBER
# undef YMODEM_VERSION_NUMBER
#endif

/**
 * YMODEM库版本号
 *
 * [YMODEM_VERSION]
 *
 * 字符串格式版本号,格式为:X.Y.Z,其中,X为主版本号;Y为次版本号;Z为发布版本号
 *
 * [YMODEM_VERSION_NUMBER]
 *
 * 整数版本号:(X*1000000 + Y*1000 + Z)
 * 对于任何一个版本,该宏的值总是比前一个版本的值大。当Y操持不变时,Z递增;当Y递增时,Z归位为0
*/
#define YMODEM_VERSION				"1.0.0"
#define YMODEM_VERSION_NUMBER 		1000000

/**
 * These interfaces provide the same information as the [YMODEM_VERSION],
 * [YMODEM_VERSION_NUMBER]
 */
YMODEM_API YMODEM_EXTERN const char ymodem_version[];
YMODEM_API const char *ymodem_libversion();
YMODEM_API int ymodem_libversion_number();

/**
 * Result Codes: result code definitions
 *
 * Many YMODEM functions return an integer result code from the set shown
 * here in order to indicate success or failure.
 *
 * New error codes may be added in future versions of YMODEM.
 */
typedef int ymodem_rt_t;
#define YMODEM_RT_OK				0	/* Successful result */
/* beginning-of-error-codes */
#define YMODEM_RT_ERR				1	/* Generic error */

/* end-of-error-codes */


/* 定义日志级别 */
#define YM_LOG_LVL_DBG    			0	// 调试级别
#define YM_LOG_LVL_INFO   			1	// 辅助级别
#define YM_LOG_LVL_WARN   			2	// 警告级别
#define YM_LOG_LVL_ERROR  			3	// 错误级别

// -----------------------------------------------------------------------------

typedef struct ymodem_mgr ymodem_mgr_t;

typedef struct ymodem_callback	ymodem_callback_t;
struct ymodem_callback 
{
	/**
	 * \brief			接收数据回调接口
	 * 
	 * @param buff		接收缓存
	 * @param len		接收缓存字节长度
	 * @param timeout	接收超时时间,单位:ms
	 */
	int (*recv_data)(char* buff, int len, int timeout);
	/**
	 * \brief			发送数据回调接口
	 * 
	 * @param buff		发送缓存
	 * @param len		发送缓存字节长度
	 */
	int (*send_data)(const char* buff, int len);
	
    /**
     * \brief	日志输出接口,如果未定义,则不打印输出任何日志信息,即使错误信息
     */
	void (*write_log)(int logLevel, const char *file, int line,
				  const char *fmt, ...);// const __attribute__((format(printf,5,6)));
};

typedef struct ymodem_cfg ymodem_cfg_t;
struct ymodem_cfg
{
	/**
	 * \brief		传输数据时,指定接收超时时间,单位:ms
	 */
	int							timeout;
	/**
	 * \brief		YMODEM数据块大小
	 * 				标准YMODEM协议采用128/1024字节大小数据块传输文件
	 * 
	 * @param blk_size
	 * 				0:			采用标准YMODEM数据块大小
	 * 				[20-1024]:	自定义字节大小的YMODEM数据库(非标准)
	 * 							自定义的YMODEM数据块大小必须满足 >= 文件名+字符串格式文件字节大小,否则会出错
	 * 				> 1024:		N/A
	 */
	char						blk_size;
};

/**
 * \brief			开始接收回调函数
 *
 * @param filename	准备接收的文件名
 * @param filesize	准备接收的文件大小,单位:byte
 */
typedef ymodem_rt_t cb_on_receive_begin(const char *filename, unsigned int filesize);
/**
 * \brief			接收文件数据回调函数
 */
typedef ymodem_rt_t cb_on_receive_packet(const unsigned char *filedata, unsigned int length);
/**
 * \brief			获取要传输的文件数据的回调函数
 *
 * @param filedata	存储文件数据的缓存
 * @param length 	filedata的字节长度
 * @param transmited_size	当前已传输字节数,可用作文件偏移
 */
typedef ymodem_rt_t cb_on_transmit_packet(unsigned char *filedata, unsigned int length, const unsigned int transmited_size);
/**
 * \brief			文件传输完成回调函数
 */
typedef ymodem_rt_t cb_on_end(unsigned int transmited_size);

// -----------------------------------------------------------------------------

/**
 * \brief		打开、关闭 ymodem对象,涉及内存分配,必须成对使用
 */
YMODEM_API ymodem_rt_t ymodem_open(ymodem_mgr_t **ym, ymodem_callback_t *callback, ymodem_cfg_t *cfg);
YMODEM_API ymodem_rt_t ymodem_close(ymodem_mgr_t *ym);

/**
 * \brief		使用YMODEM协议接收文件
 * 
 * @param ym		ymodem对象指针
 * @param on_begin	开始接收回调函数
 * @param on_packet	接收文件数据回调函数
 * @param on_end	文件接收完成回调函数
 * @param handshake_timeout	等待超时时间,单位:秒
 */
YMODEM_API ymodem_rt_t ymodem_receive(ymodem_mgr_t *ym, 
		cb_on_receive_begin *on_begin,
		cb_on_receive_packet *on_packet,
		cb_on_end *on_end,
		const int handshake_timeout);

/**
 * \brief		使用YMODEM协议传输文件
 * 
 * \input
 * @ym			ymodem对象指针
 * @param filename	要传输的文件名称
 * @param filesize	要传输的文件字节大小
 * @param on_packet	获取要传输的文件数据
 * @param on_end	文件传输完成回调函数
 * @param handshake_timeout	等待接收端CCC超时时间,单位:秒
 */
YMODEM_API ymodem_rt_t ymodem_transmit(ymodem_mgr_t *ym,
		const char *filename, unsigned int filesize,
		cb_on_transmit_packet *on_packet,
		cb_on_end *on_end,
		const int handshake_timeout);

/*
** END OF REGISTRATION API
*******************************************************************************/

#ifdef __cplusplus
}  /* end of the 'extern "C"' block */
#endif

#endif /* YMODEM_H_ */

// -----------------------------------------------------------------------------
// End of ymodem.h

YMODE源码

请等待本人上传github。

» 文章出处: reille博客—http://velep.com , 如果没有特别声明,文章均为reille博客原创作品
» 郑重声明: 原创作品未经允许不得转载,如需转载请联系reille#qq.com(#换成@)
分享到:

 Leave a Reply

(必须)

(我会替您保密的)(必须)

*

 
© 2012 velep.com | reille blog | 管理| 粤ICP备12094833号-2| 谷歌地图| 百度地图| Suffusion theme|Sayontan Sinha

无觅相关文章插件,快速提升流量