移植的PTP为linux上ptpd。目标为FRDM-K64F。
目的
记录下主要问题,日后好回顾整个过程。
关于为什么要移植,而不是完全自己编写呢?
1.因为源码中有很多数据结构,报文结构,数学公式都可以直接用,这些内容即便自己写出来,和人家的也是一样的,所以就偷懒直接用了,而且省去了逐个字节和协议文档对照的麻烦。
2.代码部分就不照搬了,因为绝大部分编译不过去,而且K64上面资源有限,也不能安装文档把功能全部实现,要不其它的功能怎么办呀,这毕竟只是其中很小一个部分,不适合占用大量的内存和存储资源。
3.可以按照它的路径逐步实现,也好有个参照,能加快进度,毕竟之前没做过这个,网上的文章大多都是纸上谈兵,没有什么参考价值。
关于实时操作系统:
一个好的实时操作系统确实能提供很多方便,不同的人对好的定义不同,我对好的定义是简单、明确的架构,方便我删改里面的任何内容,而不会给我造成任何累赘,满足这个要求有点难,所以就不用实时操作系统,反正也没什么必要,操作系统那些原理都清楚,为了免得给自己找麻烦,就不要操作系统了,这样反而对代码的控制性更强,很容易提高代码的健壮性和可维护性。
下面开始移植第一步:头文件
将各种头文件的什么都放到目录中去,因为我们需要的数据结构都在里面,编译通过就行,用的时候在具体看,这个过程不记录了。
第二步:编写PTP状态机和入口函数。
// 状态切换函数,原状态的退出函数调用,新状态的进入函数调用。
void toState(UInteger8 state, const RunTimeOpts *rtOpts, PtpClock *ptpClock);
// 状态机代码
Enumeration8 doState(RunTimeOpts *rtOpts, PtpClock *ptpClock, Octet *frame);
// 从网络接收到的报文的处理函数。
void processMessage(RunTimeOpts *rtOpts, PtpClock *ptpClock, TimeInternal *timeStamp, unsigned int length);
//*****************************************************************
// 这个函数在K64启动的时候执行一次。
// 用于设置代码的初始状态。
//*****************************************************************
void PTPSM_INIT()
{
ptpClock.portDS.portState = PTP_INITIALIZING;
}
//*****************************************************************
// 针对无操作系统的代码。
// 1.在K64的主循环中调用,每个循环调用一次,参数中传入NULL。
// 2.在网络接口处调用,参数中传入PTP报文。
//*****************************************************************
void PTPSM_ONE(void* frame_, u16_t len_)
{
TimeInternal time;
void GetPtp1588Timer(TimeInternal *ptpTime);
GetPtp1588Timer(&_time);
processMessage(&rtOpts, &ptpClock, &_time , sizeof(_time));
doState(&rtOpts, &ptpClock, (Octet*) frame_);
toState(0, &rtOpts, &ptpClock);
}