1 /*
2 * Routines to access hardware
3 *
4 * Copyright (c) 2013 Realtek Semiconductor Corp.
5 *
6 * This module is a confidential and proprietary property of RealTek and
7 * possession or use of this module requires written permission of RealTek.
8 */
9 #include "ameba_soc.h"
10 #include <stdarg.h>
11 #include "strproc.h"
12
13 #include "k_api.h"
14
15 SHELL_ROM_BSS_SECTION volatile UART_LOG_CTL shell_ctl;
16 SHELL_ROM_BSS_SECTION u8 *shell_argv_array[MAX_ARGV];
17 SHELL_ROM_BSS_SECTION UART_LOG_BUF shell_buf;
18 #ifdef CONFIG_UART_LOG_HISTORY
19 SHELL_ROM_BSS_SECTION u8 shell_history_cmd[UART_LOG_HISTORY_LEN][UART_LOG_CMD_BUFLEN];
20 #endif
21 SHELL_ROM_BSS_SECTION u32 shell_recv_all_data_onetime;
22
23 //=================================================
24
25 //======================================================
26 //<Function>: shell_array_init
27 //<Usage >: This function is to initialize an array with a given value.
28 //<Argus >: pArrayToInit --> pointer to an array
29 // ArrayLen --> number of array elements
30 // InitValue --> initial value for the array
31 //<Return >: VOID
32 //<Notes >: NA
33 //======================================================
34 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_array_init(u8 * pArrayToInit,u8 ArrayLen,u8 InitValue)35 VOID shell_array_init(u8 *pArrayToInit, u8 ArrayLen, u8 InitValue)
36 {
37 u8 ItemCount =0;
38
39 for (ItemCount=0; ItemCount<ArrayLen; ItemCount++){
40 *(pArrayToInit+ItemCount) = InitValue;
41 }
42 }
43
44
45 //======================================================
46 //<Function>: shell_get_argc
47 //<Usage >: This function is to calcute how many parameters in the cmd string
48 //<Argus >: string --> pointer to an input cmd string
49 //<Return >: number of parameters in the string.(****except the cmd itself****)
50 //<Notes >: NA
51 //======================================================
52 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_get_argc(const u8 * string)53 u8 shell_get_argc(const u8 *string)
54 {
55 u16 argc;
56 u8 *pStr;
57
58 argc = 0;
59 pStr = (u8 *)string;
60
61 while(*pStr){
62 if ((*pStr != ' ') && (*pStr)){
63 argc++;
64 while ((*pStr != ' ') && (*pStr)){
65 pStr++;
66 }
67
68 continue;
69 }
70
71 pStr++;
72 }
73
74 if (argc >= MAX_ARGV){
75 argc = MAX_ARGV - 1;
76 }
77
78 return argc;
79 }
80
81 //======================================================
82 //<Function>: shell_get_argv
83 //<Usage >: This function is to transfer a cmd string to a char array.
84 //<Argus >: string --> pointer to an input cmd string
85 //<Return >: pointer to a char array
86 //<Notes >: NA
87 //======================================================
88 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_get_argv(const u8 * string)89 u8** shell_get_argv(const u8 *string)
90 {
91 u8 ArgvCount = 0;
92 u8 *pStr;
93
94 shell_array_init((u8*)shell_argv_array, MAX_ARGV*sizeof(char *), 0);
95 pStr = (u8 *)string;
96
97 while(*pStr){
98 shell_argv_array[ArgvCount] = pStr;
99 while((*pStr != ' ') && (*pStr)){
100 pStr++;
101 }
102
103 *(pStr++) = '\0';
104
105 while((*pStr == ' ') && (*pStr)){
106 pStr++;
107 }
108
109 ArgvCount++;
110
111 if (ArgvCount == MAX_ARGV){
112 break;
113 }
114 }
115
116 return (u8 **)&shell_argv_array;
117 }
118
119
120
121
122 //======================================================
123 //<Function>: shell_cmd_exec_rom
124 //<Usage >: This function is to parse Uart-Log cmds. If there's a matched
125 // one, it goes to execute that.
126 //<Argus >: pointer to Uart-Log cmd temp buffer
127 //<Return >: VOID
128 //<Notes >: NA
129 //======================================================
130 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_cmd_exec_rom(PUART_LOG_CTL pUartLogCtlExe)131 static VOID shell_cmd_exec_rom(PUART_LOG_CTL pUartLogCtlExe)
132 {
133 u8 CmdCnt = 0;
134 u8 argc = 0;
135 u8 **argv;
136 u32 CmdNum;
137 PUART_LOG_BUF pUartLogBuf = pUartLogCtlExe->pTmpLogBuf;
138 PCOMMAND_TABLE pCmdTbl = pUartLogCtlExe->pCmdTbl;
139
140 argc = shell_get_argc((const u8*)&((*pUartLogBuf).UARTLogBuf[0]));
141 argv = shell_get_argv((const u8*)&((*pUartLogBuf).UARTLogBuf[0]));
142 CmdNum = pUartLogCtlExe->CmdTblSz;
143
144 if (argc > 0){
145 _strupr(argv[0]);
146
147 for (CmdCnt = 0; CmdCnt< CmdNum; CmdCnt++){
148 if ((_strcmp((const char*)argv[0], (const char*)(pCmdTbl[CmdCnt].cmd)))==0){
149 pCmdTbl[CmdCnt].func((argc-1) , (argv+1));
150 shell_array_init(argv[0], sizeof(argv[0]) ,0);
151 break;
152 }
153 }
154 }
155
156 (*pUartLogBuf).BufCount = 0;
157 shell_array_init(&(*pUartLogBuf).UARTLogBuf[0], UART_LOG_CMD_BUFLEN, '\0');
158 }
159
160
161 //======================================================
162 //<Function>: shell_show_backspace
163 //<Usage >: To dispaly backspace on the target interface.
164 //<Argus >: BackLen --> backspace number to show
165 // EchoFlag --> a control flag to show msg or not.
166 // pfINPUT --> func pointer to the display function
167 //<Return >: VOID
168 //<Notes >: NA
169 //======================================================
170 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_show_backspace(u8 BackLen,u8 EchoFlag,VOID * pfINPUT)171 static VOID shell_show_backspace(u8 BackLen, u8 EchoFlag, VOID *pfINPUT)
172 {
173 u8 BackCnt;
174 ECHOFUNC pfEcho;
175 pfEcho = (ECHOFUNC)pfINPUT;
176
177 for(BackCnt=0; BackCnt<BackLen; BackCnt++){
178 if (EchoFlag){
179 pfEcho((u8*)"%c",KB_ASCII_BS);
180 pfEcho((u8*)" ");
181 pfEcho((u8*)"%c",KB_ASCII_BS);
182 }
183 }
184 }
185
186 //======================================================
187 //<Function>: shell_recall_oldcmd
188 //<Usage >: To retrieve the old cmd and may show it on the target interface.
189 //<Argus >: pTmpBuf --> cmd temp buffer, the retrieved cmd will be stored in
190 // it.
191 // OldBuf --> pointer to an cmd buffer.
192 // EchoFlag --> a control flag to show msg or not.
193 // pfINPUT --> func pointer to the display function
194 //<Return >: VOID
195 //<Notes >: NA
196 //======================================================
197 #ifdef CONFIG_UART_LOG_HISTORY
198 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_recall_oldcmd(PUART_LOG_BUF pTmpBuf,u8 * OldBuf,u8 EchoFlag,VOID * pfINPUT)199 static VOID shell_recall_oldcmd(
200 PUART_LOG_BUF pTmpBuf,
201 u8 *OldBuf,
202 u8 EchoFlag,
203 VOID *pfINPUT)
204 {
205
206 ECHOFUNC pfEcho;
207 pfEcho = (ECHOFUNC)pfINPUT;
208
209 _strcpy((char*)&((*pTmpBuf).UARTLogBuf[0]), (char*)OldBuf);
210 (*pTmpBuf).BufCount = _strlen((char*)&(*pTmpBuf).UARTLogBuf[0]);
211
212 if (EchoFlag){
213 pfEcho(&((*pTmpBuf).UARTLogBuf[0]));
214 }
215
216 }
217
218 //======================================================
219 //<Function>: shell_cmd_history
220 //<Usage >: To deal with history-cmds, get the next/previous cmd and show it.
221 //<Argus >: RevData --> a received data.
222 // prvUartLogCtl --> pointer to UART_LOG_CTL
223 // EchoFlag --> a control flag to show msg or not.
224 //<Return >: VOID
225 //<Notes >: NA
226 //======================================================
227 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_cmd_history(u8 RevData,UART_LOG_CTL * prvUartLogCtl,u8 EchoFlag)228 VOID shell_cmd_history(
229 u8 RevData,
230 UART_LOG_CTL *prvUartLogCtl,
231 u8 EchoFlag)
232 {
233 ECHOFUNC pfEcho;
234 pfEcho = (ECHOFUNC)(*prvUartLogCtl).pfINPUT;
235
236 if (RevData == 'A'){
237 if ((*prvUartLogCtl).CRSTS == 0){
238 if ((*prvUartLogCtl).RevdNo > 0){
239 if ((*prvUartLogCtl).SeeIdx == 0){
240 (*prvUartLogCtl).SeeIdx = (*prvUartLogCtl).RevdNo - 1;
241 }
242 else{
243 (*prvUartLogCtl).SeeIdx--;
244 }
245 }
246 }
247
248 shell_show_backspace((*(*prvUartLogCtl).pTmpLogBuf).BufCount, EchoFlag, pfEcho);
249
250 if ((*prvUartLogCtl).RevdNo > 0){
251 shell_recall_oldcmd((*prvUartLogCtl).pTmpLogBuf , (u8*)&(*prvUartLogCtl).pHistoryBuf[(*prvUartLogCtl).SeeIdx],
252 1, (VOID*)pfEcho);
253
254 }
255
256 (*prvUartLogCtl).CRSTS = 0;
257
258 }
259 else if (RevData == 'B'){
260
261 if ((*prvUartLogCtl).RevdNo > 0){
262 if ((*prvUartLogCtl).SeeIdx == ((*prvUartLogCtl).RevdNo-1)){
263 (*prvUartLogCtl).SeeIdx = 0;
264 }
265 else{
266 (*prvUartLogCtl).SeeIdx++;
267 }
268 }
269
270 shell_show_backspace(((*(*prvUartLogCtl).pTmpLogBuf).BufCount), 1, pfEcho);
271
272 if ((*prvUartLogCtl).RevdNo > 0){
273 shell_recall_oldcmd((*prvUartLogCtl).pTmpLogBuf, (u8*)&(*prvUartLogCtl).pHistoryBuf[(*prvUartLogCtl).SeeIdx],
274 1, (VOID*)pfEcho);
275 }
276
277 (*prvUartLogCtl).CRSTS = 0;
278
279 }
280 }
281 #endif
282
283 //======================================================
284 //<Function>: shell_cmd_chk
285 //<Usage >: To deal with Uart-Log input characters
286 //<Argus >: RevData --> a received data.
287 // prvUartLogCtl --> pointer to UART_LOG_CTL
288 // EchoFlag --> a control flag to show msg or not.
289 //<Return >: VOID
290 //<Notes >: NA
291 //======================================================
292 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_cmd_chk(u8 RevData,UART_LOG_CTL * prvUartLogCtl,u8 EchoFlag)293 u8 shell_cmd_chk(
294 u8 RevData,
295 UART_LOG_CTL *prvUartLogCtl,
296 u8 EchoFlag)
297 {
298 u8 RTNSTS = 0;
299 u8 SpaceCount = 0;
300
301 //Cast the input function pointer to the actual echo function pointer type-----
302 ECHOFUNC pfEcho;
303 pfEcho = (ECHOFUNC)(*prvUartLogCtl).pfINPUT;
304 //----------------------------------------------------------------
305
306 if (((*(*prvUartLogCtl).pTmpLogBuf).BufCount<(UART_LOG_CMD_BUFLEN-1)) ||
307 (((*(*prvUartLogCtl).pTmpLogBuf).BufCount==(UART_LOG_CMD_BUFLEN-1)) &&
308 ((RevData == KB_ASCII_CR)||(RevData == '\0')||
309 (RevData == KB_ASCII_BS) || (RevData == KB_ASCII_BS_7F)))){
310
311 if (RevData == 0xFF){ //invlid char, ignore it
312 RTNSTS = 1;
313 }
314
315 if (RevData == KB_ASCII_LF){
316 RTNSTS = 1;
317 }
318 else if ((RevData == KB_ASCII_CR)||(RevData == '\0')){
319 RTNSTS = 2;
320 (*prvUartLogCtl).CRSTS = 1;
321 (*(*prvUartLogCtl).pTmpLogBuf).UARTLogBuf[(*(*prvUartLogCtl).pTmpLogBuf).BufCount] = '\0';
322 if (EchoFlag){
323 pfEcho((u8*)"\r\n");
324 }
325
326 if((*(*prvUartLogCtl).pTmpLogBuf).BufCount != 0)
327 {
328 #ifdef CONFIG_UART_LOG_HISTORY
329 _strcpy((u8*)&((*prvUartLogCtl).pHistoryBuf[(*prvUartLogCtl).NewIdx]),
330 (const u8*)&((*(*prvUartLogCtl).pTmpLogBuf).UARTLogBuf));
331
332 ((*prvUartLogCtl).RevdNo < UART_LOG_HISTORY_LEN) ?
333 ((*prvUartLogCtl).RevdNo++) : ((*prvUartLogCtl).RevdNo = UART_LOG_HISTORY_LEN);
334
335 (*prvUartLogCtl).SeeIdx = (*prvUartLogCtl).NewIdx;
336 ((*prvUartLogCtl).NewIdx < (UART_LOG_HISTORY_LEN-1)) ?
337 ((*prvUartLogCtl).NewIdx++) : ((*prvUartLogCtl).NewIdx = 0);
338
339
340 #endif
341
342 }
343 }
344 else if ((RevData == KB_ASCII_BS) || (RevData == KB_ASCII_BS_7F)){
345 RTNSTS = 1;
346
347 if ((*(*prvUartLogCtl).pTmpLogBuf).BufCount > 0){
348 (*(*prvUartLogCtl).pTmpLogBuf).BufCount--;
349
350 shell_show_backspace(1,1,(VOID *)pfEcho);
351 }
352 }
353 else if (RevData == KB_ASCII_TAB){ //the TAB is fixed to be one space(' ')
354 RTNSTS = 1;
355 for(SpaceCount=0; SpaceCount< KB_SPACENO_TAB; SpaceCount++){
356 (*(*prvUartLogCtl).pTmpLogBuf).UARTLogBuf[(*(*prvUartLogCtl).pTmpLogBuf).BufCount] = ' ';
357 (*(*prvUartLogCtl).pTmpLogBuf).BufCount++;
358 }
359
360 if (EchoFlag){
361 pfEcho((u8 *)" ");
362 }
363
364 }
365 else{
366 RTNSTS = 1;
367 if (EchoFlag){
368 pfEcho((u8*)"%c",RevData);
369 }
370
371 (*(*prvUartLogCtl).pTmpLogBuf).UARTLogBuf[(*(*prvUartLogCtl).pTmpLogBuf).BufCount] = RevData;
372 (*(*prvUartLogCtl).pTmpLogBuf).BufCount++;
373 }
374 }
375 else if ((*(*prvUartLogCtl).pTmpLogBuf).BufCount==(UART_LOG_CMD_BUFLEN-1)){
376 RTNSTS = 1;
377
378 pfEcho((u8*)"\n\r <<<Too long cmd string.>>> \n");
379 (*(*prvUartLogCtl).pTmpLogBuf).UARTLogBuf[(*(*prvUartLogCtl).pTmpLogBuf).BufCount] = '\0';
380 pfEcho(&(*(*prvUartLogCtl).pTmpLogBuf).UARTLogBuf[0]);
381 }
382
383 return RTNSTS;
384 }
385
386
387 //======================================================
388 //<Function>: shell_uart_irq_rom
389 //<Usage >: To deal with Uart-Log RX IRQ
390 //<Argus >: VOID
391 //<Return >: VOID
392 //<Notes >: NA
393 //======================================================
394 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_uart_irq_rom(VOID * Data)395 VOID shell_uart_irq_rom(VOID * Data)
396 {
397 krhino_intrpt_enter();
398 /* To avoid gcc warnings */
399 ( void ) Data;
400
401 u8 UartReceiveData = 0;
402 //For Test
403 BOOL PullMode = _FALSE;
404 u32 IrqEn = LOGUART_GetIMR();
405
406 LOGUART_SetIMR(0);
407
408 recv_again:
409 UartReceiveData = LOGUART_GetChar(PullMode);
410
411 extern int g_uart_init;
412 if(g_uart_init != 0)
413 {
414 extern size_t uart0_rx_buffer_produce(const void *buf, size_t count);
415 (void)uart0_rx_buffer_produce(&UartReceiveData, 1);
416 }
417
418 //KB_ESC chk is for cmd history, it's a special case here.
419 if (UartReceiveData == KB_ASCII_ESC) {
420 //4 Esc detection is only valid in the first stage of boot sequence (few seconds)
421 if (shell_ctl.ExecuteEsc != _TRUE) {
422 shell_ctl.ExecuteEsc = _TRUE;
423 shell_ctl.EscSTS = 0;
424 } else {
425 //4 the input commands are valid only when the task is ready to execute commands
426 if ((shell_ctl.BootRdy == 1) ||(shell_ctl.shell_task_rdy == 1)) {
427 if (shell_ctl.EscSTS==0) {
428 shell_ctl.EscSTS = 1;
429 }
430 } else {
431 shell_ctl.EscSTS = 0;
432 }
433 }
434 } else if (shell_ctl.EscSTS==1) {
435 if (UartReceiveData != KB_ASCII_LBRKT){
436 shell_ctl.EscSTS = 0;
437 } else {
438 shell_ctl.EscSTS = 2;
439 }
440 } else {
441 if (shell_ctl.EscSTS==2){
442 shell_ctl.EscSTS = 0;
443 #ifdef CONFIG_UART_LOG_HISTORY
444 if ((UartReceiveData=='A')|| UartReceiveData=='B'){
445 shell_cmd_history(UartReceiveData,(UART_LOG_CTL *)&shell_ctl,1);
446 }
447 #endif
448 } else{
449 }
450 }
451
452 /* recv all data one time */
453 if (shell_recv_all_data_onetime == 1) {
454 if (LOGUART_Readable())
455 goto recv_again;
456 }
457
458 LOGUART_SetIMR(IrqEn);
459 krhino_intrpt_exit();
460 }
461
462
463 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_init_rom(u32 TBLSz,VOID * pTBL)464 VOID shell_init_rom(u32 TBLSz, VOID *pTBL)
465 {
466 shell_buf.BufCount = 0;
467 shell_array_init(&shell_buf.UARTLogBuf[0],UART_LOG_CMD_BUFLEN,'\0');
468
469 shell_ctl.NewIdx = 0;
470 shell_ctl.SeeIdx = 0;
471 shell_ctl.RevdNo = 0;
472 shell_ctl.EscSTS = 0;
473 shell_ctl.BootRdy = 0;
474 shell_ctl.pTmpLogBuf = &shell_buf;
475 #ifdef CONFIG_UART_LOG_HISTORY
476 shell_ctl.CRSTS = 0;
477 shell_ctl.pHistoryBuf = &shell_history_cmd[0];
478 #endif
479 shell_ctl.pfINPUT = (VOID *)&DiagPrintf;
480
481 if (TBLSz != 0) {
482 shell_ctl.pCmdTbl = (PCOMMAND_TABLE) pTBL;
483 shell_ctl.CmdTblSz = TBLSz;
484 } else {
485 void *PTable = NULL;
486 u32 TblSize = cmd_rom_table(&PTable);
487
488 shell_ctl.pCmdTbl = (PCOMMAND_TABLE) PTable;
489 shell_ctl.CmdTblSz = TblSize;
490 }
491 shell_ctl.shell_task_rdy = 0;
492
493 //executing boot sequence
494 shell_ctl.ExecuteCmd = _FALSE;
495 shell_ctl.ExecuteEsc = _FALSE;
496
497 CONSOLE_AMEBA();
498 }
499
500 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_task_rom(VOID * Data)501 VOID shell_task_rom(VOID *Data)
502 {
503 /* To avoid gcc warnings */
504 ( void ) Data;
505
506 //4 Set this for UartLog check cmd history
507 #ifndef CONFIG_KERNEL
508 shell_ctl.BootRdy = 1;
509 #endif
510 do{
511
512 if ((shell_ctl.ExecuteCmd) == _TRUE) {
513 shell_cmd_exec_rom((PUART_LOG_CTL)&shell_ctl);
514 CONSOLE_AMEBA();
515 shell_ctl.ExecuteCmd = _FALSE;
516 }
517 }while(1);
518 }
519
520 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_exit(u32 MaxWaitCount)521 static BOOLEAN shell_exit(u32 MaxWaitCount)
522 {
523 u32 WaitCount = 0;
524
525 do{
526 if (WaitCount > MaxWaitCount)
527 {
528 return _TRUE;// go back to the normal boot sequence
529 }
530
531 DelayUs(100);
532
533 // DBG_8195A("Wait %d\n",WaitCount);
534 WaitCount++;
535
536 //4 there is a ESC key input in Boot Sequence check stage
537 if (shell_ctl.ExecuteEsc == _TRUE)
538 {
539 CONSOLE_AMEBA();
540
541 shell_ctl.EscSTS = 0;
542
543 break;
544 }
545 }while(1);
546
547 return _FALSE;
548
549 }
550
551
552 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_rom(u32 MaxWaitCount)553 VOID shell_rom(u32 MaxWaitCount)
554 {
555
556 if (shell_exit(MaxWaitCount)) {
557 //Go back to normal boot sequence
558 return;
559 }
560
561 /* rom cmd consol need this */
562 LOG_MASK(LEVEL_ERROR, 0xFFFFFFFF);
563
564 shell_ctl.BootRdy = 1;
565
566 //4 Stay in console stage
567 do{
568 if ((shell_ctl.ExecuteCmd) == _TRUE) {
569 shell_cmd_exec_rom((PUART_LOG_CTL)&shell_ctl);
570 CONSOLE_AMEBA();
571 shell_ctl.ExecuteCmd = _FALSE;
572 }
573 }while(1);
574 }
575
576