1.引言
本文章基于stm32官方例程实现,详细代码可下载例程。
在RT-thread系统上实现1588协议,网络驱动上需要做较多的修改。
2.代码修改
2.1驱动分析
当Accumulator register,溢出之后,会增加subsecond register一个步长,这个步长为constant value;每个时钟周期 Accumulator register会加上 addend register的值,这样做的目的是调整 subsecond register 增加的周期。
为Accumulator register提供clock的位系统时钟 HCLK,一般为72MHz,而 subsecond register 增加的频率需要为50MHz。
subsecond register的最大值为2^31,把2^31作为1秒钟,那么每20ns subsecond register需要增加 20ns * (2^31) / 10^9ns = 43 ,即constant value 为43.。
Accumulator register 溢出时间为 49 *10^9 / (2^31) ~= 20.023ns
Addend / 2^32 = (1 / 20ns) /72mhz 换算单位之后 Addend = 2979125334.90
2.2驱动层的修改
原代码的DMA描述符如下:
static ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];
//STM32的MAC加入时间戳时,会将描述符的地址覆盖,
//所以需要将地址提前保存起来,MAC的时间戳读出来之后,再将地址写回去。
//再创建两个描述符用于保存地址
ETH_DMADESCTypeDef DMAPTPRxDscrTab[ETH_RXBUFNB], DMAPTPTxDscrTab[ETH_TXBUFNB];/* Ethernet Rx & Tx PTP Helper Descriptors */
2.3发送函数的更改
rt_err_t rt_stm32_eth_tx( rt_device_t dev, struct pbuf* p)
{
struct pbuf* q;
rt_uint32_t offset = 0;
unsigned char * buffer;
/* get free tx buffer */
{
rt_err_t result;
result = rt_sem_take(&tx_buf_free, 2);
if (result != RT_EOK) return -RT_ERROR;
}
#if LWIP_PTP
unsigned int timeout = 0;
struct ptptime_t timestamp;
DMATxDescToSet->Buffer1Addr = DMAPTPTxDescToSet->Buffer1Addr; //保存地址
DMATxDescToSet->Buffer2NextDescAddr = DMAPTPTxDescToSet->Buffer2NextDescAddr;
#endif
buffer = (unsigned char *)DMATxDescToSet->Buffer1Addr;
for (q = p; q != NULL; q = q->next)
<