Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
url = https://github.com/eclipse-threadx/threadx.git
[submodule "MXChip/AZ3166/deps/lib/netxduo"]
path = MXChip/AZ3166/deps/lib/netxduo
url = https://github.com/eclipse-threadx/netxduo.git
url = git@github.com:Eclipse-SDV-Hackathon-Chapter-Four/netxduo.git
[submodule "libs/threadx"]
path = libs/threadx
url = https://github.com/eclipse-threadx/threadx.git
Expand Down
5 changes: 3 additions & 2 deletions MXChip/AZ3166/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ winget install --id=Kitware.CMake -e
To compile the application, use the provided scripts in the `MXChip/AZ3166/scripts` folder.

### Windows (PowerShell)
You can build the application using `build.ps1`. It accepts a `-Config` parameter to select the application version (`starter`, `arcade`, `telemetry`, or `mqtt`).
You can build the application using `build.ps1`. It accepts a `-Config` parameter to select the application version (`starter`, `arcade`, `telemetry`, `mqtt`, or `uprotocol-mqtt`).
```powershell
.\scripts\build.ps1 -Config starter
```
Expand Down Expand Up @@ -176,7 +176,8 @@ The application supports multiple configurations that you can select at build ti

- `starter`: Initiates the board and WiFi connectivity.
- `telemetry`: Adds code to read the on-board sensors and print the output.
- `mqtt`: Adds code to publish the telemetry over MQTT. Also creates a second thread subscribing to an MQTT topic; the received messages will be printed. (Note: This configuration builds upon `telemetry`).
- `mqtt`: The original upstream MQTT telemetry demo.
- `uprotocol-mqtt`: Publishes telemetry and receives powertrain events using uProtocol over MQTT 5. See [README-UPROTOCOL.md](MXChip/AZ3166/app/uprotocol-mqtt/README-UPROTOCOL.md) for setup and deployment.
- `arcade`: A collection of arcade games. Thanks to Sébastien Heurtematte for this contribution!


Expand Down
14 changes: 13 additions & 1 deletion MXChip/AZ3166/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ elseif(APP_CONFIG STREQUAL "mqtt")
${CONFIG_DIR}/main.c
${CONFIG_DIR}/cloud_config.h
)
elseif(APP_CONFIG STREQUAL "uprotocol-mqtt")
# uProtocol over MQTT 5, with the powertrain display demo.
list(APPEND SOURCES
${COMMON_DIR}/board_init.c
${COMMON_DIR}/screen.c
${CONFIG_DIR}/telemetry.c
${CONFIG_DIR}/mqtt_client.c
${CONFIG_DIR}/powertrain_display.c
${CONFIG_DIR}/main.c
${CONFIG_DIR}/cloud_config.h
${CONFIG_DIR}/uprotocol_config.h
)
else() # starter
list(APPEND SOURCES
${COMMON_DIR}/board_init.c
Expand Down Expand Up @@ -92,7 +104,7 @@ target_include_directories(${PROJECT_NAME}
${CONFIG_DIR}
)

if(APP_CONFIG STREQUAL "mqtt")
if(APP_CONFIG STREQUAL "mqtt" OR APP_CONFIG STREQUAL "uprotocol-mqtt")
# Also include telemetry directory for MQTT
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/telemetry)
endif()
Expand Down
57 changes: 48 additions & 9 deletions MXChip/AZ3166/app/common/sntp_client.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Copyright (c) Microsoft
* Copyright (c) 2024 Eclipse Foundation
* Copyright (c) 2026 Eclipse ThreadX contributors
*
* This program and the accompanying materials are made available
* under the terms of the MIT license which is available at
Expand All @@ -12,7 +13,7 @@
* Microsoft - Initial version
* Frédéric Desbiens - 2024 version.
*/

// Portions of this file were generated with AI assistance.
#include "sntp_client.h"

#include <stdbool.h>
Expand Down Expand Up @@ -47,43 +48,53 @@ static TX_EVENT_FLAGS_GROUP sntp_flags;
// Variables to keep track of time
static ULONG sntp_last_time = 0;
static ULONG tx_last_ticks = 0;
static uint64_t sntp_epoch_ms;
static uint64_t sntp_elapsed_ticks;
static ULONG sntp_ms_last_tick;

static VOID time_update_callback(NX_SNTP_TIME_MESSAGE* time_update_ptr, NX_SNTP_TIME* local_time)
{
// Set the update flag so we pick up the new time in the SNTP thread
tx_event_flags_set(&sntp_flags, SNTP_UPDATE_EVENT, TX_OR);
}

static void set_sntp_time()
static UINT set_sntp_time()
{
UINT status;
ULONG seconds;
ULONG milliseconds;
ULONG fraction;
TX_INTERRUPT_SAVE_AREA
CHAR time_buffer[64];

status = nx_sntp_client_get_local_time(&sntp_client, &seconds, &milliseconds, NX_NULL);
status = nx_sntp_client_get_local_time(&sntp_client, &seconds, &fraction, NX_NULL);
if (status != NX_SUCCESS)
{
printf("ERROR: Internal error with getting local time (0x%08x)\n", status);
return;
return status;
}

// Stash the Unix and ThreadX times
sntp_last_time = seconds - UNIX_TO_NTP_EPOCH_SECS;
tx_last_ticks = tx_time_get();
TX_DISABLE
sntp_epoch_ms = (uint64_t)sntp_last_time * 1000u + (((uint64_t)fraction * 1000u) >> 32);
sntp_elapsed_ticks = 0;
sntp_ms_last_tick = tx_last_ticks;
TX_RESTORE

nx_sntp_client_utility_display_date_time(&sntp_client, time_buffer, sizeof(time_buffer));

printf("\tSNTP time update: %s\r\n", time_buffer);
printf("SUCCESS: SNTP initialized\r\n");
return NX_SUCCESS;
}

static UINT sntp_client_run()
{
UINT status;
NXD_ADDRESS sntp_address;

if (sntp_server_count > (sizeof(SNTP_SERVER) / sizeof(&SNTP_SERVER)))
if (sntp_server_count >= (sizeof(SNTP_SERVER) / sizeof(SNTP_SERVER[0])))
{
// We rotated through all the servers, fail out.
return NX_SNTP_SERVER_NOT_AVAILABLE;
Expand Down Expand Up @@ -133,6 +144,22 @@ ULONG sntp_time_get()
return sntp_time;
}

/* Read/advance the millisecond clock atomically on this single-core board.
* Frequent calls retain sub-millisecond ticks instead of rounding each delta. */
uint64_t sntp_time_get_ms(void)
{
ULONG current;
uint64_t result;
TX_INTERRUPT_SAVE_AREA
TX_DISABLE
current = tx_time_get();
sntp_elapsed_ticks += (ULONG)(current - sntp_ms_last_tick);
sntp_ms_last_tick = current;
result = sntp_epoch_ms ? sntp_epoch_ms + sntp_elapsed_ticks * 1000u / TX_TIMER_TICKS_PER_SECOND : 0;
TX_RESTORE
return result;
}

UINT sntp_time(ULONG* unix_time)
{
*unix_time = sntp_time_get();
Expand Down Expand Up @@ -185,7 +212,15 @@ UINT sntp_sync()
while (NX_TRUE)
{
// Run the client
sntp_client_run();
status = sntp_client_run();
if (status != NX_SUCCESS)
{
if (sntp_server_count >= sizeof(SNTP_SERVER) / sizeof(SNTP_SERVER[0]))
{
break;
}
continue;
}

// Wait for new events
events = 0;
Expand All @@ -197,11 +232,15 @@ UINT sntp_sync()
nx_sntp_client_receiving_updates(&sntp_client, &server_status);

// New time, update our local time and we are done
set_sntp_time();
status = NX_SUCCESS;
status = set_sntp_time();
break;
}

if (sntp_server_count >= sizeof(SNTP_SERVER) / sizeof(SNTP_SERVER[0]))
{
status = NX_SNTP_SERVER_NOT_AVAILABLE;
break;
}
// Otherwise we rotate around to the next server
}

Expand Down
6 changes: 5 additions & 1 deletion MXChip/AZ3166/app/common/sntp_client.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Copyright (c) Microsoft
* Copyright (c) 2024 Eclipse Foundation
* Copyright (c) 2026 Eclipse ThreadX contributors
*
* This program and the accompanying materials are made available
* under the terms of the MIT license which is available at
Expand All @@ -12,13 +13,16 @@
* Microsoft - Initial version
* Frédéric Desbiens - 2024 version.
*/

// Portions of this file were generated with AI assistance.
#ifndef _SNTP_CLIENT_H
#define _SNTP_CLIENT_H

#include <tx_api.h>
#include <stdint.h>

ULONG sntp_time_get();
/* Unix milliseconds, or zero until a successful sync. Call at least once per tick wrap. */
uint64_t sntp_time_get_ms(void);
UINT sntp_time(ULONG* unix_time);

UINT sntp_init();
Expand Down
Loading