You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmd.c 33KB

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