15#include <flexptp_options.h>
26#ifdef FLEXPTP_NON_LINUX_OS
27#ifdef FLEXPTP_FREERTOS
28static TaskHandle_t
sTH;
29#elif defined(FLEXPTP_CMSIS_OS2)
30static osThreadId_t
sTH;
33#elif defined(FLEXPTP_LINUX)
36#elif defined(FLEXPTP_OSLESS)
47#define S (gPtpCoreState)
52#define RX_PACKET_FIFO_LENGTH (16)
53#define TX_PACKET_FIFO_LENGTH (16)
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)
62#define TX_TTL_MS (2000)
63#define RX_TTL_MS (2000)
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;
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;
133static PtpMsgBuf sRawRxMsgBuf, sRawTxMsgBuf;
149#ifndef FLEXPTP_OSLESS
155#elif defined(FLEXPTP_CMSIS_OS2)
157#elif defined(FLEXPTP_LINUX)
172#ifndef FLEXPTP_OSLESS
173 sHeartBeatTmr = NULL;
174#ifdef FLEXPTP_FREERTOS
179#elif defined(FLEXPTP_CMSIS_OS2)
181#elif defined(FLEXPTP_LINUX)
182 struct sigevent sev = {
183 .sigev_notify = SIGEV_THREAD,
185 .sigev_value = {.sival_ptr = NULL}};
186 if (timer_create(CLOCK_REALTIME, &sev, &sHeartBeatTmr) < 0) {
187 sHeartBeatTmr = NULL;
190 if (sHeartBeatTmr == NULL) {
191 MSG(
"Failed to create the PTP heartbeat timer!\n");
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);
212 sHeartBeatTmr = NULL;
217#ifdef FLEXPTP_FREERTOS
218 xTimerStart(sHeartBeatTmr, 0);
219#elif defined(FLEXPTP_CMSIS_OS2)
221#elif defined(FLEXPTP_LINUX)
222 struct itimerspec its = {
225 .it_value = {.tv_sec = 1, .tv_nsec = 0}
227 timer_settime(sHeartBeatTmr, 0, &its, NULL);
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);
249#ifdef FLEXPTP_FREERTOS
255 ok = (sRxPacketFIFO != NULL) && (sTxPacketFIFO != NULL) && (sEventFIFO != NULL) && (sNotificationFIFO != NULL) && (sTxCbFIFO != NULL);
256#elif defined(FLEXPTP_CMSIS_OS2)
262 ok = (sRxPacketFIFO != NULL) && (sTxPacketFIFO != NULL) && (sEventFIFO != NULL) && (sNotificationFIFO != NULL) && (sTxCbFIFO != NULL);
263#elif defined(FLEXPTP_LINUX)
271 ok &= pipe(sRxPacketFIFO) == 0;
273 ok &= pipe(sTxPacketFIFO) == 0;
275 ok &= pipe(sEventFIFO) == 0;
277 ok &= pipe(sTxCbFIFO) == 0;
278 ok &= sem_init(&sTxCbSem, 0, 0) == 0;
279#elif defined(FLEXPTP_OSLESS)
288 MSG(
"Failed to create the PTP message queues!\n");
300#define CLOSE_PIPE(pipefd) \
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);
340#ifdef PTP_USER_EVENT_CALLBACK
355 MSG(
"Loading the PTP-configuration!\n");
375#ifdef FLEXPTP_FREERTOS
378 if (result != pdPASS) {
379 MSG(
"Failed to create the PTP task! (errcode: %d)\n", result);
383#elif defined(FLEXPTP_CMSIS_OS2)
386 memset(&attr, 0,
sizeof(osThreadAttr_t));
392 MSG(
"Failed to create the PTP task!\n");
396#elif defined(FLEXPTP_LINUX)
398 if (pthread_create(&
sTH, NULL,
task_ptp, NULL) != 0) {
399 MSG(
"Failed to create the PTP thread!\n");
422#if defined(FLEXPTP_NON_LINUX_OS)
424#ifdef FLEXPTP_FREERTOS
426#elif defined(FLEXPTP_CMSIS_OS2)
427 osThreadTerminate(
sTH);
431#elif defined(FLEXPTP_LINUX)
435 pthread_join(
sTH, NULL);
449#ifdef FLEXPTP_FREERTOS
452 ok = xQueueSend(sEventFIFO, event, 0) == pdPASS;
454 xQueueSend(sNotificationFIFO, ¬if, 0);
456#elif defined(FLEXPTP_CMSIS_OS2)
457 ok = osMessageQueuePut(sEventFIFO, event, 0, 0U) == osOK;
459 osMessageQueuePut(sNotificationFIFO, ¬if, 0, 0U);
461#elif defined(FLEXPTP_LINUX)
463 ok = write(sEventFIFO[1], event, len) == len;
464#elif defined(FLEXPTP_OSLESS)
485 memcpy(pMsgAlloc->
data, pPayload, copyLen);
486 pMsgAlloc->
size = copyLen;
487 pMsgAlloc->
ts.
sec = ts_sec;
490 pMsgAlloc->
pTxCb = NULL;
499 bool enqueueOK =
false;
503#ifdef FLEXPTP_FREERTOS
506 if (xPortIsInsideInterrupt()) {
507 enqueueOK = (xQueueSendFromISR(sRxPacketFIFO, &uid, NULL) == pdPASS);
509 xQueueSendFromISR(sNotificationFIFO, ¬if, NULL);
512 enqueueOK = (xQueueSend(sRxPacketFIFO, &uid, 0) == pdPASS);
514 xQueueSend(sNotificationFIFO, ¬if, 0);
517#elif defined(FLEXPTP_CMSIS_OS2)
518 enqueueOK = (osMessageQueuePut(sRxPacketFIFO, &uid, 0, 0U) == osOK);
520 osMessageQueuePut(sNotificationFIFO, ¬if, 0, 0U);
522#elif defined(FLEXPTP_LINUX)
523 if (write(sRxPacketFIFO[1], &uid,
sizeof(uint32_t)) > 0) {
526#elif defined(FLEXPTP_OSLESS)
527 enqueueOK =
fifo_push(&sRxPacketFIFO, &uid);
535 S.stats.drop_cntrs.rx++;
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");
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");
555 bool enqueueOK =
false;
557#ifdef FLEXPTP_FREERTOS
558 if (xPortIsInsideInterrupt()) {
559 enqueueOK = (xQueueSendFromISR(sTxPacketFIFO, &uid, NULL) == pdPASS);
561 xQueueSendFromISR(sNotificationFIFO, ¬if, NULL);
564 enqueueOK = (xQueueSend(sTxPacketFIFO, &uid, 0) == pdPASS);
566 xQueueSend(sNotificationFIFO, ¬if, 0);
569#elif defined(FLEXPTP_CMSIS_OS2)
570 enqueueOK = (osMessageQueuePut(sTxPacketFIFO, &uid, 0, 0U) == osOK);
572 osMessageQueuePut(sNotificationFIFO, ¬if, 0, 0U);
574#elif defined(FLEXPTP_LINUX)
575 if (write(sTxPacketFIFO[1], &uid,
sizeof(uint32_t)) > 0) {
578#elif defined(FLEXPTP_OSLESS)
579 enqueueOK =
fifo_push(&sTxPacketFIFO, &uid);
586 S.stats.drop_cntrs.tx++;
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");
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);
606 TxTs ts = {.
uid = uid, .seconds = seconds, .nanoseconds = nanoseconds};
609 bool enqueueOK =
false;
611#ifdef FLEXPTP_FREERTOS
612 if (xPortIsInsideInterrupt()) {
613 enqueueOK = (xQueueSendFromISR(sTxCbFIFO, &ts, NULL) == pdPASS);
615 xQueueSendFromISR(sNotificationFIFO, ¬if, NULL);
618 enqueueOK = xQueueSend(sTxCbFIFO, &ts, 0);
620 xQueueSend(sNotificationFIFO, ¬if, 0);
623#elif defined(FLEXPTP_CMSIS_OS2)
624 enqueueOK = (osMessageQueuePut(sTxCbFIFO, &ts, 0, 0U) == osOK);
626 osMessageQueuePut(sNotificationFIFO, ¬if, 0, 0U);
628#elif defined(FLEXPTP_LINUX)
629 if (write(sTxCbFIFO[1], &ts,
sizeof(
TxTs)) > 0) {
633#elif defined(FLEXPTP_OSLESS)
641 S.stats.drop_cntrs.txts++;
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");
652 if (pRawMsg == NULL) {
672#ifdef FLEXPTP_NON_LINUX_OS
674#elif defined(FLEXPTP_LINUX)
675static void *
task_ptp(
void *pParam) {
676#elif defined(FLEXPTP_OSLESS)
680#ifndef FLEXPTP_OSLESS
688#ifdef FLEXPTP_FREERTOS
689 xQueueReceive(sNotificationFIFO, ¬ification, portMAX_DELAY);
690#elif defined(FLEXPTP_CMSIS_OS2)
691 osMessageQueueGet(sNotificationFIFO, ¬ification, NULL, osWaitForever);
692#elif defined(FLEXPTP_LINUX)
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},
709 int pret = poll(pfd, POLL_N_FD, -1);
712 for (uint32_t i = 0; i < POLL_N_FD; i++) {
713 if (pfd[i].revents & POLLIN) {
714 notification |= notif_mapping[i];
719 CLILOG(S.logging.logid && S.logging.info,
"[LOG-INFO] ");
720 CLILOG(S.logging.info,
"A polling error occurred!\n");
723#elif defined(FLEXPTP_OSLESS)
724fifo_pop(&sNotificationFIFO, ¬ification);
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)
745 CLILOG(S.logging.logid && S.logging.transmission,
"[LOG-TX] ");
746 CLILOG(S.logging.transmission,
"[% 8u]---> %u\n", S.ticks, ts.
uid);
748 if (pRawMsg != NULL) {
757 if (pRawMsg->
pTxCb != NULL) {
758 pRawMsg->
pTxCb(pRawMsg);
764 CLILOG(S.logging.logid && S.logging.transmission,
"[LOG-TX] ");
765 CLILOG(S.logging.transmission,
"[% 8u] %u AUTOFREE\n", S.ticks, ts.
uid);
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)
792 if (pRawMsg != NULL) {
793 CLILOG(S.logging.logid && S.logging.transmission,
"[LOG-TX] ");
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)
822 if (pRawMsg != NULL) {
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)
844#elif defined(FLEXPTP_OSLESS)
void ptp_load_config_from_dump(const void *pDump)
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.
@ PTP_CEV_TERMINATE
A shutdown is requested.
@ PTP_CEV_HEARTBEAT
Heartbeat event (tick)
bool fifo_pop(Fifo *f, void *item)
uint32_t fifo_get_level(const Fifo *f)
bool fifo_push(Fifo *f, void const *item)
void fifo_init(Fifo *f, uint32_t len, uint32_t esize, uint8_t *data, FifoLockFn lockFn)
#define FIFO_POOL(name, len, esize)
#define FLEXPTP_TASK_PRIORITY
void msgb_set_sent(PtpMsgBuf *buf, RawPtpMessage *msg)
RawPtpMessage * msgb_get_by_uid(PtpMsgBuf *buf, uint32_t uid)
void msgb_init(PtpMsgBuf *buf, PtpMsgBufBlock *pool, uint32_t n)
void msgb_commit(PtpMsgBuf *buf, RawPtpMessage *msg)
RawPtpMessage * msgb_get_sent_by_tag(PtpMsgBuf *buf, uint32_t tag)
uint32_t msgb_get_uid(const PtpMsgBuf *buf, const RawPtpMessage *msg)
RawPtpMessage * msgb_alloc(PtpMsgBuf *buf, uint32_t tag, uint32_t ttl)
void msgb_free(PtpMsgBuf *buf, RawPtpMessage *msg)
void msgb_tick(PtpMsgBuf *buf)
uint32_t msgb_get_error(PtpMsgBuf *buf)
#define MSGBUF_TAG_OVERWRITE
Overwrite if a message exists with the same tag.
@ MSGB_ERR_FULL
The buffer is full, cannot allocate a slot.
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)
void ptp_nsd_init(const NsdInitSettings *init)
This module implements defines a single method that prints a verbose summary of the operating PTP pro...
void ptp_process_event(const PtpCoreEvent *event)
void ptp_process_packet(RawPtpMessage *pRawMsg)
void ptp_set_user_event_callback(PtpUserEventCallback userEventCb)
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.
#define FLEXPTP_TASK_STACK_SIZE
flexPTP task stack size
#define FLEXPTP_MS_TO_TICKS(ms)
Interval conversion between milliseconds and ticks.
This module defines the fundamental PTP message and state machine type, flags, bitfields and the PTP ...
@ RPMT_RANDOM
Create a random, unique tag.
#define MAX_PTP_MSG_SIZE
Maximum PTP message size.
PtpDelayMechanism ptp_get_delay_mechanism()
PtpTransportType ptp_get_transport_type()
This module features functions to tweak around the PTP engine's almost every property.
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.
PTP message buffer entry.
uint32_t tag
unique transmit tag
uint32_t ttl
transmit Time-to-Live in ticks
uint32_t size
Packet size.
uint8_t data[(128)]
raw packet data
TxCb * pTxCb
transmit callback function
int32_t nanosec
nanoseconds
Structure for communicating transmit timestamp writeback.
uint32_t seconds
Timestamp seconds.
uint32_t nanoseconds
Timestamp nanoseconds.
#define TX_CALLBACK_FIFO_LENGTH
Transmit callback FIFO length.
void ptp_receive_enqueue(const void *pPayload, uint32_t len, uint32_t ts_sec, uint32_t ts_ns, int tp)
static void task_ptp(void *pParam)
bool ptp_transmit_enqueue(const RawPtpMessage *pMsg)
void ptp_start_heartbeat_tmr()
static bool ptp_create_message_queues()
static void ptp_destroy_message_queues()
ProcThreadNotification
Notifications for the processing thread.
@ PTN_EVENT
An event has occurred.
@ PTN_TRANSMIT
A message awaits transmission.
@ PTN_NONE
Empty notification.
@ PTN_RECEIVE
A message has been received.
@ PTN_TRANSMIT_DONE
A transmit timestamp awaits delegation.
void ptp_transmit_timestamp_cb(uint32_t uid, uint32_t seconds, uint32_t nanoseconds)
#define EVENT_FIFO_LENGTH
Event FIFO length.
bool ptp_event_enqueue(const PtpCoreEvent *event)
#define NOTIFICATION_FIFO_LENGTH
Notification FIFO length.
static bool sPTP_operating
#define RX_TTL_MS
TTL for inbound packets.
void ptp_stop_heartbeat_tmr()
bool is_flexPTP_operating()
bool ptp_read_and_clear_transmit_timestamp(uint32_t tag, TimestampI *pTs)
#define RX_PACKET_FIFO_LENGTH
Receive packet FIFO length.
static bool ptp_create_heartbeat_tmr()
#define TX_PACKET_FIFO_LENGTH
Transmit packet FIFO length.
static void ptp_heartbeat_tmr_cb(TimerHandle_t timer)
static void ptp_remove_heartbeat_tmr()
The entry point of the whole PTP-implementation. Calling reg_task_ptp() initializes the PTP-engine,...