-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathcmb_flash_log.c
206 lines (166 loc) · 5.18 KB
/
cmb_flash_log.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*
* Copyright (c) 2006-2019, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-12-14 armink the first version
*/
#define DBG_TAG "cmb_log"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <rtthread.h>
#include <stdio.h>
#include <cm_backtrace.h>
//#define CMB_USING_FAL_FLASH_LOG
//#define CMB_USING_FAL_BACKUP_LOG_TO_FILE
#if defined(CMB_USING_FAL_FLASH_LOG)
#if !defined(PKG_USING_FAL) || !defined(RT_USING_DFS)
#error "please enable the FAL package and DFS component"
#endif
#include <fal.h>
#include <dfs_posix.h>
#ifndef CMB_FAL_FLASH_LOG_PART
#define CMB_FAL_FLASH_LOG_PART "cmb_log"
#endif
#ifndef CMB_LOG_FILE_PATH
#define CMB_LOG_FILE_PATH "/log/cmb.log"
#endif
/* cmb flash log partition write granularity, default: 8 bytes */
#ifndef CMB_FLASH_LOG_PART_WG
#define CMB_FLASH_LOG_PART_WG 8
#endif
/* the log length's size which saved in flash */
#define CMB_LOG_LEN_SIZE MAX(sizeof(size_t), CMB_FLASH_LOG_PART_WG)
#ifndef MIN
#define MIN(a, b) (a < b ? a : b)
#endif
#ifndef MAX
#define MAX(a, b) (a > b ? a : b)
#endif
static const struct fal_partition *cmb_log_part = NULL;
/**
* write cmb log to flash partition @see CMB_FLASH_LOG_PART
*
* @param log log buffer
* @param len log length
*/
void cmb_flash_log_write(const char *log, size_t len)
{
static uint32_t addr = 0;
/* addr out of partition length */
if(addr >= cmb_log_part->len)
return;
uint8_t len_buf[CMB_LOG_LEN_SIZE] = { 0 };
static rt_bool_t first_write = RT_TRUE;
if (first_write)
{
fal_partition_erase_all(cmb_log_part);
first_write = RT_FALSE;
}
/* write log length */
rt_memcpy(len_buf, (uint8_t *)&len, sizeof(size_t));
fal_partition_write(cmb_log_part, addr, len_buf, sizeof(len_buf));
addr += CMB_LOG_LEN_SIZE;
/* write log content */
fal_partition_write(cmb_log_part, addr, (uint8_t *)log, len);
addr += RT_ALIGN(len, CMB_FLASH_LOG_PART_WG);
}
#if defined(RT_USING_ULOG)
static void ulog_cmb_flash_log_backend_output(struct ulog_backend *backend, rt_uint32_t level, const char *tag, rt_bool_t is_raw,
const char *log, size_t len)
{
if (!rt_strcmp(tag, CMB_LOG_TAG))
{
cmb_flash_log_write(log, len);
}
}
int ulog_cmb_flash_log_backend_init(void)
{
static struct ulog_backend backend;
cmb_log_part = fal_partition_find(CMB_FAL_FLASH_LOG_PART);
RT_ASSERT(cmb_log_part != NULL);
backend.init = RT_NULL;
backend.output = ulog_cmb_flash_log_backend_output;
ulog_backend_register(&backend, "cmb_flash_log", RT_FALSE);
return 0;
}
INIT_APP_EXPORT(ulog_cmb_flash_log_backend_init);
#else
void cmb_flash_log_println(const char *fmt, ...)
{
va_list args;
rt_size_t length;
static char rt_log_buf[RT_CONSOLEBUF_SIZE];
va_start(args, fmt);
length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
if (length > RT_CONSOLEBUF_SIZE - 1 - 2)
length = RT_CONSOLEBUF_SIZE - 3;
/* add CRLF */
rt_log_buf[length++] = '\r';
rt_log_buf[length++] = '\n';
cmb_flash_log_write(rt_log_buf, length);
va_end(args);
}
#endif /* RT_USING_ULOG */
#ifdef CMB_USING_FAL_BACKUP_LOG_TO_FILE
int cmb_backup_flash_log_to_file(void)
{
cmb_log_part = fal_partition_find(CMB_FAL_FLASH_LOG_PART);
RT_ASSERT(cmb_log_part != NULL);
size_t len;
int result = 0;
uint32_t addr = 0;
rt_bool_t has_read_log = RT_FALSE;
int log_fd = -1;
while (1)
{
result = fal_partition_read(cmb_log_part, addr, (uint8_t *)&len, sizeof(size_t));
if ((len != 0xFFFFFFFF) && (result >= 0))
{
/* addr out of partition length */
if(addr >= cmb_log_part->len)
break;
char log_buf[ULOG_LINE_BUF_SIZE];
if (!has_read_log)
{
has_read_log = RT_TRUE;
LOG_I("An CmBacktrace log was found on flash. Now will backup it to file ("CMB_LOG_FILE_PATH").");
//TODO check the folder
log_fd = open(CMB_LOG_FILE_PATH, O_WRONLY | O_CREAT | O_APPEND);
if (log_fd < 0) {
LOG_E("Open file ("CMB_LOG_FILE_PATH") failed.");
break;
}
}
addr += CMB_LOG_LEN_SIZE;
/* read log content */
result = fal_partition_read(cmb_log_part, addr, (uint8_t *)log_buf, MIN(ULOG_LINE_BUF_SIZE, len));
if (result < 0)
{
break;
}
addr += RT_ALIGN(len, CMB_FLASH_LOG_PART_WG);
/* backup log to file */
write(log_fd, log_buf, MIN(ULOG_LINE_BUF_SIZE, len));
}
else
{
break;
}
}
if (has_read_log)
{
if (log_fd >= 0)
{
LOG_I("Backup the CmBacktrace flash log to file ("CMB_LOG_FILE_PATH") successful.");
close(log_fd);
fal_partition_erase_all(cmb_log_part);
}
}
return 0;
}
INIT_APP_EXPORT(cmb_backup_flash_log_to_file);
#endif /* CMB_USING_FAL_BACKUP_LOG_TO_FILE */
#endif /* defined(CMB_USING_FLASH_LOG_BACKUP) */