Skip to content

Commit c3e7d51

Browse files
Damian-Nordicrlubos
authored andcommitted
logging: allow storing log history in flash
When CONFIG_LOG_BACKEND_RPC_HISTORY_STORAGE_FCB option is set, define the "log_history" flash partition and enable storing the log history using Flash Circular Buffer. Signed-off-by: Damian Krolik <[email protected]>
1 parent 1ee121a commit c3e7d51

File tree

5 files changed

+183
-3
lines changed

5 files changed

+183
-3
lines changed

subsys/logging/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ if (CONFIG_LOG_FORWARDER_RPC OR CONFIG_LOG_BACKEND_RPC)
99
zephyr_library_sources_ifdef(CONFIG_LOG_FORWARDER_RPC log_forwarder_rpc.c)
1010
zephyr_library_sources_ifdef(CONFIG_LOG_BACKEND_RPC log_backend_rpc.c)
1111
zephyr_library_sources_ifdef(CONFIG_LOG_BACKEND_RPC_HISTORY_STORAGE_RAM log_backend_rpc_history_ram.c)
12+
zephyr_library_sources_ifdef(CONFIG_LOG_BACKEND_RPC_HISTORY_STORAGE_FCB log_backend_rpc_history_fcb.c)
1213
endif()

subsys/logging/Kconfig

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ choice LOG_BACKEND_RPC_HISTORY_STORAGE_CHOICE
5353
config LOG_BACKEND_RPC_HISTORY_STORAGE_RAM
5454
bool "RAM buffer"
5555

56+
config LOG_BACKEND_RPC_HISTORY_STORAGE_FCB
57+
bool "Flash Circular Buffer"
58+
help
59+
Stores the log history in Flash Circular Buffer located in the "log_history"
60+
flash partition. Note that enabling this option may significantly increase
61+
the flash wear, so this option is not meant the production environments,
62+
and extra caution should be taken when using this functionality.
63+
5664
endchoice # LOG_BACKEND_RPC_HISTORY_STORAGE_CHOICE
5765

5866
config LOG_BACKEND_RPC_HISTORY_UPLOAD_THREAD_STACK_SIZE
@@ -64,12 +72,17 @@ config LOG_BACKEND_RPC_HISTORY_UPLOAD_CHUNK_SIZE
6472
default 1024
6573

6674
config LOG_BACKEND_RPC_HISTORY_SIZE
67-
int "Log history size"
68-
depends on LOG_BACKEND_RPC_HISTORY_STORAGE_RAM
69-
default 16384
75+
hex "Log history size"
76+
default 0x4000 if LOG_BACKEND_RPC_HISTORY_STORAGE_RAM
77+
default 0x8000 if LOG_BACKEND_RPC_HISTORY_STORAGE_FCB
7078
help
7179
Size of the ring buffer used to store the log history, in bytes.
7280

81+
config LOG_BACKEND_RPC_HISTORY_STORAGE_FCB_NUM_SECTORS
82+
int "Log history FCB maximum number of flash sectors"
83+
default 64
84+
depends on LOG_BACKEND_RPC_HISTORY_STORAGE_FCB
85+
7386
endif # LOG_BACKEND_RPC_HISTORY
7487

7588
config LOG_BACKEND_RPC_CRASH_LOG
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include "log_backend_rpc_history.h"
8+
9+
#include <zephyr/fs/fcb.h>
10+
#include <zephyr/sys/util.h>
11+
12+
#define LOG_HISTORY_MAGIC 0x7d2ac863
13+
#define LOG_HISTORY_AREA FIXED_PARTITION_ID(log_history)
14+
15+
static struct fcb fcb;
16+
static struct flash_sector fcb_sectors[CONFIG_LOG_BACKEND_RPC_HISTORY_STORAGE_FCB_NUM_SECTORS];
17+
static struct fcb_entry last_popped;
18+
static bool erase_oldest;
19+
static K_MUTEX_DEFINE(fcb_lock);
20+
21+
void log_rpc_history_init(void)
22+
{
23+
int rc;
24+
uint32_t sector_cnt = ARRAY_SIZE(fcb_sectors);
25+
26+
rc = flash_area_get_sectors(LOG_HISTORY_AREA, &sector_cnt, fcb_sectors);
27+
28+
if (rc) {
29+
goto out;
30+
}
31+
32+
fcb.f_magic = LOG_HISTORY_MAGIC;
33+
fcb.f_sectors = fcb_sectors;
34+
fcb.f_sector_cnt = (uint8_t)sector_cnt;
35+
erase_oldest = true;
36+
37+
rc = fcb_init(LOG_HISTORY_AREA, &fcb);
38+
39+
if (rc) {
40+
goto out;
41+
}
42+
43+
rc = fcb_clear(&fcb);
44+
45+
out:
46+
__ASSERT_NO_MSG(rc == 0);
47+
}
48+
49+
void log_rpc_history_push(const union log_msg_generic *msg)
50+
{
51+
int rc;
52+
size_t len;
53+
struct fcb_entry entry;
54+
55+
len = log_msg_generic_get_wlen(&msg->buf) * sizeof(uint32_t);
56+
57+
k_mutex_lock(&fcb_lock, K_FOREVER);
58+
rc = fcb_append(&fcb, len, &entry);
59+
60+
if (rc == -ENOSPC && erase_oldest) {
61+
/*
62+
* The log history FCB is full but overwriting is enabled.
63+
* Erase the oldest FCB page and try again.
64+
* Note that the "last popped" location is cleared so that the next log transfer
65+
* starts from the updated oldest log message.
66+
*/
67+
rc = fcb_rotate(&fcb);
68+
69+
if (rc) {
70+
goto out;
71+
}
72+
73+
memset(&last_popped, 0, sizeof(last_popped));
74+
rc = fcb_append(&fcb, len, &entry);
75+
}
76+
77+
if (rc) {
78+
goto out;
79+
}
80+
81+
rc = flash_area_write(fcb.fap, FCB_ENTRY_FA_DATA_OFF(entry), msg, len);
82+
83+
if (rc) {
84+
goto out;
85+
}
86+
87+
rc = fcb_append_finish(&fcb, &entry);
88+
89+
out:
90+
k_mutex_unlock(&fcb_lock);
91+
92+
#ifdef LOG_HISTORY_DEBUG
93+
__ASSERT_NO_MSG(rc == 0);
94+
#endif
95+
}
96+
97+
void log_rpc_history_set_overwriting(bool overwriting)
98+
{
99+
k_mutex_lock(&fcb_lock, K_FOREVER);
100+
101+
erase_oldest = overwriting;
102+
103+
k_mutex_unlock(&fcb_lock);
104+
}
105+
106+
union log_msg_generic *log_rpc_history_pop(void)
107+
{
108+
int rc;
109+
struct fcb_entry entry = last_popped;
110+
union log_msg_generic *msg = NULL;
111+
112+
k_mutex_lock(&fcb_lock, K_FOREVER);
113+
rc = fcb_getnext(&fcb, &entry);
114+
115+
if (rc) {
116+
rc = 0;
117+
goto out;
118+
}
119+
120+
msg = (union log_msg_generic *)k_malloc(entry.fe_data_len);
121+
122+
if (!msg) {
123+
goto out;
124+
}
125+
126+
rc = flash_area_read(fcb.fap, FCB_ENTRY_FA_DATA_OFF(entry), msg, entry.fe_data_len);
127+
128+
if (rc) {
129+
goto out;
130+
}
131+
132+
last_popped = entry;
133+
134+
while (fcb.f_oldest != last_popped.fe_sector) {
135+
rc = fcb_rotate(&fcb);
136+
137+
if (rc) {
138+
goto out;
139+
}
140+
}
141+
142+
out:
143+
k_mutex_unlock(&fcb_lock);
144+
145+
#ifdef LOG_HISTORY_DEBUG
146+
__ASSERT_NO_MSG(rc == 0);
147+
#endif
148+
149+
return msg;
150+
}
151+
152+
void log_rpc_history_free(const union log_msg_generic *msg)
153+
{
154+
k_free((void *)msg);
155+
}

subsys/partition_manager/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ if(CONFIG_WIFI_NRF70 AND CONFIG_NRF_WIFI_PATCHES_EXT_FLASH_STORE)
135135
ncs_add_partition_manager_config(pm.yml.wifi)
136136
endif()
137137

138+
if(CONFIG_LOG_BACKEND_RPC_HISTORY_STORAGE_FCB)
139+
ncs_add_partition_manager_config(pm.yml.log_history)
140+
endif()
141+
138142
# We are using partition manager if we are a child image or if we are
139143
# the root image and the 'partition_manager' target exists.
140144
zephyr_compile_definitions(
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <zephyr/autoconf.h>
2+
3+
log_history:
4+
size: CONFIG_LOG_BACKEND_RPC_HISTORY_SIZE
5+
placement:
6+
before: [end]
7+
align: {start: CONFIG_FPROTECT_BLOCK_SIZE}

0 commit comments

Comments
 (0)