Added basic thread support
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
venv
|
||||
**/build
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# Console and Logging
|
||||
CONFIG_LOG=y
|
||||
|
||||
# Shell and Built-in Commands
|
||||
@@ -12,5 +13,13 @@ CONFIG_FLASH_MAP=y
|
||||
CONFIG_NVS=y
|
||||
CONFIG_SETTINGS=y
|
||||
|
||||
# Network and OpenThread
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_L2_OPENTHREAD=y
|
||||
CONFIG_OPENTHREAD=y
|
||||
CONFIG_OPENTHREAD_FTD=y
|
||||
CONFIG_OPENTHREAD_SHELL=y
|
||||
|
||||
# Enable Lasertag Shared Modules
|
||||
CONFIG_LASERTAG_UTILS=y
|
||||
CONFIG_LASERTAG_UTILS=y
|
||||
CONFIG_THREAD_MGMT=y
|
||||
@@ -1,17 +1,25 @@
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <lasertag_utils.h>
|
||||
#include <thread_mgmt.h>
|
||||
|
||||
LOG_MODULE_REGISTER(leader_app, CONFIG_LOG_DEFAULT_LEVEL);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* Initialize shared project logic */
|
||||
/* Initialize shared project logic and NVS */
|
||||
lasertag_utils_init();
|
||||
|
||||
LOG_INF("Leader Application successfully started.\n");
|
||||
/* Initialize and start OpenThread stack */
|
||||
int rc = thread_mgmt_init();
|
||||
if (rc) {
|
||||
LOG_ERR("Thread initialization failed (err %d)", rc);
|
||||
} else {
|
||||
LOG_INF("Leader Application successfully started with Thread Mesh.");
|
||||
}
|
||||
|
||||
while (1) {
|
||||
/* Main loop - keep process alive */
|
||||
/* Main loop - handle high-level game logic here */
|
||||
k_sleep(K_MSEC(1000));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
# Add library subdirectories
|
||||
add_subdirectory(lasertag_utils)
|
||||
add_subdirectory(lasertag_utils)
|
||||
add_subdirectory(thread_mgmt)
|
||||
@@ -1,4 +1,3 @@
|
||||
# Main entry point for custom project Kconfigs
|
||||
# This file is included by the application's Kconfig
|
||||
|
||||
rsource "lasertag_utils/Kconfig"
|
||||
rsource "lasertag_utils/Kconfig"
|
||||
rsource "thread_mgmt/Kconfig"
|
||||
@@ -31,4 +31,22 @@ uint16_t lasertag_get_thread_pan_id(void);
|
||||
*/
|
||||
const char* lasertag_get_thread_network_name(void);
|
||||
|
||||
/**
|
||||
* @brief Get the configured Thread Channel.
|
||||
* @return 8-bit channel (usually 11-26).
|
||||
*/
|
||||
uint8_t lasertag_get_thread_channel(void);
|
||||
|
||||
/**
|
||||
* @brief Get the configured Thread Extended PAN ID.
|
||||
* @return Pointer to the 8-byte extended PAN ID.
|
||||
*/
|
||||
const uint8_t* lasertag_get_thread_ext_pan_id(void);
|
||||
|
||||
/**
|
||||
* @brief Get the configured Thread Network Key.
|
||||
* @return Pointer to the 16-byte network key.
|
||||
*/
|
||||
const uint8_t* lasertag_get_thread_network_key(void);
|
||||
|
||||
#endif /* LASERTAG_UTILS_H */
|
||||
@@ -9,10 +9,18 @@
|
||||
|
||||
LOG_MODULE_REGISTER(lasertag_utils, CONFIG_LASERTAG_UTILS_LOG_LEVEL);
|
||||
|
||||
/* Default values */
|
||||
/* Application-level persistence storage */
|
||||
static char device_name[32] = "UnknownDevice";
|
||||
|
||||
/* Thread configuration parameters */
|
||||
static uint16_t thread_pan_id = 0xabcd;
|
||||
static char thread_network_name[17] = "OpenThread-nRF";
|
||||
static uint8_t thread_channel = 15;
|
||||
static uint8_t thread_ext_pan_id[8] = {0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe};
|
||||
static uint8_t thread_network_key[16] = {
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
|
||||
};
|
||||
|
||||
/* --- Settings Handling (Persistent Storage) --- */
|
||||
|
||||
@@ -23,10 +31,7 @@ static int lasertag_settings_set(const char *name, size_t len, settings_read_cb
|
||||
if (settings_name_steq(name, "name", &next) && !next) {
|
||||
if (len > sizeof(device_name) - 1) return -EINVAL;
|
||||
ssize_t rc = read_cb(cb_arg, device_name, len);
|
||||
if (rc >= 0) {
|
||||
device_name[rc] = '\0';
|
||||
return 0;
|
||||
}
|
||||
if (rc >= 0) { device_name[rc] = '\0'; return 0; }
|
||||
return (int)rc;
|
||||
}
|
||||
|
||||
@@ -37,13 +42,22 @@ static int lasertag_settings_set(const char *name, size_t len, settings_read_cb
|
||||
if (settings_name_steq(name, "net_name", &next) && !next) {
|
||||
if (len > sizeof(thread_network_name) - 1) return -EINVAL;
|
||||
ssize_t rc = read_cb(cb_arg, thread_network_name, len);
|
||||
if (rc >= 0) {
|
||||
thread_network_name[rc] = '\0';
|
||||
return 0;
|
||||
}
|
||||
if (rc >= 0) { thread_network_name[rc] = '\0'; return 0; }
|
||||
return (int)rc;
|
||||
}
|
||||
|
||||
if (settings_name_steq(name, "channel", &next) && !next) {
|
||||
return read_cb(cb_arg, &thread_channel, sizeof(thread_channel)) >= 0 ? 0 : -EIO;
|
||||
}
|
||||
|
||||
if (settings_name_steq(name, "ext_pan_id", &next) && !next) {
|
||||
return read_cb(cb_arg, thread_ext_pan_id, sizeof(thread_ext_pan_id)) >= 0 ? 0 : -EIO;
|
||||
}
|
||||
|
||||
if (settings_name_steq(name, "net_key", &next) && !next) {
|
||||
return read_cb(cb_arg, thread_network_key, sizeof(thread_network_key)) >= 0 ? 0 : -EIO;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@@ -58,29 +72,65 @@ void lasertag_utils_init(void)
|
||||
LOG_INF("Lasertag System - Common Lib v0.0.1");
|
||||
|
||||
int rc = settings_subsys_init();
|
||||
if (rc) {
|
||||
LOG_ERR("Settings subsys init failed (err %d)", rc);
|
||||
}
|
||||
if (rc) LOG_ERR("Settings subsys init failed (err %d)", rc);
|
||||
|
||||
settings_register(&lasertag_conf);
|
||||
settings_load();
|
||||
|
||||
LOG_INF("Device Name : %s", device_name);
|
||||
LOG_INF("Thread PAN : 0x%04x", thread_pan_id);
|
||||
LOG_INF("Thread Name : %s", thread_network_name);
|
||||
LOG_INF("Device Name : %s", device_name);
|
||||
LOG_INF("Thread PAN : 0x%04x", thread_pan_id);
|
||||
LOG_INF("Thread Name : %s", thread_network_name);
|
||||
LOG_INF("Thread Chan : %d", thread_channel);
|
||||
LOG_INF("==========================================");
|
||||
}
|
||||
|
||||
const char* lasertag_get_device_name(void) { return device_name; }
|
||||
uint16_t lasertag_get_thread_pan_id(void) { return thread_pan_id; }
|
||||
const char* lasertag_get_thread_network_name(void) { return thread_network_name; }
|
||||
uint8_t lasertag_get_thread_channel(void) { return thread_channel; }
|
||||
const uint8_t* lasertag_get_thread_ext_pan_id(void) { return thread_ext_pan_id; }
|
||||
const uint8_t* lasertag_get_thread_network_key(void) { return thread_network_key; }
|
||||
|
||||
/* --- Shell Commands --- */
|
||||
|
||||
#if CONFIG_LASERTAG_SHELL
|
||||
|
||||
static int cmd_name_set(const struct shell *sh, size_t argc, char **argv)
|
||||
{
|
||||
/**
|
||||
* @brief Helper to convert hex string to binary.
|
||||
* Renamed to lasertag_hex2bin to avoid conflict with Zephyr sys/util.h
|
||||
*/
|
||||
static int lasertag_hex2bin(const char *hex, uint8_t *bin, size_t bin_len) {
|
||||
for (size_t i = 0; i < bin_len; i++) {
|
||||
char buf[3] = { hex[i*2], hex[i*2+1], '\0' };
|
||||
bin[i] = (uint8_t)strtoul(buf, NULL, 16);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_thread_set_chan(const struct shell *sh, size_t argc, char **argv) {
|
||||
thread_channel = (uint8_t)strtoul(argv[1], NULL, 10);
|
||||
settings_save_one("lasertag/channel", &thread_channel, sizeof(thread_channel));
|
||||
shell_print(sh, "Thread Channel saved: %d", thread_channel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_thread_set_extpan(const struct shell *sh, size_t argc, char **argv) {
|
||||
if (strlen(argv[1]) != 16) { shell_error(sh, "ExtPANID must be 16 hex chars"); return -EINVAL; }
|
||||
lasertag_hex2bin(argv[1], thread_ext_pan_id, 8);
|
||||
settings_save_one("lasertag/ext_pan_id", thread_ext_pan_id, 8);
|
||||
shell_print(sh, "Thread Extended PAN ID saved.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_thread_set_key(const struct shell *sh, size_t argc, char **argv) {
|
||||
if (strlen(argv[1]) != 32) { shell_error(sh, "Network Key must be 32 hex chars"); return -EINVAL; }
|
||||
lasertag_hex2bin(argv[1], thread_network_key, 16);
|
||||
settings_save_one("lasertag/net_key", thread_network_key, 16);
|
||||
shell_print(sh, "Thread Network Key saved.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_name_set(const struct shell *sh, size_t argc, char **argv) {
|
||||
strncpy(device_name, argv[1], sizeof(device_name) - 1);
|
||||
device_name[sizeof(device_name) - 1] = '\0';
|
||||
settings_save_one("lasertag/name", device_name, strlen(device_name));
|
||||
@@ -88,31 +138,16 @@ static int cmd_name_set(const struct shell *sh, size_t argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_thread_set_panid(const struct shell *sh, size_t argc, char **argv)
|
||||
{
|
||||
thread_pan_id = (uint16_t)strtoul(argv[1], NULL, 0);
|
||||
settings_save_one("lasertag/pan_id", &thread_pan_id, sizeof(thread_pan_id));
|
||||
shell_print(sh, "Thread PAN ID saved: 0x%04x", thread_pan_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_thread_set_name(const struct shell *sh, size_t argc, char **argv)
|
||||
{
|
||||
strncpy(thread_network_name, argv[1], sizeof(thread_network_name) - 1);
|
||||
thread_network_name[sizeof(thread_network_name) - 1] = '\0';
|
||||
settings_save_one("lasertag/net_name", thread_network_name, strlen(thread_network_name));
|
||||
shell_print(sh, "Thread Network Name saved: %s", thread_network_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Subcommands for 'lasertag thread' */
|
||||
SHELL_STATIC_SUBCMD_SET_CREATE(sub_thread,
|
||||
SHELL_CMD_ARG(panid, NULL, "Set PAN ID <id>", cmd_thread_set_panid, 2, 0),
|
||||
SHELL_CMD_ARG(name, NULL, "Set Network Name <name>", cmd_thread_set_name, 2, 0),
|
||||
SHELL_CMD_ARG(panid, NULL, "Set PAN ID <id>", NULL, 2, 0),
|
||||
SHELL_CMD_ARG(name, NULL, "Set Net Name <name>", NULL, 2, 0),
|
||||
SHELL_CMD_ARG(chan, NULL, "Set Channel <11-26>", cmd_thread_set_chan, 2, 0),
|
||||
SHELL_CMD_ARG(extid, NULL, "Set ExtPANID <16 hex chars>", cmd_thread_set_extpan, 2, 0),
|
||||
SHELL_CMD_ARG(key, NULL, "Set NetKey <32 hex chars>", cmd_thread_set_key, 2, 0),
|
||||
SHELL_SUBCMD_SET_END
|
||||
);
|
||||
|
||||
/* Main command 'lasertag' */
|
||||
SHELL_STATIC_SUBCMD_SET_CREATE(sub_lasertag,
|
||||
SHELL_CMD_ARG(name, NULL, "Set device name <name>", cmd_name_set, 2, 0),
|
||||
SHELL_CMD(thread, &sub_thread, "Thread network configuration", NULL),
|
||||
|
||||
5
firmware/libs/thread_mgmt/CMakeLists.txt
Normal file
5
firmware/libs/thread_mgmt/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
if(CONFIG_THREAD_MGMT)
|
||||
zephyr_library()
|
||||
zephyr_sources(src/thread_mgmt.c)
|
||||
zephyr_include_directories(include)
|
||||
endif()
|
||||
14
firmware/libs/thread_mgmt/Kconfig
Normal file
14
firmware/libs/thread_mgmt/Kconfig
Normal file
@@ -0,0 +1,14 @@
|
||||
menuconfig THREAD_MGMT
|
||||
bool "Thread Management"
|
||||
depends on OPENTHREAD
|
||||
select LASERTAG_UTILS
|
||||
help
|
||||
Library for initializing and managing the OpenThread stack.
|
||||
|
||||
if THREAD_MGMT
|
||||
config THREAD_MGMT_LOG_LEVEL
|
||||
int "Thread Management Log Level"
|
||||
default 3
|
||||
help
|
||||
Set the verbosity of the thread management library.
|
||||
endif
|
||||
17
firmware/libs/thread_mgmt/include/thread_mgmt.h
Normal file
17
firmware/libs/thread_mgmt/include/thread_mgmt.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef THREAD_MGMT_H
|
||||
#define THREAD_MGMT_H
|
||||
|
||||
/**
|
||||
* @file thread_mgmt.h
|
||||
* @brief Thread network management and stack initialization.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the OpenThread stack with parameters from NVS.
|
||||
* * This function configures the operational dataset (Network Name,
|
||||
* PAN ID, Key, etc.) and starts the Thread interface.
|
||||
* * @return 0 on success, negative error code otherwise.
|
||||
*/
|
||||
int thread_mgmt_init(void);
|
||||
|
||||
#endif /* THREAD_MGMT_H */
|
||||
77
firmware/libs/thread_mgmt/src/thread_mgmt.c
Normal file
77
firmware/libs/thread_mgmt/src/thread_mgmt.c
Normal file
@@ -0,0 +1,77 @@
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/net/openthread.h>
|
||||
#include <openthread/thread.h>
|
||||
#include <openthread/dataset.h>
|
||||
#include <openthread/instance.h>
|
||||
#include <lasertag_utils.h>
|
||||
#include <thread_mgmt.h>
|
||||
|
||||
LOG_MODULE_REGISTER(thread_mgmt, CONFIG_THREAD_MGMT_LOG_LEVEL);
|
||||
|
||||
int thread_mgmt_init(void)
|
||||
{
|
||||
struct otInstance *instance = openthread_get_default_instance();
|
||||
otOperationalDataset dataset;
|
||||
int rc;
|
||||
|
||||
if (!instance) {
|
||||
LOG_ERR("Failed to get OpenThread instance");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
LOG_INF("Configuring Thread stack with stored settings...");
|
||||
|
||||
/* Initialize dataset structure */
|
||||
memset(&dataset, 0, sizeof(otOperationalDataset));
|
||||
|
||||
/* 1. Set Network Name */
|
||||
const char *net_name = lasertag_get_thread_network_name();
|
||||
size_t name_len = strlen(net_name);
|
||||
memcpy(dataset.mNetworkName.m8, net_name, name_len);
|
||||
dataset.mComponents.mIsNetworkNamePresent = true;
|
||||
|
||||
/* 2. Set PAN ID */
|
||||
dataset.mPanId = lasertag_get_thread_pan_id();
|
||||
dataset.mComponents.mIsPanIdPresent = true;
|
||||
|
||||
/* 3. Set Channel */
|
||||
dataset.mChannel = lasertag_get_thread_channel();
|
||||
dataset.mComponents.mIsChannelPresent = true;
|
||||
|
||||
/* 4. Set Extended PAN ID */
|
||||
memcpy(dataset.mExtendedPanId.m8, lasertag_get_thread_ext_pan_id(), 8);
|
||||
dataset.mComponents.mIsExtendedPanIdPresent = true;
|
||||
|
||||
/* 5. Set Network Key */
|
||||
memcpy(dataset.mNetworkKey.m8, lasertag_get_thread_network_key(), 16);
|
||||
dataset.mComponents.mIsNetworkKeyPresent = true;
|
||||
|
||||
/* 6. Set Mesh Local Prefix (Default for OpenThread) */
|
||||
uint8_t ml_prefix[] = {0xfd, 0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0x00};
|
||||
memcpy(dataset.mMeshLocalPrefix.m8, ml_prefix, 8);
|
||||
dataset.mComponents.mIsMeshLocalPrefixPresent = true;
|
||||
|
||||
/* Apply the dataset as the Active Dataset */
|
||||
rc = otDatasetSetActive(instance, &dataset);
|
||||
if (rc != OT_ERROR_NONE) {
|
||||
LOG_ERR("Failed to set Active Dataset (err %d)", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Start the interface */
|
||||
rc = otIp6SetEnabled(instance, true);
|
||||
if (rc != OT_ERROR_NONE) {
|
||||
LOG_ERR("Failed to enable IPv6 (err %d)", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = otThreadSetEnabled(instance, true);
|
||||
if (rc != OT_ERROR_NONE) {
|
||||
LOG_ERR("Failed to enable Thread (err %d)", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
LOG_INF("Thread stack initialized and interface enabled.");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user