Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
930b97b
feat: implement RTC and sleep manager functionality; refactor existin…
wybran Dec 6, 2025
4fec1dd
fix: update zephyr revision to v4.3.0 and refine cmsis name in west.yml
wybran Mar 9, 2026
ae214eb
feat: enhance sleep manager and RTC integration; add alarm handler an…
wybran Mar 9, 2026
db71382
feat: update configuration for power management and ADC support
bykowskiolaf Mar 9, 2026
3332d76
Merge branch 'feat/rtc-sleep' into feat/sleep-stm-working
bykowskiolaf Mar 9, 2026
7dba4a1
feat: enhance sleep management and GPIO wakeup sources; refactor Appl…
wybran Mar 16, 2026
5e3e8a7
feat: implement wakeup count management in sleep manager; enhance app…
wybran Mar 16, 2026
b77063c
feat: update packet data to include wakeup event count in run_cycle
wybran Mar 16, 2026
6b20778
feat: optimize run_cycle by removing redundant sensor status retrieval
wybran Mar 16, 2026
f463f43
refactor: changed naked battery sensor pointer to unique_ptr
jacek-kow Mar 21, 2026
f016792
feat: refactor sleep manager to support multiple wakeup sources and e…
wybran Mar 23, 2026
52fd5f5
refactor: clean up formatting and improve logging in sleep manager in…
wybran Mar 23, 2026
82272f5
feat: update sleep manager to support additional STM32WLE5XX configur…
bykowskiolaf Mar 23, 2026
97080f7
feat: add GPIO wakeup debounce configuration and update STM32 series …
wybran Mar 23, 2026
9169e89
feat: add logging for wakeup ISR to track GPIO pin triggers
wybran Mar 23, 2026
bf8d56e
feat: remove unnecessary device runtime management in BME280 sensor r…
wybran Mar 23, 2026
00444f6
feat: enhance peripheral status codes and improve logging in RTC peri…
wybran Mar 23, 2026
1dd6b10
feat: add ERROR_ALREADY_INITIALIZED status code to Peripheral class
wybran Mar 23, 2026
b3f50f5
feat: refactor wakeup ISR to use atomic operations and improve deboun…
bykowskiolaf Mar 26, 2026
191999f
feat: update prj.conf for improved configuration and logging settings
bykowskiolaf Mar 26, 2026
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
7 changes: 7 additions & 0 deletions app/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ config SLEEP_TIME_MS
help
Duration for which the device will sleep before waking up. This value is in milliseconds.

config GPIO_WAKEUP_DEBOUNCE_MS
int "GPIO Wakeup Debounce Time (ms)"
default 1000
help
Time in milliseconds to ignore subsequent transitions on wakeup pins
to prevent multiple triggers from switch bouncing.

config ENABLE_ANALOG
bool "Enable Analog Sensor"
default n
Expand Down
11 changes: 9 additions & 2 deletions app/boards/nucleo_wl55jc.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@
zephyr,user {
io-channels = <&adc1 6>;
io-channels-names = "a0";
wakeup-gpios = <&gpioc 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>,
<&gpioa 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
};
};

&i2c2 {
pinctrl-0 = <&i2c2_scl_pa12 &i2c2_sda_pa11>;
pinctrl-names = "default";
status = "okay";
clock-frequency = <I2C_BITRATE_FAST>;

pinctrl-0 = <&i2c2_scl_pa12 &i2c2_sda_pa11>;
pinctrl-names = "default";

bme280@76 {
compatible = "bosch,bme280";
reg = <0x76>;
Expand All @@ -38,3 +41,7 @@
zephyr,resolution = <12>;
};
};

&pwr {
status = "okay";
};
85 changes: 58 additions & 27 deletions app/prj.conf
Original file line number Diff line number Diff line change
@@ -1,53 +1,84 @@
# Copyright (c) 2021 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
#
# This file contains selected Kconfig options for the application.

# --- Language / libc ---
CONFIG_CPP=y
CONFIG_GLIBCXX_LIBCPP=y
CONFIG_NEWLIB_LIBC=y

# --- App deps ---
CONFIG_NANOPB=y

# --- Reset / power ---
CONFIG_RESET=y
CONFIG_REBOOT=y
CONFIG_POWEROFF=y

CONFIG_I2C=y
# STM32 wakeup pins support
CONFIG_STM32_WKUP_PINS=y

# --- Buses / peripherals ---
CONFIG_GPIO=y
CONFIG_I2C=y
CONFIG_I2C_STM32_BUS_RECOVERY=y
CONFIG_SPI=y
CONFIG_ADC=y

CONFIG_BQ274XX_PM=y

CONFIG_PM_DEVICE=y
CONFIG_POWEROFF=y

# --- Sensors ---
CONFIG_SENSOR=y
CONFIG_SENSOR_ASYNC_API=y

# General Zephyr settings
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_LOG=y
# --- Stacks ---
CONFIG_MAIN_STACK_SIZE=8192
CONFIG_IDLE_STACK_SIZE=2048
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096

# --- Logging / console ---
# CONFIG_LOG=y
# CONFIG_LOG_PRINTK=n
CONFIG_PRINTK=y
CONFIG_SERIAL=y

CONFIG_LOG=y
CONFIG_LOG_BACKEND_UART=y

CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

# Random number generator required for several LoRaWAN services
# Helpful crash info
CONFIG_FAULT_DUMP=2
CONFIG_EXCEPTION_STACK_TRACE=y

# --- RNG ---
CONFIG_ENTROPY_GENERATOR=y

# LoRaWAN application layer
# --- RTC / alarm ---
CONFIG_RTC=y
CONFIG_RTC_ALARM=y

# --- Flash / settings ---
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y
CONFIG_SETTINGS_RUNTIME=y

# --- LoRa / LoRaWAN ---
CONFIG_LORA=y
CONFIG_LORAWAN=y
CONFIG_LORAWAN_NVM_SETTINGS=y

# LoRaWAN services required for FUOTA
# LoRaWAN services (FUOTA etc.)
CONFIG_LORAWAN_SERVICES=y
CONFIG_LORAWAN_LOG_LEVEL_DBG=y

CONFIG_NVS=y
CONFIG_SETTINGS=y
CONFIG_SETTINGS_RUNTIME=y
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_PM=n
CONFIG_PM_DEVICE=y
CONFIG_PM_DEVICE_RUNTIME=y
CONFIG_PM_DEVICE_SYSTEM_MANAGED=y

CONFIG_BOOTLOADER_MCUBOOT=y
# --- Bootloader ---
CONFIG_BOOTLOADER_MCUBOOT=n

# ADC config
CONFIG_ADC=y
CONFIG_CBPRINTF_FP_SUPPORT=y
CONFIG_STACK_SENTINEL=y
CONFIG_THREAD_NAME=y
CONFIG_THREAD_MONITOR=y
CONFIG_INIT_STACKS=y
CONFIG_STACK_CANARIES=y
2 changes: 1 addition & 1 deletion app/protobufs
119 changes: 59 additions & 60 deletions app/src/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,12 @@

#include "buzzverse/packet.pb.h"
#include "peripherals/lorawan_handler/lorawan_handler.hpp"
#include "utils/sleep-manager.hpp"

LOG_MODULE_REGISTER(application, CONFIG_APP_LOG_LEVEL);

Application::Application(
etl::array<etl::unique_ptr<Sensor>, NUMBER_OF_SENSORS>& sensors,
LoRaWANHandler& lorawan,
etl::unique_ptr<SleepManager> sleep_manager)
:
m_sensors(sensors),
m_lorawan(lorawan),
m_sleep_manager(etl::move(sleep_manager)) {}
Application::Application(etl::array<etl::unique_ptr<Sensor>, NUMBER_OF_SENSORS>& sensors,
LoRaWANHandler& lorawan, SleepManager* sleep_manager)
: m_sensors(sensors), m_lorawan(lorawan), m_sleep_manager(sleep_manager) {}

bool Application::init() {
LOG_INF("Application core initializing...");
Expand All @@ -26,12 +20,9 @@ bool Application::init() {
return false;
}

#if defined(CONFIG_SOC_ESP32S3)
if (m_sleep_manager && m_sleep_manager->is_ready()) {
esp_sleep_wakeup_cause_t cause = m_sleep_manager->get_wakeup_cause();
LOG_INF("ESP32S3 Wakeup cause: %d", cause);
LOG_INF("Wakeup cause: %d", static_cast<int>(m_sleep_manager->get_wakeup_cause()));
}
#endif
LOG_INF("Application core initialization complete.");
return true;
}
Expand All @@ -40,19 +31,19 @@ bool Application::initialize_peripherals() {
LOG_DBG("Initializing all application peripherals...");
bool all_essential_ready = true;

// Initialize sensors
for(auto& sensor: m_sensors) {
if(sensor) {
LOG_DBG("Initializing: %s", sensor->get_name().c_str());
if (sensor->init() != Peripheral::Status::OK) {
LOG_ERR("%s initialization failed.", sensor->get_name().c_str());
} else {
LOG_INF("%s initialized.", sensor->get_name().c_str());
}
}
}

// Initialize the LoRaWAN manager
// Initialize sensors
for (auto& sensor : m_sensors) {
if (sensor) {
LOG_DBG("Initializing: %s", sensor->get_name().c_str());
if (sensor->init() != Peripheral::Status::OK) {
LOG_ERR("%s initialization failed.", sensor->get_name().c_str());
} else {
LOG_INF("%s initialized.", sensor->get_name().c_str());
}
}
}

// Initialize the LoRaWAN manager
LOG_DBG("Initializing: %s", m_lorawan.get_name().c_str());
if (m_lorawan.init() != Peripheral::Status::OK) {
LOG_ERR("%s initialization failed.", m_lorawan.get_name().c_str());
Expand All @@ -76,59 +67,67 @@ bool Application::initialize_peripherals() {
}

void Application::generate_init_failure_report(buzzverse_v1_Packet& packet) {
LOG_INF("Generating initialization failure report...");
LOG_INF("Generating initialization failure report...");

packet.which_data = buzzverse_v1_Packet_status_tag;
auto& status_msg = packet.data.status;
packet.which_data = buzzverse_v1_Packet_status_tag;
auto& status_msg = packet.data.status;

for(const auto& sensor: m_sensors) {
if(sensor)
sensor->get_status(status_msg);
}
for (const auto& sensor : m_sensors) {
if (sensor) sensor->get_status(status_msg);
}

if (m_lorawan.is_ready()) {
status_msg.lorawan_status = buzzverse_v1_Status_ComponentState_NORMAL;
} else {
status_msg.lorawan_status = buzzverse_v1_Status_ComponentState_INITIALIZATION_FAILED;
}
if (m_lorawan.is_ready()) {
status_msg.lorawan_status = buzzverse_v1_Status_ComponentState_NORMAL;
} else {
status_msg.lorawan_status = buzzverse_v1_Status_ComponentState_INITIALIZATION_FAILED;
}
}

void Application::run_cycle() {
LOG_INF("--- Starting Application Cycle ---");

for(auto& sensor: m_sensors) {
if (sensor && sensor->is_ready()) {
buzzverse_v1_Packet packet;
if (sensor->get_packet(packet) == Sensor::Status::OK) {
send_lora_packet(packet);
} else {
LOG_ERR("Failed to get %s packet", sensor->get_name().c_str());
}
} else {
LOG_ERR("%s not ready for reading.", sensor->get_name().c_str());
}
}

LOG_INF("--- Application Cycle Complete ---");
k_msleep(50);
LOG_INF("--- Starting Application Cycle ---");

if (m_sleep_manager) {
uint32_t count = m_sleep_manager->get_and_clear_wakeup_count();

if (count > 0) {
LOG_INF("Detected %u wakeup events. Sending report...", count);

buzzverse_v1_Packet packet = buzzverse_v1_Packet_init_default;
packet.which_data = buzzverse_v1_Packet_counter_tag;
packet.data.counter.counter = count;

send_lora_packet(packet);
}
}

for (auto& sensor : m_sensors) {
if (sensor && sensor->is_ready()) {
buzzverse_v1_Packet packet = buzzverse_v1_Packet_init_default;
if (sensor->get_packet(packet) == Sensor::Status::OK) {
send_lora_packet(packet);
} else {
LOG_ERR("Failed to get %s packet", sensor->get_name().c_str());
}
}
}

LOG_INF("--- Application Cycle Complete ---");
}

void Application::enter_low_power_mode(int sleep_duration_ms) {
// Check if SleepManager is available and ready
if (!m_sleep_manager || !m_sleep_manager->is_ready()) {
LOG_WRN("SleepManager not available/ready. Defaulting to k_sleep for %d ms.",
sleep_duration_ms);
k_sleep(K_MSEC(sleep_duration_ms));
sys_reboot(SYS_REBOOT_COLD);
k_msleep(sleep_duration_ms);
return;
}

LOG_INF("Preparing system for deep sleep (duration: %d ms)...", sleep_duration_ms);

m_sleep_manager->set_sleep_duration(sleep_duration_ms);
m_sleep_manager->enter_sleep(SleepManager::SleepMode::DEEP_SLEEP);

// This code should not be reached on platforms where deep sleep causes a reset.
LOG_ERR("!!! CRITICAL: Execution continued after deep sleep call. Deep sleep failed. !!!");
sys_reboot(SYS_REBOOT_COLD);
}

void Application::send_lora_packet(const buzzverse_v1_Packet& packet) {
Expand Down
11 changes: 6 additions & 5 deletions app/src/Application.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#ifndef APPLICATION_HPP
#define APPLICATION_HPP

#include <zephyr/kernel.h>
#include "buzzverse/packet.pb.h"
#include "sensor.hpp"
#include "peripherals/sleep/sleep_manager.hpp"

// Number of supported sensor types used in the sensors array
#define BASE_SENSOR_COUNT 1
Expand All @@ -17,7 +19,6 @@
#define NUMBER_OF_SENSORS (BASE_SENSOR_COUNT + ANALOG_SENSOR_COUNT)

class LoRaWANHandler;
class SleepManager;

class Application {
public:
Expand All @@ -29,9 +30,9 @@ class Application {
* @param sleep_manager Pointer to the SleepManager. Can be nullptr if sleep is disabled.
*/
Application(
etl::array<etl::unique_ptr<Sensor>, NUMBER_OF_SENSORS>& sensors,
LoRaWANHandler& lorawan,
etl::unique_ptr<SleepManager> sleep_manager);
etl::array<etl::unique_ptr<Sensor>, NUMBER_OF_SENSORS>& sensors,
LoRaWANHandler& lorawan,
SleepManager* sleep_manager);
~Application() = default;

// Main phases of the application
Expand Down Expand Up @@ -63,7 +64,7 @@ class Application {

etl::array<etl::unique_ptr<Sensor>, NUMBER_OF_SENSORS>& m_sensors;
LoRaWANHandler& m_lorawan;
etl::unique_ptr<SleepManager> m_sleep_manager;
SleepManager* m_sleep_manager;
};

#endif // APPLICATION_HPP
Loading
Loading