flexPTP 1.0
An IEEE 1588 PTP implementation designed for microcontrollers
Loading...
Searching...
No Matches
task_ptp.c
Go to the documentation of this file.
1#include "task_ptp.h"
2
3#include <string.h>
4
5#include "config.h"
6#include "event.h"
7#include "msg_buf.h"
9#include "profiles.h"
10#include "ptp_core.h"
11#include "ptp_defs.h"
12#include "ptp_types.h"
13#include "settings_interface.h"
14
15#include <flexptp_options.h>
16#include <time.h>
17
18#include "minmax.h"
19
20#ifdef FLEXPTP_OSLESS
21#include "port/osless/fifo.h"
22#endif
23
24// ---------------------------
25
26#ifdef FLEXPTP_NON_LINUX_OS
27#ifdef FLEXPTP_FREERTOS
28static TaskHandle_t sTH; // task handle in direct FreeRTOS mode
29#elif defined(FLEXPTP_CMSIS_OS2)
30static osThreadId_t sTH; // task handle in CMSIS OS2 mode
31#endif
32static void task_ptp(void *pParam); // task routine function in non-Linux mode
33#elif defined(FLEXPTP_LINUX)
34static pthread_t sTH; // thread handle in Linux mode
35static void *task_ptp(void *pParam); // thread routine in Linux mode
36#elif defined(FLEXPTP_OSLESS)
37void task_ptp(void); // osless task function
38#endif
39
40// ---------------------------
41
42static bool sPTP_operating = false; // does the PTP subsystem operate?
43
44// ---------------------------
45
47#define S (gPtpCoreState)
49
50// ---------------------------
51
52#define RX_PACKET_FIFO_LENGTH (16)
53#define TX_PACKET_FIFO_LENGTH (16)
54
55// FIFO for incoming packets
56#if defined(FLEXPTP_NON_LINUX_OS) || defined(FLEXPTP_OSLESS)
57#define EVENT_FIFO_LENGTH (16)
58#define NOTIFICATION_FIFO_LENGTH (16)
59#define TX_CALLBACK_FIFO_LENGTH (10)
60#endif
61
62#define TX_TTL_MS (2000)
63#define RX_TTL_MS (2000)
64
65// -----------------------------
66
70typedef enum {
71 PTN_NONE = 0x00,
72 PTN_RECEIVE = 0x01,
73 PTN_TRANSMIT = 0x02,
75 PTN_EVENT = 0x08
77
81typedef struct {
82 uint32_t uid;
83 uint32_t seconds;
84 uint32_t nanoseconds;
85} TxTs;
86
87// -----------------------------
88
90
91// hearbeat timer
92#ifdef FLEXPTP_FREERTOS
93static TimerHandle_t sHeartBeatTmr;
94#elif defined(FLEXPTP_CMSIS_OS2)
95static osTimerId_t sHeartBeatTmr;
96#elif defined(FLEXPTP_LINUX)
97static timer_t sHeartBeatTmr;
98#endif
99
100// queues for message reception and transmission
101#ifdef FLEXPTP_FREERTOS
102static QueueHandle_t sEventFIFO;
103static QueueHandle_t sRxPacketFIFO;
104static QueueHandle_t sTxPacketFIFO;
105static QueueHandle_t sNotificationFIFO;
106static QueueHandle_t sTxCbFIFO;
107#elif defined(FLEXPTP_CMSIS_OS2)
108static osMessageQueueId_t sEventFIFO;
109static osMessageQueueId_t sRxPacketFIFO;
110static osMessageQueueId_t sTxPacketFIFO;
111static osMessageQueueId_t sNotificationFIFO;
112static osMessageQueueId_t sTxCbFIFO;
113#elif defined(FLEXPTP_LINUX)
114static int sRxPacketFIFO[2];
115static int sTxPacketFIFO[2];
116static int sEventFIFO[2];
117static int sTxCbFIFO[2];
118static sem_t sTxCbSem;
119#elif defined(FLEXPTP_OSLESS)
120static Fifo sEventFIFO;
121static Fifo sRxPacketFIFO;
122static Fifo sTxPacketFIFO;
123static Fifo sNotificationFIFO;
124static Fifo sTxCbFIFO;
125static FIFO_POOL(sEventFIFOPool, EVENT_FIFO_LENGTH, sizeof(PtpCoreEvent));
126static FIFO_POOL(sRxPacketFIFOPool, RX_PACKET_FIFO_LENGTH, sizeof(uint32_t));
127static FIFO_POOL(sTxPacketFIFOPool, TX_PACKET_FIFO_LENGTH, sizeof(uint32_t));
128static FIFO_POOL(sNotificationFIFOPool, NOTIFICATION_FIFO_LENGTH, sizeof(ProcThreadNotification));
129static FIFO_POOL(sTxCbFIFOPool, TX_CALLBACK_FIFO_LENGTH, sizeof(TxTs));
130#endif
131
132// buffer for PTP-messages
133static PtpMsgBuf sRawRxMsgBuf, sRawTxMsgBuf;
134static PtpMsgBufBlock sRawRxMsgBufPool[RX_PACKET_FIFO_LENGTH];
135static PtpMsgBufBlock sRawTxMsgBufPool[TX_PACKET_FIFO_LENGTH];
137
138// ----------------------------
139
140// clang-format off
141
149#ifndef FLEXPTP_OSLESS
150static
151#endif
153#ifdef FLEXPTP_FREERTOS
154 TimerHandle_t timer
155#elif defined(FLEXPTP_CMSIS_OS2)
156 void *arg
157#elif defined(FLEXPTP_LINUX)
158 union sigval data
159#endif
160 ) {
161 PtpCoreEvent event = {.code = PTP_CEV_HEARTBEAT, .w = 0, .dw = 0};
162 ptp_event_enqueue(&event);
163}
164
165// clang-format on
166
171 // create smbc timer
172#ifndef FLEXPTP_OSLESS
173 sHeartBeatTmr = NULL;
174#ifdef FLEXPTP_FREERTOS
175 sHeartBeatTmr = xTimerCreate("ptp_heartbeat", pdMS_TO_TICKS(PTP_HEARTBEAT_TICKRATE_MS), // timeout
176 true, // timer operates in repeat mode
177 NULL, // ID
178 ptp_heartbeat_tmr_cb); // callback-function
179#elif defined(FLEXPTP_CMSIS_OS2)
180 sHeartBeatTmr = osTimerNew(ptp_heartbeat_tmr_cb, osTimerPeriodic, NULL, NULL);
181#elif defined(FLEXPTP_LINUX)
182 struct sigevent sev = {
183 .sigev_notify = SIGEV_THREAD,
184 .sigev_notify_function = ptp_heartbeat_tmr_cb,
185 .sigev_value = {.sival_ptr = NULL}};
186 if (timer_create(CLOCK_REALTIME, &sev, &sHeartBeatTmr) < 0) {
187 sHeartBeatTmr = NULL;
188 }
189#endif
190 if (sHeartBeatTmr == NULL) {
191 MSG("Failed to create the PTP heartbeat timer!\n");
192 return false;
193 }
194#endif
195
196 return true;
197}
198
203#ifndef FLEXPTP_OSLESS
205#ifdef FLEXPTP_FREERTOS
206 xTimerDelete(sHeartBeatTmr, 0);
207#elif defined(FLEXPTP_CMSIS_OS2)
208 osTimerDelete(sHeartBeatTmr);
209#elif defined(FLEXPTP_LINUX)
210 timer_delete(sHeartBeatTmr);
211#endif
212 sHeartBeatTmr = NULL;
213#endif
214}
215
217#ifdef FLEXPTP_FREERTOS
218 xTimerStart(sHeartBeatTmr, 0);
219#elif defined(FLEXPTP_CMSIS_OS2)
220 osTimerStart(sHeartBeatTmr, (PTP_HEARTBEAT_TICKRATE_MS * 1000) / osKernelGetTickFreq());
221#elif defined(FLEXPTP_LINUX)
222 struct itimerspec its = {
223 .it_interval = {
224 .tv_sec = PTP_HEARTBEAT_TICKRATE_MS / 1000, .tv_nsec = (PTP_HEARTBEAT_TICKRATE_MS % 1000) * 1000000},
225 .it_value = {.tv_sec = 1, .tv_nsec = 0} // just some non-zero value
226 };
227 timer_settime(sHeartBeatTmr, 0, &its, NULL);
228#endif
229}
230
232#ifdef FLEXPTP_FREERTOS
233 xTimerStop(sHeartBeatTmr, 0);
234#elif defined(FLEXPTP_CMSIS_OS2)
235 osTimerStop(sHeartBeatTmr);
236#elif defined(FLEXPTP_LINUX)
237 struct itimerspec its;
238 memset(&its, 0, sizeof(its));
239 timer_settime(sHeartBeatTmr, 0, &its, NULL);
240#endif
241}
242
243// ----------------------------
244
245// create message queues
247 // create packet FIFO
248 bool ok = true;
249#ifdef FLEXPTP_FREERTOS
250 sRxPacketFIFO = xQueueCreate(RX_PACKET_FIFO_LENGTH, sizeof(uint32_t));
251 sTxPacketFIFO = xQueueCreate(TX_PACKET_FIFO_LENGTH, sizeof(uint32_t));
252 sEventFIFO = xQueueCreate(EVENT_FIFO_LENGTH, sizeof(PtpCoreEvent));
253 sNotificationFIFO = xQueueCreate(NOTIFICATION_FIFO_LENGTH, sizeof(ProcThreadNotification));
254 sTxCbFIFO = xQueueCreate(TX_CALLBACK_FIFO_LENGTH, sizeof(TxTs));
255 ok = (sRxPacketFIFO != NULL) && (sTxPacketFIFO != NULL) && (sEventFIFO != NULL) && (sNotificationFIFO != NULL) && (sTxCbFIFO != NULL);
256#elif defined(FLEXPTP_CMSIS_OS2)
257 sRxPacketFIFO = osMessageQueueNew(RX_PACKET_FIFO_LENGTH, sizeof(uint32_t), NULL);
258 sTxPacketFIFO = osMessageQueueNew(TX_PACKET_FIFO_LENGTH, sizeof(uint32_t), NULL);
259 sEventFIFO = osMessageQueueNew(EVENT_FIFO_LENGTH, sizeof(PtpCoreEvent), NULL);
260 sNotificationFIFO = osMessageQueueNew(NOTIFICATION_FIFO_LENGTH, sizeof(ProcThreadNotification), NULL);
261 sTxCbFIFO = osMessageQueueNew(TX_CALLBACK_FIFO_LENGTH, sizeof(TxTs), NULL);
262 ok = (sRxPacketFIFO != NULL) && (sTxPacketFIFO != NULL) && (sEventFIFO != NULL) && (sNotificationFIFO != NULL) && (sTxCbFIFO != NULL);
263#elif defined(FLEXPTP_LINUX)
264
265// clear pipe file descriptors macro
266#define CPFD(fda) \
267 fda[0] = 0; \
268 fda[1] = 0
269
270 CPFD(sRxPacketFIFO);
271 ok &= pipe(sRxPacketFIFO) == 0;
272 CPFD(sTxPacketFIFO);
273 ok &= pipe(sTxPacketFIFO) == 0;
274 CPFD(sEventFIFO);
275 ok &= pipe(sEventFIFO) == 0;
276 CPFD(sTxCbFIFO);
277 ok &= pipe(sTxCbFIFO) == 0;
278 ok &= sem_init(&sTxCbSem, 0, 0) == 0;
279#elif defined(FLEXPTP_OSLESS)
280 fifo_init(&sRxPacketFIFO, RX_PACKET_FIFO_LENGTH, sizeof(uint32_t), sRxPacketFIFOPool, FLEXPTP_OSLESS_LOCK);
281 fifo_init(&sTxPacketFIFO, TX_PACKET_FIFO_LENGTH, sizeof(uint32_t), sTxPacketFIFOPool, FLEXPTP_OSLESS_LOCK);
282 fifo_init(&sEventFIFO, EVENT_FIFO_LENGTH, sizeof(uint32_t), sEventFIFOPool, FLEXPTP_OSLESS_LOCK);
283 fifo_init(&sNotificationFIFO, NOTIFICATION_FIFO_LENGTH, sizeof(ProcThreadNotification), sNotificationFIFOPool, FLEXPTP_OSLESS_LOCK);
284 fifo_init(&sTxCbFIFO, TX_CALLBACK_FIFO_LENGTH, sizeof(TxTs), sTxCbFIFOPool, FLEXPTP_OSLESS_LOCK);
285#endif
286 // if some error has occurred, then delete the message queues
287 if (!ok) {
288 MSG("Failed to create the PTP message queues!\n");
289 return false;
290 }
291
292 // initalize packet buffers
293 msgb_init(&sRawRxMsgBuf, sRawRxMsgBufPool, RX_PACKET_FIFO_LENGTH);
294 msgb_init(&sRawTxMsgBuf, sRawTxMsgBufPool, TX_PACKET_FIFO_LENGTH);
295
296 return true;
297}
298
299#ifdef FLEXPTP_LINUX
300#define CLOSE_PIPE(pipefd) \
301 close(pipefd[0]); \
302 close(pipefd[1])
303#endif
304
305// destroy message queues
307 // destroy packet FIFO
308#ifdef FLEXPTP_FREERTOS
309 vQueueDelete(sRxPacketFIFO);
310 vQueueDelete(sTxPacketFIFO);
311 vQueueDelete(sEventFIFO);
312 vQueueDelete(sNotificationFIFO);
313 vQueueDelete(sTxCbFIFO);
314#elif defined(FLEXPTP_CMSIS_OS2)
315 osMessageQueueDelete(sRxPacketFIFO);
316 osMessageQueueDelete(sTxPacketFIFO);
317 osMessageQueueDelete(sEventFIFO);
318 osMessageQueueDelete(sNotificationFIFO);
319 osMessageQueueDelete(sTxCbFIFO);
320#elif defined(FLEXPTP_LINUX)
321 CLOSE_PIPE(sRxPacketFIFO);
322 CLOSE_PIPE(sTxPacketFIFO);
323 CLOSE_PIPE(sEventFIFO);
324 CLOSE_PIPE(sTxCbFIFO);
325 sem_destroy(&sTxCbSem);
326#endif
327
328 // packet buffers cannot be released since nothing had been allocated for them
329}
330
331// register PTP task and initialize
333 // initialize message queues and buffers
336 return false;
337 }
338
339 // set user event callback
340#ifdef PTP_USER_EVENT_CALLBACK
341 ptp_set_user_event_callback(PTP_USER_EVENT_CALLBACK);
342#endif
343
344 // create heartbeat timer
347 return false;
348 }
349
350 // initialize PTP subsystem
351 ptp_init();
352
353 // load config if provided
354#ifdef PTP_CONFIG_PTR
355 MSG("Loading the PTP-configuration!\n");
357
358 // print profile summary
359 MSG("\n\n----\n");
361 MSG("----\n\n");
362#endif
363
364 // initialize network stack driver
365 NsdInitSettings nsdInit = {
368 {},
369 {}};
370 memcpy(nsdInit.primary_p2p_8023_dest, S.profile.primary_p2p_8023_destination, 6);
371 memcpy(nsdInit.pdelay_p2p_8023_dest, S.profile.pdelay_p2p_8023_destination, 6);
372 ptp_nsd_init(&nsdInit);
373
374 // create task
375#ifdef FLEXPTP_FREERTOS
376 sTH = NULL;
377 BaseType_t result = xTaskCreate(task_ptp, "ptp", FLEXPTP_TASK_STACK_SIZE / sizeof(BaseType_t), NULL, FLEXPTP_TASK_PRIORITY, &sTH);
378 if (result != pdPASS) {
379 MSG("Failed to create the PTP task! (errcode: %d)\n", result);
380 unreg_task_ptp(); // this will also destroy message queues and the timer
381 return false;
382 }
383#elif defined(FLEXPTP_CMSIS_OS2)
384 sTH = NULL;
385 osThreadAttr_t attr;
386 memset(&attr, 0, sizeof(osThreadAttr_t));
387 attr.name = "ptp";
388 attr.stack_size = FLEXPTP_TASK_STACK_SIZE;
389 attr.priority = FLEXPTP_TASK_PRIORITY;
390 sTH = osThreadNew(task_ptp, NULL, &attr);
391 if (sTH == NULL) {
392 MSG("Failed to create the PTP task!\n");
394 return false;
395 }
396#elif defined(FLEXPTP_LINUX)
397 sTH = 0;
398 if (pthread_create(&sTH, NULL, task_ptp, NULL) != 0) {
399 MSG("Failed to create the PTP thread!\n");
401 return false;
402 }
403 // struct sched_param sched_param = { .sched_priority = 10 };
404 // if (sched_setscheduler(getpid(), SCHED_FIFO, &sched_param)) {
405 // MSG("Could not switch to realtime scheduling!\n");
406 // return;
407 // }
408#endif
409
410 // the PTP subsystem is operating
411 sPTP_operating = true;
412
413 return true;
414}
415
416// unregister PTP task
418 ptp_remove_heartbeat_tmr(); // remove the heartbeat timer
419 NsdInitSettings nsdInit = {
420 -1, -1, {}, {}};
421 ptp_nsd_init(&nsdInit); // de-initialize the network stack driver
422#if defined(FLEXPTP_NON_LINUX_OS)
423 if (sTH != NULL) {
424#ifdef FLEXPTP_FREERTOS
425 vTaskDelete(sTH); // delete task
426#elif defined(FLEXPTP_CMSIS_OS2)
427 osThreadTerminate(sTH);
428#endif
429 }
430 sTH = NULL;
431#elif defined(FLEXPTP_LINUX)
432 if (sTH != 0) {
433 PtpCoreEvent event = {.code = PTP_CEV_TERMINATE, .w = 0, .dw = 0};
434 ptp_event_enqueue(&event);
435 pthread_join(sTH, NULL);
436 }
437#endif
438 ptp_deinit(); // ptp subsystem de-initialization
439 ptp_destroy_message_queues(); // destroy message queues and buffers
440 sPTP_operating = false; // the PTP subsystem is NOT operating anymore
441}
442
443// ---------------------------
444
445bool ptp_event_enqueue(const PtpCoreEvent *event) {
447
448 bool ok;
449#ifdef FLEXPTP_FREERTOS
450 // push event and check success with no timeout:
451 // if the queue is full, then drop the event
452 ok = xQueueSend(sEventFIFO, event, 0) == pdPASS;
453 if (ok) {
454 xQueueSend(sNotificationFIFO, &notif, 0);
455 }
456#elif defined(FLEXPTP_CMSIS_OS2)
457 ok = osMessageQueuePut(sEventFIFO, event, 0, 0U) == osOK;
458 if (ok) {
459 osMessageQueuePut(sNotificationFIFO, &notif, 0, 0U);
460 }
461#elif defined(FLEXPTP_LINUX)
462 size_t len = sizeof(PtpCoreEvent);
463 ok = write(sEventFIFO[1], event, len) == len;
464#elif defined(FLEXPTP_OSLESS)
465 ok = fifo_push(&sEventFIFO, event);
466 if (ok) {
467 fifo_push(&sNotificationFIFO, &notif);
468 }
469#endif
470 return ok;
471}
472
473// put ptp message onto processing queue
474void ptp_receive_enqueue(const void *pPayload, uint32_t len, uint32_t ts_sec, uint32_t ts_ns, int tp) {
475 // only consider messages received on the matching transport layer
476 if ((!sPTP_operating) || (tp != ptp_get_transport_type())) {
477 return;
478 }
479
480 // enqueue message
482 if (pMsgAlloc) {
483 // copy payload and timestamp
484 uint32_t copyLen = MIN(len, MAX_PTP_MSG_SIZE);
485 memcpy(pMsgAlloc->data, pPayload, copyLen);
486 pMsgAlloc->size = copyLen;
487 pMsgAlloc->ts.sec = ts_sec;
488 pMsgAlloc->ts.nanosec = ts_ns;
489 pMsgAlloc->tag = RPMT_RANDOM;
490 pMsgAlloc->pTxCb = NULL; // not meaningful...
491
492 // commit the allocation
493 msgb_commit(&sRawRxMsgBuf, pMsgAlloc);
494
495 // get the UID
496 uint32_t uid = msgb_get_uid(&sRawRxMsgBuf, pMsgAlloc);
497
498 // set enqueue status
499 bool enqueueOK = false;
500
501 // set the notification
503#ifdef FLEXPTP_FREERTOS
504 // attempt to push incoming message UID:
505 // if successful, also push the notification
506 if (xPortIsInsideInterrupt()) {
507 enqueueOK = (xQueueSendFromISR(sRxPacketFIFO, &uid, NULL) == pdPASS); // send index
508 if (enqueueOK) {
509 xQueueSendFromISR(sNotificationFIFO, &notif, NULL); // send notification
510 }
511 } else {
512 enqueueOK = (xQueueSend(sRxPacketFIFO, &uid, 0) == pdPASS); // send index
513 if (enqueueOK) {
514 xQueueSend(sNotificationFIFO, &notif, 0); // send notification
515 }
516 }
517#elif defined(FLEXPTP_CMSIS_OS2)
518 enqueueOK = (osMessageQueuePut(sRxPacketFIFO, &uid, 0, 0U) == osOK);
519 if (enqueueOK) {
520 osMessageQueuePut(sNotificationFIFO, &notif, 0, 0U);
521 }
522#elif defined(FLEXPTP_LINUX)
523 if (write(sRxPacketFIFO[1], &uid, sizeof(uint32_t)) > 0) {
524 enqueueOK = true;
525 }
526#elif defined(FLEXPTP_OSLESS)
527 enqueueOK = fifo_push(&sRxPacketFIFO, &uid);
528 if (enqueueOK) {
529 fifo_push(&sNotificationFIFO, &notif);
530 }
531#endif
532 // if the message push has failed...
533 if (!enqueueOK) {
534 msgb_free(&sRawRxMsgBuf, pMsgAlloc); // free the allocated block
535 S.stats.drop_cntrs.rx++; // increase the drop counter
536
537 // notify the user
538 CLILOG(S.logging.logid && S.logging.info, "[LOG-INFO] ");
539 CLILOG(S.logging.info, "Failed to enqueue a message to the receive queue, a packet was lost.\n");
540 }
541 } else {
542 if (msgb_get_error(&sRawRxMsgBuf) == MSGB_ERR_FULL) {
543 CLILOG(S.logging.logid && S.logging.info, "[LOG-INFO] ");
544 CLILOG(S.logging.info, "The PTP receive packet buffer is full, a packet has been lost!\n");
545 }
546 }
547}
548
550 RawPtpMessage *pMsgAlloc = msgb_alloc(&sRawTxMsgBuf, pMsg->tag, pMsg->ttl);
551 if (pMsgAlloc) {
552 memcpy(pMsgAlloc, pMsg, sizeof(RawPtpMessage));
553 msgb_commit(&sRawTxMsgBuf, pMsgAlloc);
554 uint32_t uid = msgb_get_uid(&sRawTxMsgBuf, pMsgAlloc);
555 bool enqueueOK = false;
557#ifdef FLEXPTP_FREERTOS
558 if (xPortIsInsideInterrupt()) {
559 enqueueOK = (xQueueSendFromISR(sTxPacketFIFO, &uid, NULL) == pdPASS);
560 if (enqueueOK) {
561 xQueueSendFromISR(sNotificationFIFO, &notif, NULL);
562 }
563 } else {
564 enqueueOK = (xQueueSend(sTxPacketFIFO, &uid, 0) == pdPASS);
565 if (enqueueOK) {
566 xQueueSend(sNotificationFIFO, &notif, 0);
567 }
568 }
569#elif defined(FLEXPTP_CMSIS_OS2)
570 enqueueOK = (osMessageQueuePut(sTxPacketFIFO, &uid, 0, 0U) == osOK);
571 if (enqueueOK) {
572 osMessageQueuePut(sNotificationFIFO, &notif, 0, 0U);
573 }
574#elif defined(FLEXPTP_LINUX)
575 if (write(sTxPacketFIFO[1], &uid, sizeof(uint32_t)) > 0) {
576 enqueueOK = true;
577 }
578#elif defined(FLEXPTP_OSLESS)
579 enqueueOK = fifo_push(&sTxPacketFIFO, &uid);
580 if (enqueueOK) {
581 fifo_push(&sNotificationFIFO, &notif);
582 }
583#endif
584 if (!enqueueOK) {
585 msgb_free(&sRawTxMsgBuf, pMsgAlloc); // free the allocated block
586 S.stats.drop_cntrs.tx++; // increase the drop counter
587
588 // notify the user
589 CLILOG(S.logging.logid && S.logging.info, "[LOG-INFO] ");
590 CLILOG(S.logging.info, "Failed to enqueue a message to the transmit queue, a packet was lost.\n");
591 }
592
593 return enqueueOK;
594 } else {
595 if (msgb_get_error(&sRawTxMsgBuf) == MSGB_ERR_FULL) {
596 CLILOG(S.logging.logid && S.logging.info, "[LOG-INFO] ");
597 CLILOG(S.logging.info, "PTP TX Enqueue failed, buffer is full! (%u)\n", pMsg->tag);
598 PTP_IUEV(PTP_UEV_QUEUE_ERROR); // dispatch QUEUE_ERROR event
599 }
600 return false;
601 }
602}
603
604void ptp_transmit_timestamp_cb(uint32_t uid, uint32_t seconds, uint32_t nanoseconds) {
605 // create timestamp association object
606 TxTs ts = {.uid = uid, .seconds = seconds, .nanoseconds = nanoseconds};
607
608 // dispatch notification
609 bool enqueueOK = false;
611#ifdef FLEXPTP_FREERTOS
612 if (xPortIsInsideInterrupt()) {
613 enqueueOK = (xQueueSendFromISR(sTxCbFIFO, &ts, NULL) == pdPASS);
614 if (enqueueOK) {
615 xQueueSendFromISR(sNotificationFIFO, &notif, NULL);
616 }
617 } else {
618 enqueueOK = xQueueSend(sTxCbFIFO, &ts, 0);
619 if (enqueueOK) {
620 xQueueSend(sNotificationFIFO, &notif, 0);
621 }
622 }
623#elif defined(FLEXPTP_CMSIS_OS2)
624 enqueueOK = (osMessageQueuePut(sTxCbFIFO, &ts, 0, 0U) == osOK);
625 if (enqueueOK) {
626 osMessageQueuePut(sNotificationFIFO, &notif, 0, 0U);
627 }
628#elif defined(FLEXPTP_LINUX)
629 if (write(sTxCbFIFO[1], &ts, sizeof(TxTs)) > 0) {
630 sem_post(&sTxCbSem);
631 enqueueOK = true;
632 }
633#elif defined(FLEXPTP_OSLESS)
634 enqueueOK = fifo_push(&sTxCbFIFO, &ts);
635 if (enqueueOK) {
636 fifo_push(&sNotificationFIFO, &notif);
637 }
638#endif
639
640 if (!enqueueOK) {
641 S.stats.drop_cntrs.txts++; // increase the drop counter
642
643 // notify the user
644 CLILOG(S.logging.logid && S.logging.info, "[LOG-INFO] ");
645 CLILOG(S.logging.info, "Failed to enqueue transmit timestamp to the queue, the transmit timestamp was lost.\n");
646 }
647}
648
650 // fetch message
651 RawPtpMessage *pRawMsg = msgb_get_sent_by_tag(&sRawTxMsgBuf, tag);
652 if (pRawMsg == NULL) {
653 return false;
654 }
655
656 // copy timestamp
657 *pTs = pRawMsg->ts;
658
659 // release message
660 msgb_free(&sRawTxMsgBuf, pRawMsg);
661
662 return true;
663}
664
672#ifdef FLEXPTP_NON_LINUX_OS
673static void task_ptp(void *pParam) {
674#elif defined(FLEXPTP_LINUX)
675static void *task_ptp(void *pParam) {
676#elif defined(FLEXPTP_OSLESS)
677void task_ptp(void) {
678#endif
679
680#ifndef FLEXPTP_OSLESS // OS assisted mode
681 bool run = true;
682 while (run) {
683#else // OS-less mode
684 while (fifo_get_level(&sNotificationFIFO) > 0) {
685#endif
686 // wait for received packet or packet to transfer
687 ProcThreadNotification notification = PTN_NONE;
688#ifdef FLEXPTP_FREERTOS
689 xQueueReceive(sNotificationFIFO, &notification, portMAX_DELAY);
690#elif defined(FLEXPTP_CMSIS_OS2)
691 osMessageQueueGet(sNotificationFIFO, &notification, NULL, osWaitForever);
692#elif defined(FLEXPTP_LINUX)
693
694 // prepare polling
695#define POLL_N_FD (4)
696 struct pollfd pfd[POLL_N_FD] = {
697 {.fd = sRxPacketFIFO[0], .events = POLLIN, .revents = 0},
698 {.fd = sTxPacketFIFO[0], .events = POLLIN, .revents = 0},
699 {.fd = sTxCbFIFO[0], .events = POLLIN, .revents = 0},
700 {.fd = sEventFIFO[0], .events = POLLIN, .revents = 0},
701 };
702 ProcThreadNotification notif_mapping[POLL_N_FD] = {
706 PTN_EVENT};
707
708 // call the poll
709 int pret = poll(pfd, POLL_N_FD, -1);
710 if (pret > 0) {
711 // at least one of the pipes have data to read
712 for (uint32_t i = 0; i < POLL_N_FD; i++) {
713 if (pfd[i].revents & POLLIN) {
714 notification |= notif_mapping[i];
715 }
716 }
717 } else {
718 // error occurred, just skip this cycle
719 CLILOG(S.logging.logid && S.logging.info, "[LOG-INFO] ");
720 CLILOG(S.logging.info, "A polling error occurred!\n");
721 continue;
722 }
723#elif defined(FLEXPTP_OSLESS)
724fifo_pop(&sNotificationFIFO, &notification);
725#endif
726 /* ---- TRANSMIT DONE ---- */
727 if (notification & PTN_TRANSMIT_DONE) {
728
729 // get the timestamp association object
730 TxTs ts;
731
732 // clang-format off
733#ifdef FLEXPTP_FREERTOS
734 xQueueReceive(sTxCbFIFO, &ts, portMAX_DELAY);
735#elif defined(FLEXPTP_CMSIS_OS2)
736 osMessageQueueGet(sTxCbFIFO, &ts, NULL, osWaitForever);
737#elif defined(FLEXPTP_LINUX)
738 read(sTxCbFIFO[0], &ts, sizeof(TxTs));
739#elif defined(FLEXPTP_OSLESS)
740 fifo_pop(&sTxCbFIFO, &ts);
741#endif
742 // clang-format on
743
744 // fetch the message
745 CLILOG(S.logging.logid && S.logging.transmission, "[LOG-TX] ");
746 CLILOG(S.logging.transmission, "[% 8u]---> %u\n", S.ticks, ts.uid);
747 RawPtpMessage *pRawMsg = msgb_get_by_uid(&sRawTxMsgBuf, ts.uid);
748 if (pRawMsg != NULL) {
749 // insert the timestamp
750 pRawMsg->ts.sec = ts.seconds;
751 pRawMsg->ts.nanosec = ts.nanoseconds;
752
753 // set the 'sent' flag
754 msgb_set_sent(&sRawTxMsgBuf, pRawMsg);
755
756 // invoke callback
757 if (pRawMsg->pTxCb != NULL) {
758 pRawMsg->pTxCb(pRawMsg);
759 }
760
761 // release message
762 if ((pRawMsg->tag == RPMT_RANDOM) || (pRawMsg->pTxCb != NULL)) {
763 msgb_free(&sRawTxMsgBuf, pRawMsg);
764 CLILOG(S.logging.logid && S.logging.transmission, "[LOG-TX] ");
765 CLILOG(S.logging.transmission, "[% 8u] %u AUTOFREE\n", S.ticks, ts.uid);
766 }
767 } else {
768 // null messages
769 }
770 }
771
772 /* ---- TRANSMIT ----- */
773 if (notification & PTN_TRANSMIT) {
774
775 // pop packet UID from the FIFO
776 uint32_t uid = 0;
777
778 // clang-format off
779#ifdef FLEXPTP_FREERTOS
780 xQueueReceive(sTxPacketFIFO, &uid, portMAX_DELAY);
781#elif defined(FLEXPTP_CMSIS_OS2)
782 osMessageQueueGet(sTxPacketFIFO, &uid, NULL, osWaitForever);
783#elif defined(FLEXPTP_LINUX)
784 read(sTxPacketFIFO[0], &uid, sizeof(uint32_t));
785#elif defined(FLEXPTP_OSLESS)
786 fifo_pop(&sTxPacketFIFO, &uid);
787#endif
788 // clang-format on
789
790 // fetch the message
791 RawPtpMessage *pRawMsg = msgb_get_by_uid(&sRawTxMsgBuf, uid);
792 if (pRawMsg != NULL) {
793 CLILOG(S.logging.logid && S.logging.transmission, "[LOG-TX] ");
794 CLILOG(S.logging.transmission, "[% 8u] %u (%u) --->\n", S.ticks, uid, pRawMsg->tag & (~((uint32_t)MSGBUF_TAG_OVERWRITE)));
795 ptp_nsd_transmit_msg(pRawMsg, uid);
796#ifdef FLEXPTP_LINUX
797 sem_wait(&sTxCbSem);
798#endif
799 }
800 }
801
802 // if packet is on the RX queue
803 /* ---- RECIEVE ----- */
804 if (notification & PTN_RECEIVE) {
805 // pop packet UID from the FIFO
806 uint32_t uid = 0;
807
808 // clang-format off
809#ifdef FLEXPTP_FREERTOS
810 xQueueReceive(sRxPacketFIFO, &uid, portMAX_DELAY);
811#elif defined(FLEXPTP_CMSIS_OS2)
812 osMessageQueueGet(sRxPacketFIFO, &uid, NULL, osWaitForever);
813#elif defined(FLEXPTP_LINUX)
814 read(sRxPacketFIFO[0], &uid, sizeof(uint32_t));
815#elif defined(FLEXPTP_OSLESS)
816 fifo_pop(&sRxPacketFIFO, &uid);
817#endif
818 // clang-format on
819
820 // fetch message
821 RawPtpMessage *pRawMsg = msgb_get_by_uid(&sRawRxMsgBuf, uid);
822 if (pRawMsg != NULL) {
823 // process packet
824 ptp_process_packet(pRawMsg);
825
826 // free buffer
827 msgb_free(&sRawRxMsgBuf, pRawMsg);
828 }
829 }
830
831 /* ---- EVENT ----- */
832 if (notification == PTN_EVENT) {
833
834 // pop event from the FIFO
835 PtpCoreEvent event;
836
837 // clang-format off
838#ifdef FLEXPTP_FREERTOS
839 xQueueReceive(sEventFIFO, &event, portMAX_DELAY);
840#elif defined(FLEXPTP_CMSIS_OS2)
841 osMessageQueueGet(sEventFIFO, &event, NULL, osWaitForever);
842#elif defined(FLEXPTP_LINUX)
843 read(sEventFIFO[0], &event, sizeof(PtpCoreEvent));
844#elif defined(FLEXPTP_OSLESS)
845 fifo_pop(&sEventFIFO, &event);
846#endif
847 // clang-format on
848
849 // delegate event processing
850 ptp_process_event(&event);
851
852 // tick the storage
853 if (event.code == PTP_CEV_HEARTBEAT) {
854 msgb_tick(&sRawRxMsgBuf);
855 msgb_tick(&sRawTxMsgBuf);
856 }
857
858 // handle peaceful termination
859 if (event.code == PTP_CEV_TERMINATE) {
860#ifdef FLEXPTP_LINUX
861 run = false;
862#endif
863 }
864 }
865 }
866
867#ifdef FLEXPTP_LINUX
868 return NULL;
869#endif
870}
871
872// --------------------------
873
874// function to query PTP operation state
876 return sPTP_operating;
877}
878
879// --------------------------
void ptp_load_config_from_dump(const void *pDump)
Definition: config.c:89
This module defines functions for storing and loading flexPTP configurations.
In this module are the core and user events defined.
@ PTP_UEV_QUEUE_ERROR
This event signals that the flexPTP's internal transmission output queue is full and blocked.
Definition: event.h:73
#define PTP_IUEV(uev)
Definition: event.h:83
@ PTP_CEV_TERMINATE
A shutdown is requested.
Definition: event.h:22
@ PTP_CEV_HEARTBEAT
Heartbeat event (tick)
Definition: event.h:19
bool fifo_pop(Fifo *f, void *item)
Definition: fifo.c:48
uint32_t fifo_get_level(const Fifo *f)
Definition: fifo.c:44
bool fifo_push(Fifo *f, void const *item)
Definition: fifo.c:17
void fifo_init(Fifo *f, uint32_t len, uint32_t esize, uint8_t *data, FifoLockFn lockFn)
Definition: fifo.c:4
#define FIFO_POOL(name, len, esize)
Definition: fifo.h:31
#define CLILOG(en,...)
#define FLEXPTP_TASK_PRIORITY
#define PTP_CONFIG_PTR()
#define MIN(a, b)
Definition: minmax.h:8
void msgb_set_sent(PtpMsgBuf *buf, RawPtpMessage *msg)
Definition: msg_buf.c:216
RawPtpMessage * msgb_get_by_uid(PtpMsgBuf *buf, uint32_t uid)
Definition: msg_buf.c:170
void msgb_init(PtpMsgBuf *buf, PtpMsgBufBlock *pool, uint32_t n)
Definition: msg_buf.c:12
void msgb_commit(PtpMsgBuf *buf, RawPtpMessage *msg)
Definition: msg_buf.c:98
RawPtpMessage * msgb_get_sent_by_tag(PtpMsgBuf *buf, uint32_t tag)
Definition: msg_buf.c:197
uint32_t msgb_get_uid(const PtpMsgBuf *buf, const RawPtpMessage *msg)
Definition: msg_buf.c:221
RawPtpMessage * msgb_alloc(PtpMsgBuf *buf, uint32_t tag, uint32_t ttl)
Definition: msg_buf.c:39
void msgb_free(PtpMsgBuf *buf, RawPtpMessage *msg)
Definition: msg_buf.c:115
void msgb_tick(PtpMsgBuf *buf)
Definition: msg_buf.c:226
uint32_t msgb_get_error(PtpMsgBuf *buf)
Definition: msg_buf.c:253
#define MSGBUF_TAG_OVERWRITE
Overwrite if a message exists with the same tag.
Definition: msg_buf.h:15
@ MSGB_ERR_FULL
The buffer is full, cannot allocate a slot.
Definition: msg_buf.h:35
This file is a header for the employed Network Stack Driver (NSD). A NSD must define ALL four functio...
void ptp_nsd_transmit_msg(RawPtpMessage *pMsg, uint32_t uid)
Definition: nsd_etherlib.c:159
void ptp_nsd_init(const NsdInitSettings *init)
Definition: nsd_etherlib.c:63
void ptp_print_profile()
Definition: profiles.c:13
This module implements defines a single method that prints a verbose summary of the operating PTP pro...
void ptp_deinit()
Definition: ptp_core.c:101
void ptp_process_event(const PtpCoreEvent *event)
Definition: ptp_core.c:206
void ptp_process_packet(RawPtpMessage *pRawMsg)
Definition: ptp_core.c:165
void ptp_set_user_event_callback(PtpUserEventCallback userEventCb)
Definition: ptp_core.c:253
void ptp_init(void)
Definition: ptp_core.c:71
Core of the PTP implementation. Defines functions for message processing, clock tuning,...
In here reside a multitude of fundamental PTP-related constants and definitions.
#define PTP_HEARTBEAT_TICKRATE_MS
Heartbeat ticking period.
Definition: ptp_defs.h:128
#define FLEXPTP_TASK_STACK_SIZE
flexPTP task stack size
Definition: ptp_defs.h:124
#define FLEXPTP_MS_TO_TICKS(ms)
Interval conversion between milliseconds and ticks.
Definition: ptp_defs.h:238
#define FLEXPTP_FREERTOS
Definition: ptp_defs.h:86
This module defines the fundamental PTP message and state machine type, flags, bitfields and the PTP ...
@ RPMT_RANDOM
Create a random, unique tag.
Definition: ptp_types.h:181
#define MAX_PTP_MSG_SIZE
Maximum PTP message size.
Definition: ptp_types.h:165
PtpDelayMechanism ptp_get_delay_mechanism()
PtpTransportType ptp_get_transport_type()
This module features functions to tweak around the PTP engine's almost every property.
FIFO object.
Definition: fifo.h:21
Network Stack Driver initialization object.
uint8_t primary_p2p_8023_dest[6]
Destination address for primary P2P messages over Ethernet.
uint8_t pdelay_p2p_8023_dest[6]
Destination address for PDel* P2P messages over Ethernet.
uint16_t code
Event code.
Definition: event.h:27
PTP message buffer entry.
Definition: msg_buf.h:20
PTP message buffer.
Definition: msg_buf.h:43
TimestampI ts
Timestamp.
Definition: ptp_types.h:187
uint32_t tag
unique transmit tag
Definition: ptp_types.h:191
uint32_t ttl
transmit Time-to-Live in ticks
Definition: ptp_types.h:192
uint32_t size
Packet size.
Definition: ptp_types.h:188
uint8_t data[(128)]
raw packet data
Definition: ptp_types.h:199
TxCb * pTxCb
transmit callback function
Definition: ptp_types.h:193
Timestamp (signed)
Definition: timeutils.h:33
int32_t nanosec
nanoseconds
Definition: timeutils.h:35
int64_t sec
seconds
Definition: timeutils.h:34
Structure for communicating transmit timestamp writeback.
Definition: task_ptp.c:81
uint32_t uid
Message UID.
Definition: task_ptp.c:82
uint32_t seconds
Timestamp seconds.
Definition: task_ptp.c:83
uint32_t nanoseconds
Timestamp nanoseconds.
Definition: task_ptp.c:84
#define TX_CALLBACK_FIFO_LENGTH
Transmit callback FIFO length.
Definition: task_ptp.c:59
void ptp_receive_enqueue(const void *pPayload, uint32_t len, uint32_t ts_sec, uint32_t ts_ns, int tp)
Definition: task_ptp.c:474
static void task_ptp(void *pParam)
Definition: task_ptp.c:673
bool ptp_transmit_enqueue(const RawPtpMessage *pMsg)
Definition: task_ptp.c:549
void ptp_start_heartbeat_tmr()
Definition: task_ptp.c:216
static bool ptp_create_message_queues()
Definition: task_ptp.c:246
static void ptp_destroy_message_queues()
Definition: task_ptp.c:306
void unreg_task_ptp()
Definition: task_ptp.c:417
ProcThreadNotification
Notifications for the processing thread.
Definition: task_ptp.c:70
@ PTN_EVENT
An event has occurred.
Definition: task_ptp.c:75
@ PTN_TRANSMIT
A message awaits transmission.
Definition: task_ptp.c:73
@ PTN_NONE
Empty notification.
Definition: task_ptp.c:71
@ PTN_RECEIVE
A message has been received.
Definition: task_ptp.c:72
@ PTN_TRANSMIT_DONE
A transmit timestamp awaits delegation.
Definition: task_ptp.c:74
void ptp_transmit_timestamp_cb(uint32_t uid, uint32_t seconds, uint32_t nanoseconds)
Definition: task_ptp.c:604
#define EVENT_FIFO_LENGTH
Event FIFO length.
Definition: task_ptp.c:57
bool ptp_event_enqueue(const PtpCoreEvent *event)
Definition: task_ptp.c:445
#define NOTIFICATION_FIFO_LENGTH
Notification FIFO length.
Definition: task_ptp.c:58
static bool sPTP_operating
Definition: task_ptp.c:42
#define RX_TTL_MS
TTL for inbound packets.
Definition: task_ptp.c:63
void ptp_stop_heartbeat_tmr()
Definition: task_ptp.c:231
bool is_flexPTP_operating()
Definition: task_ptp.c:875
bool ptp_read_and_clear_transmit_timestamp(uint32_t tag, TimestampI *pTs)
Definition: task_ptp.c:649
#define RX_PACKET_FIFO_LENGTH
Receive packet FIFO length.
Definition: task_ptp.c:52
static bool ptp_create_heartbeat_tmr()
Definition: task_ptp.c:170
static TaskHandle_t sTH
Definition: task_ptp.c:28
#define TX_PACKET_FIFO_LENGTH
Transmit packet FIFO length.
Definition: task_ptp.c:53
static void ptp_heartbeat_tmr_cb(TimerHandle_t timer)
Definition: task_ptp.c:152
static void ptp_remove_heartbeat_tmr()
Definition: task_ptp.c:202
bool reg_task_ptp()
Definition: task_ptp.c:332
The entry point of the whole PTP-implementation. Calling reg_task_ptp() initializes the PTP-engine,...