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 上传和下载基本实现