Skip to content

Commit bab0082

Browse files
committed
ptp
1 parent cc2b142 commit bab0082

2 files changed

Lines changed: 89 additions & 9 deletions

File tree

NetX/inc/u_nx_ethernet.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <stdint.h>
1111
#include <stdbool.h>
1212
#include "nx_api.h"
13+
#include "nxd_ptp_client.h"
1314

1415
/* CONFIG */
1516
#define ETH_UDP_PORT 2006 /* UDP port for communication */
@@ -31,11 +32,11 @@ typedef enum {
3132

3233
/* These node ids are ONLY relavent to PLCA configuration.
3334
They are meant to be used when configuring a PHY. The IDs must be sequential, and the "0" id always indicates the network's coordinator node.
34-
They have no impact on application-level IP addresses or message processing.
35-
35+
They have no impact on application-level IP addresses or message processing.
36+
3637
For example, if you're using the LAN8670 PHY driver, you'd probably use these enum values like this:
3738
LAN8670_PLCA_Set_Node_Count(&lan8670, PLCA_NUM_NODES);
38-
LAN8670_PLCA_Set_Node_Id(&lan8670, PLCA_VCU) // replace 'PLCA_VCU' with whatever board it is
39+
LAN8670_PLCA_Set_Node_Id(&lan8670, PLCA_VCU) // replace 'PLCA_VCU' with whatever board it is
3940
*/
4041
typedef enum {
4142
PLCA_TPU, // 0. This is the PLCA coordinator node.
@@ -88,5 +89,11 @@ ethernet_message_t ethernet_create_message(uint8_t message_id, ethernet_node_t r
8889
*/
8990
uint8_t ethernet_send_message(ethernet_message_t *message);
9091

92+
/**
93+
* @brief Retrieves the time from PTP stack.
94+
* @return The UTC time
95+
*/
96+
NX_PTP_DATE_TIME ethernet_get_time(void);
97+
9198
// clang-format on
92-
#endif /* u_nx_ethernet.h */
99+
#endif /* u_nx_ethernet.h */

NetX/src/u_nx_ethernet.c

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// clang-format off
22
#include "u_nx_ethernet.h"
33
#include "nx_stm32_eth_driver.h"
4+
#include "nxd_ptp_client.h"
45
#include "u_nx_debug.h"
56
#include "u_tx_debug.h"
67
#include "nx_api.h"
@@ -15,18 +16,22 @@
1516
#define _IP_THREAD_PRIORITY 1
1617
#define _IP_NETWORK_MASK IP_ADDRESS(255, 255, 255, 0)
1718
#define _UDP_QUEUE_MAXIMUM 12
19+
#define _PTP_THREAD_PRIORITY 2
1820

1921
/* DEVICE INFO */
2022
typedef struct {
2123
/* NetX Objects */
2224
NX_UDP_SOCKET socket;
2325
NX_PACKET_POOL packet_pool;
2426
NX_IP ip;
27+
NX_PTP_CLIENT ptp_client;
28+
SHORT ptp_utc_offset;
2529

2630
/* Static memory for NetX stuff */
2731
UCHAR packet_pool_memory[_PACKET_POOL_SIZE];
2832
UCHAR ip_memory[_IP_THREAD_STACK_SIZE];
2933
UCHAR arp_cache_memory[_ARP_CACHE_SIZE];
34+
ULONG ptp_stack[2048 / sizeof(ULONG)];
3035

3136
/* Device config variables */
3237
bool is_initialized;
@@ -37,6 +42,45 @@ typedef struct {
3742
} _ethernet_device_t;
3843
static _ethernet_device_t device = { 0 };
3944

45+
/* Callback function. Called when a PTP event is processed. */
46+
// extern UINT ptp_clock_callback(NX_PTP_CLIENT *client_ptr, UINT operation,
47+
// NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr,
48+
// VOID *callback_data);
49+
50+
/* Callback function. Called when a PTP event is processed. */
51+
static UINT _ptp_event_callback(NX_PTP_CLIENT *ptp_client_ptr, UINT event, VOID *event_data, VOID *callback_data)
52+
{
53+
NX_PARAMETER_NOT_USED(callback_data);
54+
55+
switch (event)
56+
{
57+
case NX_PTP_CLIENT_EVENT_MASTER:
58+
{
59+
PRINTLN_WARNING("new MASTER clock!");
60+
break;
61+
}
62+
63+
case NX_PTP_CLIENT_EVENT_SYNC:
64+
{
65+
nx_ptp_client_sync_info_get((NX_PTP_CLIENT_SYNC *)event_data, NX_NULL, &device.ptp_utc_offset);
66+
PRINTLN_INFO("SYNC event: utc offset=%d", device.ptp_utc_offset);
67+
break;
68+
}
69+
70+
case NX_PTP_CLIENT_EVENT_TIMEOUT:
71+
{
72+
PRINTLN_WARNING("Master clock TIMEOUT!");
73+
break;
74+
}
75+
default:
76+
{
77+
break;
78+
}
79+
}
80+
81+
return 0;
82+
}
83+
4084
/* Callback function. Called when an ethernet message is received. */
4185
static void _receive_message(NX_UDP_SOCKET *socket) {
4286
NX_PACKET *packet;
@@ -92,8 +136,9 @@ static void _receive_message(NX_UDP_SOCKET *socket) {
92136
/* API FUNCTIONS */
93137

94138
uint8_t ethernet_init(ethernet_node_t node_id, DriverFunction driver, OnRecieve on_recieve) {
95-
139+
96140
uint8_t status;
141+
device.ptp_utc_offset = 0; // no offset to start
97142

98143
/* Make sure device isn't already initialized */
99144
if(device.is_initialized) {
@@ -162,11 +207,11 @@ uint8_t ethernet_init(ethernet_node_t node_id, DriverFunction driver, OnRecieve
162207
return status;
163208
}
164209

165-
/* Set up multicast groups.
210+
/* Set up multicast groups.
166211
* (This iterates through every possible node combination between 0b00000001 and 0b11111111.
167212
* If any of the combinations include device.node_id, that combination gets added as a multicast group.
168213
* This ensures that ethernet messages can be sent to all possible combinations of recipients.)
169-
*
214+
*
170215
* Note: This is probably pretty inefficient. I did it so you don't have to manually set up
171216
* multicast groups any time you want to send a message to a new combination of nodes,
172217
* but if this setup ends up being too slow or something, feel free to get rid of it.
@@ -181,6 +226,22 @@ uint8_t ethernet_init(ethernet_node_t node_id, DriverFunction driver, OnRecieve
181226
}
182227
}
183228

229+
/* Create the PTP client instance */
230+
status = nx_ptp_client_create(&device.ptp_client, &device.ip, 0, &device.packet_pool,
231+
_PTP_THREAD_PRIORITY, (UCHAR *)&device.ptp_stack, sizeof(device.ptp_stack),
232+
_nx_ptp_client_soft_clock_callback, NX_NULL);
233+
if(status != NX_SUCCESS) {
234+
PRINTLN_ERROR("Failed to create PTP client (Status: %d/%s).", status, nx_status_toString(status));
235+
return status;
236+
}
237+
238+
/* start the PTP client */
239+
status = nx_ptp_client_start(&device.ptp_client, NX_NULL, 0, 0, NX_PTP_TRANSPORT_SPECIFIC_NON_802, _ptp_event_callback, NX_NULL);
240+
if(status != NX_SUCCESS) {
241+
PRINTLN_ERROR("Failed to start PTP client (Status: %d/%s).", status, nx_status_toString(status));
242+
return status;
243+
}
244+
184245
/* Create UDP socket for broadcasting */
185246
status = nx_udp_socket_create(
186247
&device.ip, // IP instance
@@ -330,7 +391,19 @@ uint8_t ethernet_send_message(ethernet_message_t *message) {
330391
PRINTLN_INFO("got to nx_udp_socket_send() part of send message");
331392

332393
PRINTLN_INFO("Sent ethernet message (Recipient ID: %d, Message ID: %d, Message Contents: %d).", message->recipient_id, message->message_id, message->data);
333-
PRINTLN_INFO("TX complete count: %lu", tx_complete_count);
334394
return U_SUCCESS;
335395
}
336-
// clang-format on
396+
397+
NX_PTP_DATE_TIME ethernet_get_time(void) {
398+
NX_PTP_TIME tm;
399+
NX_PTP_DATE_TIME date;
400+
/* read the PTP clock */
401+
nx_ptp_client_time_get(&device.ptp_client, &tm);
402+
403+
/* convert PTP time to UTC date and time */
404+
nx_ptp_client_utility_convert_time_to_date(&tm, 0, &date);
405+
406+
return date;
407+
}
408+
409+
// clang-format on

0 commit comments

Comments
 (0)