2024-07-11 01:44 PM
Hi,
I have a ported version of PTPD working on my Stm32h723. Right now, I have the ETH_MACTSCR_TSENALL bit set so that every packet gets timestamped. This is, however, wasteful since it means every single packet rx, be it ptp or not uses an extra eth dma descriptor for the timestamp.
I now want to configure the mac to only timestamp PTP packets, but no matter what settings I use in MACTSCR, I cannot get this to work. Unless TSENALL is set, regardless of the rest of the MACTSCR settings, I either get no PTP packets coming through or PTP packets without timestamps. I do not want any automatic generation of messages, I just want rx timestamps on PTP packets only.
I don't really understand or believe the Stm32h723 reference manual with regard to the MACTSCR bits. For example, table 560 shows that with TSEVNTENA set, only a subset of the event messages are included at best. This doesn't make any sense, given that this bit is supposed to include event packets specifically. In table 560, I want to select all of the event messages, so I'd want all four bits (SNAPTYPSEL0,1 TSMSTRENA TSEVNTENA) cleared. That doesn't make sense to me, that you'd only ever be able to timestamp all event messages if this bit is cleared.
My setup is: Ieee1588v2 sent over PTP frames (ie, not UDP). I want the mac to capture the timestamp of ONLY all event messages (SYNC, Follow_Up, Delay_Req, Delay_Resp). I do not want the mac to auto generate messages.
What are the correct bits to set for that goal?
Thanks,
2024-07-11 02:56 PM
While debugging, I noticed that when I'm "not getting packets". It's because HAL_ETH_ErrorCallback is getting called and DMACSR = 0x1100. This is reporting a fatal bus error. This happens when I have the following ptp init squence:
static void InitMac1588v2(void)
{
// RM0468 Rev 3 2925/3357
// 1. Mask the Timestamp Trigger interrupt by clearing bit 12 of Interrupt enable register (ETH_MACIER).
//__HAL_ETH_MAC_DISABLE_IT(&EthHandle, ETH_MAC_TIMESTAMP_IT);
CLEAR_BIT(EthHandle.Instance->MACIER, ETH_MACIER_TSIE);
// 2. Set bit 0 of Timestamp control Register (ETH_MACTSCR) to enable timestamping.
SET_BIT(EthHandle.Instance->MACTSCR, ETH_MACTSCR_TSENA);
// Enable timestamping of all packets
SET_BIT(EthHandle.Instance->MACTSCR, ETH_MACTSCR_TSVER2ENA);
// 3. Program Subsecond increment register (ETH_MACSSIR) based on the PTP clock frequency.
WRITE_REG(EthHandle.Instance->MACSSIR, 43 << 16);
// 4. If you use the Fine Correction method,
// program Timestamp addend register (ETH_MACTSAR) and set bit 5 of Timestamp control Register (ETH_MACTSCR)
WRITE_REG(EthHandle.Instance->MACTSAR, PTP_ADDEND);
SET_BIT(EthHandle.Instance->MACTSCR, ETH_MACTSCR_TSADDREG);
// 5. Poll the Timestamp control Register (ETH_MACTSCR) until bit 5 is cleared.
while (READ_BIT(EthHandle.Instance->MACTSCR, ETH_MACTSCR_TSADDREG))
{
}
// 6. Program bit 1 of Timestamp control Register (ETH_MACTSCR) to select the Fine Update method (if required).
SET_BIT(EthHandle.Instance->MACTSCR, ETH_MACTSCR_TSCFUPDT);
// 7. Program System time seconds update register (ETH_MACSTSUR) and System time
// nanoseconds update register (ETH_MACSTNUR) with the appropriate time value.
EthHandle.Instance->MACSTSUR = 0;
EthHandle.Instance->MACSTNUR = 0;
// 8. Set bit 2 in Timestamp control Register (ETH_MACTSCR).
SET_BIT(EthHandle.Instance->MACTSCR, ETH_MACTSCR_TSINIT);
EthHandle.IsPtpConfigured = HAL_ETH_PTP_CONFIGURED;
}
Any ideas why? It works fine if I only set TSENA.
2024-07-12 04:20 AM
Does the MAC generate any auto messages when TSENALL is enabled?
Not here...
When checking any received ethernet frames, I first check for "context type" (after some basic checks that the current descriptor's OWN bit is not set and that the current descr pbuf != NULL), if yes the pbuf is instantly freed, then I check the descriptor's flag "waiting for timestamp", if yes the timestamp is copied from the descriptor to the first RX pbuf (I added timestamps to the pbuf struct) in the chain, if not nothing's done.
So I have TSENALL enabled all the time.
Do you have some other bits enabled elsewhere?
Anyway, here's my PTP setup:
/* PTP / MAC control register setup
* and increment & addend calculation, depending on internal PTP clock
*/
uint8_t ETH_PtpStart(uint8_t u8PtpUpdate)
{
uint8_t u8RetVal = 0;
uint32_t u32TempReg = 0;
/* set clock variables */
dflPTP_ClkRef_Hz = (double)HAL_RCC_GetHCLKFreq();
dflPTP_AccClk_ns = (double)(1.0 / dflPTP_ClkRef_Hz);
/* 1. Mask the time stamp trigger interrupt */
ETH->MACIER &= ~ETH_MACIER_TSIE;
/* reset interrupt flag */
u8PtpTargetIrqFlag = 0;
/* 2. Program time stamp register bit 0 to enable time stamping. */
/* Enable the PTP time stamp for transmit and receive frames, IPv4, IPv6, PTPv2 */
u32TempReg = ( ETH_MACTSCR_TSENA | ETH_MACTSCR_TSVER2ENA |
ETH_MACTSCR_TSIPV4ENA | ETH_MACTSCR_TSIPV6ENA |
ETH_MACTSCR_TSENALL );
ETH->MACTSCR = u32TempReg;
if( u8PtpUpdate == PTP_UPDATE_FINE )
{
/* 5. Poll the time stamp control register until bit 5 is cleared. */
u8RetVal = PTP_PollCSBitClear(ETH_MACTSCR_TSADDREG, PTP_TIMEOUT_MS_TSADDREG);
if( u8RetVal ) Error_Handler_FL(__FILE__, __LINE__);
/* 6. To select the fine correction method program time stamp control register bit 1. */
ETH->MACTSCR |= ETH_MACTSCR_TSCFUPDT;
}
else
{
ETH->MACTSCR &= ~ETH_MACTSCR_TSCFUPDT;
}
/* rollover bit TSCTRLSSR selects between full nanoseconds and sub ns
* -> MUST use sub nano, otherwise PPS output is useless
* -> NOT set
*/
ETH->MACTSCR &= ~ETH_MACTSCR_TSCTRLSSR;
/* 3. Program the sub-second increment register based on the PTP clock frequency. */
/* 4. Program the time stamp addend register and set time stamp control register bit 5
* (addend register update).
*/
u8RetVal = PTP_CalcIncrAdnd((float)dflPTP_ClkRef_Hz);
if( u8RetVal ) Error_Handler_FL(__FILE__, __LINE__);
u32PtpAddendStart = u32PtpAddend;
/* 7. Program the time stamp high update and time stamp low update registers with the
* appropriate time value. (can be zero)
*/
/* Reset Time stamp high update and Time stamp low update registers */
ETH_SetPtpTimeStampUpdate(ETH_PTP_PositiveTime, 0, 0);
/* 8. Set time stamp control register bit 2 (time stamp init). */
u8RetVal = PTP_CtrlBit_Update(ETH_MACTSCR_TSINIT, PTP_TIMEOUT_MS_CTRLBU);
if( u8RetVal ) Error_Handler_FL(__FILE__, __LINE__);
/* 9. The time stamp counter starts operation as soon as it is initialized with the value written
* in the time stamp update register.
*/
/* 10. Enable the MAC receiver and transmitter for proper time stamping. */
/* -> ethernetif.c EthLowLevelInit() */
/* set PPS output (PB5, set in ethernetif.c) to default frequency */
ETH->MACPPSCR = PTP_PPS_OUT_FDEF;
/* set ingress (RX) & egress (TX) correction registers,
* fixed offsets depending on PHY
* ingress value must be negative, depends on TSCTRLSSR
* NOTE: absolutely useless... or wrong?
*/
#if( 0 )
float flVal = (float)PTP_H7_RX_CORRECT_DEF / (float)PTP_SUBSEC_REG_RES_NS;
u32TempReg = 0x8000000; // 2^31;
u32TempReg -= (uint32_t)flVal;
u32TempReg |= 0x80000000;
ETH->MACTSICNR = u32TempReg;
ETH->MACTSECNR = PTP_H7_TX_CORRECT_DEF;
#else
ETH->MACTSICNR = 0;
ETH->MACTSECNR = 0;
#endif
return u8RetVal;
}
2024-07-12 06:19 AM
Hey @LCE , in your setup, I *think* (but would like ST to please check me on?) that TSENALL will basically override the other bits (ETH_MACTSCR_TSVER2ENA | ETH_MACTSCR_TSIPV4ENA | ETH_MACTSCR_TSIPV6ENA) (in the case of (ETH_MACTSCR_TSVER2ENA, I think that it doesn't matter if v1 or v2 is selected because you are just wholesale timestamping ever packet).
I'm hoping to set mine up so that only PTP packets are timestamped.
There is something in your description though, that caught my eye: You mention that if you get a context type descriptor you immediately free it's pbuf? So in my implementation I don't do that, I just return that descriptor to DMA. My thinking was that the pbuf address is still in the descriptor internally and it hasn't been used, so no need to free it. What do you think? (ST, can you *please* tell me if that is the right approach?)
LCE, I attached my code if you want to take a look at how I'm doing it. This implementation does work, I just wanted to get away from timestamping every frame though.
2024-07-12 07:03 AM
Well... I'm not using HAL and no OS - and I'm rather a hardware guy...
I think you can skip timestamping every RX packet if you check RX descriptor 3 for the "context" flag, which indicates that the hardware actually captured the timestamp exactly when the MAC rxd the packet, then copy the timestamp from DESC0 & DESC1.
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* check CONTEXT bit -> PTP timestamp
* CONTEXT format:
* further bits should not be set in DESC3, so we can
* proceed as with non-context descriptors
*/
__DMB();
if( pDmaRxDescrCur->DESC3 & ETH_DMADESC_CTXT )
{
/* always free CONTEXT descriptor's pbuf, it was NOT used anyway */
pbuf_free(pDmaRxDescrCur->pPbuf);
/* check wait for timestamp flag */
if( pDmaRxDescrCur->Flags & ETH_DESCR_FLAG_RX_WT_PTP )
{
u8RxPktRdy = 1;
#if LWIP_PTP_HW
/* save timestamp to RX first descriptor's pbuf */
pPbufRxFirst->time_sec = pDmaRxDescrCur->DESC1;
pPbufRxFirst->time_nsec = ETH_PtpSubSecond2NanoSecond(pDmaRxDescrCur->DESC0);
#endif /* LWIP_PTP_HW */
}
}
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* WRITE-BACK format: data received from here on */
else
{
2024-07-12 07:04 AM - edited 2024-07-12 07:07 AM
It's really ridiculous how good I'm at forgetting things...
I think the MAC auto-detects that it received a PTP packet, that's how it sets the context bit and auto-copies the timestamp to DESC0/1.
The MAC can do some PTP message detection, but I still haven't build that into my ethernet driver / PTPd, but checking for the context bit and then copying is a must. And works.
2024-07-15 02:08 PM
Bump. ST, can you please reply with the correct MACSCR (And any other related bitfields) settings to get the MAC to timestamp only PTP packets?
2024-07-18 05:41 AM
Hello @chris1seto ,
I'm actively trying to support you on this issue on your other thread.
I'll come back to you as soon as possible.
Regards