Skip to content

Commit

Permalink
Refactor for readability and maintainability
Browse files Browse the repository at this point in the history
Memory optimization
Code cleanup
Bug fixes

Everything is working with the sole exception of the clock adjust not adjusting the clock enough which seems to be and issue with how offset is calculated.
  • Loading branch information
albinwwoxnerud committed May 14, 2024
1 parent 700ce79 commit edb67de
Show file tree
Hide file tree
Showing 13 changed files with 721 additions and 519 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ FreeRTOS/*

# VS Code
.vscode
src/qemu.log
2 changes: 1 addition & 1 deletion run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ run() {
run "./setup_network.sh"
run "cd src"
run "make clean"
run "make -j"
run "make -j > /dev/null"

QEMU_MAC_ADDRESS="52:54:00:12:34:AD"
CMD="qemu-system-arm -machine mps2-an385 -cpu cortex-m3 \
Expand Down
241 changes: 132 additions & 109 deletions src/NTPTask.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,184 +2,207 @@

#include "NTP_main_utility.h"
#include "NTP_peer.h"
#include "NTP_poll.h"
#include "NTP_vfo.h"

static void vNTPTaskSendUsingStandardInterface(void *pvParameters);
SemaphoreHandle_t timeMutex;

// Global NTP client variables
uint32_t NTP1_server_IP;
Socket_t xSocket;
struct freertos_sockaddr xDestinationAddress;
Assoc_table *assoc_table;
struct ntp_s s;
struct ntp_c c;

// Task function declaration
static void vNTPTask(void *pvParameters);
static void vNTPTaskInterrupt(void *pvParameters);

// Function to start NTP client task
void vStartNTPClientTasks_SingleTasks(uint16_t usTaskStackSize, UBaseType_t uxTaskPriority)
{
BaseType_t x;

/* Create the echo client tasks. */

xTaskCreate(vNTPTaskSendUsingStandardInterface, /* The function that implements the task. */
"Echo0", /* Just a text name for the task to aid debugging. */
usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
(void *)x, /* The task parameter, not used in this case. */
uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
NULL); /* The task handle is not used. */
// Create the NTP client task
xTaskCreate(vNTPTask, /* Task function */
"NTPSyncTask", /* Task name */
usTaskStackSize, /* Stack size */
(void *)x, /* Task parameter (unused) */
uxTaskPriority, /* Task priority */
NULL); /* No task handle required */
// Create the NTP client task for clock adjustment
// xTaskCreate(vNTPTaskInterrupt, /* Task function */
// "NTPClockAdjustTask", /* Task name */
// usTaskStackSize / 25, /* Stack size */
// (void *)x, /* Task parameter (unused) */
// uxTaskPriority, /* Task priority */
// NULL); /* No task handle required */
}

static void vNTPTaskSendUsingStandardInterface(void *pvParameters)
void initTimeMutex() { timeMutex = xSemaphoreCreateMutex(); }

static void init_network_and_DNS(const char *pcHostNames[], uint32_t NTP_server_IPs[])
{
// setup sleep
const TickType_t x100ms = 100UL / portTICK_PERIOD_MS;
const TickType_t x700ms = 700UL / portTICK_PERIOD_MS;
const TickType_t x1000ms = 1000UL / portTICK_PERIOD_MS;
const TickType_t x10000ms = 10000UL / portTICK_PERIOD_MS;

/* Create the socket. */
xSocket = FreeRTOS_socket(FREERTOS_AF_INET4, /* Used for IPv4 UDP socket. */
/* FREERTOS_AF_INET6 can be used for IPv6 UDP socket. */
FREERTOS_SOCK_DGRAM, /*FREERTOS_SOCK_DGRAM for UDP.*/
xSocket = FreeRTOS_socket(FREERTOS_AF_INET4, /* IPv4 UDP socket */
FREERTOS_SOCK_DGRAM, /* Datagram (UDP) */
FREERTOS_IPPROTO_UDP);

/* Check the socket was created. */
// Check socket creation
configASSERT(xSocket != FREERTOS_INVALID_SOCKET);

// Array of hostname strings
const char *pcHostNames[NMAX] = {"sth1.ntp.se", // first one should be closest to user
"sth2.ntp.se", "svl1.ntp.se", "mmo1.ntp.se",
"lul1.ntp.se"}; // , "time-a-g.nist.gov", "time-a-wwv.nist.gov"

uint32_t NTP_server_IPs[NMAX];
uint8_t DNSok;

// Resolve hostnames to IPs
for (int i = 0; i < NMAX; i++)
{
DNSok = 0;
int retry = 0;
while (DNSok == 0)
for (int retry = 0; retry < 10; retry++)
{
if (retry >= 10)
{
// FreeRTOS_printf(("\n\nDNS lookup failed, killing process.\n\n"));
return;
}

/* get the IP of the NTP server with FreeRTOS_gethostbyname */
// Resolve hostname
NTP_server_IPs[i] = FreeRTOS_gethostbyname(pcHostNames[i]);

if (NTP_server_IPs[i] == 0)
{
// FreeRTOS_printf(("\n\nDNS lookup failed, trying again in 1 second. \n\n"));
retry++;
vTaskDelay(x1000ms);
FreeRTOS_printf(("\n\nDNS lookup failed, retrying in 1 second. \n\n"));
vTaskDelay(x1000ms); // Retry delay
}
else
{
// print successful and the hostname
DNSok = 1;
FreeRTOS_printf(("\n\nDNS lookup successful for %s\n\n", pcHostNames[i]));
break;
}

// Exit if max retries reached
if (retry == 9)
{
FreeRTOS_printf(("\n\nDNS lookup failed after multiple attempts. Exiting task.\n\n"));
return;
}
}
}
// FreeRTOS_printf(("\n\nDNS lookup successful\n\n"));

/* Setup destination address */
xDestinationAddress.sin_family = FREERTOS_AF_INET4; // or FREERTOS_AF_INET6 if the destination's IP is IPv6.
xDestinationAddress.sin_address.ulIP_IPv4 = NTP1_server_IP; // destination IP
xDestinationAddress.sin_port = FreeRTOS_htons(123); // dest port
xDestinationAddress.sin_len = (uint8_t)sizeof(struct freertos_sockaddr);

struct ntp_r *r;
r = malloc(sizeof(ntp_r));
// memset(r, 0, sizeof(ntp_r));
// r->dstaddr = DSTADDR;
// r->version = VERSION;
// r->leap = NOSYNC;
// r->mode = MODE;
// r->stratum = MAXSTRAT;
// r->poll = MINPOLL;
// r->precision = -18;

struct ntp_x *x;
x = malloc(sizeof(ntp_x));
memset(x, 0, sizeof(ntp_x));
x->dstaddr = DSTADDR;

// Set up destination address
xDestinationAddress.sin_family = FREERTOS_AF_INET4;
xDestinationAddress.sin_port = FreeRTOS_htons(123); // NTP default port
xDestinationAddress.sin_len = sizeof(struct freertos_sockaddr);
}

// Task function for NTP client
static void vNTPTask(void *pvParameters)
{
// Sleep intervals in milliseconds
const TickType_t x100ms = 100UL / portTICK_PERIOD_MS;
const TickType_t x1000ms = 1000UL / portTICK_PERIOD_MS;
const TickType_t x10000ms = 10000UL / portTICK_PERIOD_MS;

const char *pcHostNames[NMAX] = {"sth1.ntp.se", "sth2.ntp.se", "svl1.ntp.se", "mmo1.ntp.se", "lul1.ntp.se"};

// Array to store resolved IP addresses of NTP servers
uint32_t NTP_server_IPs[NMAX] = {0};
init_network_and_DNS(pcHostNames, NTP_server_IPs);
initTimeMutex();

// Allocate and initialize NTP packet structures
struct ntp_r *r = malloc(sizeof(ntp_r));
struct ntp_x *x = calloc(1, sizeof(ntp_x)); // Zero-initialized

x->version = VERSION;
x->leap = NOSYNC;
x->mode = MODE;
x->stratum = MAXSTRAT;
x->poll = MINPOLL;
x->precision = -18;

// Initialize NTP system and control structures
memset(&s, 0, sizeof(ntp_s));
s.leap = NOSYNC;
s.stratum = MAXSTRAT;
s.poll = MINPOLL;
s.precision = -18;
s.p = NULL;

memset(&c, 0, sizeof(ntp_c));
c.lastTimeStampTick = 0;

// Handle frequency settings
if (FREQ_EXISTS)
{
c.freq = (double)SYSCLK_FRQ;
c.freq = (double)configTICK_RATE_HZ;
rstclock(FSET, 0, 0);
}
else
{
rstclock(NSET, 0, 0);
}

c.jitter = LOG2D(s.precision);
assoc_table_init(NTP_server_IPs);
/*
get time from one NTP server, use as start reference
*/

// Initialize time with the first NTP server
NTP1_server_IP = NTP_server_IPs[0];
x->srcaddr = NTP1_server_IP;
xDestinationAddress.sin_address.ulIP_IPv4 = NTP1_server_IP;
// FreeRTOS_printf(("\n\n Getting first initial reference time from IP (which is %s): %lu.%lu.%lu.%lu \n\n",
// pcHostNames[0],
// NTP1_server_IP & 0xFF, // Extract the fourth byte
// (NTP1_server_IP >> 8) & 0xFF, // Extract the third byte
// (NTP1_server_IP >> 16) & 0xFF, // Extract the second byte
// (NTP1_server_IP >> 24) & 0xFF)); // Extract the first byte

prep_xmit(x);
xmit_packet(x);
recv_packet(r);
x->xmt = r->xmt;
x->srcaddr = NTP1_server_IP;

prep_xmit(x); // Prepare for transmission
xmit_packet(x); // Send initial request
recv_packet(r); // Receive the response

x->xmt = r->xmt; // Set initial transmission timestamp
settime(x->xmt);
gettime(1);

uint32_t ulCount = 0UL;
for (int i = 0; i < NMAX; i++)
{
// Update destination address with current NTP server
NTP1_server_IP = NTP_server_IPs[i];

FreeRTOS_printf(("\n\nGetting time from IP (%s): %lu.%lu.%lu.%lu\n\n", pcHostNames[i], (NTP1_server_IP & 0xFF),
((NTP1_server_IP >> 8) & 0xFF), ((NTP1_server_IP >> 16) & 0xFF),
((NTP1_server_IP >> 24) & 0xFF)));

prep_xmit(x); // Prepare NTP packet
xmit_packet(x); // Send request
recv_packet(r); // Receive response

// Process the received response
receive(r);
vTaskDelay(x1000ms); // Delay before next init
}
// return;

// Main NTP client loop
for (;;)
{
for (int i = 0; i < NMAX; i++)
{
// set the destination IP to the current NTP server
NTP1_server_IP = NTP_server_IPs[i];
x->srcaddr = NTP1_server_IP;
xDestinationAddress.sin_address.ulIP_IPv4 = NTP1_server_IP;

FreeRTOS_printf(("\n\n Getting from IP (which is %s): %lu.%lu.%lu.%lu \n\n", pcHostNames[i],
NTP1_server_IP & 0xFF, // Extract the fourth byte
(NTP1_server_IP >> 8) & 0xFF, // Extract the third byte
(NTP1_server_IP >> 16) & 0xFF, // Extract the second byte
(NTP1_server_IP >> 24) & 0xFF)); // Extract the first byte

prep_xmit(x);
xmit_packet(x);
recv_packet(r);
x->xmt = r->xmt;
printTimestamp(r->rec, "r->rec");

receive(r); // handle the response
}
// gettime(1); // Get current time
printTimestamp(c.localTime, "current time\n\n");

clock_adjust(r); // Adjust the clock

FreeRTOS_printf(("\n\nSleeping for 10 seconds before next get\n\n"));
vTaskDelay(x100ms); // Delay before next adjustment

// sleep for 10 seconds
vTaskDelay(x10000ms);
// recv_packet(r); // Receive response
// receive(r);
}

// Cleanup allocated memory (typically not reached in FreeRTOS tasks)
free(r);
free(x);
}

// static void vNTPTaskInterrupt(void *pvParameters)
// {
// // Sleep intervals in milliseconds
// const TickType_t x100ms = 100UL / portTICK_PERIOD_MS;
// const TickType_t x1000ms = 1000UL / portTICK_PERIOD_MS;
// const TickType_t x10000ms = 10000UL / portTICK_PERIOD_MS;

// while (!init)
// {
// vTaskDelay(x1000ms);
// }
// for (;;)
// {
// FreeRTOS_printf(("\n\nAdjust clock\n\n"));
// clock_adjust(); // Adjust the clock
// FreeRTOS_printf(("\n\nAdjusted clock\n\n"));

// vTaskDelay(x100ms); // Delay before next adjustment
// }
// }
8 changes: 3 additions & 5 deletions src/NTPTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,17 @@
#include "freq.h"

/*
* Create the UDP echo client tasks. This is the version where an echo request
* is made from the same task that listens for the echo reply.
* Create the NTP client task and the clock adjust interrupt task.
*/
void vStartNTPClientTasks_SingleTasks(uint16_t usTaskStackSize, UBaseType_t uxTaskPriority);

extern SemaphoreHandle_t timeMutex;

extern uint32_t NTP1_server_IP;
extern Socket_t xSocket;
extern struct freertos_sockaddr xDestinationAddress;
extern Assoc_table *assoc_table;
extern struct ntp_s s;
extern struct ntp_c c;

extern TickType_t lastTimeStampTick;
extern tstamp lastTimeStampTstamp;

#endif /* UDP_ECHO_CLIENT_DEMO_H */
Loading

0 comments on commit edb67de

Please sign in to comment.