1 2 /* 3 * Copyright (c) 2006-2018, RT-Thread Development Team 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 * 7 * Change Logs: 8 * Date Author Notes 9 * 2006-04-30 Bernard first implementation 10 * 2006-05-04 Bernard add list_thread, 11 * list_sem, 12 * list_timer 13 * 2006-05-20 Bernard add list_mutex, 14 * list_mailbox, 15 * list_msgqueue, 16 * list_event, 17 * list_fevent, 18 * list_mempool 19 * 2006-06-03 Bernard display stack information in list_thread 20 * 2006-08-10 Bernard change version to invoke rt_show_version 21 * 2008-09-10 Bernard update the list function for finsh syscall 22 * list and sysvar list 23 * 2009-05-30 Bernard add list_device 24 * 2010-04-21 yi.qiu add list_module 25 * 2012-04-29 goprife improve the command line auto-complete feature. 26 * 2012-06-02 lgnq add list_memheap 27 * 2012-10-22 Bernard add MS VC++ patch. 28 * 2016-06-02 armink beautify the list_thread command 29 * 2018-11-22 Jesven list_thread add smp support 30 * 2018-12-27 Jesven Fix the problem that disable interrupt too long in list_thread 31 * Provide protection for the "first layer of objects" when list_* 32 */ 33 34 #include <rthw.h> 35 #include <rtthread.h> 36 37 #ifdef RT_USING_FINSH 38 39 #include "finsh.h" 40 41 #define LIST_FIND_OBJ_NR 8 42 43 long hello(void) 44 { 45 rt_kprintf("Hello RT-Thread!\n"); 46 47 return 0; 48 } 49 FINSH_FUNCTION_EXPORT(hello, say hello world); 50 51 extern void rt_show_version(void); 52 long version(void) 53 { 54 rt_show_version(); 55 56 return 0; 57 } 58 FINSH_FUNCTION_EXPORT(version, show RT-Thread version information); 59 MSH_CMD_EXPORT(version, show RT-Thread version information); 60 61 rt_inline void object_split(int len) 62 { 63 while (len--) rt_kprintf("-"); 64 } 65 66 typedef struct 67 { 68 rt_list_t *list; 69 rt_list_t **array; 70 rt_uint8_t type; 71 int nr; /* input: max nr, can't be 0 */ 72 int nr_out; /* out: got nr */ 73 } list_get_next_t; 74 75 static void list_find_init(list_get_next_t *p, rt_uint8_t type, rt_list_t **array, int nr) 76 { 77 struct rt_object_information *info; 78 rt_list_t *list; 79 80 info = rt_object_get_information((enum rt_object_class_type)type); 81 list = &info->object_list; 82 83 p->list = list; 84 p->type = type; 85 p->array = array; 86 p->nr = nr; 87 p->nr_out = 0; 88 } 89 90 static rt_list_t *list_get_next(rt_list_t *current, list_get_next_t *arg) 91 { 92 int first_flag = 0; 93 rt_ubase_t level; 94 rt_list_t *node, *list; 95 rt_list_t **array; 96 int nr; 97 98 arg->nr_out = 0; 99 100 if (!arg->nr || !arg->type) 101 { 102 return (rt_list_t *)RT_NULL; 103 } 104 105 list = arg->list; 106 107 if (!current) /* find first */ 108 { 109 node = list; 110 first_flag = 1; 111 } 112 else 113 { 114 node = current; 115 } 116 117 level = rt_hw_interrupt_disable(); 118 119 if (!first_flag) 120 { 121 struct rt_object *obj; 122 /* The node in the list? */ 123 obj = rt_list_entry(node, struct rt_object, list); 124 if ((obj->type & ~RT_Object_Class_Static) != arg->type) 125 { 126 rt_hw_interrupt_enable(level); 127 return (rt_list_t *)RT_NULL; 128 } 129 } 130 131 nr = 0; 132 array = arg->array; 133 while (1) 134 { 135 node = node->next; 136 137 if (node == list) 138 { 139 node = (rt_list_t *)RT_NULL; 140 break; 141 } 142 nr++; 143 *array++ = node; 144 if (nr == arg->nr) 145 { 146 break; 147 } 148 } 149 150 rt_hw_interrupt_enable(level); 151 arg->nr_out = nr; 152 return node; 153 } 154 155 long list_thread(void) 156 { 157 rt_ubase_t level; 158 list_get_next_t find_arg; 159 rt_list_t *obj_list[LIST_FIND_OBJ_NR]; 160 rt_list_t *next = (rt_list_t*)RT_NULL; 161 const char *item_title = "thread"; 162 int maxlen; 163 164 list_find_init(&find_arg, RT_Object_Class_Thread, obj_list, sizeof(obj_list)/sizeof(obj_list[0])); 165 166 maxlen = RT_NAME_MAX; 167 168 #ifdef RT_USING_SMP 169 rt_kprintf("%-*.s cpu pri status sp stack size max used left tick error\n", maxlen, item_title); object_split(maxlen); 170 rt_kprintf( " --- --- ------- ---------- ---------- ------ ---------- ---\n"); 171 #else 172 rt_kprintf("%-*.s pri status sp stack size max used left tick error\n", maxlen, item_title); object_split(maxlen); 173 rt_kprintf( " --- ------- ---------- ---------- ------ ---------- ---\n"); 174 #endif /*RT_USING_SMP*/ 175 176 do 177 { 178 next = list_get_next(next, &find_arg); 179 { 180 int i; 181 for (i = 0; i < find_arg.nr_out; i++) 182 { 183 struct rt_object *obj; 184 struct rt_thread thread_info, *thread; 185 186 obj = rt_list_entry(obj_list[i], struct rt_object, list); 187 level = rt_hw_interrupt_disable(); 188 189 if ((obj->type & ~RT_Object_Class_Static) != find_arg.type) 190 { 191 rt_hw_interrupt_enable(level); 192 continue; 193 } 194 /* copy info */ 195 memcpy(&thread_info, obj, sizeof thread_info); 196 rt_hw_interrupt_enable(level); 197 198 thread = (struct rt_thread*)obj; 199 { 200 rt_uint8_t stat; 201 rt_uint8_t *ptr; 202 203 #ifdef RT_USING_SMP 204 if (thread->oncpu != RT_CPU_DETACHED) 205 rt_kprintf("%-*.*s %3d %3d ", maxlen, RT_NAME_MAX, thread->name, thread->oncpu, thread->current_priority); 206 else 207 rt_kprintf("%-*.*s N/A %3d ", maxlen, RT_NAME_MAX, thread->name, thread->current_priority); 208 209 #else 210 rt_kprintf("%-*.*s %3d ", maxlen, RT_NAME_MAX, thread->name, thread->current_priority); 211 #endif /*RT_USING_SMP*/ 212 stat = (thread->stat & RT_THREAD_STAT_MASK); 213 if (stat == RT_THREAD_READY) rt_kprintf(" ready "); 214 else if (stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend"); 215 else if (stat == RT_THREAD_INIT) rt_kprintf(" init "); 216 else if (stat == RT_THREAD_CLOSE) rt_kprintf(" close "); 217 else if (stat == RT_THREAD_RUNNING) rt_kprintf(" running"); 218 219 #if defined(ARCH_CPU_STACK_GROWS_UPWARD) 220 ptr = (rt_uint8_t *)thread->stack_addr + thread->stack_size - 1; 221 while (*ptr == '#')ptr --; 222 223 rt_kprintf(" 0x%08x 0x%08x %02d%% 0x%08x %03d\n", 224 ((rt_ubase_t)thread->sp - (rt_ubase_t)thread->stack_addr), 225 thread->stack_size, 226 ((rt_ubase_t)ptr - (rt_ubase_t)thread->stack_addr) * 100 / thread->stack_size, 227 thread->remaining_tick, 228 thread->error); 229 #else 230 ptr = (rt_uint8_t *)thread->stack_addr; 231 while (*ptr == '#')ptr ++; 232 233 rt_kprintf(" 0x%08x 0x%08x %02d%% 0x%08x %03d\n", 234 thread->stack_size + ((rt_ubase_t)thread->stack_addr - (rt_ubase_t)thread->sp), 235 thread->stack_size, 236 (thread->stack_size - ((rt_ubase_t) ptr - (rt_ubase_t) thread->stack_addr)) * 100 237 / thread->stack_size, 238 thread->remaining_tick, 239 thread->error); 240 #endif 241 } 242 } 243 } 244 } 245 while (next != (rt_list_t*)RT_NULL); 246 247 return 0; 248 } 249 FINSH_FUNCTION_EXPORT(list_thread, list thread); 250 MSH_CMD_EXPORT(list_thread, list thread); 251 252 static void show_wait_queue(struct rt_list_node *list) 253 { 254 struct rt_thread *thread; 255 struct rt_list_node *node; 256 257 for (node = list->next; node != list; node = node->next) 258 { 259 thread = rt_list_entry(node, struct rt_thread, tlist); 260 rt_kprintf("%s", thread->name); 261 262 if (node->next != list) 263 rt_kprintf("/"); 264 } 265 } 266 267 #ifdef RT_USING_SEMAPHORE 268 long list_sem(void) 269 { 270 rt_ubase_t level; 271 list_get_next_t find_arg; 272 rt_list_t *obj_list[LIST_FIND_OBJ_NR]; 273 rt_list_t *next = (rt_list_t*)RT_NULL; 274 275 int maxlen; 276 const char *item_title = "semaphore"; 277 278 list_find_init(&find_arg, RT_Object_Class_Semaphore, obj_list, sizeof(obj_list)/sizeof(obj_list[0])); 279 280 maxlen = RT_NAME_MAX; 281 282 rt_kprintf("%-*.s v suspend thread\n", maxlen, item_title); object_split(maxlen); 283 rt_kprintf( " --- --------------\n"); 284 285 do 286 { 287 next = list_get_next(next, &find_arg); 288 { 289 int i; 290 for (i = 0; i < find_arg.nr_out; i++) 291 { 292 struct rt_object *obj; 293 struct rt_semaphore *sem; 294 295 obj = rt_list_entry(obj_list[i], struct rt_object, list); 296 level = rt_hw_interrupt_disable(); 297 if ((obj->type & ~RT_Object_Class_Static) != find_arg.type) 298 { 299 rt_hw_interrupt_enable(level); 300 continue; 301 } 302 rt_hw_interrupt_enable(level); 303 304 sem = (struct rt_semaphore*)obj; 305 if (!rt_list_isempty(&sem->parent.suspend_thread)) 306 { 307 rt_kprintf("%-*.*s %03d %d:", 308 maxlen, RT_NAME_MAX, 309 sem->parent.parent.name, 310 sem->value, 311 rt_list_len(&sem->parent.suspend_thread)); 312 show_wait_queue(&(sem->parent.suspend_thread)); 313 rt_kprintf("\n"); 314 } 315 else 316 { 317 rt_kprintf("%-*.*s %03d %d\n", 318 maxlen, RT_NAME_MAX, 319 sem->parent.parent.name, 320 sem->value, 321 rt_list_len(&sem->parent.suspend_thread)); 322 } 323 } 324 } 325 } 326 while (next != (rt_list_t*)RT_NULL); 327 328 return 0; 329 } 330 FINSH_FUNCTION_EXPORT(list_sem, list semaphore in system); 331 MSH_CMD_EXPORT(list_sem, list semaphore in system); 332 #endif 333 334 #ifdef RT_USING_EVENT 335 long list_event(void) 336 { 337 rt_ubase_t level; 338 list_get_next_t find_arg; 339 rt_list_t *obj_list[LIST_FIND_OBJ_NR]; 340 rt_list_t *next = (rt_list_t*)RT_NULL; 341 342 int maxlen; 343 const char *item_title = "event"; 344 345 list_find_init(&find_arg, RT_Object_Class_Event, obj_list, sizeof(obj_list)/sizeof(obj_list[0])); 346 347 maxlen = RT_NAME_MAX; 348 349 rt_kprintf("%-*.s set suspend thread\n", maxlen, item_title); object_split(maxlen); 350 rt_kprintf( " ---------- --------------\n"); 351 352 do 353 { 354 next = list_get_next(next, &find_arg); 355 { 356 int i; 357 for (i = 0; i < find_arg.nr_out; i++) 358 { 359 struct rt_object *obj; 360 struct rt_event *e; 361 362 obj = rt_list_entry(obj_list[i], struct rt_object, list); 363 level = rt_hw_interrupt_disable(); 364 if ((obj->type & ~RT_Object_Class_Static) != find_arg.type) 365 { 366 rt_hw_interrupt_enable(level); 367 continue; 368 } 369 370 rt_hw_interrupt_enable(level); 371 372 e = (struct rt_event *)obj; 373 if (!rt_list_isempty(&e->parent.suspend_thread)) 374 { 375 rt_kprintf("%-*.*s 0x%08x %03d:", 376 maxlen, RT_NAME_MAX, 377 e->parent.parent.name, 378 e->set, 379 rt_list_len(&e->parent.suspend_thread)); 380 show_wait_queue(&(e->parent.suspend_thread)); 381 rt_kprintf("\n"); 382 } 383 else 384 { 385 rt_kprintf("%-*.*s 0x%08x 0\n", 386 maxlen, RT_NAME_MAX, e->parent.parent.name, e->set); 387 } 388 } 389 } 390 } 391 while (next != (rt_list_t*)RT_NULL); 392 393 return 0; 394 } 395 FINSH_FUNCTION_EXPORT(list_event, list event in system); 396 MSH_CMD_EXPORT(list_event, list event in system); 397 #endif 398 399 #ifdef RT_USING_MUTEX 400 long list_mutex(void) 401 { 402 rt_ubase_t level; 403 list_get_next_t find_arg; 404 rt_list_t *obj_list[LIST_FIND_OBJ_NR]; 405 rt_list_t *next = (rt_list_t*)RT_NULL; 406 407 int maxlen; 408 const char *item_title = "mutex"; 409 410 list_find_init(&find_arg, RT_Object_Class_Mutex, obj_list, sizeof(obj_list)/sizeof(obj_list[0])); 411 412 maxlen = RT_NAME_MAX; 413 414 rt_kprintf("%-*.s owner hold suspend thread\n", maxlen, item_title); object_split(maxlen); 415 rt_kprintf( " -------- ---- --------------\n"); 416 417 do 418 { 419 next = list_get_next(next, &find_arg); 420 { 421 int i; 422 for (i = 0; i < find_arg.nr_out; i++) 423 { 424 struct rt_object *obj; 425 struct rt_mutex *m; 426 427 obj = rt_list_entry(obj_list[i], struct rt_object, list); 428 level = rt_hw_interrupt_disable(); 429 if ((obj->type & ~RT_Object_Class_Static) != find_arg.type) 430 { 431 rt_hw_interrupt_enable(level); 432 continue; 433 } 434 435 rt_hw_interrupt_enable(level); 436 437 m = (struct rt_mutex *)obj; 438 rt_kprintf("%-*.*s %-8.*s %04d %d\n", 439 maxlen, RT_NAME_MAX, 440 m->parent.parent.name, 441 RT_NAME_MAX, 442 m->owner->name, 443 m->hold, 444 rt_list_len(&m->parent.suspend_thread)); 445 446 } 447 } 448 } 449 while (next != (rt_list_t*)RT_NULL); 450 451 return 0; 452 } 453 FINSH_FUNCTION_EXPORT(list_mutex, list mutex in system); 454 MSH_CMD_EXPORT(list_mutex, list mutex in system); 455 #endif 456 457 #ifdef RT_USING_MAILBOX 458 long list_mailbox(void) 459 { 460 rt_ubase_t level; 461 list_get_next_t find_arg; 462 rt_list_t *obj_list[LIST_FIND_OBJ_NR]; 463 rt_list_t *next = (rt_list_t*)RT_NULL; 464 465 int maxlen; 466 const char *item_title = "mailbox"; 467 468 list_find_init(&find_arg, RT_Object_Class_MailBox, obj_list, sizeof(obj_list)/sizeof(obj_list[0])); 469 470 maxlen = RT_NAME_MAX; 471 472 rt_kprintf("%-*.s entry size suspend thread\n", maxlen, item_title); object_split(maxlen); 473 rt_kprintf( " ---- ---- --------------\n"); 474 475 do 476 { 477 next = list_get_next(next, &find_arg); 478 { 479 int i; 480 for (i = 0; i < find_arg.nr_out; i++) 481 { 482 struct rt_object *obj; 483 struct rt_mailbox *m; 484 485 obj = rt_list_entry(obj_list[i], struct rt_object, list); 486 level = rt_hw_interrupt_disable(); 487 if ((obj->type & ~RT_Object_Class_Static) != find_arg.type) 488 { 489 rt_hw_interrupt_enable(level); 490 continue; 491 } 492 493 rt_hw_interrupt_enable(level); 494 495 m = (struct rt_mailbox *)obj; 496 if (!rt_list_isempty(&m->parent.suspend_thread)) 497 { 498 rt_kprintf("%-*.*s %04d %04d %d:", 499 maxlen, RT_NAME_MAX, 500 m->parent.parent.name, 501 m->entry, 502 m->size, 503 rt_list_len(&m->parent.suspend_thread)); 504 show_wait_queue(&(m->parent.suspend_thread)); 505 rt_kprintf("\n"); 506 } 507 else 508 { 509 rt_kprintf("%-*.*s %04d %04d %d\n", 510 maxlen, RT_NAME_MAX, 511 m->parent.parent.name, 512 m->entry, 513 m->size, 514 rt_list_len(&m->parent.suspend_thread)); 515 } 516 517 } 518 } 519 } 520 while (next != (rt_list_t*)RT_NULL); 521 522 return 0; 523 } 524 FINSH_FUNCTION_EXPORT(list_mailbox, list mail box in system); 525 MSH_CMD_EXPORT(list_mailbox, list mail box in system); 526 #endif 527 528 #ifdef RT_USING_MESSAGEQUEUE 529 long list_msgqueue(void) 530 { 531 rt_ubase_t level; 532 list_get_next_t find_arg; 533 rt_list_t *obj_list[LIST_FIND_OBJ_NR]; 534 rt_list_t *next = (rt_list_t*)RT_NULL; 535 536 int maxlen; 537 const char *item_title = "msgqueue"; 538 539 list_find_init(&find_arg, RT_Object_Class_MessageQueue, obj_list, sizeof(obj_list)/sizeof(obj_list[0])); 540 541 maxlen = RT_NAME_MAX; 542 543 rt_kprintf("%-*.s entry suspend thread\n", maxlen, item_title); object_split(maxlen); 544 rt_kprintf( " ---- --------------\n"); 545 do 546 { 547 next = list_get_next(next, &find_arg); 548 { 549 int i; 550 for (i = 0; i < find_arg.nr_out; i++) 551 { 552 struct rt_object *obj; 553 struct rt_messagequeue *m; 554 555 obj = rt_list_entry(obj_list[i], struct rt_object, list); 556 level = rt_hw_interrupt_disable(); 557 if ((obj->type & ~RT_Object_Class_Static) != find_arg.type) 558 { 559 rt_hw_interrupt_enable(level); 560 continue; 561 } 562 563 rt_hw_interrupt_enable(level); 564 565 m = (struct rt_messagequeue *)obj; 566 if (!rt_list_isempty(&m->parent.suspend_thread)) 567 { 568 rt_kprintf("%-*.*s %04d %d:", 569 maxlen, RT_NAME_MAX, 570 m->parent.parent.name, 571 m->entry, 572 rt_list_len(&m->parent.suspend_thread)); 573 show_wait_queue(&(m->parent.suspend_thread)); 574 rt_kprintf("\n"); 575 } 576 else 577 { 578 rt_kprintf("%-*.*s %04d %d\n", 579 maxlen, RT_NAME_MAX, 580 m->parent.parent.name, 581 m->entry, 582 rt_list_len(&m->parent.suspend_thread)); 583 } 584 } 585 } 586 } 587 while (next != (rt_list_t*)RT_NULL); 588 589 return 0; 590 } 591 FINSH_FUNCTION_EXPORT(list_msgqueue, list message queue in system); 592 MSH_CMD_EXPORT(list_msgqueue, list message queue in system); 593 #endif 594 595 #ifdef RT_USING_MEMHEAP 596 long list_memheap(void) 597 { 598 rt_ubase_t level; 599 list_get_next_t find_arg; 600 rt_list_t *obj_list[LIST_FIND_OBJ_NR]; 601 rt_list_t *next = (rt_list_t*)RT_NULL; 602 603 int maxlen; 604 const char *item_title = "memheap"; 605 606 list_find_init(&find_arg, RT_Object_Class_MemHeap, obj_list, sizeof(obj_list)/sizeof(obj_list[0])); 607 608 maxlen = RT_NAME_MAX; 609 610 rt_kprintf("%-*.s pool size max used size available size\n", maxlen, item_title); object_split(maxlen); 611 rt_kprintf( " ---------- ------------- --------------\n"); 612 do 613 { 614 next = list_get_next(next, &find_arg); 615 { 616 int i; 617 for (i = 0; i < find_arg.nr_out; i++) 618 { 619 struct rt_object *obj; 620 struct rt_memheap *mh; 621 622 obj = rt_list_entry(obj_list[i], struct rt_object, list); 623 level = rt_hw_interrupt_disable(); 624 if ((obj->type & ~RT_Object_Class_Static) != find_arg.type) 625 { 626 rt_hw_interrupt_enable(level); 627 continue; 628 } 629 630 rt_hw_interrupt_enable(level); 631 632 mh = (struct rt_memheap *)obj; 633 634 rt_kprintf("%-*.*s %-010d %-013d %-05d\n", 635 maxlen, RT_NAME_MAX, 636 mh->parent.name, 637 mh->pool_size, 638 mh->max_used_size, 639 mh->available_size); 640 641 } 642 } 643 } 644 while (next != (rt_list_t*)RT_NULL); 645 646 return 0; 647 } 648 FINSH_FUNCTION_EXPORT(list_memheap, list memory heap in system); 649 MSH_CMD_EXPORT(list_memheap, list memory heap in system); 650 #endif 651 652 #ifdef RT_USING_MEMPOOL 653 long list_mempool(void) 654 { 655 rt_ubase_t level; 656 list_get_next_t find_arg; 657 rt_list_t *obj_list[LIST_FIND_OBJ_NR]; 658 rt_list_t *next = (rt_list_t*)RT_NULL; 659 660 int maxlen; 661 const char *item_title = "mempool"; 662 663 list_find_init(&find_arg, RT_Object_Class_MemPool, obj_list, sizeof(obj_list)/sizeof(obj_list[0])); 664 665 maxlen = RT_NAME_MAX; 666 667 rt_kprintf("%-*.s block total free suspend thread\n", maxlen, item_title); object_split(maxlen); 668 rt_kprintf( " ---- ---- ---- --------------\n"); 669 do 670 { 671 next = list_get_next(next, &find_arg); 672 { 673 int i; 674 for (i = 0; i < find_arg.nr_out; i++) 675 { 676 struct rt_object *obj; 677 struct rt_mempool *mp; 678 679 obj = rt_list_entry(obj_list[i], struct rt_object, list); 680 level = rt_hw_interrupt_disable(); 681 if ((obj->type & ~RT_Object_Class_Static) != find_arg.type) 682 { 683 rt_hw_interrupt_enable(level); 684 continue; 685 } 686 687 rt_hw_interrupt_enable(level); 688 689 mp = (struct rt_mempool *)obj; 690 if (mp->suspend_thread_count > 0) 691 { 692 rt_kprintf("%-*.*s %04d %04d %04d %d:", 693 maxlen, RT_NAME_MAX, 694 mp->parent.name, 695 mp->block_size, 696 mp->block_total_count, 697 mp->block_free_count, 698 mp->suspend_thread_count); 699 show_wait_queue(&(mp->suspend_thread)); 700 rt_kprintf("\n"); 701 } 702 else 703 { 704 rt_kprintf("%-*.*s %04d %04d %04d %d\n", 705 maxlen, RT_NAME_MAX, 706 mp->parent.name, 707 mp->block_size, 708 mp->block_total_count, 709 mp->block_free_count, 710 mp->suspend_thread_count); 711 } 712 } 713 } 714 } 715 while (next != (rt_list_t*)RT_NULL); 716 717 return 0; 718 } 719 FINSH_FUNCTION_EXPORT(list_mempool, list memory pool in system) 720 MSH_CMD_EXPORT(list_mempool, list memory pool in system); 721 #endif 722 723 long list_timer(void) 724 { 725 rt_ubase_t level; 726 list_get_next_t find_arg; 727 rt_list_t *obj_list[LIST_FIND_OBJ_NR]; 728 rt_list_t *next = (rt_list_t*)RT_NULL; 729 730 int maxlen; 731 const char *item_title = "timer"; 732 733 list_find_init(&find_arg, RT_Object_Class_Timer, obj_list, sizeof(obj_list)/sizeof(obj_list[0])); 734 735 maxlen = RT_NAME_MAX; 736 737 rt_kprintf("%-*.s periodic timeout flag\n", maxlen, item_title); object_split(maxlen); 738 rt_kprintf( " ---------- ---------- -----------\n"); 739 do { 740 next = list_get_next(next, &find_arg); 741 { 742 int i; 743 for (i = 0; i < find_arg.nr_out; i++) 744 { 745 struct rt_object *obj; 746 struct rt_timer *timer; 747 748 obj = rt_list_entry(obj_list[i], struct rt_object, list); 749 level = rt_hw_interrupt_disable(); 750 if ((obj->type & ~RT_Object_Class_Static) != find_arg.type) 751 { 752 rt_hw_interrupt_enable(level); 753 continue; 754 } 755 756 rt_hw_interrupt_enable(level); 757 758 timer = (struct rt_timer *)obj; 759 rt_kprintf("%-*.*s 0x%08x 0x%08x ", 760 maxlen, RT_NAME_MAX, 761 timer->parent.name, 762 timer->init_tick, 763 timer->timeout_tick); 764 if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED) 765 rt_kprintf("activated\n"); 766 else 767 rt_kprintf("deactivated\n"); 768 769 } 770 } 771 } 772 while (next != (rt_list_t*)RT_NULL); 773 774 rt_kprintf("current tick:0x%08x\n", rt_tick_get()); 775 776 return 0; 777 } 778 FINSH_FUNCTION_EXPORT(list_timer, list timer in system); 779 MSH_CMD_EXPORT(list_timer, list timer in system); 780 781 #ifdef RT_USING_DEVICE 782 static char *const device_type_str[] = 783 { 784 "Character Device", 785 "Block Device", 786 "Network Interface", 787 "MTD Device", 788 "CAN Device", 789 "RTC", 790 "Sound Device", 791 "Graphic Device", 792 "I2C Bus", 793 "USB Slave Device", 794 "USB Host Bus", 795 "SPI Bus", 796 "SPI Device", 797 "SDIO Bus", 798 "PM Pseudo Device", 799 "Pipe", 800 "Portal Device", 801 "Timer Device", 802 "Miscellaneous Device", 803 "Unknown" 804 }; 805 806 long list_device(void) 807 { 808 rt_ubase_t level; 809 list_get_next_t find_arg; 810 rt_list_t *obj_list[LIST_FIND_OBJ_NR]; 811 rt_list_t *next = (rt_list_t*)RT_NULL; 812 813 int maxlen; 814 const char *item_title = "device"; 815 816 list_find_init(&find_arg, RT_Object_Class_Device, obj_list, sizeof(obj_list)/sizeof(obj_list[0])); 817 818 maxlen = RT_NAME_MAX; 819 820 rt_kprintf("%-*.s type ref count\n", maxlen, item_title); object_split(maxlen); 821 rt_kprintf( " -------------------- ----------\n"); 822 do 823 { 824 next = list_get_next(next, &find_arg); 825 { 826 int i; 827 for (i = 0; i < find_arg.nr_out; i++) 828 { 829 struct rt_object *obj; 830 struct rt_device *device; 831 832 obj = rt_list_entry(obj_list[i], struct rt_object, list); 833 level = rt_hw_interrupt_disable(); 834 if ((obj->type & ~RT_Object_Class_Static) != find_arg.type) 835 { 836 rt_hw_interrupt_enable(level); 837 continue; 838 } 839 840 rt_hw_interrupt_enable(level); 841 842 device = (struct rt_device *)obj; 843 rt_kprintf("%-*.*s %-20s %-8d\n", 844 maxlen, RT_NAME_MAX, 845 device->parent.name, 846 (device->type <= RT_Device_Class_Unknown) ? 847 device_type_str[device->type] : 848 device_type_str[RT_Device_Class_Unknown], 849 device->ref_count); 850 851 } 852 } 853 } 854 while (next != (rt_list_t*)RT_NULL); 855 856 return 0; 857 } 858 FINSH_FUNCTION_EXPORT(list_device, list device in system); 859 MSH_CMD_EXPORT(list_device, list device in system); 860 #endif 861 862 long list(void) 863 { 864 #ifndef FINSH_USING_MSH_ONLY 865 struct finsh_syscall_item *syscall_item; 866 struct finsh_sysvar_item *sysvar_item; 867 #endif 868 869 rt_kprintf("--Function List:\n"); 870 { 871 struct finsh_syscall *index; 872 for (index = _syscall_table_begin; 873 index < _syscall_table_end; 874 FINSH_NEXT_SYSCALL(index)) 875 { 876 /* skip the internal command */ 877 if (strncmp((char *)index->name, "__", 2) == 0) continue; 878 879 #ifdef FINSH_USING_DESCRIPTION 880 rt_kprintf("%-16s -- %s\n", index->name, index->desc); 881 #else 882 rt_kprintf("%s\n", index->name); 883 #endif 884 } 885 } 886 887 #ifndef FINSH_USING_MSH_ONLY 888 /* list syscall list */ 889 syscall_item = global_syscall_list; 890 while (syscall_item != NULL) 891 { 892 rt_kprintf("[l] %s\n", syscall_item->syscall.name); 893 syscall_item = syscall_item->next; 894 } 895 896 rt_kprintf("--Variable List:\n"); 897 { 898 struct finsh_sysvar *index; 899 for (index = _sysvar_table_begin; 900 index < _sysvar_table_end; 901 FINSH_NEXT_SYSVAR(index)) 902 { 903 #ifdef FINSH_USING_DESCRIPTION 904 rt_kprintf("%-16s -- %s\n", index->name, index->desc); 905 #else 906 rt_kprintf("%s\n", index->name); 907 #endif 908 } 909 } 910 911 sysvar_item = global_sysvar_list; 912 while (sysvar_item != NULL) 913 { 914 rt_kprintf("[l] %s\n", sysvar_item->sysvar.name); 915 sysvar_item = sysvar_item->next; 916 } 917 #endif 918 919 return 0; 920 } 921 FINSH_FUNCTION_EXPORT(list, list all symbol in system) 922 923 #ifndef FINSH_USING_MSH_ONLY 924 static int str_is_prefix(const char *prefix, const char *str) 925 { 926 while ((*prefix) && (*prefix == *str)) 927 { 928 prefix ++; 929 str ++; 930 } 931 932 if (*prefix == 0) 933 return 0; 934 935 return -1; 936 } 937 938 static int str_common(const char *str1, const char *str2) 939 { 940 const char *str = str1; 941 942 while ((*str != 0) && (*str2 != 0) && (*str == *str2)) 943 { 944 str ++; 945 str2 ++; 946 } 947 948 return (str - str1); 949 } 950 951 void list_prefix(char *prefix) 952 { 953 struct finsh_syscall_item *syscall_item; 954 struct finsh_sysvar_item *sysvar_item; 955 rt_uint16_t func_cnt, var_cnt; 956 int length, min_length; 957 const char *name_ptr; 958 959 func_cnt = 0; 960 var_cnt = 0; 961 min_length = 0; 962 name_ptr = RT_NULL; 963 964 /* checks in system function call */ 965 { 966 struct finsh_syscall *index; 967 for (index = _syscall_table_begin; 968 index < _syscall_table_end; 969 FINSH_NEXT_SYSCALL(index)) 970 { 971 /* skip internal command */ 972 if (str_is_prefix("__", index->name) == 0) continue; 973 974 if (str_is_prefix(prefix, index->name) == 0) 975 { 976 if (func_cnt == 0) 977 { 978 rt_kprintf("--function:\n"); 979 980 if (*prefix != 0) 981 { 982 /* set name_ptr */ 983 name_ptr = index->name; 984 985 /* set initial length */ 986 min_length = strlen(name_ptr); 987 } 988 } 989 990 func_cnt ++; 991 992 if (*prefix != 0) 993 { 994 length = str_common(name_ptr, index->name); 995 if (length < min_length) 996 min_length = length; 997 } 998 999 #ifdef FINSH_USING_DESCRIPTION 1000 rt_kprintf("%-16s -- %s\n", index->name, index->desc); 1001 #else 1002 rt_kprintf("%s\n", index->name); 1003 #endif 1004 } 1005 } 1006 } 1007 1008 /* checks in dynamic system function call */ 1009 syscall_item = global_syscall_list; 1010 while (syscall_item != NULL) 1011 { 1012 if (str_is_prefix(prefix, syscall_item->syscall.name) == 0) 1013 { 1014 if (func_cnt == 0) 1015 { 1016 rt_kprintf("--function:\n"); 1017 if (*prefix != 0 && name_ptr == NULL) 1018 { 1019 /* set name_ptr */ 1020 name_ptr = syscall_item->syscall.name; 1021 1022 /* set initial length */ 1023 min_length = strlen(name_ptr); 1024 } 1025 } 1026 1027 func_cnt ++; 1028 1029 if (*prefix != 0) 1030 { 1031 length = str_common(name_ptr, syscall_item->syscall.name); 1032 if (length < min_length) 1033 min_length = length; 1034 } 1035 1036 rt_kprintf("[l] %s\n", syscall_item->syscall.name); 1037 } 1038 syscall_item = syscall_item->next; 1039 } 1040 1041 /* checks in system variable */ 1042 { 1043 struct finsh_sysvar *index; 1044 for (index = _sysvar_table_begin; 1045 index < _sysvar_table_end; 1046 FINSH_NEXT_SYSVAR(index)) 1047 { 1048 if (str_is_prefix(prefix, index->name) == 0) 1049 { 1050 if (var_cnt == 0) 1051 { 1052 rt_kprintf("--variable:\n"); 1053 1054 if (*prefix != 0 && name_ptr == NULL) 1055 { 1056 /* set name_ptr */ 1057 name_ptr = index->name; 1058 1059 /* set initial length */ 1060 min_length = strlen(name_ptr); 1061 1062 } 1063 } 1064 1065 var_cnt ++; 1066 1067 if (*prefix != 0) 1068 { 1069 length = str_common(name_ptr, index->name); 1070 if (length < min_length) 1071 min_length = length; 1072 } 1073 1074 #ifdef FINSH_USING_DESCRIPTION 1075 rt_kprintf("%-16s -- %s\n", index->name, index->desc); 1076 #else 1077 rt_kprintf("%s\n", index->name); 1078 #endif 1079 } 1080 } 1081 } 1082 1083 /* checks in dynamic system variable */ 1084 sysvar_item = global_sysvar_list; 1085 while (sysvar_item != NULL) 1086 { 1087 if (str_is_prefix(prefix, sysvar_item->sysvar.name) == 0) 1088 { 1089 if (var_cnt == 0) 1090 { 1091 rt_kprintf("--variable:\n"); 1092 if (*prefix != 0 && name_ptr == NULL) 1093 { 1094 /* set name_ptr */ 1095 name_ptr = sysvar_item->sysvar.name; 1096 1097 /* set initial length */ 1098 min_length = strlen(name_ptr); 1099 } 1100 } 1101 1102 var_cnt ++; 1103 1104 if (*prefix != 0) 1105 { 1106 length = str_common(name_ptr, sysvar_item->sysvar.name); 1107 if (length < min_length) 1108 min_length = length; 1109 } 1110 1111 rt_kprintf("[v] %s\n", sysvar_item->sysvar.name); 1112 } 1113 sysvar_item = sysvar_item->next; 1114 } 1115 1116 /* only one matched */ 1117 if (name_ptr != NULL) 1118 { 1119 rt_strncpy(prefix, name_ptr, min_length); 1120 } 1121 } 1122 #endif 1123 1124 #if defined(FINSH_USING_SYMTAB) && !defined(FINSH_USING_MSH_ONLY) 1125 static int dummy = 0; 1126 FINSH_VAR_EXPORT(dummy, finsh_type_int, dummy variable for finsh) 1127 #endif 1128 1129 #endif /* RT_USING_FINSH */ 1130 1131