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"
8#include "msg_buf.h"
10#include "profiles.h"
11#include "ptp_core.h"
12#include "ptp_defs.h"
13#include "ptp_types.h"
14#include "settings_interface.h"
15
16#include <flexptp_options.h>
17#include <time.h>
18
19#include "minmax.h"
20
21// ---------------------------
22
23#ifdef FLEXPTP_NON_LINUX_OS
24#ifdef FLEXPTP_FREERTOS
25static TaskHandle_t sTH; // task handle in direct FreeRTOS mode
26#elif defined(FLEXPTP_CMSIS_OS2)
27static osThreadId_t sTH; // task handle in CMSIS OS2 mode
28#endif
29static void task_ptp(void *pParam); // task routine function in non-Linux mode
30#elif defined(FLEXPTP_LINUX)
31static pthread_t sTH; // thread handle in Linux mode
32static void *task_ptp(void *pParam); // thread routine in Linux mode
33#elif defined(FLEXPTP_OSLESS)
34void task_ptp(void); // osless task function
35#endif
36
37// ---------------------------
38
39static bool sPTP_operating = false; // does the PTP subsystem operate?
40
41// ---------------------------
42
44#define S (gPtpCoreState)
46
47// ---------------------------
48
49#define RX_PACKET_FIFO_LENGTH (16)
50#define TX_PACKET_FIFO_LENGTH (16)
51
52// FIFO for incoming packets
53#if defined(FLEXPTP_NON_LINUX_OS) || defined(FLEXPTP_OSLESS)
54#define EVENT_FIFO_LENGTH (16)
55#define NOTIFICATION_FIFO_LENGTH (16)
56#define TX_CALLBACK_FIFO_LENGTH (10)
57#endif
58
59#define TX_TTL_MS (2000)
60#define RX_TTL_MS (2000)
61
62// -----------------------------
63
67typedef enum {
68 PTN_NONE = 0x00,
69 PTN_RECEIVE = 0x01,
70 PTN_TRANSMIT = 0x02,
72 PTN_EVENT = 0x08
74
78typedef struct {
79 uint32_t uid;
80 uint32_t seconds;
81 uint32_t nanoseconds;
82} TxTs;
83
84// -----------------------------
85
87
88// hearbeat timer
89#ifdef FLEXPTP_FREERTOS
90static TimerHandle_t sHeartBeatTmr;
91#elif defined(FLEXPTP_CMSIS_OS2)
92static osTimerId_t sHeartBeatTmr;
93#elif defined(FLEXPTP_LINUX)
94static timer_t sHeartBeatTmr;
95#endif
96
97// queues for message reception and transmission
98#ifdef FLEXPTP_FREERTOS
99static QueueHandle_t sEventFIFO;
100static QueueHandle_t sRxPacketFIFO;
101static QueueHandle_t sTxPacketFIFO;
102static QueueHandle_t sNotificationFIFO;
103static QueueHandle_t sTxCbFIFO;
104#elif defined(FLEXPTP_CMSIS_OS2)
105static osMessageQueueId_t sEventFIFO;
106static osMessageQueueId_t sRxPacketFIFO;
107static osMessageQueueId_t sTxPacketFIFO;
108static osMessageQueueId_t sNotificationFIFO;
109static osMessageQueueId_t sTxCbFIFO;
110#elif defined(FLEXPTP_LINUX)
111static int sRxPacketFIFO[2];
112static int sTxPacketFIFO[2];
113static int sEventFIFO[2];
114static int sTxCbFIFO[2];
115static sem_t sTxCbSem;
116#elif defined(FLEXPTP_OSLESS)
117static Fifo sEventFIFO;
118static Fifo sRxPacketFIFO;
119static Fifo sTxPacketFIFO;
120static Fifo sNotificationFIFO;
121static Fifo sTxCbFIFO;
122static FIFO_POOL(sEventFIFOPool, EVENT_FIFO_LENGTH, sizeof(PtpCoreEvent));
123static FIFO_POOL(sRxPacketFIFOPool, RX_PACKET_FIFO_LENGTH, sizeof(uint32_t));
124static FIFO_POOL(sTxPacketFIFOPool, TX_PACKET_FIFO_LENGTH, sizeof(uint32_t));
125static FIFO_POOL(sNotificationFIFOPool, NOTIFICATION_FIFO_LENGTH, sizeof(ProcThreadNotification));
126static FIFO_POOL(sTxCbFIFOPool, TX_CALLBACK_FIFO_LENGTH, sizeof(TxTs));
127#endif
128
129// buffer for PTP-messages
130static PtpMsgBuf sRawRxMsgBuf, sRawTxMsgBuf;
131static PtpMsgBufBlock sRawRxMsgBufPool[RX_PACKET_FIFO_LENGTH];
132static PtpMsgBufBlock sRawTxMsgBufPool[TX_PACKET_FIFO_LENGTH];
134
135// ----------------------------
136
144#ifndef FLEXPTP_OSLESS
145static
146#endif
147 void
149#ifdef FLEXPTP_FREERTOS
150 TimerHandle_t timer
151#elif defined(FLEXPTP_CMSIS_OS2)
152 void *arg
153#elif defined(FLEXPTP_LINUX)
154 union sigval data
155#endif
156 ) {
157 PtpCoreEvent event = {.code = PTP_CEV_HEARTBEAT, .w = 0, .dw = 0};
158 ptp_event_enqueue(&event);
159}
160
165 // create smbc timer
166#ifndef FLEXPTP_OSLESS
167 sHeartBeatTmr = NULL;
168#ifdef FLEXPTP_FREERTOS
169 sHeartBeatTmr = xTimerCreate("ptp_heartbeat", pdMS_TO_TICKS(PTP_HEARTBEAT_TICKRATE_MS), // timeout
170 true, // timer operates in repeat mode
171 NULL, // ID
172 ptp_heartbeat_tmr_cb); // callback-function
173#elif defined(FLEXPTP_CMSIS_OS2)
174 sHeartBeatTmr = osTimerNew(ptp_heartbeat_tmr_cb, osTimerPeriodic, NULL, NULL);
175#elif defined(FLEXPTP_LINUX)
176 struct sigevent sev = {
177 .sigev_notify = SIGEV_THREAD,
178 .sigev_notify_function = ptp_heartbeat_tmr_cb,
179 .sigev_value = {.sival_ptr = NULL}};
180 if (timer_create(CLOCK_REALTIME, &sev, &sHeartBeatTmr) < 0) {
181 sHeartBeatTmr = NULL;
182 }
183#endif
184 if (sHeartBeatTmr == NULL) {
185 MSG("Failed to create the PTP heartbeat timer!\n");
186 return false;
187 }
188#endif
189
190 return true;
191}
192
197#ifndef FLEXPTP_OSLESS
199#ifdef FLEXPTP_FREERTOS
200 xTimerDelete(sHeartBeatTmr, 0);
201#elif defined(FLEXPTP_CMSIS_OS2)
202 osTimerDelete(sHeartBeatTmr);
203#elif defined(FLEXPTP_LINUX)
204 timer_delete(sHeartBeatTmr);
205#endif
206 sHeartBeatTmr = NULL;
207#endif
208}
209
211#ifdef FLEXPTP_FREERTOS
212 xTimerStart(sHeartBeatTmr, 0);
213#elif defined(FLEXPTP_CMSIS_OS2)
214 osTimerStart(sHeartBeatTmr, (PTP_HEARTBEAT_TICKRATE_MS * 1000) / osKernelGetTickFreq());
215#elif defined(FLEXPTP_LINUX)
216 struct itimerspec its = {
217 .it_interval = {
218 .tv_sec = PTP_HEARTBEAT_TICKRATE_MS / 1000, .tv_nsec = (PTP_HEARTBEAT_TICKRATE_MS % 1000) * 1000000},
219 .it_value = {.tv_sec = 1, .tv_nsec = 0} // just some non-zero value
220 };
221 timer_settime(sHeartBeatTmr, 0, &its, NULL);
222#endif
223}
224
226#ifdef FLEXPTP_FREERTOS
227 xTimerStop(sHeartBeatTmr, 0);
228#elif defined(FLEXPTP_CMSIS_OS2)
229 osTimerStop(sHeartBeatTmr);
230#elif defined(FLEXPTP_LINUX)
231 struct itimerspec its;
232 memset(&its, 0, sizeof(its));
233 timer_settime(sHeartBeatTmr, 0, &its, NULL);
234#endif
235}
236
237// ----------------------------
238
239// create message queues
241 // create packet FIFO
242 bool ok = true;
243#ifdef FLEXPTP_FREERTOS
244 sRxPacketFIFO = xQueueCreate(RX_PACKET_FIFO_LENGTH, sizeof(uint32_t));
245 sTxPacketFIFO = xQueueCreate(TX_PACKET_FIFO_LENGTH, sizeof(uint32_t));
246 sEventFIFO = xQueueCreate(EVENT_FIFO_LENGTH, sizeof(PtpCoreEvent));
247 sNotificationFIFO = xQueueCreate(NOTIFICATION_FIFO_LENGTH, sizeof(ProcThreadNotification));
248 sTxCbFIFO = xQueueCreate(TX_CALLBACK_FIFO_LENGTH, sizeof(TxTs));
249 ok = (sRxPacketFIFO != NULL) && (sTxPacketFIFO != NULL) && (sEventFIFO != NULL) && (sNotificationFIFO != NULL) && (sTxCbFIFO != NULL);
250#elif defined(FLEXPTP_CMSIS_OS2)
251 sRxPacketFIFO = osMessageQueueNew(RX_PACKET_FIFO_LENGTH, sizeof(uint32_t), NULL);
252 sTxPacketFIFO = osMessageQueueNew(TX_PACKET_FIFO_LENGTH, sizeof(uint32_t), NULL);
253 sEventFIFO = osMessageQueueNew(EVENT_FIFO_LENGTH, sizeof(PtpCoreEvent), NULL);
254 sNotificationFIFO = osMessageQueueNew(NOTIFICATION_FIFO_LENGTH, sizeof(ProcThreadNotification), NULL);
255 sTxCbFIFO = osMessageQueueNew(TX_CALLBACK_FIFO_LENGTH, sizeof(TxTs), NULL);
256 ok = (sRxPacketFIFO != NULL) && (sTxPacketFIFO != NULL) && (sEventFIFO != NULL) && (sNotificationFIFO != NULL) && (sTxCbFIFO != NULL);
257#elif defined(FLEXPTP_LINUX)
258
259// clear pipe file descriptors macro
260#define CPFD(fda) \
261 fda[0] = 0; \
262 fda[1] = 0
263
264 CPFD(sRxPacketFIFO);
265 ok &= pipe(sRxPacketFIFO) == 0;
266 CPFD(sTxPacketFIFO);
267 ok &= pipe(sTxPacketFIFO) == 0;
268 CPFD(sEventFIFO);
269 ok &= pipe(sEventFIFO) == 0;
270 CPFD(sTxCbFIFO);
271 ok &= pipe(sTxCbFIFO) == 0;
272 ok &= sem_init(&sTxCbSem, 0, 0) == 0;
273#elif defined(FLEXPTP_OSLESS)
274 fifo_init(&sRxPacketFIFO, RX_PACKET_FIFO_LENGTH, sizeof(uint32_t), sRxPacketFIFOPool, FLEXPTP_OSLESS_LOCK);
275 fifo_init(&sTxPacketFIFO, TX_PACKET_FIFO_LENGTH, sizeof(uint32_t), sTxPacketFIFOPool, FLEXPTP_OSLESS_LOCK);
276 fifo_init(&sEventFIFO, EVENT_FIFO_LENGTH, sizeof(uint32_t), sEventFIFOPool, FLEXPTP_OSLESS_LOCK);
277 fifo_init(&sNotificationFIFO, NOTIFICATION_FIFO_LENGTH, sizeof(ProcThreadNotification), sNotificationFIFOPool, FLEXPTP_OSLESS_LOCK);
278 fifo_init(&sTxCbFIFO, TX_CALLBACK_FIFO_LENGTH, sizeof(TxTs), sTxCbFIFOPool, FLEXPTP_OSLESS_LOCK);
279#endif
280 // if some error has occurred, then delete the message queues
281 if (!ok) {
282 MSG("Failed to create the PTP message queues!\n");
283 return false;
284 }
285
286 // initalize packet buffers
287 msgb_init(&sRawRxMsgBuf, sRawRxMsgBufPool, RX_PACKET_FIFO_LENGTH);
288 msgb_init(&sRawTxMsgBuf, sRawTxMsgBufPool, TX_PACKET_FIFO_LENGTH);
289
290 return true;
291}
292
293#ifdef FLEXPTP_LINUX
294#define CLOSE_PIPE(pipefd) \
295 close(pipefd[0]); \
296 close(pipefd[1])
297#endif
298
299// destroy message queues
301 // destroy packet FIFO
302#ifdef FLEXPTP_FREERTOS
303 vQueueDelete(sRxPacketFIFO);
304 vQueueDelete(sTxPacketFIFO);
305 vQueueDelete(sEventFIFO);
306 vQueueDelete(sNotificationFIFO);
307 vQueueDelete(sTxCbFIFO);
308#elif defined(FLEXPTP_CMSIS_OS2)
309 osMessageQueueDelete(sRxPacketFIFO);
310 osMessageQueueDelete(sTxPacketFIFO);
311 osMessageQueueDelete(sEventFIFO);
312 osMessageQueueDelete(sNotificationFIFO);
313 osMessageQueueDelete(sTxCbFIFO);
314#elif defined(FLEXPTP_LINUX)
315 CLOSE_PIPE(sRxPacketFIFO);
316 CLOSE_PIPE(sTxPacketFIFO);
317 CLOSE_PIPE(sEventFIFO);
318 CLOSE_PIPE(sTxCbFIFO);
319 sem_destroy(&sTxCbSem);
320#endif
321
322 // packet buffers cannot be released since nothing had been allocated for them
323}
324
325// register PTP task and initialize
327 // initialize message queues and buffers
330 return false;
331 }
332
333 // set user event callback
334#ifdef PTP_USER_EVENT_CALLBACK
335 ptp_set_user_event_callback(PTP_USER_EVENT_CALLBACK);
336#endif
337
338 // create heartbeat timer
341 return false;
342 }
343
344 // initialize PTP subsystem
345 ptp_init();
346
347 // load config if provided
348#ifdef PTP_CONFIG_PTR
349 MSG("Loading the PTP-configuration!\n");
351
352 // print profile summary
353 MSG("\n\n----\n");
355 MSG("----\n\n");
356#endif
357
358 // initialize network stack driver
360
361 // create task
362#ifdef FLEXPTP_FREERTOS
363 sTH = NULL;
364 BaseType_t result = xTaskCreate(task_ptp, "ptp", FLEXPTP_TASK_STACK_SIZE / sizeof(BaseType_t), NULL, FLEXPTP_TASK_PRIORITY, &sTH);
365 if (result != pdPASS) {
366 MSG("Failed to create the PTP task! (errcode: %d)\n", result);
367 unreg_task_ptp(); // this will also destroy message queues and the timer
368 return false;
369 }
370#elif defined(FLEXPTP_CMSIS_OS2)
371 sTH = NULL;
372 osThreadAttr_t attr;
373 memset(&attr, 0, sizeof(osThreadAttr_t));
374 attr.name = "ptp";
375 attr.stack_size = FLEXPTP_TASK_STACK_SIZE;
376 attr.priority = FLEXPTP_TASK_PRIORITY;
377 sTH = osThreadNew(task_ptp, NULL, &attr);
378 if (sTH == NULL) {
379 MSG("Failed to create the PTP task!\n");
381 return false;
382 }
383#elif defined(FLEXPTP_LINUX)
384 sTH = 0;
385 if (pthread_create(&sTH, NULL, task_ptp, NULL) != 0) {
386 MSG("Failed to create the PTP thread!\n");
388 return false;
389 }
390 // struct sched_param sched_param = { .sched_priority = 10 };
391 // if (sched_setscheduler(getpid(), SCHED_FIFO, &sched_param)) {
392 // MSG("Could not switch to realtime scheduling!\n");
393 // return;
394 // }
395#endif
396
397 // the PTP subsystem is operating
398 sPTP_operating = true;
399
400 return true;
401}
402
403// unregister PTP task
405 ptp_remove_heartbeat_tmr(); // remove the heartbeat timer
406 ptp_nsd_init(-1, -1); // de-initialize the network stack driver
407#if defined(FLEXPTP_NON_LINUX_OS)
408 if (sTH != NULL) {
409#ifdef FLEXPTP_FREERTOS
410 vTaskDelete(sTH); // delete task
411#elif defined(FLEXPTP_CMSIS_OS2)
412 osThreadTerminate(sTH);
413#endif
414 }
415 sTH = NULL;
416#elif defined(FLEXPTP_LINUX)
417 if (sTH != 0) {
418 PtpCoreEvent event = {.code = PTP_CEV_TERMINATE, .w = 0, .dw = 0};
419 ptp_event_enqueue(&event);
420 pthread_join(sTH, NULL);
421 }
422#endif
423 ptp_deinit(); // ptp subsystem de-initialization
424 ptp_destroy_message_queues(); // destroy message queues and buffers
425 sPTP_operating = false; // the PTP subsystem is NOT operating anymore
426}
427
428// ---------------------------
429
430bool ptp_event_enqueue(const PtpCoreEvent *event) {
432
433 bool ok;
434#ifdef FLEXPTP_FREERTOS
435 ok = xQueueSend(sEventFIFO, event, portMAX_DELAY) == pdPASS;
436 if (ok) {
437 xQueueSend(sNotificationFIFO, &notif, portMAX_DELAY);
438 }
439#elif defined(FLEXPTP_CMSIS_OS2)
440 ok = osMessageQueuePut(sEventFIFO, event, 0, osWaitForever) == osOK;
441 if (ok) {
442 osMessageQueuePut(sNotificationFIFO, &notif, 0, osWaitForever);
443 }
444#elif defined(FLEXPTP_LINUX)
445 size_t len = sizeof(PtpCoreEvent);
446 ok = write(sEventFIFO[1], event, len) == len;
447#elif defined(FLEXPTP_OSLESS)
448 ok = fifo_push(&sEventFIFO, event);
449 if (ok) {
450 fifo_push(&sNotificationFIFO, &notif);
451 }
452#endif
453 return ok;
454}
455
456// put ptp message onto processing queue
457void ptp_receive_enqueue(const void *pPayload, uint32_t len, uint32_t ts_sec, uint32_t ts_ns, int tp) {
458 // only consider messages received on the matching transport layer
459 if ((!sPTP_operating) || (tp != ptp_get_transport_type())) {
460 return;
461 }
462
463 // enqueue message
465 if (pMsgAlloc) {
466 // copy payload and timestamp
467 uint32_t copyLen = MIN(len, MAX_PTP_MSG_SIZE);
468 memcpy(pMsgAlloc->data, pPayload, copyLen);
469 pMsgAlloc->size = copyLen;
470 pMsgAlloc->ts.sec = ts_sec;
471 pMsgAlloc->ts.nanosec = ts_ns;
472 pMsgAlloc->tag = RPMT_RANDOM;
473 pMsgAlloc->pTxCb = NULL; // not meaningful...
474
475 // commit the allocation
476 msgb_commit(&sRawRxMsgBuf, pMsgAlloc);
477
478 // get the UID
479 uint32_t uid = msgb_get_uid(&sRawRxMsgBuf, pMsgAlloc);
480
481 // set the notification
483#ifdef FLEXPTP_FREERTOS
484 xQueueSend(sRxPacketFIFO, &uid, portMAX_DELAY); // send index
485 xQueueSend(sNotificationFIFO, &notif, portMAX_DELAY); // send notification
486#elif defined(FLEXPTP_CMSIS_OS2)
487 osMessageQueuePut(sRxPacketFIFO, &uid, 0, osWaitForever);
488 osMessageQueuePut(sNotificationFIFO, &notif, 0, osWaitForever);
489#elif defined(FLEXPTP_LINUX)
490 write(sRxPacketFIFO[1], &uid, sizeof(uint32_t));
491#elif defined(FLEXPTP_OSLESS)
492 fifo_push(&sRxPacketFIFO, &uid);
493 fifo_push(&sNotificationFIFO, &notif);
494#endif
495 } else {
496 if (msgb_get_error(&sRawRxMsgBuf) == MSGB_ERR_FULL) {
497 CLILOG(S.logging.info, "The PTP receive packet buffer is full, a packet was lost!\n");
498 }
499 }
500}
501
503 RawPtpMessage *pMsgAlloc = msgb_alloc(&sRawTxMsgBuf, pMsg->tag, pMsg->ttl);
504 if (pMsgAlloc) {
505 memcpy(pMsgAlloc, pMsg, sizeof(RawPtpMessage));
506 msgb_commit(&sRawTxMsgBuf, pMsgAlloc);
507 uint32_t uid = msgb_get_uid(&sRawTxMsgBuf, pMsgAlloc);
509#ifdef FLEXPTP_FREERTOS
510 BaseType_t hptWoken = false;
511 if (xPortIsInsideInterrupt()) {
512 xQueueSendFromISR(sTxPacketFIFO, &uid, &hptWoken);
513 xQueueSendFromISR(sNotificationFIFO, &notif, &hptWoken);
514 } else {
515 xQueueSend(sTxPacketFIFO, &uid, portMAX_DELAY);
516 xQueueSend(sNotificationFIFO, &notif, portMAX_DELAY);
517 }
518#elif defined(FLEXPTP_CMSIS_OS2)
519 osMessageQueuePut(sTxPacketFIFO, &uid, 0, osWaitForever);
520 osMessageQueuePut(sNotificationFIFO, &notif, 0, osWaitForever);
521#elif defined(FLEXPTP_LINUX)
522 write(sTxPacketFIFO[1], &uid, sizeof(uint32_t));
523#elif defined(FLEXPTP_OSLESS)
524 fifo_push(&sTxPacketFIFO, &uid);
525 fifo_push(&sNotificationFIFO, &notif);
526#endif
527 return true;
528 } else {
529 if (msgb_get_error(&sRawTxMsgBuf) == MSGB_ERR_FULL) {
530 CLILOG(S.logging.info, "PTP TX Enqueue failed, buffer is full! (%u)\n", pMsg->tag);
531 PTP_IUEV(PTP_UEV_QUEUE_ERROR); // dispatch QUEUE_ERROR event
532 }
533 return false;
534 }
535}
536
537void ptp_transmit_timestamp_cb(uint32_t uid, uint32_t seconds, uint32_t nanoseconds) {
538 // create timestamp association object
539 TxTs ts = {.uid = uid, .seconds = seconds, .nanoseconds = nanoseconds};
540
541 // dispatch notification
543#ifdef FLEXPTP_FREERTOS
544 BaseType_t hptWoken = false;
545 if (xPortIsInsideInterrupt()) {
546 xQueueSendFromISR(sTxCbFIFO, &ts, &hptWoken);
547 xQueueSendFromISR(sNotificationFIFO, &notif, &hptWoken);
548 } else {
549 xQueueSend(sTxCbFIFO, &ts, portMAX_DELAY);
550 xQueueSend(sNotificationFIFO, &notif, portMAX_DELAY);
551 }
552#elif defined(FLEXPTP_CMSIS_OS2)
553 osMessageQueuePut(sTxCbFIFO, &ts, 0, osWaitForever);
554 osMessageQueuePut(sNotificationFIFO, &notif, 0, osWaitForever);
555#elif defined(FLEXPTP_LINUX)
556 write(sTxCbFIFO[1], &ts, sizeof(TxTs));
557 sem_post(&sTxCbSem);
558#elif defined(FLEXPTP_OSLESS)
559 fifo_push(&sTxCbFIFO, &ts);
560 fifo_push(&sNotificationFIFO, &notif);
561#endif
562}
563
565 // fetch message
566 RawPtpMessage *pRawMsg = msgb_get_sent_by_tag(&sRawTxMsgBuf, tag);
567 if (pRawMsg == NULL) {
568 return false;
569 }
570
571 // copy timestamp
572 *pTs = pRawMsg->ts;
573
574 // release message
575 msgb_free(&sRawTxMsgBuf, pRawMsg);
576
577 return true;
578}
579
587#ifdef FLEXPTP_NON_LINUX_OS
588static void task_ptp(void *pParam) {
589#elif defined(FLEXPTP_LINUX)
590static void *task_ptp(void *pParam) {
591#elif defined(FLEXPTP_OSLESS)
592void task_ptp(void) {
593#endif
594
595#ifndef FLEXPTP_OSLESS // OS assisted mode
596 bool run = true;
597 while (run) {
598#else // OS-less mode
599 while (fifo_get_level(&sNotificationFIFO) > 0) {
600#endif
601 // wait for received packet or packet to transfer
602 ProcThreadNotification notification = PTN_NONE;
603#ifdef FLEXPTP_FREERTOS
604 xQueueReceive(sNotificationFIFO, &notification, portMAX_DELAY);
605#elif defined(FLEXPTP_CMSIS_OS2)
606 osMessageQueueGet(sNotificationFIFO, &notification, NULL, osWaitForever);
607#elif defined(FLEXPTP_LINUX)
608
609 // prepare polling
610#define POLL_N_FD (4)
611 struct pollfd pfd[POLL_N_FD] = {
612 {.fd = sRxPacketFIFO[0], .events = POLLIN, .revents = 0},
613 {.fd = sTxPacketFIFO[0], .events = POLLIN, .revents = 0},
614 {.fd = sTxCbFIFO[0], .events = POLLIN, .revents = 0},
615 {.fd = sEventFIFO[0], .events = POLLIN, .revents = 0},
616 };
617 ProcThreadNotification notif_mapping[POLL_N_FD] = {
621 PTN_EVENT};
622
623 // call the poll
624 int pret = poll(pfd, POLL_N_FD, -1);
625 if (pret > 0) {
626 // at least one of the pipes have data to read
627 for (uint32_t i = 0; i < POLL_N_FD; i++) {
628 if (pfd[i].revents & POLLIN) {
629 notification |= notif_mapping[i];
630 }
631 }
632 } else {
633 // error occurred, just skip this cycle
634 CLILOG(S.logging.info, "A polling error occurred!\n");
635 continue;
636 }
637#elif defined(FLEXPTP_OSLESS)
638 fifo_pop(&sNotificationFIFO, &notification);
639#endif
640 /* ---- TRANSMIT DONE ---- */
641 if (notification & PTN_TRANSMIT_DONE) {
642
643 // get the timestamp association object
644 TxTs ts;
645
646 // clang-format off
647#ifdef FLEXPTP_FREERTOS
648 xQueueReceive(sTxCbFIFO, &ts, portMAX_DELAY);
649#elif defined(FLEXPTP_CMSIS_OS2)
650 osMessageQueueGet(sTxCbFIFO, &ts, NULL, osWaitForever);
651#elif defined(FLEXPTP_LINUX)
652 read(sTxCbFIFO[0], &ts, sizeof(TxTs));
653#elif defined(FLEXPTP_OSLESS)
654 fifo_pop(&sTxCbFIFO, &ts);
655#endif
656 // clang-format on
657
658 // fetch the message
659 CLILOG(S.logging.transmission, "[% 8u]---> %u\n", S.ticks, ts.uid);
660 RawPtpMessage *pRawMsg = msgb_get_by_uid(&sRawTxMsgBuf, ts.uid);
661 if (pRawMsg != NULL) {
662 // insert the timestamp
663 pRawMsg->ts.sec = ts.seconds;
664 pRawMsg->ts.nanosec = ts.nanoseconds;
665
666 // set the 'sent' flag
667 msgb_set_sent(&sRawTxMsgBuf, pRawMsg);
668
669 // invoke callback
670 if (pRawMsg->pTxCb != NULL) {
671 pRawMsg->pTxCb(pRawMsg);
672 }
673
674 // release message
675 if ((pRawMsg->tag == RPMT_RANDOM) || (pRawMsg->pTxCb != NULL)) {
676 msgb_free(&sRawTxMsgBuf, pRawMsg);
677 CLILOG(S.logging.transmission, "[% 8u] %u AUTOFREE\n", S.ticks, ts.uid);
678 }
679 } else {
680 // null messages
681 }
682 }
683
684 /* ---- TRANSMIT ----- */
685 if (notification & PTN_TRANSMIT) {
686
687 // pop packet UID from the FIFO
688 uint32_t uid = 0;
689
690 // clang-format off
691#ifdef FLEXPTP_FREERTOS
692 xQueueReceive(sTxPacketFIFO, &uid, portMAX_DELAY);
693#elif defined(FLEXPTP_CMSIS_OS2)
694 osMessageQueueGet(sTxPacketFIFO, &uid, NULL, osWaitForever);
695#elif defined(FLEXPTP_LINUX)
696 read(sTxPacketFIFO[0], &uid, sizeof(uint32_t));
697#elif defined(FLEXPTP_OSLESS)
698 fifo_pop(&sTxPacketFIFO, &uid);
699#endif
700 // clang-format on
701
702 // fetch the message
703 RawPtpMessage *pRawMsg = msgb_get_by_uid(&sRawTxMsgBuf, uid);
704 if (pRawMsg != NULL) {
705 CLILOG(S.logging.transmission, "[% 8u] %u (%u) --->\n", S.ticks, uid, pRawMsg->tag & (~((uint32_t)MSGBUF_TAG_OVERWRITE)));
706 ptp_nsd_transmit_msg(pRawMsg, uid);
707#ifdef FLEXPTP_LINUX
708 sem_wait(&sTxCbSem);
709#endif
710 }
711 }
712
713 // if packet is on the RX queue
714 /* ---- RECIEVE ----- */
715 if (notification & PTN_RECEIVE) {
716 // pop packet UID from the FIFO
717 uint32_t uid = 0;
718
719 // clang-format off
720#ifdef FLEXPTP_FREERTOS
721 xQueueReceive(sRxPacketFIFO, &uid, portMAX_DELAY);
722#elif defined(FLEXPTP_CMSIS_OS2)
723 osMessageQueueGet(sRxPacketFIFO, &uid, NULL, osWaitForever);
724#elif defined(FLEXPTP_LINUX)
725 read(sRxPacketFIFO[0], &uid, sizeof(uint32_t));
726#elif defined(FLEXPTP_OSLESS)
727 fifo_pop(&sRxPacketFIFO, &uid);
728#endif
729 // clang-format on
730
731 // fetch message
732 RawPtpMessage *pRawMsg = msgb_get_by_uid(&sRawRxMsgBuf, uid);
733 if (pRawMsg != NULL) {
734 // process packet
735 ptp_process_packet(pRawMsg);
736
737 // free buffer
738 msgb_free(&sRawRxMsgBuf, pRawMsg);
739 }
740 }
741
742 /* ---- EVENT ----- */
743 if (notification == PTN_EVENT) {
744
745 // pop event from the FIFO
746 PtpCoreEvent event;
747
748 // clang-format off
749#ifdef FLEXPTP_FREERTOS
750 xQueueReceive(sEventFIFO, &event, portMAX_DELAY);
751#elif defined(FLEXPTP_CMSIS_OS2)
752 osMessageQueueGet(sEventFIFO, &event, NULL, osWaitForever);
753#elif defined(FLEXPTP_LINUX)
754 read(sEventFIFO[0], &event, sizeof(PtpCoreEvent));
755#elif defined(FLEXPTP_OSLESS)
756 fifo_pop(&sEventFIFO, &event);
757#endif
758 // clang-format on
759
760 // delegate event processing
761 ptp_process_event(&event);
762
763 // tick the storage
764 if (event.code == PTP_CEV_HEARTBEAT) {
765 msgb_tick(&sRawRxMsgBuf);
766 msgb_tick(&sRawTxMsgBuf);
767 }
768
769 // handle peaceful termination
770 if (event.code == PTP_CEV_TERMINATE) {
771#ifdef FLEXPTP_LINUX
772 run = false;
773#endif
774 }
775 }
776 }
777
778#ifdef FLEXPTP_LINUX
779 return NULL;
780#endif
781}
782
783// --------------------------
784
785// function to query PTP operation state
787 return sPTP_operating;
788}
789
790// --------------------------
void ptp_load_config_from_dump(const void *pDump)
Definition: config.c:82
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:123
void ptp_nsd_init(PtpTransportType tp, PtpDelayMechanism dm)
Definition: nsd_etherlib.c:50
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:198
void ptp_process_packet(RawPtpMessage *pRawMsg)
Definition: ptp_core.c:157
void ptp_set_user_event_callback(PtpUserEventCallback userEventCb)
Definition: ptp_core.c:245
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
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:198
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:78
uint32_t uid
Message UID.
Definition: task_ptp.c:79
uint32_t seconds
Timestamp seconds.
Definition: task_ptp.c:80
uint32_t nanoseconds
Timestamp nanoseconds.
Definition: task_ptp.c:81
#define TX_CALLBACK_FIFO_LENGTH
Transmit callback FIFO length.
Definition: task_ptp.c:56
void ptp_receive_enqueue(const void *pPayload, uint32_t len, uint32_t ts_sec, uint32_t ts_ns, int tp)
Definition: task_ptp.c:457
static void task_ptp(void *pParam)
Definition: task_ptp.c:588
bool ptp_transmit_enqueue(const RawPtpMessage *pMsg)
Definition: task_ptp.c:502
void ptp_start_heartbeat_tmr()
Definition: task_ptp.c:210
static bool ptp_create_message_queues()
Definition: task_ptp.c:240
static void ptp_destroy_message_queues()
Definition: task_ptp.c:300
void unreg_task_ptp()
Definition: task_ptp.c:404
ProcThreadNotification
Notifications for the processing thread.
Definition: task_ptp.c:67
@ PTN_EVENT
An event has occurred.
Definition: task_ptp.c:72
@ PTN_TRANSMIT
A message awaits transmission.
Definition: task_ptp.c:70
@ PTN_NONE
Empty notification.
Definition: task_ptp.c:68
@ PTN_RECEIVE
A message has been received.
Definition: task_ptp.c:69
@ PTN_TRANSMIT_DONE
A transmit timestamp awaits delegation.
Definition: task_ptp.c:71
void ptp_transmit_timestamp_cb(uint32_t uid, uint32_t seconds, uint32_t nanoseconds)
Definition: task_ptp.c:537
#define EVENT_FIFO_LENGTH
Event FIFO length.
Definition: task_ptp.c:54
bool ptp_event_enqueue(const PtpCoreEvent *event)
Definition: task_ptp.c:430
#define NOTIFICATION_FIFO_LENGTH
Notification FIFO length.
Definition: task_ptp.c:55
static bool sPTP_operating
Definition: task_ptp.c:39
#define RX_TTL_MS
TTL for inbound packets.
Definition: task_ptp.c:60
void ptp_stop_heartbeat_tmr()
Definition: task_ptp.c:225
bool is_flexPTP_operating()
Definition: task_ptp.c:786
bool ptp_read_and_clear_transmit_timestamp(uint32_t tag, TimestampI *pTs)
Definition: task_ptp.c:564
#define RX_PACKET_FIFO_LENGTH
Receive packet FIFO length.
Definition: task_ptp.c:49
static bool ptp_create_heartbeat_tmr()
Definition: task_ptp.c:164
static TaskHandle_t sTH
Definition: task_ptp.c:25
#define TX_PACKET_FIFO_LENGTH
Transmit packet FIFO length.
Definition: task_ptp.c:50
static void ptp_heartbeat_tmr_cb(TimerHandle_t timer)
Definition: task_ptp.c:148
static void ptp_remove_heartbeat_tmr()
Definition: task_ptp.c:196
bool reg_task_ptp()
Definition: task_ptp.c:326
The entry point of the whole PTP-implementation. Calling reg_task_ptp() initializes the PTP-engine,...