cmd.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. /*
  2. * File : cmd.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2006-04-30 Bernard first implementation
  13. * 2006-05-04 Bernard add list_thread,
  14. * list_sem,
  15. * list_timer
  16. * 2006-05-20 Bernard add list_mutex,
  17. * list_mailbox,
  18. * list_msgqueue,
  19. * list_event,
  20. * list_fevent,
  21. * list_mempool
  22. * 2006-06-03 Bernard display stack information in list_thread
  23. * 2006-08-10 Bernard change version to invoke rt_show_version
  24. * 2008-09-10 Bernard update the list function for finsh syscall
  25. * list and sysvar list
  26. * 2009-05-30 Bernard add list_device
  27. * 2010-04-21 yi.qiu add list_module
  28. */
  29. #include <rtthread.h>
  30. #include "finsh.h"
  31. // Copy from kservice.h because we can not use it out of the kernel.
  32. // Ugly. Should let kservice.h avaliable for applications?
  33. rt_inline int rt_list_isempty(const rt_list_t *l)
  34. {
  35. return l->next == l;
  36. }
  37. rt_inline unsigned int rt_list_len(const rt_list_t *l)
  38. {
  39. unsigned int len = 0;
  40. const rt_list_t *p = l;
  41. while( p->next != l )
  42. {
  43. p = p->next;
  44. len++;
  45. }
  46. return len;
  47. }
  48. long hello(void)
  49. {
  50. rt_kprintf("Hello RT-Thread!\n");
  51. return 0;
  52. }
  53. FINSH_FUNCTION_EXPORT(hello, say hello world);
  54. extern void rt_show_version(void);
  55. long version(void)
  56. {
  57. rt_show_version();
  58. return 0;
  59. }
  60. FINSH_FUNCTION_EXPORT(version, show RT-Thread version information);
  61. #define rt_list_entry(node, type, member) \
  62. ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member)))
  63. extern struct rt_object_information rt_object_container[];
  64. static long _list_thread(struct rt_list_node* list)
  65. {
  66. struct rt_thread *thread;
  67. struct rt_list_node *node;
  68. rt_uint8_t* ptr;
  69. rt_kprintf(" thread pri status sp stack size max used left tick error\n");
  70. rt_kprintf("-------- ---- ------- ---------- ---------- ---------- ---------- ---\n");
  71. for (node = list->next; node != list; node = node->next)
  72. {
  73. thread = rt_list_entry(node, struct rt_thread, list);
  74. rt_kprintf("%-8s 0x%02x", thread->name, thread->current_priority);
  75. if (thread->stat == RT_THREAD_READY) rt_kprintf(" ready ");
  76. else if (thread->stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend");
  77. else if (thread->stat == RT_THREAD_INIT) rt_kprintf(" init ");
  78. ptr = (rt_uint8_t*)thread->stack_addr;
  79. while (*ptr == '#')ptr ++;
  80. rt_kprintf(" 0x%08x 0x%08x 0x%08x 0x%08x %03d\n",
  81. thread->stack_size + ((rt_uint32_t)thread->stack_addr - (rt_uint32_t)thread->sp),
  82. thread->stack_size,
  83. thread->stack_size - ((rt_uint32_t) ptr - (rt_uint32_t)thread->stack_addr),
  84. thread->remaining_tick,
  85. thread->error);
  86. }
  87. return 0;
  88. }
  89. long list_thread(void)
  90. {
  91. return _list_thread(&rt_object_container[RT_Object_Class_Thread].object_list);
  92. }
  93. FINSH_FUNCTION_EXPORT(list_thread, list thread);
  94. static void show_wait_queue(struct rt_list_node* list)
  95. {
  96. struct rt_thread *thread;
  97. struct rt_list_node *node;
  98. for (node = list->next; node != list; node = node->next)
  99. {
  100. thread = rt_list_entry(node, struct rt_thread, tlist);
  101. rt_kprintf("%s", thread->name);
  102. if (node->next != list) rt_kprintf("/");
  103. }
  104. }
  105. #ifdef RT_USING_SEMAPHORE
  106. static long _list_sem(struct rt_list_node *list)
  107. {
  108. struct rt_semaphore *sem;
  109. struct rt_list_node *node;
  110. rt_kprintf("semaphore v suspend thread\n");
  111. rt_kprintf("-------- --- --------------\n");
  112. for (node = list->next; node != list; node = node->next)
  113. {
  114. sem = (struct rt_semaphore*)(rt_list_entry(node, struct rt_object, list));
  115. if( !rt_list_isempty(&sem->parent.suspend_thread) )
  116. {
  117. rt_kprintf("%-8s %03d %d:", sem->parent.parent.name, sem->value, rt_list_len(&sem->parent.suspend_thread) );
  118. show_wait_queue(&(sem->parent.suspend_thread));
  119. rt_kprintf("\n");
  120. }
  121. else
  122. {
  123. rt_kprintf("%-8s %03d %d\n", sem->parent.parent.name, sem->value, rt_list_len(&sem->parent.suspend_thread));
  124. }
  125. }
  126. return 0;
  127. }
  128. long list_sem(void)
  129. {
  130. return _list_sem(&rt_object_container[RT_Object_Class_Semaphore].object_list);
  131. }
  132. FINSH_FUNCTION_EXPORT(list_sem, list semaphone in system)
  133. #endif
  134. #ifdef RT_USING_EVENT
  135. static long _list_event(struct rt_list_node *list)
  136. {
  137. struct rt_event *e;
  138. struct rt_list_node *node;
  139. rt_kprintf("event set suspend thread\n");
  140. rt_kprintf("-------- ---------- --------------\n");
  141. for (node = list->next; node != list; node = node->next)
  142. {
  143. e = (struct rt_event*)(rt_list_entry(node, struct rt_object, list));
  144. rt_kprintf("%-8s 0x%08x %03d\n", e->parent.parent.name, e->set, rt_list_len(&e->parent.suspend_thread));
  145. }
  146. return 0;
  147. }
  148. long list_event(void)
  149. {
  150. return _list_event(&rt_object_container[RT_Object_Class_Event].object_list);
  151. }
  152. FINSH_FUNCTION_EXPORT(list_event, list event in system)
  153. #endif
  154. #ifdef RT_USING_MUTEX
  155. static long _list_mutex(struct rt_list_node *list)
  156. {
  157. struct rt_mutex *m;
  158. struct rt_list_node *node;
  159. rt_kprintf("mutex owner hold suspend thread\n");
  160. rt_kprintf("-------- -------- ---- --------------\n");
  161. for (node = list->next; node != list; node = node->next)
  162. {
  163. m = (struct rt_mutex*)(rt_list_entry(node, struct rt_object, list));
  164. rt_kprintf("%-8s %-8s %04d %d\n", m->parent.parent.name, m->owner->name, m->hold, rt_list_len(&m->parent.suspend_thread));
  165. }
  166. return 0;
  167. }
  168. long list_mutex(void)
  169. {
  170. return _list_mutex(&rt_object_container[RT_Object_Class_Mutex].object_list);
  171. }
  172. FINSH_FUNCTION_EXPORT(list_mutex, list mutex in system)
  173. #endif
  174. #ifdef RT_USING_MAILBOX
  175. static long _list_mailbox(struct rt_list_node *list)
  176. {
  177. struct rt_mailbox *m;
  178. struct rt_list_node *node;
  179. rt_kprintf("mailbox entry size suspend thread\n");
  180. rt_kprintf("-------- ---- ---- --------------\n");
  181. for (node = list->next; node != list; node = node->next)
  182. {
  183. m = (struct rt_mailbox*)(rt_list_entry(node, struct rt_object, list));
  184. if( !rt_list_isempty(&m->parent.suspend_thread) )
  185. {
  186. rt_kprintf("%-8s %04d %04d %d:", m->parent.parent.name, m->entry, m->size, rt_list_len(&m->parent.suspend_thread));
  187. show_wait_queue(&(m->parent.suspend_thread));
  188. rt_kprintf("\n");
  189. }
  190. else
  191. {
  192. rt_kprintf("%-8s %04d %04d %d\n", m->parent.parent.name, m->entry, m->size, rt_list_len(&m->parent.suspend_thread));
  193. }
  194. }
  195. return 0;
  196. }
  197. long list_mailbox(void)
  198. {
  199. return _list_mailbox(&rt_object_container[RT_Object_Class_MailBox].object_list);
  200. }
  201. FINSH_FUNCTION_EXPORT(list_mailbox, list mail box in system)
  202. #endif
  203. #ifdef RT_USING_MESSAGEQUEUE
  204. static long _list_msgqueue(struct rt_list_node *list)
  205. {
  206. struct rt_messagequeue *m;
  207. struct rt_list_node *node;
  208. rt_kprintf("msgqueue entry suspend thread\n");
  209. rt_kprintf("-------- ---- --------------\n");
  210. for (node = list->next; node != list; node = node->next)
  211. {
  212. m = (struct rt_messagequeue*)(rt_list_entry(node, struct rt_object, list));
  213. if( !rt_list_isempty(&m->parent.suspend_thread) )
  214. {
  215. rt_kprintf("%-8s %04d %d:", m->parent.parent.name, m->entry, rt_list_len(&m->parent.suspend_thread));
  216. show_wait_queue(&(m->parent.suspend_thread));
  217. rt_kprintf("\n");
  218. }
  219. else
  220. {
  221. rt_kprintf("%-8s %04d %d\n", m->parent.parent.name, m->entry, rt_list_len(&m->parent.suspend_thread));
  222. }
  223. }
  224. return 0;
  225. }
  226. long list_msgqueue(void)
  227. {
  228. return _list_msgqueue(&rt_object_container[RT_Object_Class_MessageQueue].object_list);
  229. }
  230. FINSH_FUNCTION_EXPORT(list_msgqueue, list message queue in system)
  231. #endif
  232. #ifdef RT_USING_MEMPOOL
  233. static long _list_mempool(struct rt_list_node *list)
  234. {
  235. struct rt_mempool *mp;
  236. struct rt_list_node *node;
  237. rt_kprintf("mempool block total free suspend thread\n");
  238. rt_kprintf("-------- ---- ---- ---- --------------\n");
  239. for (node = list->next; node != list; node = node->next)
  240. {
  241. mp = (struct rt_mempool*)rt_list_entry(node, struct rt_object, list);
  242. if (mp->suspend_thread_count > 0)
  243. {
  244. rt_kprintf("%-8s %04d %04d %04d %d:", mp->parent.name,
  245. mp->block_size, mp->block_total_count, mp->block_free_count,
  246. mp->suspend_thread_count);
  247. show_wait_queue(&(mp->suspend_thread));
  248. rt_kprintf("\n");
  249. }
  250. else
  251. {
  252. rt_kprintf("%-8s %04d %04d %04d %d\n", mp->parent.name,
  253. mp->block_size, mp->block_total_count, mp->block_free_count,
  254. mp->suspend_thread_count);
  255. }
  256. }
  257. return 0;
  258. }
  259. long list_mempool(void)
  260. {
  261. return _list_mempool(&rt_object_container[RT_Object_Class_MemPool].object_list);
  262. }
  263. FINSH_FUNCTION_EXPORT(list_mempool, list memory pool in system)
  264. #endif
  265. static long _list_timer(struct rt_list_node *list)
  266. {
  267. struct rt_timer *timer;
  268. struct rt_list_node *node;
  269. rt_kprintf("timer periodic timeout flag\n");
  270. rt_kprintf("-------- ---------- ---------- -----------\n");
  271. for (node = list->next; node != list; node = node->next)
  272. {
  273. timer = (struct rt_timer*)(rt_list_entry(node, struct rt_object, list));
  274. rt_kprintf("%-8s 0x%08x 0x%08x ", timer->parent.name, timer->init_tick, timer->timeout_tick);
  275. if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED) rt_kprintf("activated\n");
  276. else rt_kprintf("deactivated\n");
  277. }
  278. rt_kprintf("current tick:0x%08x\n", rt_tick_get());
  279. return 0;
  280. }
  281. long list_timer(void)
  282. {
  283. return _list_timer(&rt_object_container[RT_Object_Class_Timer].object_list);
  284. }
  285. FINSH_FUNCTION_EXPORT(list_timer, list timer in system)
  286. #ifdef RT_USING_DEVICE
  287. static long _list_device(struct rt_list_node *list)
  288. {
  289. struct rt_device *device;
  290. struct rt_list_node *node;
  291. const char *device_type_str[] =
  292. {
  293. "Character Device",
  294. "Block Device",
  295. "Network Interface",
  296. "MTD Device",
  297. "CAN",
  298. "RTC",
  299. "Unknown"
  300. };
  301. rt_kprintf("device type \n");
  302. rt_kprintf("-------- ---------- \n");
  303. for (node = list->next; node != list; node = node->next)
  304. {
  305. device = (struct rt_device*)(rt_list_entry(node, struct rt_object, list));
  306. rt_kprintf("%-8s %-8s \n", device->parent.name, device_type_str[device->type]);
  307. }
  308. return 0;
  309. }
  310. long list_device(void)
  311. {
  312. return _list_device(&rt_object_container[RT_Object_Class_Device].object_list);
  313. }
  314. FINSH_FUNCTION_EXPORT(list_device, list device in system)
  315. #endif
  316. #ifdef RT_USING_MODULE
  317. int list_module(void)
  318. {
  319. struct rt_module *module;
  320. struct rt_list_node *list, *node;
  321. list = &rt_object_container[RT_Object_Class_Module].object_list;
  322. for (node = list->next; node != list; node = node->next)
  323. {
  324. struct rt_list_node *tlist;
  325. struct rt_thread *thread;
  326. rt_uint8_t* ptr;
  327. module = (struct rt_module*)(rt_list_entry(node, struct rt_object, list));
  328. rt_kprintf("______________________________________________________________________\n");
  329. rt_kprintf("[module]%-8s \n", module->parent.name);
  330. /* list main thread in module */
  331. if(module->module_thread != RT_NULL)
  332. {
  333. rt_kprintf("main thread pri status sp stack size max used left tick error\n");
  334. rt_kprintf("------------- ---- ------- ---------- ---------- ---------- ---------- ---\n");
  335. thread = module->module_thread;
  336. rt_kprintf("%-8s 0x%02x", thread->name, thread->current_priority);
  337. if (thread->stat == RT_THREAD_READY) rt_kprintf(" ready ");
  338. else if (thread->stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend");
  339. else if (thread->stat == RT_THREAD_INIT) rt_kprintf(" init ");
  340. ptr = (rt_uint8_t*)thread->stack_addr;
  341. while (*ptr == '#')ptr ++;
  342. rt_kprintf(" 0x%08x 0x%08x 0x%08x 0x%08x %03d\n",
  343. thread->stack_size + ((rt_uint32_t)thread->stack_addr - (rt_uint32_t)thread->sp),
  344. thread->stack_size,
  345. thread->stack_size - ((rt_uint32_t) ptr - (rt_uint32_t)thread->stack_addr),
  346. thread->remaining_tick,
  347. thread->error);
  348. }
  349. /* list sub thread in module */
  350. tlist = &module->module_object[RT_Object_Class_Thread].object_list;
  351. if(!rt_list_isempty(tlist)) _list_thread(tlist);
  352. #ifdef RT_USING_SEMAPHORE
  353. /* list semaphored in module */
  354. tlist = &module->module_object[RT_Object_Class_Semaphore].object_list;
  355. if(!rt_list_isempty(tlist)) _list_sem(tlist);
  356. #endif
  357. #ifdef RT_USING_MUTEX
  358. /* list mutex in module */
  359. tlist = &module->module_object[RT_Object_Class_Mutex].object_list;
  360. if(!rt_list_isempty(tlist)) _list_mutex(tlist);
  361. #endif
  362. #ifdef RT_USING_EVENT
  363. /* list event in module */
  364. tlist = &module->module_object[RT_Object_Class_Event].object_list;
  365. if(!rt_list_isempty(tlist)) _list_event(tlist);
  366. #endif
  367. #ifdef RT_USING_MAILBOX
  368. /* list mailbox in module */
  369. tlist = &module->module_object[RT_Object_Class_MailBox].object_list;
  370. if(!rt_list_isempty(tlist)) _list_mailbox(tlist);
  371. #endif
  372. #ifdef RT_USING_MESSAGEQUEUE
  373. /* list message queue in module */
  374. tlist = &module->module_object[RT_Object_Class_MessageQueue].object_list;
  375. if(!rt_list_isempty(tlist)) _list_msgqueue(tlist);
  376. #endif
  377. #ifdef RT_USING_MEMPOOL
  378. /* list memory pool in module */
  379. tlist = &module->module_object[RT_Object_Class_MemPool].object_list;
  380. if(!rt_list_isempty(tlist)) _list_mempool(tlist);
  381. #endif
  382. #ifdef RT_USING_DEVICE
  383. /* list device in module */
  384. tlist = &module->module_object[RT_Object_Class_Device].object_list;
  385. if(!rt_list_isempty(tlist)) _list_device(tlist);
  386. #endif
  387. /* list timer in module */
  388. tlist = &module->module_object[RT_Object_Class_Timer].object_list;
  389. if(!rt_list_isempty(tlist)) _list_timer(tlist);
  390. }
  391. rt_kprintf("______________________________________________________________________\n");
  392. return 0;
  393. }
  394. FINSH_FUNCTION_EXPORT(list_module, list module in system)
  395. #endif
  396. int list()
  397. {
  398. struct finsh_syscall_item* syscall_item;
  399. struct finsh_sysvar_item* sysvar_item;
  400. rt_kprintf("--Function List:\n");
  401. {
  402. struct finsh_syscall* index;
  403. for (index = _syscall_table_begin; index < _syscall_table_end; index ++)
  404. {
  405. #ifdef FINSH_USING_DESCRIPTION
  406. rt_kprintf("%-16s -- %s\n", index->name, index->desc);
  407. #else
  408. rt_kprintf("%s\n", index->name);
  409. #endif
  410. }
  411. }
  412. /* list syscall list */
  413. syscall_item = global_syscall_list;
  414. while (syscall_item != NULL)
  415. {
  416. rt_kprintf("[l] %s\n", syscall_item->syscall.name);
  417. syscall_item = syscall_item->next;
  418. }
  419. rt_kprintf("--Variable List:\n");
  420. {
  421. struct finsh_sysvar* index;
  422. for (index = _sysvar_table_begin; index < _sysvar_table_end; index ++)
  423. {
  424. #ifdef FINSH_USING_DESCRIPTION
  425. rt_kprintf("%-16s -- %s\n", index->name, index->desc);
  426. #else
  427. rt_kprintf("%s\n", index->name);
  428. #endif
  429. }
  430. }
  431. sysvar_item = global_sysvar_list;
  432. while (sysvar_item != NULL)
  433. {
  434. rt_kprintf("[l] %s\n", sysvar_item->sysvar.name);
  435. sysvar_item = sysvar_item->next;
  436. }
  437. return 0;
  438. }
  439. FINSH_FUNCTION_EXPORT(list, list all symbol in system)
  440. static int str_is_prefix(const char* prefix, const char* str)
  441. {
  442. while ((*prefix) && (*prefix == *str))
  443. {
  444. prefix ++;
  445. str ++;
  446. }
  447. if (*prefix == 0) return 0;
  448. return -1;
  449. }
  450. void list_prefix(char* prefix)
  451. {
  452. struct finsh_syscall_item* syscall_item;
  453. struct finsh_sysvar_item* sysvar_item;
  454. rt_uint16_t func_cnt, var_cnt;
  455. const char* name_ptr;
  456. func_cnt = 0;
  457. var_cnt = 0;
  458. name_ptr = RT_NULL;
  459. {
  460. struct finsh_syscall* index;
  461. for (index = _syscall_table_begin; index < _syscall_table_end; index ++)
  462. {
  463. if (str_is_prefix(prefix, index->name) == 0)
  464. {
  465. if (func_cnt == 0)
  466. rt_kprintf("--function:\n");
  467. func_cnt ++;
  468. /* set name_ptr */
  469. name_ptr = index->name;
  470. #ifdef FINSH_USING_DESCRIPTION
  471. rt_kprintf("%-16s -- %s\n", index->name, index->desc);
  472. #else
  473. rt_kprintf("%s\n", index->name);
  474. #endif
  475. }
  476. }
  477. }
  478. /* list syscall list */
  479. syscall_item = global_syscall_list;
  480. while (syscall_item != NULL)
  481. {
  482. if (str_is_prefix(prefix, syscall_item->syscall.name) == 0)
  483. {
  484. if (func_cnt == 0)
  485. rt_kprintf("--function:\n");
  486. func_cnt ++;
  487. /* set name_ptr */
  488. name_ptr = syscall_item->syscall.name;
  489. rt_kprintf("[l] %s\n", syscall_item->syscall.name);
  490. }
  491. syscall_item = syscall_item->next;
  492. }
  493. {
  494. struct finsh_sysvar* index;
  495. for (index = _sysvar_table_begin; index < _sysvar_table_end; index ++)
  496. {
  497. if (str_is_prefix(prefix, index->name) == 0)
  498. {
  499. if (var_cnt == 0)
  500. rt_kprintf("--variable:\n");
  501. var_cnt ++;
  502. /* set name ptr */
  503. name_ptr = index->name;
  504. #ifdef FINSH_USING_DESCRIPTION
  505. rt_kprintf("%-16s -- %s\n", index->name, index->desc);
  506. #else
  507. rt_kprintf("%s\n", index->name);
  508. #endif
  509. }
  510. }
  511. }
  512. sysvar_item = global_sysvar_list;
  513. while (sysvar_item != NULL)
  514. {
  515. if (str_is_prefix(prefix, sysvar_item->sysvar.name) == 0)
  516. {
  517. if (var_cnt == 0)
  518. rt_kprintf("--variable:\n");
  519. var_cnt ++;
  520. /* set name ptr */
  521. name_ptr = sysvar_item->sysvar.name;
  522. rt_kprintf("[l] %s\n", sysvar_item->sysvar.name);
  523. }
  524. sysvar_item = sysvar_item->next;
  525. }
  526. /* only one matched */
  527. if ((func_cnt + var_cnt) == 1)
  528. {
  529. rt_strncpy(prefix, name_ptr, strlen(name_ptr));
  530. }
  531. }
  532. #ifdef FINSH_USING_SYMTAB
  533. static int dummy = 0;
  534. FINSH_VAR_EXPORT(dummy, finsh_type_int, dummy variable for finsh)
  535. #endif