1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2006-04-30 Bernard the first version for FinSH 9 * 2006-05-08 Bernard change finsh thread stack to 2048 10 * 2006-06-03 Bernard add support for skyeye 11 * 2006-09-24 Bernard remove the code related with hardware 12 * 2010-01-18 Bernard fix down then up key bug. 13 * 2010-03-19 Bernard fix backspace issue and fix device read in shell. 14 * 2010-04-01 Bernard add prompt output when start and remove the empty history 15 * 2011-02-23 Bernard fix variable section end issue of finsh shell 16 * initialization when use GNU GCC compiler. 17 * 2016-11-26 armink add password authentication 18 * 2018-07-02 aozima add custome prompt support. 19 */ 20 21 #include <rthw.h> 22 23 #ifdef RT_USING_FINSH 24 25 #include "finsh.h" 26 #include "shell.h" 27 28 #ifdef FINSH_USING_MSH 29 #include "msh.h" 30 #endif 31 32 #ifdef _WIN32 33 #include <stdio.h> /* for putchar */ 34 #endif 35 36 /* finsh thread */ 37 #ifndef RT_USING_HEAP 38 static struct rt_thread finsh_thread; 39 ALIGN(RT_ALIGN_SIZE) 40 static char finsh_thread_stack[FINSH_THREAD_STACK_SIZE]; 41 struct finsh_shell _shell; 42 #endif 43 44 struct finsh_shell *shell; 45 static char *finsh_prompt_custom = RT_NULL; 46 47 #ifdef RT_USING_HEAP 48 int finsh_set_prompt(const char * prompt) 49 { 50 if(finsh_prompt_custom) 51 { 52 rt_free(finsh_prompt_custom); 53 finsh_prompt_custom = RT_NULL; 54 } 55 56 /* strdup */ 57 if(prompt) 58 { 59 finsh_prompt_custom = rt_malloc(strlen(prompt)+1); 60 if(finsh_prompt_custom) 61 { 62 strcpy(finsh_prompt_custom, prompt); 63 } 64 } 65 66 return 0; 67 } 68 #endif /* RT_USING_HEAP */ 69 70 #if defined(RT_USING_DFS) 71 #include <dfs_posix.h> 72 #endif /* RT_USING_DFS */ 73 74 const char *finsh_get_prompt() 75 { 76 #define _MSH_PROMPT "msh " 77 #define _PROMPT "finsh " 78 static char finsh_prompt[RT_CONSOLEBUF_SIZE + 1] = {0}; 79 80 /* check prompt mode */ 81 if (!shell->prompt_mode) 82 { 83 finsh_prompt[0] = '\0'; 84 return finsh_prompt; 85 } 86 87 if(finsh_prompt_custom) 88 { 89 strncpy(finsh_prompt, finsh_prompt_custom, sizeof(finsh_prompt)-1); 90 return finsh_prompt; 91 } 92 93 #ifdef FINSH_USING_MSH 94 if (msh_is_used()) strcpy(finsh_prompt, _MSH_PROMPT); 95 else 96 #endif 97 strcpy(finsh_prompt, _PROMPT); 98 99 #if defined(RT_USING_DFS) && defined(DFS_USING_WORKDIR) 100 /* get current working directory */ 101 getcwd(&finsh_prompt[rt_strlen(finsh_prompt)], RT_CONSOLEBUF_SIZE - rt_strlen(finsh_prompt)); 102 #endif 103 104 strcat(finsh_prompt, ">"); 105 106 return finsh_prompt; 107 } 108 109 /** 110 * @ingroup finsh 111 * 112 * This function get the prompt mode of finsh shell. 113 * 114 * @return prompt the prompt mode, 0 disable prompt mode, other values enable prompt mode. 115 */ 116 rt_uint32_t finsh_get_prompt_mode(void) 117 { 118 RT_ASSERT(shell != RT_NULL); 119 return shell->prompt_mode; 120 } 121 122 /** 123 * @ingroup finsh 124 * 125 * This function set the prompt mode of finsh shell. 126 * 127 * The parameter 0 disable prompt mode, other values enable prompt mode. 128 * 129 * @param prompt the prompt mode 130 */ 131 void finsh_set_prompt_mode(rt_uint32_t prompt_mode) 132 { 133 RT_ASSERT(shell != RT_NULL); 134 shell->prompt_mode = prompt_mode; 135 } 136 137 static char finsh_getchar(void) 138 { 139 #ifdef RT_USING_POSIX 140 return getchar(); 141 #else 142 char ch; 143 144 RT_ASSERT(shell != RT_NULL); 145 while (rt_device_read(shell->device, -1, &ch, 1) != 1) 146 rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER); 147 148 return ch; 149 #endif 150 } 151 152 #ifndef RT_USING_POSIX 153 static rt_err_t finsh_rx_ind(rt_device_t dev, rt_size_t size) 154 { 155 RT_ASSERT(shell != RT_NULL); 156 157 /* release semaphore to let finsh thread rx data */ 158 rt_sem_release(&shell->rx_sem); 159 160 return RT_EOK; 161 } 162 163 /** 164 * @ingroup finsh 165 * 166 * This function sets the input device of finsh shell. 167 * 168 * @param device_name the name of new input device. 169 */ 170 void finsh_set_device(const char *device_name) 171 { 172 rt_device_t dev = RT_NULL; 173 174 RT_ASSERT(shell != RT_NULL); 175 dev = rt_device_find(device_name); 176 if (dev == RT_NULL) 177 { 178 rt_kprintf("finsh: can not find device: %s\n", device_name); 179 return; 180 } 181 182 /* check whether it's a same device */ 183 if (dev == shell->device) return; 184 /* open this device and set the new device in finsh shell */ 185 if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | \ 186 RT_DEVICE_FLAG_STREAM) == RT_EOK) 187 { 188 if (shell->device != RT_NULL) 189 { 190 /* close old finsh device */ 191 rt_device_close(shell->device); 192 rt_device_set_rx_indicate(shell->device, RT_NULL); 193 } 194 195 /* clear line buffer before switch to new device */ 196 memset(shell->line, 0, sizeof(shell->line)); 197 shell->line_curpos = shell->line_position = 0; 198 199 shell->device = dev; 200 rt_device_set_rx_indicate(dev, finsh_rx_ind); 201 } 202 } 203 204 /** 205 * @ingroup finsh 206 * 207 * This function returns current finsh shell input device. 208 * 209 * @return the finsh shell input device name is returned. 210 */ 211 const char *finsh_get_device() 212 { 213 RT_ASSERT(shell != RT_NULL); 214 return shell->device->parent.name; 215 } 216 #endif 217 218 /** 219 * @ingroup finsh 220 * 221 * This function set the echo mode of finsh shell. 222 * 223 * FINSH_OPTION_ECHO=0x01 is echo mode, other values are none-echo mode. 224 * 225 * @param echo the echo mode 226 */ 227 void finsh_set_echo(rt_uint32_t echo) 228 { 229 RT_ASSERT(shell != RT_NULL); 230 shell->echo_mode = (rt_uint8_t)echo; 231 } 232 233 /** 234 * @ingroup finsh 235 * 236 * This function gets the echo mode of finsh shell. 237 * 238 * @return the echo mode 239 */ 240 rt_uint32_t finsh_get_echo() 241 { 242 RT_ASSERT(shell != RT_NULL); 243 244 return shell->echo_mode; 245 } 246 247 #ifdef FINSH_USING_AUTH 248 /** 249 * set a new password for finsh 250 * 251 * @param password new password 252 * 253 * @return result, RT_EOK on OK, -RT_ERROR on the new password length is less than 254 * FINSH_PASSWORD_MIN or greater than FINSH_PASSWORD_MAX 255 */ 256 rt_err_t finsh_set_password(const char *password) { 257 rt_ubase_t level; 258 rt_size_t pw_len = rt_strlen(password); 259 260 if (pw_len < FINSH_PASSWORD_MIN || pw_len > FINSH_PASSWORD_MAX) 261 return -RT_ERROR; 262 263 level = rt_hw_interrupt_disable(); 264 rt_strncpy(shell->password, password, FINSH_PASSWORD_MAX); 265 rt_hw_interrupt_enable(level); 266 267 return RT_EOK; 268 } 269 270 /** 271 * get the finsh password 272 * 273 * @return password 274 */ 275 const char *finsh_get_password(void) 276 { 277 return shell->password; 278 } 279 280 static void finsh_wait_auth(void) 281 { 282 char ch; 283 rt_bool_t input_finish = RT_FALSE; 284 char password[FINSH_PASSWORD_MAX] = { 0 }; 285 rt_size_t cur_pos = 0; 286 /* password not set */ 287 if (rt_strlen(finsh_get_password()) == 0) return; 288 289 while (1) 290 { 291 rt_kprintf("Password for login: "); 292 while (!input_finish) 293 { 294 while (1) 295 { 296 /* read one character from device */ 297 ch = finsh_getchar(); 298 299 if (ch >= ' ' && ch <= '~' && cur_pos < FINSH_PASSWORD_MAX) 300 { 301 /* change the printable characters to '*' */ 302 rt_kprintf("*"); 303 password[cur_pos++] = ch; 304 } 305 else if (ch == '\b' && cur_pos > 0) 306 { 307 /* backspace */ 308 password[cur_pos] = '\0'; 309 cur_pos--; 310 rt_kprintf("\b \b"); 311 } 312 else if (ch == '\r' || ch == '\n') 313 { 314 rt_kprintf("\n"); 315 input_finish = RT_TRUE; 316 break; 317 } 318 } 319 } 320 if (!rt_strncmp(shell->password, password, FINSH_PASSWORD_MAX)) return; 321 else 322 { 323 /* authentication failed, delay 2S for retry */ 324 rt_thread_delay(2 * RT_TICK_PER_SECOND); 325 rt_kprintf("Sorry, try again.\n"); 326 cur_pos = 0; 327 input_finish = RT_FALSE; 328 rt_memset(password, '\0', FINSH_PASSWORD_MAX); 329 } 330 } 331 } 332 #endif /* FINSH_USING_AUTH */ 333 334 static void shell_auto_complete(char *prefix) 335 { 336 337 rt_kprintf("\n"); 338 #ifdef FINSH_USING_MSH 339 if (msh_is_used() == RT_TRUE) 340 { 341 msh_auto_complete(prefix); 342 } 343 else 344 #endif 345 { 346 #ifndef FINSH_USING_MSH_ONLY 347 extern void list_prefix(char * prefix); 348 list_prefix(prefix); 349 #endif 350 } 351 352 rt_kprintf("%s%s", FINSH_PROMPT, prefix); 353 } 354 355 #ifndef FINSH_USING_MSH_ONLY 356 void finsh_run_line(struct finsh_parser *parser, const char *line) 357 { 358 const char *err_str; 359 360 if(shell->echo_mode) 361 rt_kprintf("\n"); 362 finsh_parser_run(parser, (unsigned char *)line); 363 364 /* compile node root */ 365 if (finsh_errno() == 0) 366 { 367 finsh_compiler_run(parser->root); 368 } 369 else 370 { 371 err_str = finsh_error_string(finsh_errno()); 372 rt_kprintf("%s\n", err_str); 373 } 374 375 /* run virtual machine */ 376 if (finsh_errno() == 0) 377 { 378 char ch; 379 finsh_vm_run(); 380 381 ch = (unsigned char)finsh_stack_bottom(); 382 if (ch > 0x20 && ch < 0x7e) 383 { 384 rt_kprintf("\t'%c', %d, 0x%08x\n", 385 (unsigned char)finsh_stack_bottom(), 386 (unsigned int)finsh_stack_bottom(), 387 (unsigned int)finsh_stack_bottom()); 388 } 389 else 390 { 391 rt_kprintf("\t%d, 0x%08x\n", 392 (unsigned int)finsh_stack_bottom(), 393 (unsigned int)finsh_stack_bottom()); 394 } 395 } 396 397 finsh_flush(parser); 398 } 399 #endif 400 401 #ifdef FINSH_USING_HISTORY 402 static rt_bool_t shell_handle_history(struct finsh_shell *shell) 403 { 404 #if defined(_WIN32) 405 int i; 406 rt_kprintf("\r"); 407 408 for (i = 0; i <= 60; i++) 409 putchar(' '); 410 rt_kprintf("\r"); 411 412 #else 413 rt_kprintf("\033[2K\r"); 414 #endif 415 rt_kprintf("%s%s", FINSH_PROMPT, shell->line); 416 return RT_FALSE; 417 } 418 419 static void shell_push_history(struct finsh_shell *shell) 420 { 421 if (shell->line_position != 0) 422 { 423 /* push history */ 424 if (shell->history_count >= FINSH_HISTORY_LINES) 425 { 426 /* if current cmd is same as last cmd, don't push */ 427 if (memcmp(&shell->cmd_history[FINSH_HISTORY_LINES - 1], shell->line, FINSH_CMD_SIZE)) 428 { 429 /* move history */ 430 int index; 431 for (index = 0; index < FINSH_HISTORY_LINES - 1; index ++) 432 { 433 memcpy(&shell->cmd_history[index][0], 434 &shell->cmd_history[index + 1][0], FINSH_CMD_SIZE); 435 } 436 memset(&shell->cmd_history[index][0], 0, FINSH_CMD_SIZE); 437 memcpy(&shell->cmd_history[index][0], shell->line, shell->line_position); 438 439 /* it's the maximum history */ 440 shell->history_count = FINSH_HISTORY_LINES; 441 } 442 } 443 else 444 { 445 /* if current cmd is same as last cmd, don't push */ 446 if (shell->history_count == 0 || memcmp(&shell->cmd_history[shell->history_count - 1], shell->line, FINSH_CMD_SIZE)) 447 { 448 shell->current_history = shell->history_count; 449 memset(&shell->cmd_history[shell->history_count][0], 0, FINSH_CMD_SIZE); 450 memcpy(&shell->cmd_history[shell->history_count][0], shell->line, shell->line_position); 451 452 /* increase count and set current history position */ 453 shell->history_count ++; 454 } 455 } 456 } 457 shell->current_history = shell->history_count; 458 } 459 #endif 460 461 void finsh_thread_entry(void *parameter) 462 { 463 char ch; 464 465 /* normal is echo mode */ 466 #ifndef FINSH_ECHO_DISABLE_DEFAULT 467 shell->echo_mode = 1; 468 #else 469 shell->echo_mode = 0; 470 #endif 471 472 #ifndef FINSH_USING_MSH_ONLY 473 finsh_init(&shell->parser); 474 #endif 475 476 #ifndef RT_USING_POSIX 477 /* set console device as shell device */ 478 if (shell->device == RT_NULL) 479 { 480 rt_device_t console = rt_console_get_device(); 481 if (console) 482 { 483 finsh_set_device(console->parent.name); 484 } 485 } 486 #endif 487 488 #ifdef FINSH_USING_AUTH 489 /* set the default password when the password isn't setting */ 490 if (rt_strlen(finsh_get_password()) == 0) 491 { 492 if (finsh_set_password(FINSH_DEFAULT_PASSWORD) != RT_EOK) 493 { 494 rt_kprintf("Finsh password set failed.\n"); 495 } 496 } 497 /* waiting authenticate success */ 498 finsh_wait_auth(); 499 #endif 500 501 rt_kprintf(FINSH_PROMPT); 502 503 while (1) 504 { 505 ch = finsh_getchar(); 506 507 /* 508 * handle control key 509 * up key : 0x1b 0x5b 0x41 510 * down key: 0x1b 0x5b 0x42 511 * right key:0x1b 0x5b 0x43 512 * left key: 0x1b 0x5b 0x44 513 */ 514 if (ch == 0x1b) 515 { 516 shell->stat = WAIT_SPEC_KEY; 517 continue; 518 } 519 else if (shell->stat == WAIT_SPEC_KEY) 520 { 521 if (ch == 0x5b) 522 { 523 shell->stat = WAIT_FUNC_KEY; 524 continue; 525 } 526 527 shell->stat = WAIT_NORMAL; 528 } 529 else if (shell->stat == WAIT_FUNC_KEY) 530 { 531 shell->stat = WAIT_NORMAL; 532 533 if (ch == 0x41) /* up key */ 534 { 535 #ifdef FINSH_USING_HISTORY 536 /* prev history */ 537 if (shell->current_history > 0) 538 shell->current_history --; 539 else 540 { 541 shell->current_history = 0; 542 continue; 543 } 544 545 /* copy the history command */ 546 memcpy(shell->line, &shell->cmd_history[shell->current_history][0], 547 FINSH_CMD_SIZE); 548 shell->line_curpos = shell->line_position = strlen(shell->line); 549 shell_handle_history(shell); 550 #endif 551 continue; 552 } 553 else if (ch == 0x42) /* down key */ 554 { 555 #ifdef FINSH_USING_HISTORY 556 /* next history */ 557 if (shell->current_history < shell->history_count - 1) 558 shell->current_history ++; 559 else 560 { 561 /* set to the end of history */ 562 if (shell->history_count != 0) 563 shell->current_history = shell->history_count - 1; 564 else 565 continue; 566 } 567 568 memcpy(shell->line, &shell->cmd_history[shell->current_history][0], 569 FINSH_CMD_SIZE); 570 shell->line_curpos = shell->line_position = strlen(shell->line); 571 shell_handle_history(shell); 572 #endif 573 continue; 574 } 575 else if (ch == 0x44) /* left key */ 576 { 577 if (shell->line_curpos) 578 { 579 rt_kprintf("\b"); 580 shell->line_curpos --; 581 } 582 583 continue; 584 } 585 else if (ch == 0x43) /* right key */ 586 { 587 if (shell->line_curpos < shell->line_position) 588 { 589 rt_kprintf("%c", shell->line[shell->line_curpos]); 590 shell->line_curpos ++; 591 } 592 593 continue; 594 } 595 } 596 597 /* received null or error */ 598 if (ch == '\0' || ch == 0xFF) continue; 599 /* handle tab key */ 600 else if (ch == '\t') 601 { 602 int i; 603 /* move the cursor to the beginning of line */ 604 for (i = 0; i < shell->line_curpos; i++) 605 rt_kprintf("\b"); 606 607 /* auto complete */ 608 shell_auto_complete(&shell->line[0]); 609 /* re-calculate position */ 610 shell->line_curpos = shell->line_position = strlen(shell->line); 611 612 continue; 613 } 614 /* handle backspace key */ 615 else if (ch == 0x7f || ch == 0x08) 616 { 617 /* note that shell->line_curpos >= 0 */ 618 if (shell->line_curpos == 0) 619 continue; 620 621 shell->line_position--; 622 shell->line_curpos--; 623 624 if (shell->line_position > shell->line_curpos) 625 { 626 int i; 627 628 rt_memmove(&shell->line[shell->line_curpos], 629 &shell->line[shell->line_curpos + 1], 630 shell->line_position - shell->line_curpos); 631 shell->line[shell->line_position] = 0; 632 633 rt_kprintf("\b%s \b", &shell->line[shell->line_curpos]); 634 635 /* move the cursor to the origin position */ 636 for (i = shell->line_curpos; i <= shell->line_position; i++) 637 rt_kprintf("\b"); 638 } 639 else 640 { 641 rt_kprintf("\b \b"); 642 shell->line[shell->line_position] = 0; 643 } 644 645 continue; 646 } 647 648 /* handle end of line, break */ 649 if (ch == '\r' || ch == '\n') 650 { 651 #ifdef FINSH_USING_HISTORY 652 shell_push_history(shell); 653 #endif 654 655 #ifdef FINSH_USING_MSH 656 if (msh_is_used() == RT_TRUE) 657 { 658 if (shell->echo_mode) 659 rt_kprintf("\n"); 660 msh_exec(shell->line, shell->line_position); 661 } 662 else 663 #endif 664 { 665 #ifndef FINSH_USING_MSH_ONLY 666 /* add ';' and run the command line */ 667 shell->line[shell->line_position] = ';'; 668 669 if (shell->line_position != 0) finsh_run_line(&shell->parser, shell->line); 670 else 671 if (shell->echo_mode) rt_kprintf("\n"); 672 #endif 673 } 674 675 rt_kprintf(FINSH_PROMPT); 676 memset(shell->line, 0, sizeof(shell->line)); 677 shell->line_curpos = shell->line_position = 0; 678 continue; 679 } 680 681 /* it's a large line, discard it */ 682 if (shell->line_position >= FINSH_CMD_SIZE) 683 shell->line_position = 0; 684 685 /* normal character */ 686 if (shell->line_curpos < shell->line_position) 687 { 688 int i; 689 690 rt_memmove(&shell->line[shell->line_curpos + 1], 691 &shell->line[shell->line_curpos], 692 shell->line_position - shell->line_curpos); 693 shell->line[shell->line_curpos] = ch; 694 if (shell->echo_mode) 695 rt_kprintf("%s", &shell->line[shell->line_curpos]); 696 697 /* move the cursor to new position */ 698 for (i = shell->line_curpos; i < shell->line_position; i++) 699 rt_kprintf("\b"); 700 } 701 else 702 { 703 shell->line[shell->line_position] = ch; 704 if (shell->echo_mode) 705 rt_kprintf("%c", ch); 706 } 707 708 ch = 0; 709 shell->line_position ++; 710 shell->line_curpos++; 711 if (shell->line_position >= FINSH_CMD_SIZE) 712 { 713 /* clear command line */ 714 shell->line_position = 0; 715 shell->line_curpos = 0; 716 } 717 } /* end of device read */ 718 } 719 720 void finsh_system_function_init(const void *begin, const void *end) 721 { 722 _syscall_table_begin = (struct finsh_syscall *) begin; 723 _syscall_table_end = (struct finsh_syscall *) end; 724 } 725 726 void finsh_system_var_init(const void *begin, const void *end) 727 { 728 _sysvar_table_begin = (struct finsh_sysvar *) begin; 729 _sysvar_table_end = (struct finsh_sysvar *) end; 730 } 731 732 #if defined(__ICCARM__) || defined(__ICCRX__) /* for IAR compiler */ 733 #ifdef FINSH_USING_SYMTAB 734 #pragma section="FSymTab" 735 #pragma section="VSymTab" 736 #endif 737 #elif defined(__ADSPBLACKFIN__) /* for VisaulDSP++ Compiler*/ 738 #ifdef FINSH_USING_SYMTAB 739 extern "asm" int __fsymtab_start; 740 extern "asm" int __fsymtab_end; 741 extern "asm" int __vsymtab_start; 742 extern "asm" int __vsymtab_end; 743 #endif 744 #elif defined(_MSC_VER) 745 #pragma section("FSymTab$a", read) 746 const char __fsym_begin_name[] = "__start"; 747 const char __fsym_begin_desc[] = "begin of finsh"; 748 __declspec(allocate("FSymTab$a")) const struct finsh_syscall __fsym_begin = 749 { 750 __fsym_begin_name, 751 __fsym_begin_desc, 752 NULL 753 }; 754 755 #pragma section("FSymTab$z", read) 756 const char __fsym_end_name[] = "__end"; 757 const char __fsym_end_desc[] = "end of finsh"; 758 __declspec(allocate("FSymTab$z")) const struct finsh_syscall __fsym_end = 759 { 760 __fsym_end_name, 761 __fsym_end_desc, 762 NULL 763 }; 764 #endif 765 766 /* 767 * @ingroup finsh 768 * 769 * This function will initialize finsh shell 770 */ 771 int finsh_system_init(void) 772 { 773 rt_err_t result = RT_EOK; 774 rt_thread_t tid; 775 776 #ifdef FINSH_USING_SYMTAB 777 #if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM C Compiler */ 778 extern const int FSymTab$$Base; 779 extern const int FSymTab$$Limit; 780 extern const int VSymTab$$Base; 781 extern const int VSymTab$$Limit; 782 finsh_system_function_init(&FSymTab$$Base, &FSymTab$$Limit); 783 #ifndef FINSH_USING_MSH_ONLY 784 finsh_system_var_init(&VSymTab$$Base, &VSymTab$$Limit); 785 #endif 786 #elif defined (__ICCARM__) || defined(__ICCRX__) /* for IAR Compiler */ 787 finsh_system_function_init(__section_begin("FSymTab"), 788 __section_end("FSymTab")); 789 finsh_system_var_init(__section_begin("VSymTab"), 790 __section_end("VSymTab")); 791 #elif defined (__GNUC__) || defined(__TI_COMPILER_VERSION__) 792 /* GNU GCC Compiler and TI CCS */ 793 extern const int __fsymtab_start; 794 extern const int __fsymtab_end; 795 extern const int __vsymtab_start; 796 extern const int __vsymtab_end; 797 finsh_system_function_init(&__fsymtab_start, &__fsymtab_end); 798 finsh_system_var_init(&__vsymtab_start, &__vsymtab_end); 799 #elif defined(__ADSPBLACKFIN__) /* for VisualDSP++ Compiler */ 800 finsh_system_function_init(&__fsymtab_start, &__fsymtab_end); 801 finsh_system_var_init(&__vsymtab_start, &__vsymtab_end); 802 #elif defined(_MSC_VER) 803 unsigned int *ptr_begin, *ptr_end; 804 805 if(shell) 806 { 807 rt_kprintf("finsh shell already init.\n"); 808 return RT_EOK; 809 } 810 811 ptr_begin = (unsigned int *)&__fsym_begin; 812 ptr_begin += (sizeof(struct finsh_syscall) / sizeof(unsigned int)); 813 while (*ptr_begin == 0) ptr_begin ++; 814 815 ptr_end = (unsigned int *) &__fsym_end; 816 ptr_end --; 817 while (*ptr_end == 0) ptr_end --; 818 819 finsh_system_function_init(ptr_begin, ptr_end); 820 #endif 821 #endif 822 823 #ifdef RT_USING_HEAP 824 /* create or set shell structure */ 825 shell = (struct finsh_shell *)rt_calloc(1, sizeof(struct finsh_shell)); 826 if (shell == RT_NULL) 827 { 828 rt_kprintf("no memory for shell\n"); 829 return -1; 830 } 831 tid = rt_thread_create(FINSH_THREAD_NAME, 832 finsh_thread_entry, RT_NULL, 833 FINSH_THREAD_STACK_SIZE, FINSH_THREAD_PRIORITY, 10); 834 #else 835 shell = &_shell; 836 tid = &finsh_thread; 837 result = rt_thread_init(&finsh_thread, 838 FINSH_THREAD_NAME, 839 finsh_thread_entry, RT_NULL, 840 &finsh_thread_stack[0], sizeof(finsh_thread_stack), 841 FINSH_THREAD_PRIORITY, 10); 842 #endif /* RT_USING_HEAP */ 843 844 rt_sem_init(&(shell->rx_sem), "shrx", 0, 0); 845 finsh_set_prompt_mode(1); 846 847 if (tid != NULL && result == RT_EOK) 848 rt_thread_startup(tid); 849 return 0; 850 } 851 INIT_APP_EXPORT(finsh_system_init); 852 853 #endif /* RT_USING_FINSH */ 854 855