xref: /nrf52832-nimble/rt-thread/components/finsh/cmd.c (revision 104654410c56c573564690304ae786df310c91fc)
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