SatNOGS-COMMS
4.1.0
A COMMS subsystem for CubeSats
Toggle main menu visibility
Loading...
Searching...
No Matches
memory_monitor.cpp
Go to the documentation of this file.
1
/*
2
* SatNOGS-COMMS MCU software
3
*
4
* Copyright (C) 2025, Libre Space Foundation <http://libre.space>
5
*
6
* This program is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18
*
19
* SPDX-License-Identifier: GNU General Public License v3.0 or later
20
*/
21
22
#include "
memory_monitor.hpp
"
23
#include "
callbacks.hpp
"
24
#include "
error_handler.hpp
"
25
#include <zephyr/dfu/mcuboot.h>
26
#include <zephyr/drivers/flash.h>
27
#include <zephyr/sys/printk.h>
28
29
namespace
satnogs::comms
30
{
31
32
static
K_WORK_DELAYABLE_DEFINE(scan_work,
memory_monitor::flash_monitor_hdlr
);
33
34
/* ─────────────────── Flash device & constants ───────────────────────── */
35
static
const
struct
device *
const
flash = DEVICE_DT_GET(DT_NODELABEL(flash));
36
37
static
constexpr
size_t
chunk_bytes = 32;
/* one flash_read() */
38
static
constexpr
size_t
burst_bytes = 1024;
/* pause every 1 KB */
39
uint8_t
buf
[chunk_bytes];
40
52
void
53
memory_monitor::start
(int32_t delay)
54
{
55
/* if already running -> do nothing */
56
if
(atomic_cas(&m_running,
settings::FALSE_MAGIC
,
settings::TRUE_MAGIC
)) {
57
m_burst_delay_ms = delay * 1000;
/* convert to milliseconds */
58
m_scan_off = 0;
59
k_work_schedule(&scan_work, K_NO_WAIT);
/* first sweep now */
60
}
61
}
62
72
void
73
memory_monitor::stop
()
74
{
75
/* if already stopped -> do nothing */
76
if
(atomic_cas(&m_running,
settings::TRUE_MAGIC
,
settings::FALSE_MAGIC
)) {
77
k_work_cancel_delayable(&scan_work);
78
}
79
}
80
81
memory_monitor::memory_monitor
()
82
: m_running(
settings
::FALSE_MAGIC),
83
m_burst_delay_ms(CONFIG_FLASH_MONITOR_BURST_DELAY_SECS * 1000),
84
m_scan_off(0)
85
{
86
#ifdef CONFIG_BOOTLOADER_MCUBOOT
87
const
struct
flash_area *fa;
88
if
(flash_area_open(boot_fetch_active_slot(), &fa) != 0) {
89
throw
flash_init_exception
(__FILE__, __LINE__);
90
}
91
m_flash_size = fa->fa_size;
92
m_flash_offset = fa->fa_off;
93
#else
94
m_flash_size = DT_REG_SIZE(DT_NODELABEL(slot0_partition));
95
m_flash_offset = DT_REG_ADDR(DT_NODELABEL(slot0_partition));
96
#endif
97
}
98
116
void
117
memory_monitor::flash_monitor_hdlr
(
struct
k_work *work)
118
{
119
try
{
120
auto
&mem_mon =
memory_monitor::get_instance
();
121
if
(atomic_get(&mem_mon.m_running) ==
122
static_cast<
atomic_val_t
>
(
settings::TRUE_MAGIC
)) {
123
124
/* ---- scan at most one 1 KiB burst per invocation ---- */
125
const
off_t off_start = mem_mon.m_scan_off;
126
const
off_t off_end = MIN(off_start +
static_cast<
off_t
>
(burst_bytes),
127
static_cast<
off_t
>
(mem_mon.m_flash_size));
128
129
for
(off_t off = off_start; off < off_end; off += chunk_bytes) {
130
const
size_t
len = MIN(chunk_bytes, mem_mon.m_flash_size - off);
131
const
off_t addr = mem_mon.m_flash_offset + off;
132
133
int
err = flash_read(flash, addr,
buf
, len);
134
if
(err == -EIO) {
135
throw
flash_read_exception
(__FILE__, __LINE__);
136
}
137
}
138
mem_mon.m_scan_off = off_end;
139
if
(mem_mon.m_scan_off >=
static_cast<
off_t
>
(mem_mon.m_flash_size)) {
140
mem_mon.m_scan_off = 0;
141
}
142
k_work_reschedule(&scan_work, K_MSEC(mem_mon.m_burst_delay_ms));
143
}
144
}
catch
(
const
lib::exception
&e) {
145
auto
&err =
error_handler::get_instance
();
146
err.handle(e);
147
}
catch
(
const
std::exception &e) {
148
auto
&err =
error_handler::get_instance
();
149
err.handle(e);
150
}
151
}
152
153
}
// namespace satnogs::comms
callbacks.hpp
satnogs::comms::error_handler::get_instance
static error_handler & get_instance()
Singleton access to the error_handler subsystem.
Definition
error_handler.hpp:61
satnogs::comms::flash_init_exception
Definition
memory_monitor.hpp:71
satnogs::comms::flash_read_exception
Definition
memory_monitor.hpp:82
satnogs::comms::lib::exception
Exception base class.
Definition
exception.hpp:63
satnogs::comms::memory_monitor::start
void start(int32_t delay=CONFIG_FLASH_MONITOR_BURST_DELAY_SECS)
Start the flash-monitor task.
Definition
memory_monitor.cpp:53
satnogs::comms::memory_monitor::get_instance
static memory_monitor & get_instance()
Definition
memory_monitor.hpp:39
satnogs::comms::memory_monitor::flash_monitor_hdlr
static void flash_monitor_hdlr(struct k_work *work)
Work-queue handler that scans the active firmware image for unrecoverable flash ECC errors.
Definition
memory_monitor.cpp:117
satnogs::comms::memory_monitor::memory_monitor
memory_monitor(memory_monitor const &)=delete
satnogs::comms::memory_monitor::stop
void stop()
Stop the flash-monitor task.
Definition
memory_monitor.cpp:73
satnogs::comms::settings
Store and retrieve reliably persistent settings.
Definition
settings.hpp:60
satnogs::comms::settings::FALSE_MAGIC
static constexpr uint32_t FALSE_MAGIC
Definition
settings.hpp:63
satnogs::comms::settings::TRUE_MAGIC
static constexpr uint32_t TRUE_MAGIC
Definition
settings.hpp:62
error_handler.hpp
memory_monitor.hpp
satnogs::comms
Definition
bsp.cpp:28
satnogs::comms::buf
uint8_t buf[chunk_bytes]
Definition
memory_monitor.cpp:39
src
memory_monitor.cpp
Generated by
1.17.0