星期一叙述了将eboot的tftp端口改一下,就可以和普通的tftp client通信。
从星期二到今天,一直就设法将eboot改成client模式,今天终于可以了。
1)初始化tftp是在EbootInitEtherTransport 函数中。tftp的连接首先由client发起,所以要在这个函数添加一个发请求的函数。很幸运的是MS已经实现了这个函数,只是有一点bug,需要修正。所以我们就用这个函数TFtpOpen发tftp请求。
这是又有一点注意事项:由于只发一次请求,所以如果这个RRQ request丢失的话,那么tftp肯定建立不起来,所以要确保这一点。但实际上在发这个请求的时候,网络的物理层还没有通,这时要在TFtpOpen之前加一个等待的过程:
while((OEMEthGetSecs() - dwCurSec) < 12);
当host的server收到RRQ的时候,就以DATA packet回应。这样,连路就通了。tftp连接建成。当然Eboot要收到DATA,才算真正建立。
2)下面进入读数据的环节。
Eboot读数据是用EbootEtherReadData。进入这个函数,我们发现它调用了一个tftp函数EbootTFtpReceiver。它读取数据,同时看是否是一个已建立的连接上传来的数据,如果是,那么返回,由下面的TFtpRead函数读取。如果不是,那么要建立一个新的连接,调用TFtpdFormNewLink,当然,这个DATA仍要读取。
3)TFTP的几个数据报格式:
TFTP Formats
Type Op # Format without header
2 bytes string 1 byte string 1 byte
-----------------------------------------------
RRQ/ | 01/02 | Filename | 0 | Mode | 0 |
WRQ -----------------------------------------------
2 bytes 2 bytes n bytes
---------------------------------
DATA | 03 | Block # | Data |
---------------------------------
2 bytes 2 bytes
-------------------
ACK | 04 | Block # |
--------------------
2 bytes 2 bytes string 1 byte
----------------------------------------
ERROR | 05 | ErrorCode | ErrMsg | 0 |
----------------------------------------
Initial Connection Protocol for reading a file
1. Host A sends a "RRQ" to host B with source= A's TID,
destination= 69.
2. Host B sends a "DATA" (with block number= 1) to host A with
source= B's TID, destination= A's TID.
我们再看一下TFtpOpen函数:
UINT16 TFtpOpen( EDBG_ADDR *pHostAddr, EDBG_ADDR *pMyAddr, char *pszFileName, TFtpLinkDir DataDir ) {
..............................
// Put in Read Request or Write Request as appropriate
*((UINT16*)(TFtpLinks[iLinkSlot].Buffer)) = htons((DataDir == H2OLink) ? 1 : 2);
TFtpLinks[iLinkSlot].cwMsgLen = 2;
// Put in the file name
strcpy( TFtpLinks[iLinkSlot].Buffer + 2, pszFileName );
TFtpLinks[iLinkSlot].cwMsgLen += strlen( pszFileName );
// add NULL terminate
*(TFtpLinks[iLinkSlot].Buffer + TFtpLinks[iLinkSlot].cwMsgLen) = '\0';
TFtpLinks[iLinkSlot].cwMsgLen++;
// Specify octet (binary) mode
strcpy( TFtpLinks[iLinkSlot].Buffer + TFtpLinks[iLinkSlot].cwMsgLen, "octet" );
TFtpLinks[iLinkSlot].cwMsgLen += 6;
// add NULL terminate
*(TFtpLinks[iLinkSlot].Buffer + TFtpLinks[iLinkSlot].cwMsgLen) = '\0';
TFtpLinks[iLinkSlot].cwMsgLen++;
......................................
}
从上面可以看出它填充了RRQ的每一个域。其中
*(TFtpLinks[iLinkSlot].Buffer + TFtpLinks[iLinkSlot].cwMsgLen) = '\0';
*(TFtpLinks[iLinkSlot].Buffer + TFtpLinks[iLinkSlot].cwMsgLen) = '\0';
这两行是修正bug的。从RRQ的format可以看出filename和mode后面都有一个字节的NULL。
4)由于Eboot做了client,需要在pc端装一个server,我从HTTP://WWW.WINAGENTS.COM下了一个server端,将root directory配置成nk.bin所在的目录。然后将build好的Eboot.nb0烧到目标板里面。上电,你就什么都不用做,就将nk.bin download到目标板里面。
当然还要是release版本。而且不能自动boot。(关于这个问题,我看了新闻组,说download完成pb会发一个boot命令。目前还没有看到这段代码)
所以要重新上电,然后按space,选择L,就可以了。
还忘记了一个有趣的东西。
昨天景阳要我测试一下624MHz板子能否运行,我就改了代码,让eboot运行在624MHz。
今天在做client的时候,eboot也一直工作在624MHz。今天上午用client模式download发现总是download大概30个data packet时,就失败,当时总是找不到原因。
下午将eboot改为调用正常的eboot.lib,然后download,发现中途总是失败。我当时怀疑是不是板子出了问题。然后烧一个以前备份的一个eboot,再download,居然正常。
这才突然想起来,频率作了改动。
将频率改成520MHz,然后用client模式download,OK!