Lwip2.0.3 版本的tftp 协议笔记
Lwip2.0.3中的tftp与旧版本的lwip的部分改动挺大,新版本的提供的接口更加方便, 新版本中tftp-server.h定义了一个结构体,声明了一个初始化函数,这个函数就是给开发人员的接口,里面是四个函数接口,open,close write read,我们只需要重新建立这四个函数,与其对应即可。.h如下:
*/ struct tftp_context { /** * Open file for read/write. * @param fname Filename * @param mode Mode string from TFTP RFC 1350 (netascii, octet, mail) * @param write Flag indicating read (0) or write (!= 0) access * @returns File handle supplied to other functions */ void* (*open)(const char* fname, const char* mode, u8_t write); /** * Close file handle * @param handle File handle returned by open() */ void (*close)(void* handle); /** * Read from file * @param handle File handle returned by open() * @param buf Target buffer to copy read data to * @param bytes Number of bytes to copy to buf * @returns >= 0: Success; < 0: Error */ int (*read)(void* handle, void* buf, int bytes); /** * Write to file * @param handle File handle returned by open() * @param pbuf PBUF adjusted such that payload pointer points * to the beginning of write data. In other words, * TFTP headers are stripped off. begainning of actualdata * @returns >= 0: Success; < 0: Error */ int (*write)(void* handle, struct pbuf* p); }; extern err_t tftp_init(const struct tftp_context* ctx);函数的具体参数的意义自己翻译一下就知道了,其中open函数无论是写还是读都会被调用,在此之前你应该很了解了tftp的传输协议的理论部分,对传输过程很清晰,官方给的库里面的结构体代表的意义应该清楚,回到上面,open函数返回的函数句柄要被其他几个函数使用,编写好四个函数后取地址传给库里的tftp_init函数
uint8_t Tftp_Context_Init(void) { if(tftp_init(&tftpContext) == ERR_OK) return 0; return 1; }此函数被主函数初始化一下即可。 例:
#define MY_MALLOC(type,n) (type*)malloc(sizeof(type) * n) typedef struct { uint8_t byOpenFileFlag; // 1 : Open file succeed 0: fail uint8_t W_R_Mode; // read or write Mode ,1: write 0 :read uint32_t First_Flash_Addr; // address you want to write }TyTftp_IAP_Flash; static void * Tftp_Open_File(const char* fname, const char* mode, u8_t Iswrite); static void Tftp_Close_File(void* handle); static int32_t Tftp_Read_File(void* handle, void* buf, int bytes); static int32_t Tftp_Write_File(void* handle, struct pbuf* p); static TyTftp_IAP_Flash Tftp_IAP_Flash; struct tftp_context TftpContext = { Tftp_Open_File, Tftp_Close_File, Tftp_Read_File, Tftp_Write_File, }; static void *Tftp_Open_File(const char* fname, const char* mode, u8_t Iswrite) { Tftp_IAP_Flash.W_R_Mode = Iswrite; /*compare the file name we want to read or write*/ if(Tftp_IAP_Flash.W_R_Mode == 1) //: is write { Tftp_IAP_Flash.byOpenFileFlag = 1; } else if(Tftp_IAP_Flash.W_R_Mode == 0) //:is read { Tftp_IAP_Flash.byOpenFileFlag = 1; } /*tftp open file init successful*/ if(Tftp_IAP_Flash.byOpenFileFlag == 1) return &Tftp_IAP_Flash; else return 0 ; } static int32_t Tftp_Read_File(void* handle, void* buf, int bytes) { uint16_t Count ; TyTftp_IAP_Flash * Filehandle = (TyTftp_IAP_Flash *) handle ; if(!Filehandle->byOpenFileFlag) //未初始化 { return ERR_MEM ; } #if 0 /* copy data from Address to opening file*/ for(Count = 0; Count < bytes; Count++ ) { if(Filehandle->First_Flash_Addr <= FLASH_APP_END_ADDRESS) { ((uint8_t *)buf)[Count] = *((__IO uint8_t *) Filehandle->First_Flash_Addr); Filehandle->First_Flash_Addr++; } else { break; } } #endif return Count; } static int32_t Tftp_Write_File(void* handle, struct pbuf* p) { uint16_t Count; int8_t byErr = ERR_OK; TyTftp_IAP_Flash * Filehandle = (TyTftp_IAP_Flash *) handle ; if(!Filehandle->byOpenFileFlag) { return ERR_MEM ; } Count = p->len; //lenth of data : 512byte or <512 //code return byErr; } static void Tftp_Close_File(void* handle) { Tftp_IAP_Flash.byOpenFileFlag = 0; if(Tftp_IAP_Flash.W_R_Mode == 1) { //code } } } uint8_t Tftp_Context_Init(uint16_t ReUpdate, uint8_t BootFlag) { TftpFileStart(BootFlag); if (ReUpdate == 1) { if(tftp_init(&TftpContext) == ERR_OK) return 0; } return 1; }最后利用TFTP32软件和下位机结合实际业务进行文件的读取和写入。只需要在code处填写你自己的代码就行了,有需要可以联系我。