• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Beken Corporation
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 
16 #include <stdio.h>
17 #include <stdarg.h>
18 #include <string.h>
19 
20 #include "cli.h"
21 #include <os/os.h>
22 #include <common/bk_compiler.h>
23 #include "shell_drv.h"
24 
25 #define SHELL_TASK_DEF_TICK  (1000)		// 1000ms -> 1s
26 #define SHELL_EVENT_TX_REQ   0x01
27 #define SHELL_EVENT_RX_IND   0x02
28 
29 #define SHELL_LOG_BUF1_LEN      136
30 #define SHELL_LOG_BUF2_LEN      64
31 #define SHELL_LOG_BUF3_LEN      40
32 
33 #ifdef CONFIG_SLAVE_CORE
34 #define SHELL_LOG_BUF1_NUM      6
35 #define SHELL_LOG_BUF2_NUM      16
36 #define SHELL_LOG_BUF3_NUM      20
37 
38 #define SHELL_LOG_BUF_NUM       (SHELL_LOG_BUF1_NUM + SHELL_LOG_BUF2_NUM + SHELL_LOG_BUF3_NUM)
39 #define SHELL_LOG_PEND_NUM      (SHELL_LOG_BUF_NUM + 3)  /* 1: for RSP, 1: reserved(queue empty), 1: cmd ovf. */
40 #define SHELL_LOG_BUSY_NUM      (SHELL_LOG_PEND_NUM)     /* depending on lower driver's pending queue size. IPC drv no busy state. */
41 #else
42 #define SHELL_LOG_BUF1_NUM      16
43 #define SHELL_LOG_BUF2_NUM      48
44 #define SHELL_LOG_BUF3_NUM      64
45 
46 #define SHELL_LOG_BUF_NUM       (SHELL_LOG_BUF1_NUM + SHELL_LOG_BUF2_NUM + SHELL_LOG_BUF3_NUM)
47 #define SHELL_LOG_PEND_NUM      (SHELL_LOG_BUF_NUM * 2 + 3)  /* 1: for RSP, 1: reserved(queue empty, 1: cmd ovf). */ /* the worst case may be (one log + one hint) in pending queue.*/
48 #define SHELL_LOG_BUSY_NUM      (20)         /* depending on lower driver's pending queue size. drv's queue size < BUSY_NUM <= PEND_NUM. */
49 #endif
50 
51 #define SHELL_ASSERT_BUF_LEN	140
52 #define SHELL_CMD_BUF_LEN		140
53 #define SHELL_RSP_BUF_LEN		200
54 
55 #define SHELL_RSP_QUEUE_ID	    (7)
56 #define SHELL_FW_QUE_ID         (8)
57 #define SHELL_ROM_QUEUE_ID		(9)
58 
59 #define MAX_TRACE_ARGS      10
60 #define MOD_NAME_LEN        4
61 
62 #define HEX_SYNC_CHAR       0xFE
63 #define HEX_MOD_CHAR        0xFF
64 #define HEX_ESC_CHAR        0xFD
65 
66 #ifndef MIN
67 #define MIN(a,b)	((a) < (b) ? (a) : (b))
68 #endif
69 
70 #define TBL_SIZE(tbl)		(sizeof(tbl) / sizeof(tbl[0]))
71 
72 enum
73 {
74 	CMD_TYPE_TEXT = 0,
75 	CMD_TYPE_HEX,
76 	CMD_TYPE_BKREG,   /* patch for BK_REG tool cmd. */
77 	CMD_TYPE_INVALID,
78 };
79 
80 /* patch for BK_REG tool. */
81 enum
82 {
83 	BKREG_WAIT_01 = 0,
84 	BKREG_WAIT_E0,
85 	BKREG_WAIT_FC,
86 };
87 
88 typedef struct
89 {
90 	u8     rsp_buff[SHELL_RSP_BUF_LEN];
91 	bool_t   rsp_ongoing;
92 
93 	u8     cur_cmd_type;
94 	u8     cmd_buff[SHELL_CMD_BUF_LEN];
95 	u8     cmd_data_len;
96 
97 	/* patch for BK_REG tool. */
98 	/* added one state machine for BK_REG tool cmd. */
99 	u8     bkreg_state;
100 	u8     bkreg_left_byte;
101 	/* patch end. */
102 
103 	u8     assert_buff[SHELL_ASSERT_BUF_LEN];
104 	u8     assert_data_len;
105 
106 	u8     log_level;
107 	bool_t   echo_enable;
108 } cmd_line_t;
109 
110 #define GET_BLOCK_ID(blocktag)          ((blocktag) & 0xFF)
111 #define GET_QUEUE_ID(blocktag)          (((blocktag) & 0x0F00) >> 8)
112 #define MAKE_BLOCK_TAG(blk_id, q_id)    (((blk_id) & 0xFF) | (((q_id) & 0x0F) << 8) )
113 
114 typedef struct
115 {
116 	u16     blk_tag;        /* bit0~bit7: blk_id,    bit8~bit11: queue_id; */
117 	u16     packet_len;
118 } tx_packet_t;
119 
120 typedef struct
121 {
122 	tx_packet_t     packet_list[SHELL_LOG_PEND_NUM];
123 	u16     list_out_idx;
124 	u16     list_in_idx;
125 } pending_queue_t;
126 
127 typedef struct
128 {
129 	u16     blk_list[SHELL_LOG_BUSY_NUM];
130 	u16     list_out_idx;
131 	u16     list_in_idx;
132 } busy_queue_t;
133 
134 typedef struct
135 {
136 	u8   *  const  log_buf;
137 	u16   * const  blk_list;
138 	const u16      blk_num;
139 	const u16      blk_len;
140 	u16     list_out_idx;
141 	u16     list_in_idx;
142 	u16     free_blk_num;
143 	u32     empty_cnt;
144 } free_queue_t;
145 
146 #if CONFIG_ARCH_RISCV && !CONFIG_SLAVE_CORE
147 static __attribute__((section(".dtcm_sec_data "))) u8    shell_log_buff1[SHELL_LOG_BUF1_NUM * SHELL_LOG_BUF1_LEN];
148 static __attribute__((section(".dtcm_sec_data "))) u8    shell_log_buff2[SHELL_LOG_BUF2_NUM * SHELL_LOG_BUF2_LEN];
149 static __attribute__((section(".dtcm_sec_data "))) u8    shell_log_buff3[SHELL_LOG_BUF3_NUM * SHELL_LOG_BUF3_LEN];
150 static __attribute__((section(".dtcm_sec_data "))) u16   buff1_free_list[SHELL_LOG_BUF1_NUM];
151 static __attribute__((section(".dtcm_sec_data "))) u16   buff2_free_list[SHELL_LOG_BUF2_NUM];
152 static __attribute__((section(".dtcm_sec_data "))) u16   buff3_free_list[SHELL_LOG_BUF3_NUM];
153 #else
154 static u8    shell_log_buff1[SHELL_LOG_BUF1_NUM * SHELL_LOG_BUF1_LEN];
155 static u8    shell_log_buff2[SHELL_LOG_BUF2_NUM * SHELL_LOG_BUF2_LEN];
156 static u8    shell_log_buff3[SHELL_LOG_BUF3_NUM * SHELL_LOG_BUF3_LEN];
157 static u16   buff1_free_list[SHELL_LOG_BUF1_NUM];
158 static u16   buff2_free_list[SHELL_LOG_BUF2_NUM];
159 static u16   buff3_free_list[SHELL_LOG_BUF3_NUM];
160 #endif
161 
162 /*    queue sort ascending in blk_len.    */
163 static free_queue_t       free_queue[3] =
164 	{
165 		{.log_buf = shell_log_buff3, .blk_list = buff3_free_list, .blk_num = SHELL_LOG_BUF3_NUM, \
166 			.blk_len = SHELL_LOG_BUF3_LEN, .list_out_idx = 0, .list_in_idx = 0, \
167 			.free_blk_num = SHELL_LOG_BUF3_NUM, .empty_cnt = 0},
168 
169 		{.log_buf = shell_log_buff2, .blk_list = buff2_free_list, .blk_num = SHELL_LOG_BUF2_NUM, \
170 			.blk_len = SHELL_LOG_BUF2_LEN, .list_out_idx = 0, .list_in_idx = 0, \
171 			.free_blk_num = SHELL_LOG_BUF2_NUM, .empty_cnt = 0},
172 
173 		{.log_buf = shell_log_buff1, .blk_list = buff1_free_list, .blk_num = SHELL_LOG_BUF1_NUM, \
174 			.blk_len = SHELL_LOG_BUF1_LEN, .list_out_idx = 0, .list_in_idx = 0, \
175 			.free_blk_num = SHELL_LOG_BUF1_NUM, .empty_cnt = 0},
176 	};
177 
178 static busy_queue_t       log_busy_queue;
179 static pending_queue_t    pending_queue;
180 
181 static cmd_line_t  cmd_line_buf;
182 
183 #ifdef CONFIG_SLAVE_CORE
184 #if 1
185 static shell_dev_t * log_dev = &shell_dev_mb;
186 static shell_dev_t * cmd_dev = &shell_dev_mb;
187 #else
188 static shell_dev_t * log_dev = &shell_uart3;
189 static shell_dev_t * cmd_dev = &shell_uart3;
190 #endif
191 static const char	 shell_fault_str[] = "\r\n!!CPU1:some LOGs discarded!!\r\n";
192 static const u16     shell_fault_str_len = sizeof(shell_fault_str) - 1;
193 #else
194 
195 static shell_dev_t * log_dev = &shell_uart;
196 static shell_dev_t * cmd_dev = &shell_uart;
197 
198 #ifdef CONFIG_MASTER_CORE
199 static shell_dev_ipc_t * ipc_dev = &shell_dev_ipc;
200 static int shell_ipc_rx_indication(u16 cmd, u8 *data, u16 data_len);
201 #endif
202 static const char	 shell_fault_str[] = "\r\n!!some LOGs discarded!!\r\n";
203 static const u16     shell_fault_str_len = sizeof(shell_fault_str) - 1;
204 #endif
205 
206 static const char	 shell_cmd_ovf_str[] = "\r\n!!some CMDs lost!!\r\n";
207 static const u16     shell_cmd_ovf_str_len = sizeof(shell_cmd_ovf_str) - 1;
208 
209 static bool_t shell_init_ok = bFALSE;
210 static u8     fault_hint_print = 0;
211 static u32    shell_log_overflow = 0;
212 static u32    shell_log_count = 0;
213 
214 static beken_semaphore_t   shell_semaphore;  // will release from ISR.
215 
216 
create_shell_event(void)217 static bool_t create_shell_event(void)
218 {
219 	rtos_init_semaphore(&shell_semaphore, 1);
220 
221 	return bTRUE;
222 }
223 
set_shell_event(u32 event_flag)224 static bool_t set_shell_event(u32 event_flag)
225 {
226 	(void)event_flag;
227 
228 	rtos_set_semaphore(&shell_semaphore);
229 
230 	return bTRUE;
231 }
232 
wait_any_event(u32 timeout)233 static u32 wait_any_event(u32 timeout)
234 {
235 	int result;
236 
237 	result = rtos_get_semaphore(&shell_semaphore, timeout);
238 
239 	if(result == kTimeoutErr)
240 		return 0;
241 
242 	return SHELL_EVENT_RX_IND;
243 }
244 
245 static void tx_req_process(void);
246 
247 #if 0
248 static u16 get_free_buff_cnt(free_queue_t *free_q)
249 {
250 	u16    free_cnt;
251 
252 	if(free_q->list_out_idx >= free_q->list_in_idx)
253 	{
254 		free_cnt = free_q->blk_num + free_q->list_in_idx - free_q->list_out_idx;
255 	}
256 	else
257 	{
258 		free_cnt = free_q->list_in_idx - free_q->list_out_idx;
259 	}
260 
261 	return free_cnt; /* should reserve 1 block. *//* (list_out_idx == list_in_idx) means all buf free. */
262 }
263 #endif
264 
alloc_log_blk(u16 log_len,u16 * blk_tag)265 static u8 * alloc_log_blk(u16 log_len, u16 *blk_tag)
266 {
267 	u16    free_blk_id;
268 	u8     queue_id;
269 	free_queue_t * free_q;
270 	u8     *       blk_buf = NULL;
271 
272 	//disable_interrupt(); // called from task context, use semaphore instead of locking interrupt.
273 	//get_shell_mutex();
274 	u32  int_mask = rtos_disable_int();
275 
276 	for(queue_id = 0; queue_id < TBL_SIZE(free_queue); queue_id++)
277 	{
278 		free_q = &free_queue[queue_id];
279 
280 		/*    queue ascending in blk_len.    */
281 		if(free_q->blk_len < log_len)
282 			continue;
283 
284 		if(/*get_free_buff_cnt(free_q) */ free_q->free_blk_num > 0)
285 		{
286 			free_blk_id = free_q->blk_list[free_q->list_out_idx];
287 			free_q->list_out_idx = (free_q->list_out_idx + 1) % free_q->blk_num;
288 			free_q->free_blk_num--;
289 
290 			blk_buf = &free_q->log_buf[free_blk_id * free_q->blk_len];
291 			*blk_tag = MAKE_BLOCK_TAG(free_blk_id, queue_id);
292 
293 			break;
294 		}
295 		else
296 		{
297 			free_q->empty_cnt++;
298 		}
299 	}
300 
301 	if(blk_buf == NULL)
302 	{
303 		shell_log_overflow++;
304 	}
305 	else
306 	{
307 		fault_hint_print = 0;
308 		shell_log_count++;
309 	}
310 
311 	//enable_interrupt(); // called from task context, use semaphore instead of locking interrupt.
312 	//release_shell_mutex();
313 	rtos_enable_int(int_mask);
314 
315 	return blk_buf;
316 }
317 
free_log_blk(u16 block_tag)318 static bool_t free_log_blk(u16 block_tag)
319 {
320 	u8      queue_id = GET_QUEUE_ID(block_tag);
321 	u16     blk_id = GET_BLOCK_ID(block_tag);
322 	free_queue_t *free_q;
323 
324 	if(queue_id >= TBL_SIZE(free_queue))
325 		return bFALSE;
326 
327 	free_q = &free_queue[queue_id];
328 
329 	if(blk_id >= free_q->blk_num)
330 		return bFALSE;
331 
332 	//disable_interrupt(); // called from tx-complete only, don't lock interrupt.
333 
334 	free_q->blk_list[free_q->list_in_idx] = blk_id;
335 	free_q->list_in_idx = (free_q->list_in_idx + 1) % free_q->blk_num;
336 	free_q->free_blk_num++;
337 
338 	//enable_interrupt(); // called from tx-complete only, don't lock interrupt.
339 
340 	return bTRUE;
341 }
342 
push_pending_queue(u16 blk_tag,u16 data_len)343 static void push_pending_queue(u16 blk_tag, u16 data_len)
344 {
345 	//get_shell_mutex();
346 
347 	pending_queue.packet_list[pending_queue.list_in_idx].blk_tag = blk_tag;
348 	pending_queue.packet_list[pending_queue.list_in_idx].packet_len = data_len;
349 
350 	pending_queue.list_in_idx = (pending_queue.list_in_idx + 1) % SHELL_LOG_PEND_NUM;
351 
352 	//release_shell_mutex();
353 
354 	return;
355 }
356 
pull_pending_queue(u16 * blk_tag,u16 * data_len)357 static void pull_pending_queue(u16 *blk_tag, u16 *data_len)
358 {
359 	*blk_tag     = pending_queue.packet_list[pending_queue.list_out_idx].blk_tag;
360 	*data_len   = pending_queue.packet_list[pending_queue.list_out_idx].packet_len;
361 
362 	pending_queue.list_out_idx = (pending_queue.list_out_idx + 1) % SHELL_LOG_PEND_NUM;
363 
364 	return;
365 }
366 
367 int shell_assert_out(bool bContinue, char * format, ...);
368 
369 /* call from TX ISR. */
shell_tx_complete(u8 * pbuf,u16 buf_tag)370 static void shell_tx_complete(u8 *pbuf, u16 buf_tag)
371 {
372 	u16     block_tag;
373 	u8      queue_id = GET_QUEUE_ID(buf_tag);
374 	u16     blk_id = GET_BLOCK_ID(buf_tag);
375 	free_queue_t *free_q;
376 
377 	/* rsp ok ?? */
378 	if( queue_id == SHELL_RSP_QUEUE_ID )    /* rsp. */
379 	{
380 		/* it is called from cmd_dev tx ISR. */
381 
382 		if ( (pbuf != cmd_line_buf.rsp_buff) || (blk_id != 0) ||
383 			( !cmd_line_buf.rsp_ongoing ) )
384 		{
385 			/* something wrong!!! */
386 			shell_assert_out(bTRUE, "FAULT: in rsp.\r\n");
387 		}
388 
389 		cmd_line_buf.rsp_ongoing = bFALSE;   /* rsp compelete, rsp_buff can be used for next cmd/response. */
390 
391 		//set_shell_event(SHELL_EVENT_TX_REQ);  // notify shell task to process the log tx.
392 		tx_req_process();
393 
394 		return;
395 	}
396 
397 	if( queue_id == SHELL_ROM_QUEUE_ID )    /* fault hints buffer, point to flash. */
398 	{
399 		/* it is called from log_dev/cmd_dev tx ISR. */
400 
401 		if ( (blk_id == 0) && (pbuf == (u8 *)shell_fault_str) )
402 		{
403 		}
404 		else if ( (blk_id == 1) && (pbuf == (u8 *)shell_cmd_ovf_str) )
405 		{
406 		}
407 		else
408 		{
409 			/* something wrong!!! */
410 			shell_assert_out(bTRUE, "FATAL:t-%x,p-%x\r\n", buf_tag, pbuf);
411 		}
412 
413 		//set_shell_event(SHELL_EVENT_TX_REQ);  // notify shell task to process the log tx.
414 		tx_req_process();
415 
416 		return;
417 	}
418 
419 	if (queue_id < TBL_SIZE(free_queue))   /* from log busy queue. */
420 	{
421 		/* it is called from log_dev tx ISR. */
422 
423 		free_q = &free_queue[queue_id];
424 
425 		block_tag = log_busy_queue.blk_list[log_busy_queue.list_out_idx];
426 
427 		if( ( buf_tag != block_tag ) || (blk_id >= free_q->blk_num) ||
428 			( (&free_q->log_buf[blk_id * free_q->blk_len]) != pbuf) )
429 		{
430 			/* something wrong!!! */
431 			/*        FAULT !!!!      */
432 			shell_assert_out(bTRUE, "FATAL:%x,%x\r\n", buf_tag, block_tag);
433 
434 			return;
435 		}
436 
437 		/* de-queue from busy queue. */
438 		log_busy_queue.list_out_idx = (log_busy_queue.list_out_idx + 1) % SHELL_LOG_BUSY_NUM;
439 
440 		/* free buffer to queue. */
441 		free_log_blk(block_tag);
442 
443 		//set_shell_event(SHELL_EVENT_TX_REQ);  // notify shell task to process the log tx.
444 		tx_req_process();
445 
446 		return;
447 	}
448 
449 	/*        FAULT !!!!      */
450 	shell_assert_out(bTRUE, "FATAL:%x,\r\n", buf_tag);
451 
452 	return;
453 }
454 
455 /* call from RX ISR. */
shell_rx_indicate(void)456 static void shell_rx_indicate(void)
457 {
458 	set_shell_event(SHELL_EVENT_RX_IND);
459 
460 	return;
461 }
462 
append_link_data_byte(u8 * link_buf,u16 buf_len,u8 * data_ptr,u16 data_len)463 static u16 append_link_data_byte(u8 * link_buf, u16 buf_len, u8 * data_ptr, u16 data_len)
464 {
465 	u16   cnt = 0, i;
466 
467 	for(i = 0; i < data_len; i++)
468 	{
469 		if( (*data_ptr == HEX_SYNC_CHAR) ||
470 			(*data_ptr == HEX_ESC_CHAR) )
471 		{
472 			if(cnt < (buf_len - 1))
473 			{
474 				link_buf[cnt] = HEX_ESC_CHAR;
475 				cnt++;
476 				link_buf[cnt] = (*data_ptr) ^ HEX_MOD_CHAR;
477 				cnt++;
478 			}
479 		}
480 		else
481 		{
482 			if(cnt < buf_len)
483 			{
484 				link_buf[cnt] = (*data_ptr);
485 				cnt++;
486 			}
487 		}
488 
489 		data_ptr++;
490 	}
491 
492 	return cnt;
493 }
494 
echo_out(u8 * echo_str,u16 len)495 static bool_t echo_out(u8 * echo_str, u16 len)
496 {
497 	u16	 wr_cnt;
498 
499 	if(len == 0)
500 		return bTRUE;
501 
502 	wr_cnt = cmd_dev->dev_drv->write_echo(cmd_dev, echo_str, len);
503 
504 	return (wr_cnt == len);
505 }
506 
507 /*    NOTICE:  this can only be called by shell task internally (cmd handler). */
508 /*             it is not re-enterance function. */
rsp_out(u8 * rsp_msg,u16 msg_len)509 static bool_t rsp_out(u8 * rsp_msg, u16 msg_len)
510 {
511 	u16    rsp_blk_tag = MAKE_BLOCK_TAG(0, SHELL_RSP_QUEUE_ID);
512 
513 	if(rsp_msg != cmd_line_buf.rsp_buff)
514 	{
515 		if(msg_len > sizeof(cmd_line_buf.rsp_buff))
516 		{
517 			msg_len = sizeof(cmd_line_buf.rsp_buff);;
518 		}
519 
520 		memcpy(cmd_line_buf.rsp_buff, rsp_msg, msg_len);
521 	}
522 
523 	if(log_dev != cmd_dev)
524 	{
525 		// set TRUE, then call driver, in case TX_COMPLETE_ISR will happen before set TRUE.
526 		cmd_line_buf.rsp_ongoing = bTRUE;  // one by one for cmd handler.
527 
528 		/* dedicated device for cmd/response, don't enqueue the msg to pending queue. */
529 		/* send to cmd dev directly. */
530 		cmd_dev->dev_drv->write_async(cmd_dev, cmd_line_buf.rsp_buff, msg_len, rsp_blk_tag);
531 	}
532 	else
533 	{
534 		/* shared device for response & log, push the rsp msg to pending queue. */
535 
536 		u32  int_mask = rtos_disable_int();
537 
538 		cmd_line_buf.rsp_ongoing = bTRUE;  // one by one for cmd handler. set to true before trigger the TX.
539 
540 		push_pending_queue(rsp_blk_tag, msg_len);
541 
542 		//set_shell_event(SHELL_EVENT_TX_REQ);  // notify shell task to process the log tx.
543 		tx_req_process();
544 
545 		rtos_enable_int(int_mask);
546 	}
547 
548 	return bTRUE;
549 }
550 
cmd_hint_out(void)551 static bool_t cmd_hint_out(void)
552 {
553 	u16    hint_blk_tag = MAKE_BLOCK_TAG(1, SHELL_ROM_QUEUE_ID);
554 
555 	if(log_dev != cmd_dev)
556 	{
557 		/* dedicated device for cmd_hint, don't enqueue the msg to pending queue. */
558 		/* send to cmd dev directly. */
559 		cmd_dev->dev_drv->write_async(cmd_dev, (u8 *)shell_cmd_ovf_str, shell_cmd_ovf_str_len, hint_blk_tag);
560 	}
561 	else
562 	{
563 		/* shared device for response & log, push the cmd_hint msg to pending queue. */
564 
565 		u32  int_mask = rtos_disable_int();
566 
567 		push_pending_queue(hint_blk_tag, shell_fault_str_len);
568 
569 		//set_shell_event(SHELL_EVENT_TX_REQ);  // notify shell task to process the log tx.
570 		tx_req_process();
571 
572 		rtos_enable_int(int_mask);
573 	}
574 
575 	return bTRUE;
576 }
577 
log_hint_out(void)578 static bool_t log_hint_out(void)
579 {
580 	if(fault_hint_print)	/* sent one hint since last allocation fail.*/
581 		return bTRUE;
582 
583 	u16    hint_blk_tag = MAKE_BLOCK_TAG(0, SHELL_ROM_QUEUE_ID);
584 
585 	u32  int_mask = rtos_disable_int();
586 
587 	push_pending_queue(hint_blk_tag, shell_fault_str_len);
588 
589 	//set_shell_event(SHELL_EVENT_TX_REQ);  // notify shell task to process the log tx.
590 	tx_req_process();
591 
592 	fault_hint_print = 1;
593 
594 	rtos_enable_int(int_mask);
595 
596 	return bTRUE;
597 }
598 
599 /* call this in !* DISABLE *! interrupt context. */
tx_req_process(void)600 static void tx_req_process(void)
601 {
602 	u8		*packet_buf = NULL;
603 	u16		block_tag;
604 	u16		log_len;
605 	u16		tx_ready;
606 	u16		blk_id;
607 	u8		queue_id;
608 	free_queue_t *free_q;
609 
610 	/* maybe tx_req is from tx_complete_callback, check if there any log in queue. */
611 	if(pending_queue.list_out_idx == pending_queue.list_in_idx)  /* queue empty! */
612 		return;
613 
614 	tx_ready = 0;
615 
616 	log_dev->dev_drv->io_ctrl(log_dev, SHELL_IO_CTRL_GET_STATUS, &tx_ready);
617 
618 	if(tx_ready == 0)
619 		return;
620 
621 	/**    ====     POP from pending queue     ====    **/
622 	pull_pending_queue(&block_tag, &log_len);
623 
624 	queue_id = GET_QUEUE_ID(block_tag);
625 	blk_id = GET_BLOCK_ID(block_tag);
626 
627 	if (queue_id < TBL_SIZE(free_queue))
628 	{
629 		free_q = &free_queue[queue_id];
630 
631 		if(blk_id < free_q->blk_num)
632 		{
633 			packet_buf = &free_q->log_buf[blk_id * free_q->blk_len];
634 		}
635 	}
636 	else if(queue_id == SHELL_RSP_QUEUE_ID)
637 	{
638 		packet_buf = cmd_line_buf.rsp_buff;
639 
640 		if((cmd_line_buf.rsp_ongoing == bFALSE) || (log_dev != cmd_dev) || (blk_id != 0))
641 		{
642 			shell_assert_out(bTRUE, "xFATAL: in Tx_req\r\n");
643 			/*		  FAULT !!!!	  */
644 			/* if log_dev is not the same with cmd_dev,
645 			 * rsp will not be pushed into pending queue.
646 			 */
647 		}
648 	}
649 	else if(queue_id == SHELL_ROM_QUEUE_ID)
650 	{
651 		if(blk_id == 0)
652 		{
653 			packet_buf = (u8 *)shell_fault_str;
654 		}
655 		else if(blk_id == 1)
656 		{
657 			packet_buf = (u8 *)shell_cmd_ovf_str;
658 			if(log_dev != cmd_dev)
659 			{
660 				shell_assert_out(bTRUE, "xFATAL: in Tx_req id=%x\r\n", blk_id);
661 				/*		  FAULT !!!!	  */
662 				/* if log_dev is not the same with cmd_dev,
663 				 * cmd_hint will not be pushed into pending queue.
664 				 */
665 			}
666 		}
667 		else
668 		{
669 				/*		  FAULT !!!!	  */
670 				shell_assert_out(bTRUE, "xFATAL: in Tx_req id=%x\r\n", blk_id);
671 		}
672 	}
673 	else
674 	{
675 		/*		  FAULT !!!!	  */
676 		shell_assert_out(bTRUE, "xFATAL: in Tx_req %x.\r\n", block_tag);
677 	}
678 
679 	if(packet_buf == NULL)
680 		return;
681 
682 	/* rom & rsp buff not enter busy-queue. */
683 	if(queue_id < TBL_SIZE(free_queue))
684 	{
685 		log_busy_queue.blk_list[log_busy_queue.list_in_idx] = block_tag;
686 		log_busy_queue.list_in_idx = (log_busy_queue.list_in_idx + 1) % SHELL_LOG_BUSY_NUM;
687 	}
688 
689 	log_dev->dev_drv->write_async(log_dev, packet_buf, log_len, block_tag); /* send to log dev driver. */
690 	/* if driver return 0, should free log-block or not de-queue pending queue and try again. */
691 	/* if return 1, push log-block into busy queue is OK. */
692 
693 	return;
694 }
695 
696 int shell_trace_out( u32 trace_id, ... );
697 int shell_spy_out( u16 spy_id, u8 * data_buf, u16 data_len);
698 
rx_ind_process(void)699 static void rx_ind_process(void)
700 {
701 	u16   read_cnt, buf_len, echo_len;
702 	u16   i = 0;
703 	bool_t  cmd_rx_done = bFALSE, need_backspace = bFALSE;
704 
705 	if(cmd_line_buf.rsp_ongoing)
706 	{
707 		/* previous cmd not complete, inform itself to handle it later. */
708 		set_shell_event(SHELL_EVENT_RX_IND);
709 
710 		rtos_delay_milliseconds(100);	/* delay 100ms, wait cmd to be completed. */
711 
712 		return;
713 	}
714 
715 	/* cmd_line_buf.rsp_buff is free, can be used for read buff temporarily  */
716 
717 	if(cmd_dev->dev_type == SHELL_DEV_MAILBOX)
718 	{
719 		buf_len = MIN(SHELL_CMD_BUF_LEN, SHELL_RSP_BUF_LEN);
720 	}
721 	else /* if(cmd_dev->dev_type == SHELL_DEV_UART) */
722 	{
723 		buf_len = 1;  /* for UART device, read one by one. */
724 	}
725 
726 	while(bTRUE)
727 	{
728 		u8  * rx_temp_buff = &cmd_line_buf.rsp_buff[0];
729 
730 		read_cnt = cmd_dev->dev_drv->read(cmd_dev, rx_temp_buff, buf_len);
731 
732 		echo_len = 0;
733 
734 		for(i = 0; i < read_cnt; i++)
735 		{
736 			if(cmd_line_buf.cur_cmd_type == CMD_TYPE_INVALID)
737 			{
738 				#if 0
739 				if(rx_temp_buff[i] == HEX_SYNC_CHAR)  // SYNC_CHAR, hex frame start.
740 				{
741 					cmd_line_buf.cur_cmd_type = CMD_TYPE_HEX;
742 
743 					cmd_line_buf.cmd_data_len = 0;
744 					cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len] = HEX_SYNC_CHAR;
745 					cmd_line_buf.cmd_data_len++;
746 
747 					continue;
748 				}
749 				#endif
750 
751 				echo_len++;          /* SYNC_CHAR not echo. */
752 
753 				if((rx_temp_buff[i] >= 0x20) && (rx_temp_buff[i] < 0x7f))
754 				{
755 					cmd_line_buf.cur_cmd_type = CMD_TYPE_TEXT;
756 
757 					cmd_line_buf.cmd_data_len = 0;
758 					cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len] = rx_temp_buff[i];
759 					cmd_line_buf.cmd_data_len++;
760 
761 					continue;
762 				}
763 
764 				/* patch for BK_REG tool. */
765 				if(cmd_line_buf.bkreg_state == BKREG_WAIT_01)
766 				{
767 					if(rx_temp_buff[i] == 0x01)
768 						cmd_line_buf.bkreg_state = BKREG_WAIT_E0;
769 				}
770 				else if(cmd_line_buf.bkreg_state == BKREG_WAIT_E0)
771 				{
772 					if(rx_temp_buff[i] == 0xE0)
773 						cmd_line_buf.bkreg_state = BKREG_WAIT_FC;
774 					else if(rx_temp_buff[i] != 0x01)
775 						cmd_line_buf.bkreg_state = BKREG_WAIT_01;
776 				}
777 				else if(cmd_line_buf.bkreg_state == BKREG_WAIT_FC)
778 				{
779 					if(rx_temp_buff[i] == 0xFC)
780 					{
781 						cmd_line_buf.cur_cmd_type = CMD_TYPE_BKREG;
782 
783 						cmd_line_buf.cmd_buff[0] = 0x01;
784 						cmd_line_buf.cmd_buff[1] = 0xE0;
785 						cmd_line_buf.cmd_buff[2] = 0xFC;
786 
787 						cmd_line_buf.cmd_data_len = 3;
788 
789 						echo_len = 0;   // cann't echo anything.
790 
791 						continue;
792 					}
793 					else if(rx_temp_buff[i] != 0x01)
794 						cmd_line_buf.bkreg_state = BKREG_WAIT_01;
795 					else
796 						cmd_line_buf.bkreg_state = BKREG_WAIT_E0;
797 				}
798 
799 			}
800 
801 			#if 0
802 			if(cmd_line_buf.cur_cmd_type == CMD_TYPE_HEX)
803 			{
804 				if(cmd_line_buf.cmd_data_len < sizeof(cmd_line_buf.cmd_buff))
805 				{
806 					cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len] = rx_temp_buff[i];
807 					cmd_line_buf.cmd_data_len++;
808 				}
809 
810 				if(rx_temp_buff[i] == HEX_SYNC_CHAR)  // SYNC_CHAR, hex frame end.
811 				{
812 					cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len - 1] = HEX_SYNC_CHAR;  // in case cmd_data_len overflow.
813 					cmd_rx_done = bTRUE;
814 					break;
815 				}
816 			}
817 			#endif
818 
819 			if(cmd_line_buf.cur_cmd_type == CMD_TYPE_TEXT)
820 			{
821 				echo_len++;
822 				if(rx_temp_buff[i] == '\b')
823 				{
824 					if(cmd_line_buf.cmd_data_len > 0)
825 					{
826 						cmd_line_buf.cmd_data_len--;
827 
828 						if(cmd_line_buf.cmd_data_len == 0)
829 							need_backspace = bTRUE;
830 					}
831 				}
832 				else if((rx_temp_buff[i] == '\n') || (rx_temp_buff[i] == '\r'))
833 				{
834 					if(cmd_line_buf.cmd_data_len < sizeof(cmd_line_buf.cmd_buff))
835 					{
836 						cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len] = 0;
837 					}
838 					else
839 					{
840 						cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len - 1] = 0;  // in case cmd_data_len overflow.
841 					}
842 
843 					cmd_rx_done = bTRUE;
844 					break;
845 				}
846 				else if((rx_temp_buff[i] >= 0x20))
847 				{
848 					if(cmd_line_buf.cmd_data_len < sizeof(cmd_line_buf.cmd_buff))
849 					{
850 						cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len] = rx_temp_buff[i];
851 						cmd_line_buf.cmd_data_len++;
852 					}
853 				}
854 
855 			}
856 
857 			/* patch for BK_REG tool. */
858 			if(cmd_line_buf.cur_cmd_type == CMD_TYPE_BKREG)
859 			{
860 				echo_len = 0;   // cann't echo anything.
861 
862 				/* p[0] = 0x1, p[1]=0xe0, p[2]=0xfc, p[3]=len. */
863 				if(cmd_line_buf.cmd_data_len == 3)
864 				{
865 					cmd_line_buf.bkreg_left_byte = rx_temp_buff[i] + 1;  // +1, because will -1 in next process.
866 
867 					if((cmd_line_buf.bkreg_left_byte + 3) >= sizeof(cmd_line_buf.cmd_buff))  // 3 bytes of header + 1 byte of len.
868 					{
869 						cmd_line_buf.cmd_data_len = 0;
870 
871 						cmd_rx_done = bTRUE;
872 						break;
873 					}
874 				}
875 
876 				if(cmd_line_buf.cmd_data_len < sizeof(cmd_line_buf.cmd_buff))
877 				{
878 					cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len] = rx_temp_buff[i];
879 					cmd_line_buf.cmd_data_len++;
880 				}
881 
882 				cmd_line_buf.bkreg_left_byte--;
883 
884 				if(cmd_line_buf.bkreg_left_byte == 0)
885 				{
886 					cmd_rx_done = bTRUE;
887 					break;
888 				}
889 			}
890 		}
891 
892 		if( cmd_rx_done )
893 		{
894 			/* patch for BK_REG tool. */
895 			if(cmd_line_buf.cur_cmd_type == CMD_TYPE_BKREG)
896 			{
897 				break;  // cann't echo anything.
898 			}
899 
900 			if(cmd_line_buf.echo_enable)
901 			{
902 				echo_out(&rx_temp_buff[0], echo_len);
903 				echo_out((u8 *)"\r\n", 2);
904 			}
905 
906 			break;
907 		}
908 		else
909 		{
910 			/* patch for BK_REG tool. */
911 			if( (cmd_line_buf.cur_cmd_type == CMD_TYPE_BKREG) ||
912 				((cmd_line_buf.cur_cmd_type == CMD_TYPE_INVALID) && (cmd_line_buf.bkreg_state != BKREG_WAIT_01)) )
913 			{
914 				 // cann't echo anything.
915 			}
916 			else if(cmd_line_buf.echo_enable)
917 			{
918 				if(echo_len > 0)
919 				{
920 					if( (rx_temp_buff[echo_len - 1] == '\b') ||
921 						(rx_temp_buff[echo_len - 1] == 0x7f) ) /* DEL */
922 					{
923 						echo_len--;
924 						if((cmd_line_buf.cmd_data_len > 0) || need_backspace)
925 							echo_out((u8 *)"\b \b", 3);
926 					}
927 
928 					u8    cr_lf = 0;
929 
930 					if(echo_len == 1)
931 					{
932 						if( (rx_temp_buff[echo_len - 1] == '\r') ||
933 							(rx_temp_buff[echo_len - 1] == '\n') )
934 						{
935 							cr_lf = 1;
936 						}
937 					}
938 					else if(echo_len == 2)
939 					{
940 						if( (memcmp(rx_temp_buff, "\r\n", 2) == 0) ||
941 							(memcmp(rx_temp_buff, "\n\r", 2) == 0) )
942 						{
943 							cr_lf = 1;
944 						}
945 					}
946 
947 					if(cr_lf != 0)
948 					{
949 						echo_out((u8 *)"\r\n#", sizeof("\r\n#") - 1);
950 						echo_len = 0;
951 					}
952 				}
953 				echo_out(rx_temp_buff, echo_len);
954 			}
955 		}
956 
957 		if(read_cnt < buf_len) /* all data are read out. */
958 			break;
959 	}
960 
961 	if(read_cnt < buf_len) /* all data are read out. */
962 	{
963 	}
964 	else  /* cmd pends in buffer, handle it in new loop cycle. */
965 	{
966 		set_shell_event(SHELL_EVENT_RX_IND);
967 	}
968 
969 	/* can re-use *buf_len*. */
970 	if( cmd_rx_done )
971 	{
972 		#if 0
973 		if(cmd_line_buf.cur_cmd_type == CMD_TYPE_HEX)
974 		{
975 			#if 1   /* it's test code. */
976 			buf_len = sprintf((char *)&cmd_line_buf.rsp_buff[0], "\r\nHex count: %d, ", cmd_line_buf.cmd_data_len);
977 			buf_len += sprintf((char *)&cmd_line_buf.rsp_buff[buf_len], "Hdr: %x, Tail: %x.\r\n", \
978 				           cmd_line_buf.cmd_buff[0], cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len - 1]);
979 
980 			for(i = 1; (i < cmd_line_buf.cmd_data_len) && (i < 18); i++)
981 			{
982 				buf_len += sprintf((char *)&cmd_line_buf.rsp_buff[buf_len], "%x ", cmd_line_buf.cmd_buff[i]);
983 			}
984 
985 			strcpy((char *)&cmd_line_buf.rsp_buff[buf_len], "\r\n#");
986 			rsp_out(cmd_line_buf.rsp_buff, strlen((char *)cmd_line_buf.rsp_buff));
987 
988 			shell_trace_out(0x39, 8, cmd_line_buf.cmd_buff[0], cmd_line_buf.cmd_buff[1], cmd_line_buf.cmd_buff[2], cmd_line_buf.cmd_buff[3],  \
989 				cmd_line_buf.cmd_buff[4], cmd_line_buf.cmd_buff[5], cmd_line_buf.cmd_buff[6], cmd_line_buf.cmd_buff[7]);
990 			shell_spy_out(0x40, cmd_line_buf.cmd_buff, 9);
991 
992 			#endif
993 		}
994 		#endif
995 
996 		if(cmd_line_buf.cur_cmd_type == CMD_TYPE_TEXT)
997 		{
998 			u16		rx_ovf = 0;
999 			cmd_dev->dev_drv->io_ctrl(cmd_dev, SHELL_IO_CTRL_GET_RX_STATUS, &rx_ovf);
1000 
1001 			if(rx_ovf != 0)
1002 			{
1003 				cmd_hint_out();
1004 			}
1005 
1006 			cmd_line_buf.rsp_buff[0] = 0;
1007 			/* handle command. */
1008 			if( cmd_line_buf.cmd_data_len > 0 )
1009 				handle_shell_input( (char *)cmd_line_buf.cmd_buff, cmd_line_buf.cmd_data_len, (char *)cmd_line_buf.rsp_buff, sizeof(cmd_line_buf.rsp_buff) );
1010 
1011 			cmd_line_buf.rsp_buff[SHELL_RSP_BUF_LEN - 4] = 0;
1012 
1013 			buf_len = strlen((char *)cmd_line_buf.rsp_buff);
1014 			if(buf_len > (SHELL_RSP_BUF_LEN - 4))
1015 				buf_len = (SHELL_RSP_BUF_LEN - 4);
1016 			buf_len += sprintf((char *)&cmd_line_buf.rsp_buff[buf_len], "\r\n#");
1017 
1018 			rsp_out(cmd_line_buf.rsp_buff, buf_len);
1019 		}
1020 
1021 		/* patch for BK_REG tool. */
1022 		if(cmd_line_buf.cur_cmd_type == CMD_TYPE_BKREG)
1023 		{
1024 			if(cmd_line_buf.cmd_data_len > 3)
1025 			{
1026 #if CONFIG_BKREG
1027 				extern int bkreg_run_command(const char *cmd, int flag);
1028 
1029 				bkreg_run_command((const char *)&cmd_line_buf.cmd_buff[0], (int)cmd_line_buf.cmd_data_len);
1030 #endif // CONFIG_BKREG
1031 			}
1032 		}
1033 
1034 		cmd_line_buf.cur_cmd_type = CMD_TYPE_INVALID;  /* reset cmd line to interpret new cmd. */
1035 		cmd_line_buf.cmd_data_len = 0;
1036 		cmd_line_buf.bkreg_state = BKREG_WAIT_01;	/* reset state machine. */
1037 	}
1038 
1039 	return;
1040 }
1041 
shell_task_init(void)1042 static void shell_task_init(void)
1043 {
1044 	u16		i;
1045 
1046 	for(i = 0; i < SHELL_LOG_BUF1_NUM; i++)
1047 	{
1048 		buff1_free_list[i] = i;
1049 	}
1050 	for(i = 0; i < SHELL_LOG_BUF2_NUM; i++)
1051 	{
1052 		buff2_free_list[i] = i;
1053 	}
1054 	for(i = 0; i < SHELL_LOG_BUF3_NUM; i++)
1055 	{
1056 		buff3_free_list[i] = i;
1057 	}
1058 
1059 	memset(&log_busy_queue, 0, sizeof(log_busy_queue));
1060 	memset(&pending_queue, 0, sizeof(pending_queue));
1061 
1062 	cmd_line_buf.rsp_ongoing = bFALSE;
1063 	cmd_line_buf.cur_cmd_type = CMD_TYPE_INVALID;
1064 	cmd_line_buf.cmd_data_len = 0;
1065 	cmd_line_buf.bkreg_state = BKREG_WAIT_01;
1066 	cmd_line_buf.assert_data_len = 0;
1067 	cmd_line_buf.log_level = LOG_LEVEL;
1068 	cmd_line_buf.echo_enable = bTRUE;
1069 
1070 	create_shell_event();
1071 
1072 	cmd_dev->dev_drv->init(cmd_dev);
1073 	cmd_dev->dev_drv->open(cmd_dev, shell_tx_complete, shell_rx_indicate);
1074 
1075 	if(log_dev != cmd_dev)
1076 	{
1077 		log_dev->dev_drv->init(log_dev);
1078 		log_dev->dev_drv->open(log_dev, shell_tx_complete, NULL);
1079 	}
1080 
1081 	#ifdef CONFIG_MASTER_CORE
1082 	ipc_dev->dev_drv->init(ipc_dev);
1083 	ipc_dev->dev_drv->open(ipc_dev, (shell_ipc_rx_t)shell_ipc_rx_indication);   /* register rx-callback to copy log data to buffer. */
1084 	#endif
1085 
1086 	shell_init_ok = bTRUE;
1087 
1088 }
1089 
shell_task(void * para)1090 void shell_task( void *para )
1091 {
1092 	u32    Events;
1093 
1094 	shell_task_init();
1095 
1096 	echo_out((u8 *)"\r\n#", sizeof("\r\n#") - 1);
1097 
1098 	while(bTRUE)
1099 	{
1100 		Events = wait_any_event(SHELL_TASK_DEF_TICK); // WAIT_EVENT;
1101 
1102 		if(Events & SHELL_EVENT_TX_REQ)
1103 		{
1104 			echo_out((u8 *)"Unsolicited\r\n#", sizeof("Unsolicited\r\n#") - 1);
1105 		}
1106 
1107 		if(Events & SHELL_EVENT_RX_IND)
1108 		{
1109 			rx_ind_process();
1110 		}
1111 	}
1112 }
1113 
shell_log_check(u8 level,char * mod_name)1114 __bk_weak int shell_log_check(u8 level, char *mod_name)
1115 {
1116 	if(level > cmd_line_buf.log_level)
1117 		return 0; //bFALSE;
1118 
1119 	return 1;// bTRUE;
1120 }
1121 
shell_log_out_direct(const char * format,va_list ap)1122 int shell_log_out_direct(const char *format, va_list ap)
1123 {
1124 	u32         int_mask;
1125 	char       *pbuf;
1126 	u16         data_len, buf_len;
1127 	va_list     arg_list;
1128 
1129 	pbuf = (char *)&cmd_line_buf.assert_buff[0];
1130 	buf_len = sizeof(cmd_line_buf.assert_buff);
1131 
1132 	int_mask = rtos_disable_int();
1133 
1134 	va_copy(arg_list, ap);
1135 	data_len = vsnprintf( pbuf, buf_len -1, format, arg_list );
1136 	va_end( arg_list );
1137 
1138 	if ( (data_len != 0) && (pbuf[data_len - 1] == '\n') )
1139 	{
1140 		if (data_len == 1 || pbuf[data_len - 2] != '\r')
1141 		{
1142 			pbuf[data_len] = '\n';
1143 			pbuf[data_len - 1] = '\r';
1144 			data_len++;
1145 		}
1146 	}
1147 
1148 	log_dev->dev_drv->write_sync(log_dev, (u8 *)pbuf, data_len);
1149 
1150 	rtos_enable_int(int_mask);
1151 
1152 	return 1;
1153 }
1154 
shell_log_raw_data(const u8 * data,u16 data_len)1155 int shell_log_raw_data(const u8 *data, u16 data_len)
1156 {
1157 	u8   *packet_buf;
1158 	u16   free_blk_tag;
1159 
1160 	if (!shell_init_ok)
1161 	{
1162 		return 0; // bFALSE;
1163 	}
1164 
1165 	if (NULL == data || 0 == data_len)
1166 	{
1167 		return 0; // bFALSE;
1168 	}
1169 
1170 	packet_buf = alloc_log_blk(data_len, &free_blk_tag);
1171 
1172 	if (NULL == packet_buf)
1173 	{
1174 		log_hint_out();
1175 		return 0; // bFALSE;
1176 	}
1177 
1178 	memcpy(packet_buf, data, data_len);
1179 
1180 	u32 int_mask = rtos_disable_int();
1181 
1182 	// push to pending queue.
1183 	push_pending_queue(free_blk_tag, data_len);
1184 
1185 	// notify shell task to process the log tx.
1186 	tx_req_process();
1187 
1188 	rtos_enable_int(int_mask);
1189 
1190 	return 1; // bTRUE;
1191 }
1192 
shell_log_out_port(int level,char * mod_name,const char * format,va_list ap)1193 void shell_log_out_port(int level, char *mod_name, const char *format, va_list ap)
1194 {
1195 	u8   * packet_buf;
1196 	u16    free_blk_tag;
1197 	u16    log_len = 0, buf_len;
1198 	va_list  arg_list;
1199 
1200 	if( !shell_init_ok )
1201 	{
1202 		cmd_line_buf.log_level = LOG_LEVEL;	// if not intialized, set log_level temporarily here. !!!patch!!!
1203 		shell_log_out_direct(format, ap);
1204 		return ; // bFALSE;
1205 	}
1206 
1207 	if(shell_log_check(level, mod_name) == 0)//bFALSE)
1208 	{
1209 		return ; // bFALSE;
1210 	}
1211 
1212 	va_copy(arg_list, ap);
1213 	buf_len = vsnprintf( NULL, 0, format, arg_list ) + 1;
1214 	va_end( arg_list );
1215 
1216 	if(mod_name != NULL)
1217 		buf_len += MOD_NAME_LEN + 2;
1218 
1219 	packet_buf = alloc_log_blk(buf_len, &free_blk_tag);
1220 
1221 	if(packet_buf == NULL)
1222 	{
1223 		log_hint_out();
1224 		return ; // bFALSE;
1225 	}
1226 
1227 	log_len = 0;
1228 
1229 	if(mod_name != NULL)
1230 	{
1231 		memcpy(&packet_buf[0], mod_name, MOD_NAME_LEN);
1232 		packet_buf[MOD_NAME_LEN] = 0;
1233 		log_len = strlen((char *)packet_buf);  // log_len <= MOD_NAME_LEN;
1234 		packet_buf[log_len] = ':';
1235 		log_len++;
1236 		packet_buf[log_len] = 0;
1237 	}
1238 
1239 	log_len += vsnprintf( (char *)&packet_buf[log_len], buf_len - log_len, format, ap );
1240 	if ( (log_len != 0) && (packet_buf[log_len - 1] == '\n') )
1241 	{
1242 		if (log_len == 1 || packet_buf[log_len - 2] != '\r')
1243 		{
1244 			packet_buf[log_len] = '\n';
1245 			packet_buf[log_len - 1] = '\r';
1246 			log_len++;
1247 		}
1248 	}
1249 
1250 	u32  int_mask = rtos_disable_int();
1251 
1252 	// push to pending queue.
1253 	push_pending_queue(free_blk_tag, log_len);
1254 
1255 	//set_shell_event(SHELL_EVENT_TX_REQ);  // notify shell task to process the log tx.
1256 	tx_req_process();
1257 
1258 	rtos_enable_int(int_mask);
1259 
1260 	return ; // bTRUE;;
1261 }
1262 
shell_log_out(u8 level,char * mod_name,const char * format,...)1263 int shell_log_out(u8 level, char *mod_name, const char *format, ...)
1264 {
1265 	va_list  arg_list;
1266 
1267 	if ( !shell_init_ok )
1268 		return 0; // bFALSE;
1269 
1270 	if (shell_log_check(level, mod_name) == 0)
1271 	{
1272 		return 0; // bFALSE;
1273 	}
1274 
1275 	va_start(arg_list, format);
1276 	shell_log_out_port(level, mod_name, format, arg_list);
1277 	va_end(arg_list);
1278 
1279 	return 1; // bTRUE;;
1280 }
1281 
shell_trace_out(u32 trace_id,...)1282 int shell_trace_out( u32 trace_id, ... )
1283 {
1284 	u8    * packet_buf;
1285 	u16     free_blk_tag;
1286 	u16     trace_len = 0, buf_len;
1287 
1288 	va_list arg_list;
1289 	u32     arg_num, i, temp;
1290 
1291 	if( !shell_init_ok )
1292 		return 0; //bFALSE;
1293 
1294 	/* init variable length argument list */
1295 	va_start( arg_list, trace_id );
1296 	arg_num = ( u32 ) va_arg( arg_list, u32 );
1297 	/* clean up variable argument pointer */
1298 	va_end( arg_list );
1299 
1300 	if(arg_num > MAX_TRACE_ARGS)
1301 		arg_num = MAX_TRACE_ARGS;
1302 
1303 	arg_num++;	/* one u32 for system time. */
1304 
1305 	/* treat trace_id as u16 type. */
1306 
1307 	buf_len = (sizeof(u16) + arg_num * sizeof(u32)) * 2 + 2; /* +2 for hdr&tail, *2 for the worst case of escape every byte. */
1308 
1309 	packet_buf = alloc_log_blk(buf_len, &free_blk_tag);
1310 
1311 	if(packet_buf == NULL)
1312 	{
1313 		log_hint_out();
1314 		return 0; // bFALSE;
1315 	}
1316 
1317 	packet_buf[0] = HEX_SYNC_CHAR;
1318 	trace_len = 1;
1319 	trace_len += append_link_data_byte(&packet_buf[trace_len], buf_len - trace_len, (u8 *)&trace_id, sizeof(u16));
1320 
1321 	temp = rtos_get_time();
1322 	trace_len += append_link_data_byte(&packet_buf[trace_len], buf_len - trace_len, (u8 *)&temp, sizeof(u32));
1323 
1324 	/* init variable length argument list */
1325 	va_start( arg_list, trace_id );
1326 	arg_num = ( u32 ) va_arg( arg_list, u32 );
1327 
1328 	for (i = 0; (i < arg_num) && (i < MAX_TRACE_ARGS); i++)
1329 	{
1330 		temp = ( u32 ) va_arg( arg_list, u32 );
1331 		trace_len += append_link_data_byte(&packet_buf[trace_len], buf_len - trace_len, (u8 *)&temp, sizeof(u32));
1332 	}
1333 
1334 	packet_buf[trace_len] = HEX_SYNC_CHAR;
1335 	trace_len++;
1336 
1337 	/* clean up variable argument pointer */
1338 	va_end( arg_list );
1339 
1340 	u32  int_mask = rtos_disable_int();
1341 
1342 	// push to pending queue.
1343 	push_pending_queue(free_blk_tag, trace_len);
1344 
1345 	//set_shell_event(SHELL_EVENT_TX_REQ);  // notify shell task to process the log tx.
1346 	tx_req_process();
1347 
1348 	rtos_enable_int(int_mask);
1349 
1350 	return 1;//bTRUE;;
1351 }
1352 
shell_spy_out(u16 spy_id,u8 * data_buf,u16 data_len)1353 int shell_spy_out( u16 spy_id, u8 * data_buf, u16 data_len)
1354 {
1355 	u8    * packet_buf;
1356 	u16     free_blk_tag;
1357 	u16     spy_len = 0, buf_len;
1358 
1359 	u32     temp;
1360 
1361 	if( !shell_init_ok )
1362 		return 0; //bFALSE;
1363 
1364 	buf_len = (sizeof(u16) + sizeof(u32) + data_len) * 2 + 2; /* +2 for hdr&tail, *2 for the worst case of escape every byte. */
1365 
1366 	packet_buf = alloc_log_blk(buf_len, &free_blk_tag);
1367 
1368 	if(packet_buf == NULL)
1369 	{
1370 		log_hint_out();
1371 		return 0; // bFALSE;
1372 	}
1373 
1374 	packet_buf[0] = HEX_SYNC_CHAR;
1375 	spy_len = 1;
1376 	spy_len += append_link_data_byte(&packet_buf[spy_len], buf_len - spy_len, (u8 *)&spy_id, sizeof(u16));
1377 
1378 	temp = rtos_get_time();
1379 	spy_len += append_link_data_byte(&packet_buf[spy_len], buf_len - spy_len, (u8 *)&temp, sizeof(u32));
1380 
1381 	spy_len += append_link_data_byte(&packet_buf[spy_len], buf_len - spy_len, data_buf, data_len);
1382 
1383 	packet_buf[spy_len] = HEX_SYNC_CHAR;
1384 	spy_len++;
1385 
1386 	u32  int_mask = rtos_disable_int();
1387 
1388 	// push to pending queue.
1389 	push_pending_queue(free_blk_tag, spy_len);
1390 
1391 	//set_shell_event(SHELL_EVENT_TX_REQ);  // notify shell task to process the log tx.
1392 	tx_req_process();
1393 
1394 	rtos_enable_int(int_mask);
1395 
1396 	return 1;//bTRUE;;
1397 }
1398 
shell_assert_out(bool bContinue,char * format,...)1399 int shell_assert_out(bool bContinue, char * format, ...)
1400 {
1401 	u32         int_mask;
1402 	char       *pbuf;
1403 	u16         data_len, buf_len;
1404 	va_list     arg_list;
1405 
1406 	pbuf = (char *)&cmd_line_buf.assert_buff[0];
1407 	buf_len = sizeof(cmd_line_buf.assert_buff);
1408 
1409 	int_mask = rtos_disable_int();
1410 
1411 	va_start( arg_list, format );
1412 
1413 	data_len = vsnprintf( pbuf, buf_len - 1, format, arg_list );
1414 
1415 	va_end( arg_list );
1416 
1417 	log_dev->dev_drv->write_sync(log_dev, (u8 *)pbuf, data_len);
1418 
1419 	if( bContinue )
1420 	{
1421 		rtos_enable_int(int_mask);
1422 	}
1423 	else
1424 	{
1425 		while(bTRUE)
1426 		{
1427 		}
1428 	}
1429 
1430 	return 1;//bTRUE;;
1431 
1432 }
1433 
shell_assert_raw(bool bContinue,char * data_buff,u16 data_len)1434 int shell_assert_raw(bool bContinue, char * data_buff, u16 data_len)
1435 {
1436 	u32         int_mask;
1437 
1438 	int_mask = rtos_disable_int();
1439 
1440 	log_dev->dev_drv->write_sync(log_dev, (u8 *)data_buff, data_len);
1441 
1442 	if( bContinue )
1443 	{
1444 		rtos_enable_int(int_mask);
1445 	}
1446 	else
1447 	{
1448 		while(1)
1449 		{
1450 		}
1451 	}
1452 
1453 	return 1;//bTRUE;;
1454 
1455 }
1456 
1457 #ifdef CONFIG_MASTER_CORE
shell_ipc_rx_indication(u16 cmd,u8 * data,u16 data_len)1458 static int shell_ipc_rx_indication(u16 cmd, u8 *data, u16 data_len)
1459 {
1460 	if(cmd == MB_CMD_LOG_OUT)
1461 	{
1462 		return shell_log_raw_data(data, data_len);
1463 	}
1464 
1465 	if(cmd == MB_CMD_ASSERT_OUT)
1466 	{
1467 		return shell_assert_raw(true, (char *)data, data_len);
1468 	}
1469 
1470 	/* no cmd handler. */
1471 	return 0;
1472 }
1473 
shell_cmd_forward(char * cmd,u16 cmd_len)1474 int shell_cmd_forward(char *cmd, u16 cmd_len)
1475 {
1476 	ipc_dev->dev_drv->write_sync(ipc_dev, (u8 *)cmd, cmd_len);
1477 
1478 	return 1;//bTRUE;
1479 }
1480 #endif
1481 
shell_echo_set(int en_flag)1482 void shell_echo_set(int en_flag)
1483 {
1484 	if(en_flag != 0)
1485 		cmd_line_buf.echo_enable = bTRUE;
1486 	else
1487 		cmd_line_buf.echo_enable = bFALSE;
1488 }
1489 
shell_echo_get(void)1490 int shell_echo_get(void)
1491 {
1492 	if(cmd_line_buf.echo_enable)
1493 		return 1;
1494 
1495 	return 0;
1496 }
1497 
shell_set_log_level(int level)1498 void shell_set_log_level(int level)
1499 {
1500 	cmd_line_buf.log_level = level;
1501 }
1502 
shell_get_log_level(void)1503 int shell_get_log_level(void)
1504 {
1505 	return cmd_line_buf.log_level;
1506 }
1507 
shell_get_log_statist(u32 * info_list,u32 num)1508 int shell_get_log_statist(u32 * info_list, u32 num)
1509 {
1510 	int   cnt = 0;
1511 	if(num > 0)
1512 	{
1513 		info_list[0] = shell_log_overflow;
1514 		cnt++;
1515 	}
1516 	if(num > 1)
1517 	{
1518 		info_list[1] = shell_log_count;
1519 		cnt++;
1520 	}
1521 	if(num > 2)
1522 	{
1523 		info_list[2] = free_queue[0].empty_cnt;
1524 		cnt++;
1525 	}
1526 	if(num > 3)
1527 	{
1528 		info_list[3] = free_queue[1].empty_cnt;
1529 		cnt++;
1530 	}
1531 	if(num > 4)
1532 	{
1533 		info_list[4] = free_queue[2].empty_cnt;
1534 		cnt++;
1535 	}
1536 
1537 	return cnt;
1538 }
1539 
shell_log_flush(void)1540 void shell_log_flush(void)
1541 {
1542 	u32         int_mask;
1543 
1544 	int_mask = rtos_disable_int();
1545 
1546 	log_dev->dev_drv->io_ctrl(log_dev, SHELL_IO_CTRL_FLUSH, NULL);
1547 
1548 	rtos_enable_int(int_mask);
1549 }
1550 
shell_set_uart_port(uint8_t uart_port)1551 void shell_set_uart_port(uint8_t uart_port) {
1552 #if (!CONFIG_SLAVE_CORE)
1553 	if (bk_get_printf_port() != uart_port && uart_port < UART_ID_MAX) {
1554 		u32  int_mask = rtos_disable_int();
1555 
1556 		shell_log_flush();
1557 		bk_set_printf_port(uart_port);
1558 
1559 		log_dev->dev_drv->close(log_dev);
1560 		log_dev->dev_drv->io_ctrl(log_dev, SHELL_IO_CTRL_SET_UART_PORT, &uart_port);
1561 		log_dev->dev_drv->init(log_dev);
1562 		log_dev->dev_drv->open(log_dev, shell_tx_complete, shell_rx_indicate);
1563 
1564 		rtos_enable_int(int_mask);
1565 	}
1566 #endif
1567 }
1568