1 // Copyright (C) 2022 Beken Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <stdarg.h>
16 #include <string.h>
17 #include <driver/uart.h>
18 #include "bk_uart.h"
19 #include <common/sys_config.h>
20 #include <common/bk_compiler.h>
21 #include <os/mem.h>
22 #include "printf_impl.h"
23 #if CONFIG_SHELL_ASYNCLOG
24 #include "bk_api_cli.h"
25 #endif
26
27 #if (CONFIG_SHELL_ASYNCLOG && CONFIG_SLAVE_CORE)
28 #define CPU1_TAG "cpu1"
29 #endif
30
31 #ifndef CONFIG_PRINTF_BUF_SIZE
32 #define CONFIG_PRINTF_BUF_SIZE (128)
33 #endif
34
35 static char s_exception_mode_printf_buf[CONFIG_PRINTF_BUF_SIZE] = {0};
36 // static char s_task_mode_printf_buf[CONFIG_PRINTF_BUF_SIZE] = {0};
37
38 static uint8_t s_printf_enable = 1;
39 #if CONFIG_SHELL_ASYNCLOG
40 static volatile uint8_t s_printf_sync = 0;
41
42 typedef struct
43 {
44 char mod_name[15];
45 u8 disabled;
46 } __bk_packed mod_disable_list_t;
47
48 static mod_disable_list_t mod_tag_list[20];
49
50 #endif
51
52 static beken_mutex_t s_printf_lock = NULL;
53
printf_lock(void)54 void printf_lock(void)
55 {
56 rtos_lock_mutex(&s_printf_lock);
57 }
58
printf_unlock(void)59 void printf_unlock(void)
60 {
61 rtos_unlock_mutex(&s_printf_lock);
62 }
63
printf_lock_init(void)64 int printf_lock_init(void)
65 {
66 int ret = rtos_init_mutex(&s_printf_lock);
67 if (kNoErr != ret) {
68 return BK_ERR_NO_MEM;
69 }
70
71 #if CONFIG_SHELL_ASYNCLOG
72 memset(&mod_tag_list[0], 0, sizeof(mod_tag_list));
73 shell_set_log_level(LOG_LEVEL);
74 #endif
75
76 return BK_OK;
77 }
78
printf_lock_deinit(void)79 int printf_lock_deinit(void)
80 {
81 if (s_printf_lock)
82 rtos_deinit_mutex(&s_printf_lock);
83
84 s_printf_lock = NULL;
85 return BK_OK;
86 }
87
exception_mode_printf(const char * fmt,va_list ap)88 static void exception_mode_printf(const char *fmt, va_list ap)
89 {
90 vsnprintf(s_exception_mode_printf_buf, sizeof(s_exception_mode_printf_buf) - 1, fmt, ap);
91 s_exception_mode_printf_buf[CONFIG_PRINTF_BUF_SIZE - 1] = 0;
92 uart_write_string(bk_get_printf_port(), s_exception_mode_printf_buf);
93 }
94
95 #if (!CONFIG_ARCH_RISCV)
irq_printf(const char * fmt,va_list ap)96 static void irq_printf(const char *fmt, va_list ap)
97 {
98 char string[CONFIG_PRINTF_BUF_SIZE];
99
100 vsnprintf(string, sizeof(string) - 1, fmt, ap);
101 string[CONFIG_PRINTF_BUF_SIZE - 1] = 0;
102 uart_write_string(bk_get_printf_port(), string);
103 }
104 #endif
105
106
task_printf(const char * fmt,va_list ap)107 static void task_printf(const char *fmt, va_list ap)
108 {
109 char string[CONFIG_PRINTF_BUF_SIZE];
110
111 vsnprintf(string, sizeof(string) - 1, fmt, ap);
112 string[CONFIG_PRINTF_BUF_SIZE - 1] = 0;
113 uart_write_string(bk_get_printf_port(), string);
114
115 }
116
117
bk_printf_sync(const char * fmt,va_list args)118 static void bk_printf_sync(const char *fmt, va_list args)
119 {
120 if(!printf_is_init())
121 return;
122
123 #if (CONFIG_ARCH_RISCV)
124
125 if (rtos_is_in_interrupt_context() || (!rtos_is_scheduler_started()))
126 exception_mode_printf(fmt, args);
127 else
128 task_printf(fmt, args);
129
130 #else // #if CONFIG_ARCH_RISCV
131
132 uint32_t cpsr_val = rtos_get_cpsr();
133 uint32_t arm_mode = cpsr_val & /*ARM968_MODE_MASK*/0x1f;
134
135 if ((/*ARM_MODE_FIQ*/17 == arm_mode)
136 || (/*ARM_MODE_ABT*/23 == arm_mode)
137 || (/*ARM_MODE_UND*/27 == arm_mode)
138 || (!rtos_is_scheduler_started()))
139 exception_mode_printf(fmt, args);
140 else if (/*ARM_MODE_IRQ*/18 == arm_mode)
141 irq_printf(fmt, args);
142 else
143 task_printf(fmt, args);
144
145 #endif // #if CONFIG_ARCH_RISCV
146 }
147
bk_printf_port(int level,char * tag,const char * fmt,va_list args)148 void bk_printf_port(int level, char *tag, const char *fmt, va_list args)
149 {
150 if (!rtos_is_scheduler_started()) {
151 exception_mode_printf(fmt, args);
152 return;
153 }
154
155 #if CONFIG_SHELL_ASYNCLOG
156
157 if(s_printf_sync == 0)
158 {
159 #if (CONFIG_SLAVE_CORE)
160 shell_log_out_port(level, CPU1_TAG, fmt, args);
161 #else
162 shell_log_out_port(level, NULL, fmt, args);
163 #endif
164 }
165 else
166 {
167 bk_printf_sync(fmt, args);
168 }
169
170 #else
171 bk_printf_sync(fmt, args);
172 #endif // #if CONFIG_SHELL_ASYNCLOG
173 }
174
bk_printf(const char * fmt,...)175 void bk_printf(const char *fmt, ...)
176 {
177 va_list args;
178
179 if(!printf_is_init())
180 return;
181
182 if(!s_printf_enable)
183 return;
184
185 va_start(args, fmt);
186
187 bk_printf_port(BK_LOG_ERROR, NULL, fmt, args);
188
189 va_end(args);
190
191 return;
192 }
193
194 #if CONFIG_SHELL_ASYNCLOG
bk_mod_printf_disbled(char * tag)195 static int bk_mod_printf_disbled(char * tag)
196 {
197 int i, result;
198
199 for(i = 0; i < ARRAY_SIZE(mod_tag_list); i++)
200 {
201 if(mod_tag_list[i].disabled)
202 {
203 result = strncmp(mod_tag_list[i].mod_name, tag, sizeof(mod_tag_list[i].mod_name) - 1);
204
205 if(result == 0)
206 return 1;
207 }
208 }
209
210 return 0;
211 }
212 #endif // #if CONFIG_SHELL_ASYNCLOG
213
bk_buf_printf_sync(char * buf,int buf_len)214 void bk_buf_printf_sync(char *buf, int buf_len)
215 {
216 if (!printf_is_init())
217 return;
218
219 if (!s_printf_enable) {
220 return;
221 }
222
223 if (NULL == buf || buf_len <= 0)
224 return;
225
226 buf[buf_len -1] = '\0';
227
228 uart_write_string(bk_get_printf_port(), buf);
229 }
230
231
232
bk_printf_ex(int level,char * tag,const char * fmt,...)233 void bk_printf_ex(int level, char *tag, const char *fmt, ...)
234 {
235 #if CONFIG_SHELL_ASYNCLOG
236
237 va_list args;
238
239 if(!printf_is_init())
240 return;
241
242 if(level > shell_get_log_level()) /* check here instead of in shell_log_out to reduce API instructions. */
243 return;
244
245 if(bk_mod_printf_disbled(tag))
246 return;
247
248 va_start(args, fmt);
249
250 bk_printf_port(level, tag, fmt, args);
251
252 va_end(args);
253
254 #endif
255 return;
256 }
257
bk_set_printf_enable(uint8_t enable)258 void bk_set_printf_enable(uint8_t enable)
259 {
260 #if CONFIG_SHELL_ASYNCLOG
261 if(0 == enable) {
262 shell_echo_set(0);
263 shell_set_log_level(0);
264 } else {
265 shell_echo_set(1);
266 shell_set_log_level(LOG_LEVEL);
267 }
268 #endif
269 s_printf_enable = enable;
270 }
271
bk_set_printf_sync(uint8_t enable)272 void bk_set_printf_sync(uint8_t enable)
273 {
274 #if CONFIG_SHELL_ASYNCLOG
275 #if CONFIG_SLAVE_CORE
276 s_printf_sync = 0;
277 #else
278 s_printf_sync = enable;
279 #endif
280 #endif
281 }
282
bk_get_printf_sync(void)283 int bk_get_printf_sync(void)
284 {
285 #if CONFIG_SHELL_ASYNCLOG
286 return s_printf_sync;
287 #endif
288
289 return 1;
290 }
291
bk_disable_mod_printf(char * mod_name,uint8_t disable)292 void bk_disable_mod_printf(char *mod_name, uint8_t disable)
293 {
294 #if CONFIG_SHELL_ASYNCLOG
295
296 int i, j, result;
297
298 if(disable == 0)
299 {
300 for(i = 0; i < ARRAY_SIZE(mod_tag_list); i++)
301 {
302 if(mod_tag_list[i].disabled)
303 {
304 result = strncmp(mod_tag_list[i].mod_name, mod_name, sizeof(mod_tag_list[i].mod_name) - 1);
305
306 if(result == 0)
307 {
308 mod_tag_list[i].disabled = 0;
309 }
310 }
311 }
312 }
313 else
314 {
315 j = ARRAY_SIZE(mod_tag_list);
316
317 for(i = 0; i < ARRAY_SIZE(mod_tag_list); i++)
318 {
319 if(mod_tag_list[i].disabled)
320 {
321 result = strncmp(mod_tag_list[i].mod_name, mod_name, sizeof(mod_tag_list[i].mod_name) - 1);
322
323 if(result == 0)
324 {
325 return;
326 }
327 }
328 else
329 j = i;
330 }
331
332 if(j >= ARRAY_SIZE(mod_tag_list)) /* no free slot to record this module name. */
333 return;
334 else
335 {
336 strncpy(mod_tag_list[j].mod_name, mod_name, sizeof(mod_tag_list[j].mod_name) - 1);
337 mod_tag_list[j].mod_name[sizeof(mod_tag_list[j].mod_name) - 1] = 0;
338 mod_tag_list[j].disabled = 1;
339 }
340 }
341
342 return;
343
344 #endif
345 }
346
bk_get_disable_mod(int * idx)347 char * bk_get_disable_mod(int * idx)
348 {
349 #if CONFIG_SHELL_ASYNCLOG
350
351 int i;
352
353 for(i = *idx; i < ARRAY_SIZE(mod_tag_list); i++)
354 {
355 (*idx)++;
356 if(mod_tag_list[i].disabled)
357 {
358 return &mod_tag_list[i].mod_name[0];
359 }
360 }
361
362 return NULL;
363
364 #endif
365
366 return NULL;
367 }
368
369