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

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

LCE
Principal II

Thanks for your setup code!

Unfortunately there must be something else, I still don't get anything from the PTP offload - otherwise ETH is working - so maybe there's something blocking this ? 

 

Anyway, are you already working somehow with the ETH's descriptors? Are you using the HAL driver for other ETH stuff? If yes, which IP stack if not LWIP?

It's not that simple...
You need to create an array and linked list of RX descriptors in a special internal SRAM range.

These descriptors must be initialized and handed over to DMA by setting the OWN bit (mind the necessary memory barriers) (and probably others), and assigning buffer addresses, and, ... 

Then the current RX descriptor can be polled by checking if DMA released it by resetting the OWN bit, then check some more descriptor bits, and so on.

 

Although I don't like and use it, the ETH HAL function can be used, or used as a basis.

max65
Associate II

Hello @LCE , I am calling the function when the link is up, that is:

 

	HAL_ETH_GetMACConfig(&heth, &MACConf) ;
	MACConf.DuplexMode = fullduplex ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE ;
	MACConf.Speed = centomega ? ETH_SPEED_100M : ETH_SPEED_10M ;
	HAL_ETH_SetMACConfig(&heth, &MACConf) ;

#ifdef USA_PTP
	PTP_ini(false/true) ;
#endif

	HAL_NVIC_EnableIRQ(ETH_IRQn) ;

	CONTROLLA(HAL_OK == HAL_ETH_Start_IT(&heth)) ;

 

I am not receiving/trasmitting so no desc is involved (to partially confirm this, I have used "live watch" in iar ewarm, and I don't see any change)

 

LCE
Principal II

Check 

ETH_DMARxDescListInit() in ETH HAL file.

But mind the placement of the descriptors in SRAM! Maybe check some examples for your H743.

You should start by reading the TX timestamps (master: SYNC, slave: Delay Request) when the interrupt occurs.

In your PTP offload setup add the interrupt enable, then write an interrupt handler.

/* enable interrupt for TX timestamp */
ETH->MACIER |= ETH_MACIER_TSIE;

...

void ETH_IRQHandler(void)
{

/* PTP target time reached ? */
	if( ETH->MACTSSR & ETH_MACTSSR_TSTARGT0 )
	{
		PTP_TargetTime_IRQHandler();
	}

/* PTP offload TX timestamp available ? */
	if( ETH->MACTSSR & ETH_MACTSSR_TXTSSIS )
	{
		PTP_TxTsis_IRQHandler();
	}

...

/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* ISR for PTP: TX timestamp */
void PTP_TxTsis_IRQHandler(void)
{
	/* MUST read status register to reset interrupt (?) */
	uint32_t u32TempReg = ETH->MACISR;
	u32TempReg = ETH->MACTSSR;
	UNUSED(u32TempReg);

	/* read TX timestamp here ?
	 *	NOTE: different register names in reference manual
	 *		MACTTSSNR -> MACTXTSSNR
	 *		MACTTSSSR -> MACTXTSSSR
	 */
	u32TxTsNano = ETH->MACTTSSNR;
	u32TxTsSecs = ETH->MACTTSSSR;
}