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