2025-06-30 7:46 AM - last edited on 2025-06-30 8:53 AM by mƎALLEm
Hello all,
I am developing ptp master and slave with offload.
Now I have a master sending the sync
and a slave sending delay_req:
with the master sending back delay_resp:
Given this message exchange, the slave should be able to correct its time, but, to do this, it needs some timestamp.
Referring to figure 788:
How can I (the slave) get t1,..,t4?
Thank you
P.S.
Every delay_req has :
originTimestamp (seconds): 0
so it seems that hw does not correct the timestamp
2025-06-30 9:22 AM
The PTP offload does NOT do any time correction, it only takes care of the messaging, which is quite a lot.
You need to get the t1 .. t4 timestamps from the TX & RX descriptors, then do the correction stuff by yourself.
But I'm really curious, because last week I failed to get any message from the PTP offload.
1) Is your master another STM32H7 ?
2) What are your register settings / contents for
- ETH->MACTSCR
- ETH->MACPOCR
- ETH->MACLMIR
- ETH->MACIER
?
ST doesn't give any answers concerning PTP offload.
And that's very frustrating, I have all that ethernet stuff running smoothly (no HAL), but can't get this working...
2025-06-30 9:41 AM - edited 2025-06-30 9:43 AM
Warning: this is all theory by reference manual for the H723 .. H735 series - and I don't have this working!
Timestamps & descriptors:
TX:
- set the TX timestamp enable interrupt: ETH->MACIER |= ETH_MACIER_TSIE;
- get the TX timestamp in the interrupt handler from:
ETH->MACTTSSNR and ETH->MACTTSSSR (attention: these registers are called MACTXTSSNR / MACTXTSSSR in RM0468)
RX:
- check each RX descriptor group for:
- write back format:
if( (pDmaRxDescrCur->DESC3 & ETH_DMADESC_CTXT) == 0 )
- last descriptor in chain:
if( pDmaRxDescrCur->DESC3 & ETH_DMADESC_LD )
- valid & timestamp available:
- then PTP message check, timestamp is in next descriptor (CONTEXT)
/* check message type for:
* SYNC -> t1 (slave, from master)
* DELAY REQUEST -> t3 (master, from slave)
*/
if( (pDmaRxDescrCur->DESC1 & ETH_DMARXNDESCWBF_PMT_SYNC) != 0 )
{
((EthDmaDescr_t *)pDmaRxDescrCur->pNext)->u32Flags |= ETH_DESCR_FLAG_RX_PTP_SYNC;
}
else if( (pDmaRxDescrCur->DESC1 & ETH_DMARXNDESCWBF_PMT_DREQ) != 0 )
{
((EthDmaDescr_t *)pDmaRxDescrCur->pNext)->u32Flags |= ETH_DESCR_FLAG_RX_PTP_DLRQ;
}
2025-06-30 11:14 PM
Thank you @LCE , but I am not using lwip to send/receive udp packets, so it is not clear how can I get timestamps from tx/rx descriptors: can you spend some word about this?
This is my code:
void PTP_ini(bool master)
{
uint32_t mactscr = MACTSCR_TXTSSTSM | MACTSCR_TSIPENA | MACTSCR_TSVER2ENA | MACTSCR_TSCTRLSSR | MACTSCR_TSENA;
if (master) {
mactscr |= MACTSCR_SNAPTYPSEL(0) | MACTSCR_TSMSTRENA | MACTSCR_TSEVNTENA;
}
else {
mactscr |= MACTSCR_SNAPTYPSEL(0) | MACTSCR_TSEVNTENA;
}
ETH->MACTSCR = mactscr;
if (master) {
// imposto data
// clk_ptp_ref_i Digital input PTP reference clock input. This input is connected to eth_hclk clock
uint32_t nani = 1000000000 / HAL_RCC_GetHCLKFreq();
if (0 == nani) {
nani = 1;
}
ETH->MACSSIR = MACSSIR_SSINC(nani);
ETH->MACSTSUR = 1751269181;
ETH->MACSTNUR = 0;
// This bit should be zero before it is updated
while ((ETH->MACTSCR & MACTSCR_TSINIT) == MACTSCR_TSINIT) {
}
ETH->MACTSCR |= MACTSCR_TSINIT;
// This bit is reset when the initialization is complete
while ((ETH->MACTSCR & MACTSCR_TSINIT) == MACTSCR_TSINIT) {
}
}
// offload
uint32_t macpocr = MACPOCR_DN(0) | MACPOCR_PTOEN;
if (master) {
macpocr |= MACPOCR_ASYNCEN;
ETH->MACLMIR = MACLMIR_LSI(1);
}
else {
ETH->MACLMIR = MACLMIR_DRSYNCR(0);
}
ETH->MACPOCR = macpocr;
// clockidentity || sourceportid ==
// MACSPI2R || MACSPI1R || MACSPI0R
uint32_t tmp;
CONTROLLA(HAL_OK == HAL_RNG_GenerateRandomNumber(&hrng, &tmp));
// sourceportid = 0x0001
tmp &= 0xFFFF0000;
tmp |= 1;
ETH->MACSPI0R = tmp;
CONTROLLA(HAL_OK == HAL_RNG_GenerateRandomNumber(&hrng, &tmp));
ETH->MACSPI1R = tmp;
CONTROLLA(HAL_OK == HAL_RNG_GenerateRandomNumber(&hrng, &tmp));
tmp &= 0xFFFF;
ETH->MACSPI2R = tmp;
}
: