flexPTP 1.0
An IEEE 1588 PTP implementation designed for microcontrollers
Loading...
Searching...
No Matches
ptp_port_stm32h743_etherlib.c
Go to the documentation of this file.
2
3#include <stdbool.h>
4#include <stdint.h>
5#include <stdlib.h>
6
7#include "FreeRTOS.h"
8#include "task.h"
9
10#include "stm32h7xx_hal.h"
11
12#include <flexptp_options.h>
13
14extern ETH_HandleTypeDef EthHandle;
15
16static unsigned sFreq = 1;
17
18void ptphw_set_pps_freq(double freq) {
19 #ifdef PPS_SIMPLE
20 int fc_exp;
21
22 if (freq > 0) {
23 fc_exp = round(log2f(freq)) + 1;
24
25 // lower limit
26 if (fc_exp < ETHHW_PTP_PPS_1Hz) {
27 fc_exp = ETHHW_PTP_PPS_1Hz;
28 }
29
30 // upper limit
31 if (fc_exp > ETHHW_PTP_PPS_16384Hz) {
32 fc_exp = ETHHW_PTP_PPS_16384Hz;
33 }
34
35 sFreq = exp2(fc_exp - 1);
36 } else {
37 sFreq = 0;
38 fc_exp = 0;
39 }
40
41 ETHHW_SetPTPPPSFreq(ETH, fc_exp);
42
43#elif defined(PPS_PULSETRAIN)
44 // convert to integer (integer only!)
45 uint32_t freq_Hz = (uint32_t)freq;
46
47 if (freq_Hz == 0) {
48 // stop pulse train generation
49 ETHHW_StopPTPPPSPulseTrain(ETH);
50 } else {
51 // compute period [ns]
52 uint32_t period_ns = NANO_PREFIX / freq_Hz;
53
54 // display warning if frequency is not integer divisor of 1E+09
55 if ((NANO_PREFIX % freq_Hz) != 0) {
56 MSG("Warning! PPS frequency is not totally accurate, "
57 "choose a frequency corresponding to a period "
58 "that is an integer divisor of 1E+09!\n");
59 }
60
61 // set duty cycle (try 50%) by specifying positive pulse length
62 uint32_t high_ns = period_ns / 2;
63
64 // start pulse train generation
65 ETHHW_StartPTPPPSPulseTrain(ETH, high_ns, period_ns);
66 }
67
68 // store frequency setting
69 sFreq = freq_Hz;
70#else
71#error "No decision was made on how the PPS signal is generated! Please define either PPS_SIMPLE or PPL_PULSETRAIN!"
72#endif
73}
74
76 double freq = sFreq;
79}
80
81#ifdef CLI_REG_CMD
82
83static int CB_pps(const CliToken_Type *ppArgs, uint8_t argc) {
84 if (argc >= 1) {
85 double freq = atof(ppArgs[0]);
87 }
88
89 if (sFreq > 0) {
90 MSG("PPS frequency: %u Hz\n", sFreq);
91 } else {
92 MSG("PPS output is turned off.\n");
93 }
94
95 return 0;
96}
97
98static void ptphw_register_cli_commands() {
99 CLI_REG_CMD("ptp pps {freq} \t\t\tSet or query PPS signal frequency [Hz]", 2, 0, CB_pps);
100}
101
102#endif // CLI_REG_CMD
103
104void ptphw_init(uint32_t increment, uint32_t addend) {
105 MSG("Turning PTP on!");
106
107 // enable PTP timestamping
108 ETHHW_EnablePTPTimeStamping(ETH);
109
110 vTaskDelay(pdMS_TO_TICKS(10));
111
112 // initialize PTP time
113 ETHHW_InitPTPTime(ETH, 0, 0);
114
115 // enable fine correction
116 ETHHW_EnablePTPFineCorr(ETH, true);
117
118 // set addend register value
119 ETHHW_SetPTPAddend(ETH, addend);
120
121 // set increment register value
122 ETHHW_SetPTPSubsecondIncrement(ETH, increment);
123
124 // ETH_StartPTPPPSPulseTrain(&EthHandle, 500E+06, 1E+09);
126
127 __HAL_RCC_GPIOG_CLK_ENABLE();
128
129 // setup PPS-pin
130 GPIO_InitTypeDef GPIO_InitStructure;
131 GPIO_InitStructure.Pin = GPIO_PIN_8;
132 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
133 GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
134 GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
135 GPIO_InitStructure.Pull = GPIO_NOPULL;
136 HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
137
138#ifdef CLI_REG_CMD
139 // register cli commands
140 ptphw_register_cli_commands();
141#endif // CLI_REG_CMD
142}
143
145 pTime->sec = ETH->MACSTSR;
146 pTime->nanosec = ETH->MACSTNR & ETH_MACSTNR_TSSS;
147}
#define CLI_REG_CMD(cmd_hintline, n_cmd, n_min_arg, cb)
void ptphw_set_pps_freq(double freq)
void ptphw_restart_pps()
ETH_HandleTypeDef EthHandle
static unsigned sFreq
void ptphw_gettime(TimestampU *pTime)
void ptphw_init(uint32_t increment, uint32_t addend)
Timestamp (unsigned)
Definition: timeutils.h:20
uint32_t nanosec
nanoseconds
Definition: timeutils.h:22
uint64_t sec
seconds
Definition: timeutils.h:21
#define NANO_PREFIX
Integer nano prefix.
Definition: timeutils.h:34