cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H743 PTP offload timestamps

max65
Associate II

Hello all,

I am developing ptp master and slave with offload.

Now I have a master sending the sync

max65_0-1751294125207.png

and a slave sending delay_req:

max65_1-1751294193182.png

with the master sending back delay_resp:

max65_2-1751294248439.png

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:

max65_3-1751294404413.png

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

3 REPLIES 3
LCE
Principal II

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...

 

LCE
Principal II

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:

    if( ((pDmaRxDescrCur->DESC3 & ETH_DMARXNDESCWBF_RS1V) != 0) &&
    ((pDmaRxDescrCur->DESC1 & ETH_DMARXNDESCWBF_TSA) != 0) )

  - 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;
				}
 
 
That's at least working with PTP over UDP with LWIP.

 

 

max65
Associate II

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;
}