TFTP 实现上传和下载数据 以及固件升级

STM32 专栏收录该内容
7 篇文章 0 订阅

                                        TFTP  实现上传和下载数据 以及固件升级

       TFTP协议全称为简单文件传输协议,它是以UDP为基础的应用层协议。在实现TFTP服务器之前,需要详细理解协议。目前很多介绍TFTP协议的书籍都是参照RFC1350,比如著名的《TCP/IP详解》。然而RFC1350已经被后来RFC2347、RFC2348、RFC2349等所代替。

TFTP协议支持三种传输模式,分别为:

       netascii:ASCII文本模式
        octet:二进制模式,每字节8位
        mail:现在已经不使用 

TFTP协议支持六种数据包格式

 

操作码(opcode)描述
1读请求 RRQ
2写请求 WRQ
3数据 DATA
4应答 ACK
5错误 ERROR
6选项应答

  TFTP  上传数据实现源码

 

static void tput ( int8 *pFilename , int32 nullk , meminterst *type , int sock )
{
	int32 fd;
	int8 *Txbuf = NULL;
	uint8 cnt = 0;
	uint16 opcode = 0;
	uint16 seq = 0;
	uint32 Contlen = nullk , len;
	uint32 total = 0 , flag = 1;
	uint32 tiks = 0 , k , lastseq;
	float spd;
	int32 i , j = 0;
	tiks = tickGet ( );
	Txbuf = ( uint8* ) cmMalloc ( 1024 );
	memset ( Txbuf , 0 , 1024 );
	while ( j < 10 ) {

		for ( i = 0; i < TIMEOUT ; i++ ) /* this for loop will just keep checking the non-blocking socket until timeout */
		{
			if ( ptftprxbuf->posw != ptftprxbuf->posr ) {
				if ( ptftprxbuf->rxlen [ ptftprxbuf->posr ] > 0 ) {
					opcode = ptftprxbuf->rxbuf [ ptftprxbuf->posr ] [ 0 ] * 256 + ptftprxbuf->rxbuf [ ptftprxbuf->posr ] [ 1 ];

					if ( opcode == 6 ) {
						lastseq = seq;
						seq = 1;
					}
					if ( opcode == 4 ) {
						lastseq = seq;
						seq = ptftprxbuf->rxbuf [ ptftprxbuf->posr ] [ 2 ] * 256 + ptftprxbuf->rxbuf [ ptftprxbuf->posr ] [ 3 ];
						if ( lastseq == seq ) {

						} else {
							ConsoleSendChar ( '.' );
						}
						seq = seq + 1;

					}
					if ( ( opcode == 4 ) || ( opcode == 6 ) ) {
						cnt++;
						Txbuf [ 0 ] = 0;
						Txbuf [ 1 ] = 3;
						Txbuf [ 2 ] = seq / 256 % 256;
						Txbuf [ 3 ] = seq % 256;
						if ( Contlen > 512 ) {
							len = 512;

							Contlen = Contlen - 512;
						} else {
							len = Contlen;
							Contlen = 0;

						}
						if ( type->flag == ExternFlash ) {
							flashRead ( type->addr + total , ( Txbuf + 4 ) , len );
						} else if ( type->flag == InterFlashB0 ) {
							register uint8_t *src = ( uint8_t* ) ( type->baseaddr + type->addr + total );
							memcpy ( ( Txbuf + 4 ) , src , len );
						} else if ( type->flag == InterFlashB1 ) {
							register uint8_t *src = ( uint8_t* ) ( type->baseaddr + type->addr + total );
							memcpy ( ( Txbuf + 4 ) , src , len );
						} else if ( type->flag == App1Zone ) {
							register uint8_t *src = ( uint8_t* ) ( type->baseaddr + type->addr + total );
							memcpy ( ( Txbuf + 4 ) , src , len );
						} else if ( type->flag == App2Zone ) {
							register uint8_t *src = ( uint8_t* ) ( type->baseaddr + type->addr + total );
							memcpy ( ( Txbuf + 4 ) , src , len );
						} else if ( type->flag == Appdata ) {
							register uint8_t *src = ( uint8_t* ) ( type->baseaddr + type->addr + total );
							memcpy ( ( Txbuf + 4 ) , src , len );
						} else if ( type->flag == Secrect ) {
							register uint8_t *src = ( uint8_t* ) ( type->baseaddr + type->addr + total );
							memcpy ( ( Txbuf + 4 ) , src , len );
						} else if ( type->flag == EEPROM ) {
							register uint8_t *src = ( uint8_t* ) ( type->baseaddr + type->addr + total );
							memcpy ( ( Txbuf + 4 ) , src , len );
						} else if ( type->flag == InRam ) {
							register uint8_t *src = ( uint8_t* ) ( type->baseaddr + type->addr + total );
							memcpy ( ( Txbuf + 4 ) , src , len );
						} else if ( type->flag == ExSram ) {
							register uint8_t *src = ( uint8_t* ) ( type->baseaddr + type->addr + total );
							memcpy ( ( Txbuf + 4 ) , src , len );
						} else if ( type->flag == env ) {
							register uint8_t *src = ( uint8_t* ) ( type->baseaddr + type->addr + total );
							memcpy ( ( Txbuf + 4 ) , src , len );
						} else if ( type->flag == Fram ) {
							if ( len == 512 ) {
								for ( k = 0; k < 8 ; k++ ) {
									if ( 64 != bspi2cFramRead ( type->addr + total + k * 64 , ( uint8 * ) &Txbuf [ 4 + 64 * k ] , 64 ) ) {

									}
									bspDelay ( 1000 );
								}
							} else {
								for ( k = 0; ( len / 64 + ( ( ( len % 64 ) == 0 ) ? 0 : 1 ) ) ; k++ ) {
									if ( 64 != bspi2cFramRead ( type->addr + total + k * 64 , ( uint8 * ) &Txbuf [ 4 + 64 * k ] , 64 ) ) {

									}
									bspDelay ( 1000 );
								}
							}
						}

						total = total + len;
						if ( bspethSend1 ( sock , ( uint8 * ) Txbuf , len + 4 ) != ( len + 4 ) ) {
							bspPrintString ( "Mismatch in number of sent bytes while trying to send mode error packet\r\n" );
						}
					}
					if ( ( seq % 10 ) == 0 )
						ConsoleSendChar ( '*' );
					ptftprxbuf->rxlen [ ptftprxbuf->posr ] = 0;
					ptftprxbuf->posr = ( ptftprxbuf->posr + 1 ) % FRAMESIZE;
					break;
				}
			} else {
				bspDelay ( 10 );
			}
		}

		if ( i == TIMEOUT ) {
			j++;
			ConsoleSendChar ( '$' );
		} else {
			j = 0;
		}
		if ( j == 10 ) {
			break;
		}

		if ( ( Contlen == 0 ) && ( ( nullk % 512 ) != 0 ) ) {
			break;
			bspPrintString ( "transportok\r\n" );
		}
		if ( Contlen == 0 ) {
			sprintf ( ( char * ) Txbuf , "%c%c%c%cIllegal operation%c" , 0x00 , 0x05 , 0x00 , 0x04 , 0x00 );
			len = 20;
			if ( bspethSend1 ( sock , ( uint8 * ) Txbuf , len ) != len ) /* send the data packet */
			{
				bspPrintString ( "Mismatch in number of sent bytes while trying to send mode error packet\r\n" );
			}
			break;
		}

	}
	tiks = tickGet ( ) - tiks;
	UARTprintf ( "\r\nTFTP file %s tarnsport take time :%dms\r\n" , pFilename , tiks );
	spd = ( float ) ( total ) / 1024.0;
	spd = spd / ( ( float ) ( tiks ) / 1000.0 );
	sprintf ( Txbuf , "TFTP speed %0.1fKB/S\r\n" , spd );
	UARTprintf ( "%s" , Txbuf );
	if ( nullk != total ) {
		UARTprintf ( "TFTP Transport Interrupt\r\n" );
	} else {
		UARTprintf ( "TFTP Transport OK\r\n" );
	}
	UARTprintf ( "File Size %d Tran Size %d\r\n" , nullk , total );
	if ( Txbuf ) {
		cmFree ( Txbuf );
	}
	return;

}

  TFTP  下载数据实现源码

static void tget ( int8 *pFilename , int32 nullk , meminterst *type , int sock )
{

	int32 len , i , j = 0;
	int8 *pDat;
	int8 *bufindex , *txbuf = NULL;
	int32 rxDatlen;
	int32 seqCont = 0;
	uint16 opcode = 0;
	uint32 tesflag = 0;
	uint32 total = 0;
	uint32 tiks , k;
	float spd;
	int32 blks;
	memInfo_st *info;
	txbuf = ( int8 * ) cmMalloc ( 512 );
	tiks = tickGet ( );
	ftfpLen = 0;
	while ( j < 10 ) {
		for ( i = 0; ( i < TIMEOUT ) ; i++ ) /* this for loop will just keep checking the non-blocking socket until timeout */
		{

			if ( ptftprxbuf->rxlen [ ptftprxbuf->posr ] > 0 ) {
				rxDatlen = ptftprxbuf->rxlen [ ptftprxbuf->posr ];
				ptftprxbuf->rxlen [ ptftprxbuf->posr ] = 0;
				pDat = ptftprxbuf->rxbuf [ ptftprxbuf->posr ];
				opcode = ptftprxbuf->rxbuf [ ptftprxbuf->posr ] [ 0 ] * 256 + ptftprxbuf->rxbuf [ ptftprxbuf->posr ] [ 1 ];
				if ( opcode == 3 ) {
					seqCont = pDat [ 2 ] * 256 + pDat [ 3 ];
					//写数据
					if ( type->flag == ExternFlash ) {
						flashWrite ( type->addr + ftfpLen , pDat + 4 , rxDatlen - 4 );
					} else if ( type->flag == ExSram ) {
						register uint8_t *src = ( uint8_t* ) ( type->baseaddr + type->addr + ftfpLen );
						memcpy ( src , pDat + 4 , rxDatlen - 4 );
					}

					ftfpLen = rxDatlen + ftfpLen - 4;
					if ( ( seqCont % 10 ) == 0 )
						ConsoleSendChar ( '*' );
					//--------------------------
					sprintf ( txbuf , "%c%c%c%c" , 0x00 , 0x04 , 0x00 , 0x00 );
					len = 20;
					txbuf [ 2 ] = ( seqCont & 0xFF00 ) >> 8;	//fill in the count (top number first)
					txbuf [ 3 ] = ( seqCont & 0x00FF );	//fill in the lower part of the count
					if ( bspethSend1 ( sock , ( uint8 * ) txbuf , len ) != len ) {

					}
					if ( rxDatlen != 516 ) {

						goto done;

					}
				}
				if ( opcode == 5 ) {
					goto done;
				}
				if ( opcode == 6 ) {
					if ( ( pDat [ 2 ] == 't' ) && ( pDat [ 3 ] == 's' ) && ( pDat [ 4 ] == 'i' ) && ( pDat [ 5 ] == 'z' ) && ( pDat [ 6 ] == 'e' ) ) {
						total = getNumint ( &pDat [ 8 ] );
						UARTprintf ( "File Attribute %s Addr:0x%08x Len:%d\r\n" , type->type , type->addr , total );
						info = ( memInfo_st* ) type->private;
						if ( ( info->endAddr + 1 ) < ( type->addr + total ) ) {
							bspPrintString ( "argc paramter Error\r\n " );
							sprintf ( ( char * ) txbuf , "%c%c%c%cIllegal operation%c" , 0x00 , 0x05 , 0x00 , 0x04 , 0x00 );
							len = 64;
						} else {
							if ( type->flag == ExternFlash ) {

								blks = total / info->sizeCell;
								if ( ( total % info->sizeCell ) != 0 ) {
									blks++;
								}
								for ( k = 0; k < blks ; k++ ) {
									flashEraseBlock ( k + type->addr / info->sizeCell );
									UARTprintf ( "ADDR %x,Erase blks %d %dByte \r\n" , type->addr+k* info->sizeCell , k + type->addr / info->sizeCell , info->sizeCell );
								}

							}
							sprintf ( txbuf , "%c%c%c%c" , 0x00 , 0x04 , 0x00 , 0x00 );
							len = 20;
						}
					}

					if ( bspethSend1 ( sock , ( uint8 * ) txbuf , len ) != len ) /* send the data packet */
					{
						bspPrintString ( "Mismatch in number of sent bytes while trying to send mode error packet\r\n" );
					}
				}

				ptftprxbuf->posr = ( ptftprxbuf->posr + 1 ) % FRAMESIZE;

				break;

			} else {
				bspDelay ( 10 );
			}
		}

		if ( i == TIMEOUT ) {
			j++;
			ConsoleSendChar ( '$' );
			sprintf ( txbuf , "%c%c%c%c" , 0x00 , 0x04 , 0x00 , 0x00 );
			len = 20;

			txbuf [ 2 ] = ( seqCont & 0xFF00 ) >> 8;	//fill in the count (top number first)
			txbuf [ 3 ] = ( seqCont & 0x00FF );	//fill in the lower part of the count
			if ( bspethSend1 ( sock , ( uint8 * ) txbuf , len ) != len ) {

			}

		} else {
			j = 0;
		}

	}
	done : if ( txbuf ) {
		cmFree ( txbuf );
	}
	tiks = tickGet ( ) - tiks;
	UARTprintf ( "\r\nTFTP file %s tarnsport take time :%dms\r\n" , pFilename , tiks );
	spd = ( float ) ( ftfpLen ) / 1024.0;
	spd = spd / ( ( float ) ( tiks ) / 1000.0 );
	sprintf ( txbuf , "TFTP speed %0.1fKB/S\r\n" , spd );
	UARTprintf ( "%s" , txbuf );
	if ( ftfpLen != total ) {
		UARTprintf ( "TFTP Transport Interrupt\r\n" );
	} else {
		UARTprintf ( "TFTP Transport OK\r\n" );
	}
	UARTprintf ( "File Size %d Tran Size %d\r\n" , total , ftfpLen );
	return;
}

集成到cmdline

void ht_tftp ( int8 argc , int8 * argv [ ] )
{
	int32 i;

	uint8 *tftpbuf = NULL;
	cmMemClearUseMax ( ); //
	if ( strcmp ( ( char const * ) argv [ 0 ] , "get" ) == 0 ) {
		tftpbuf = ( uint8* ) cmMalloc ( 1024 );
		if ( argc >= 4 )
			tftp_get_file ( argv , argv [ 1 ] , tftpbuf );
		else {
			bspPrintString ( "argc paramter Error\r\n " );
		}

		cmFree ( tftpbuf );
		cmMemGetUseMax ( );
	} else if ( strcmp ( ( char const * ) argv [ 0 ] , "put" ) == 0 ) {
		tftpbuf = ( uint8* ) cmMalloc ( 1024 );
		if ( argc >= 4 )
			tftp_put_file ( argv , argv [ 1 ] , tftpbuf );
		else {
			bspPrintString ( "argc paramter Error\r\n " );
		}
		cmFree ( tftpbuf );
		cmMemGetUseMax ( );
	} else if ( strcmp ( ( char const * ) argv [ 0 ] , "info" ) == 0 ) {
		UARTprintf ( "\tmemtype\t\tsize\t\tblks\t\tCell\r\n" );
		UARTprintf ( "-----------------------------------------------------------------------\r\n" );
		for ( i = 0; i < sizeof ( memInfo ) / sizeof(memInfo_st) ; i++ ) {
			UARTprintf ( "\t\b%s " , memInfo [ i ].memtype );
			UARTprintf ( "\r\t\t\t%dByte" , memInfo [ i ].sizeCell * memInfo [ i ].blks );
			UARTprintf ( "\r\t\t\t\t\t%d" , memInfo [ i ].blks );
			UARTprintf ( "\r\t\t\t\t\t\t\t%d\r\n" , memInfo [ i ].sizeCell );
		}
		UARTprintf ( "-----------------------------------------------------------------------\r\n" );
	} else if ( strcmp ( ( char const * ) argv [ 0 ] , "help" ) == 0 ) {

		UARTprintf ( "\tcmd(tftp put filename (a:f:s) )    Explain(put update data)\r\n" );
		UARTprintf ( "\tcmd(tftp get filename)             Explain(get down data)\r\n" );
		UARTprintf ( "\tcmd(tftp info)                     Explain(info memory information)\r\n" );

	} else {
		UARTprintf ( "Unknown command   - try 'tftp help' \r\n" );
	}
}
#define  tftpHelp "tftp:上传和下载数据"
CMD_DEFINE( tftp , tftpHelp , ht_tftp );

 

测试结果:

  1、查看内存设备信息

 2 读取环境变量

3、上传App1.bin 数据 

   输入run app1read 读取内部flash APP1程序段数据 速率600K左右

输入run framread 读取内部铁电数据 速度为9.7k 主要是因为铁电数据操作慢 接口为I2C接口

输入 tftp put sram.bin InRam a:0#f:1#s:10000# 读取内部内存数据

输入 tftp put flash.bin ExternFlash a:0#f:1#s:1000000# 读取外部flash 全部数据 16M字节

   2 下载数据

输入run t

到此TFTP 上传和下载基本实现

 

 

 

 

          

 

  • 1
    点赞
  • 0
    评论
  • 5
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:游动-白 设计师:白松林 返回首页

打赏作者

janet2013t

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值