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
hello(void)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);
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
object_split(int len)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
list_find_init(list_get_next_t * p,rt_uint8_t type,rt_list_t ** array,int nr)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
list_get_next(rt_list_t * current,list_get_next_t * arg)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
list_thread(void)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
show_wait_queue(struct rt_list_node * list)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
list_sem(void)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
list_event(void)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
list_mutex(void)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
list_mailbox(void)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
list_msgqueue(void)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
list_memheap(void)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
list_mempool(void)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
list_timer(void)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
list_device(void)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
list(void)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 }
FINSH_FUNCTION_EXPORT(list,list all symbol in system)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
str_common(const char * str1,const char * str2)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
list_prefix(char * prefix)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