2025-05-02 1:05 AM
Hello
I’m busy with the implementation of PTP support inside my project.
I choose the STM32H745, because there is PTP support in hardware, with a nice offload function. After reading and try to understand the manual I create this code:
uint32_t SubSecondValue = 43;
#define ADJ_FREQ_BASE_ADDEND 0x35455A81
// Mask the Timestamp Trigger interrupt by clearing bit 12 of Interrupt enable register (ETH_MACIER).
heth->Instance->MACIER &= ~(ETH_MACIER_TSIE);
// Set bit 0 of Timestamp control Register (ETH_MACTSCR) to enable timestamping.
//heth->Instance->MACTSCR |= 1; // Done at the END! :)
//Program Subsecond increment register (ETH_MACSSIR) based on the PTP clock frequency.
heth->Instance->MACSSIR = (SubSecondValue<<16);
// if you use the Fine Correction method, program Timestamp addend register (ETH_MACTSAR) and set bit 5 of Timestamp control Register (ETH_MACTSCR)
heth->Instance->MACTSAR = ADJ_FREQ_BASE_ADDEND;
heth->Instance->MACTSCR |= ETH_MACTSCR_TSADDREG;
/* Poll the Time stamp control register until bit 5 is cleared. */
while(ETH_GetPTPFlagStatus(heth, ETH_PTP_FLAG_TSARU) == SET);
/* Enable the PTP Fine Update method Fine*/
heth->Instance->MACTSCR |= ETH_MACTSCR_TSCFUPDT;
/* Program the Time stamp high update and Time stamp low update registers
* with the appropriate time value. */
/* Set the PTP Time Update High Register */
heth->Instance->MACSTSUR = 0;
/* Set the PTP Time Update Low Register with sign */
heth->Instance->MACSTNUR = ETH_PTP_PositiveTime | 0;
/* Set Time stamp control register bit 2 (Time stamp init). */
heth->Instance->MACTSCR |= ETH_MACTSCR_TSINIT;
/* Set PPS frequency to 128 Hz */
heth->Instance->MACPPSCR = 7;
// Source: RM0399 Page 3039
// 1. Program SNAPTYPSEL, TSMSTRENA and TSEVNTENA fields of Timestamp control Register (ETH_MACTSCR) to 0, 0, and 1 respectively.
heth->Instance->MACTSCR &= ~((0b00)<<16); // Clear SNAPTYPSEL
heth->Instance->MACTSCR &= ~((0b0)<<15); // Clear TSMSTRENA
heth->Instance->MACTSCR |= (1 << 14); // Set TSEVNTENA
// 2. Program the PTOEN bit and DN field of PTP Offload control register (ETH_MACPOCR) to enable PTP Offload feature and domain Number to match with ingress PTP Sync message and send in egress PTP Delay_Req message.
heth->Instance->MACPOCR &= ~((0b00000000)<<8); // Set Domain number to 0
heth->Instance->MACPOCR |= 4; // Set APDREQEN
// 3. Program the 80-bit Source Port Identity in PTP Source Port Identity 0 Register (ETH_MACSPI0R), PTP Source port identity 1 register (ETH_MACSPI1R) and PTP Source port identity 2 register (ETH_MACSPI2R) to match with ingress PTP Sync message and send in egress PTP Delay_Req message.
heth->Instance->MACSPI0R = 0x57ffec79;
heth->Instance->MACSPI1R = 0xfe81d0c8;
heth->Instance->MACSPI2R = 0x0001;
// 4. Program the DRSYNCR field in Log message interval register (ETH_MACLMIR) to indicate one PTP Delay_Req message is generated in response to how many received PTP Sync messages.
heth->Instance->MACLMIR |= (2<<24);
heth->Instance->MACPOCR |= 1; // Set PTOEN
This code is called just before “low_level_init” returns.
What I try to do: I want to implement PTP Slave device that reacts on PTP message and try to synchronize the time inside the hardware counter. Without any software interaction, hardware offload.
When I sniff with Wireshark nothing happens, there is no communication send from the STM to the PTP master. What do I wrong?
My PTP master, is a off the shelve box specially made for PTP. The SYNC and Follow up data packets are sending though the network.
My ClockIdentity: 0xd0c857fffe81ec79
SourcePortID: 0x0001
2025-05-06 9:30 AM
2025-05-13 11:02 PM - edited 2025-05-13 11:23 PM
Since my heavily modified PTPd code is working (without any extra STM32H7 hardware features), I didn't have another look at the hardware capabilities, and it's very low down on my priority list.
I have no idea how far the "automation" of the messages and replies is working.
Right now I cannot imagine that the hardware is creating any UDP messages which are needed for SYNC reply and DELAY REQUEST.
Anyway, you'll need a lot of filtering to control the slave clock, in PTPd a PI controller and a low pass is used for TMS and TSM timing results. I had to adjust these settings, and add some kind of "lucky packet filtering".
But I'm curious, just reading the H723 RM...
Edit: in general it is helpful - mostly for yourself, but also to others reading your code - to use the pre-defined bits / bitmasks from the stm32h7yyxx.h file, like:
heth->Instance->MACTSCR |= ETH_MACTSCR_TSEVNTENA;
2025-05-14 12:09 AM - edited 2025-05-14 12:28 AM
It looks like it does support message generation (except for follow up as master, but that should not be necessary).
I would start with checking if the PTP messages from the master are actually received, so check the received descriptors for the PTP flags, and toggle a LED or use the UART.
2025-05-15 10:21 PM
Have you made any progress or got new insights?
2025-05-17 9:23 AM
Many Thanks for your answer and suggestion.
I'm just back from a business trip and try to adapt my code to do some debugging.
I shoos the STM32H7 series specially for the PTP support offloading. When i read the manual, the hardware is able to create al the "magic" stuff to-do this... But at ST nobody have some example... How do they test there hardware? We need to do this?
2025-05-19 12:19 AM
Let's hope that they tested that.
But yes, it's really disappointing that they never published any example code for the H7's PTP features.
2025-05-19 10:28 PM
Hello
Here the first test:
No PTP on the network, there is is no output from the printf.
When the PTP master is active i received the "Sync Inside", so there is "live".
if((ETH->MACTSSR & 0x008000) > 1){
printf("Sync Inside! \r\n");
}
When i debug with wire shark there is no packet send by the STM. It is enabled (of at least it was the intention :) )
Any suggestion what i can try more?
2025-05-19 11:29 PM
I would check again the registers how delay request messages are triggered.
Also the IO port ID settings, and compare this with what's in the SYNC message.
2025-05-19 11:47 PM
Sourceport ID = 0x0001
My ID is: 0xD0C857FFFE81EC79
In combination to get an 80 bit number: 0xD0C857FFFE81EC790001
I programmed this in this way:
heth->Instance->MACSPI0R = 0xEC790001;
heth->Instance->MACSPI1R = 0x57FFFE81;
heth->Instance->MACSPI2R = 0x0000D0C8;
Is this correct?