cmd.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  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://openlab.rt-thread.com/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. */
  28. #include <rtthread.h>
  29. #include "finsh.h"
  30. // Copy from kservice.h because we can not use it out of the kernel.
  31. // Ugly. Should let kservice.h avaliable for applications?
  32. rt_inline int rt_list_isempty(const rt_list_t *l)
  33. {
  34. return l->next == l;
  35. }
  36. rt_inline unsigned int rt_list_len(const rt_list_t *l)
  37. {
  38. unsigned int len = 0;
  39. const rt_list_t *p = l;
  40. while( p->next != l )
  41. {
  42. p = p->next;
  43. len++;
  44. }
  45. return len;
  46. }
  47. long hello()
  48. {
  49. rt_kprintf("Hello RT-Thread!\n");
  50. return 0;
  51. }
  52. FINSH_FUNCTION_EXPORT(hello, say hello world);
  53. extern void rt_show_version(void);
  54. long version()
  55. {
  56. rt_show_version();
  57. return 0;
  58. }
  59. FINSH_FUNCTION_EXPORT(version, show RT-Thread version information);
  60. #define rt_list_entry(node, type, member) \
  61. ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member)))
  62. extern struct rt_object_information rt_object_container[];
  63. int list_thread()
  64. {
  65. struct rt_thread *thread;
  66. struct rt_list_node *list, *node;
  67. rt_uint8_t* ptr;
  68. list = &rt_object_container[RT_Object_Class_Thread].object_list;
  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. FINSH_FUNCTION_EXPORT(list_thread, list thread);
  90. static void show_wait_queue(struct rt_list_node* list)
  91. {
  92. struct rt_thread *thread;
  93. struct rt_list_node *node;
  94. for (node = list->next; node != list; node = node->next)
  95. {
  96. thread = rt_list_entry(node, struct rt_thread, tlist);
  97. rt_kprintf("%s", thread->name);
  98. if (node->next != list) rt_kprintf("/");
  99. }
  100. }
  101. #ifdef RT_USING_SEMAPHORE
  102. int list_sem()
  103. {
  104. struct rt_semaphore *sem;
  105. struct rt_list_node *list, *node;
  106. list = &rt_object_container[RT_Object_Class_Semaphore].object_list;
  107. rt_kprintf("semaphore v suspend thread\n");
  108. rt_kprintf("-------- --- --------------\n");
  109. for (node = list->next; node != list; node = node->next)
  110. {
  111. sem = (struct rt_semaphore*)(rt_list_entry(node, struct rt_object, list));
  112. if( !rt_list_isempty(&sem->parent.suspend_thread) )
  113. {
  114. rt_kprintf("%-8s %03d %d:", sem->parent.parent.name, sem->value, rt_list_len(&sem->parent.suspend_thread) );
  115. show_wait_queue(&(sem->parent.suspend_thread));
  116. rt_kprintf("\n");
  117. }
  118. else
  119. {
  120. rt_kprintf("%-8s %03d %d\n", sem->parent.parent.name, sem->value, rt_list_len(&sem->parent.suspend_thread));
  121. }
  122. }
  123. return 0;
  124. }
  125. FINSH_FUNCTION_EXPORT(list_sem, list semaphone in system)
  126. #endif
  127. #ifdef RT_USING_EVENT
  128. int list_event()
  129. {
  130. struct rt_event *e;
  131. struct rt_list_node *list, *node;
  132. list = &rt_object_container[RT_Object_Class_Event].object_list;
  133. rt_kprintf("event set suspend thread\n");
  134. rt_kprintf("-------- ---------- --------------\n");
  135. for (node = list->next; node != list; node = node->next)
  136. {
  137. e = (struct rt_event*)(rt_list_entry(node, struct rt_object, list));
  138. rt_kprintf("%-8s 0x%08x %03d\n", e->parent.parent.name, e->set, rt_list_len(&e->parent.suspend_thread));
  139. }
  140. return 0;
  141. }
  142. FINSH_FUNCTION_EXPORT(list_event, list event in system)
  143. #endif
  144. #ifdef RT_USING_MUTEX
  145. int list_mutex()
  146. {
  147. struct rt_mutex *m;
  148. struct rt_list_node *list, *node;
  149. list = &rt_object_container[RT_Object_Class_Mutex].object_list;
  150. rt_kprintf("mutex owner hold suspend thread\n");
  151. rt_kprintf("-------- -------- ---- --------------\n");
  152. for (node = list->next; node != list; node = node->next)
  153. {
  154. m = (struct rt_mutex*)(rt_list_entry(node, struct rt_object, list));
  155. rt_kprintf("%-8s %-8s %04d %d\n", m->parent.parent.name, m->owner->name, m->hold, rt_list_len(&m->parent.suspend_thread));
  156. }
  157. return 0;
  158. }
  159. FINSH_FUNCTION_EXPORT(list_mutex, list mutex in system)
  160. #endif
  161. #ifdef RT_USING_MAILBOX
  162. int list_mailbox()
  163. {
  164. struct rt_mailbox *m;
  165. struct rt_list_node *list, *node;
  166. list = &rt_object_container[RT_Object_Class_MailBox].object_list;
  167. rt_kprintf("mailbox entry size suspend thread\n");
  168. rt_kprintf("-------- ---- ---- --------------\n");
  169. for (node = list->next; node != list; node = node->next)
  170. {
  171. m = (struct rt_mailbox*)(rt_list_entry(node, struct rt_object, list));
  172. if( !rt_list_isempty(&m->parent.suspend_thread) )
  173. {
  174. rt_kprintf("%-8s %04d %04d %d:", m->parent.parent.name, m->entry, m->size, rt_list_len(&m->parent.suspend_thread));
  175. show_wait_queue(&(m->parent.suspend_thread));
  176. rt_kprintf("\n");
  177. }
  178. else
  179. {
  180. rt_kprintf("%-8s %04d %04d %d\n", m->parent.parent.name, m->entry, m->size, rt_list_len(&m->parent.suspend_thread));
  181. }
  182. }
  183. return 0;
  184. }
  185. FINSH_FUNCTION_EXPORT(list_mailbox, list mail box in system)
  186. #endif
  187. #ifdef RT_USING_MESSAGEQUEUE
  188. int list_msgqueue()
  189. {
  190. struct rt_messagequeue *m;
  191. struct rt_list_node *list, *node;
  192. list = &rt_object_container[RT_Object_Class_MessageQueue].object_list;
  193. rt_kprintf("msgqueue entry suspend thread\n");
  194. rt_kprintf("-------- ---- --------------\n");
  195. for (node = list->next; node != list; node = node->next)
  196. {
  197. m = (struct rt_messagequeue*)(rt_list_entry(node, struct rt_object, list));
  198. if( !rt_list_isempty(&m->parent.suspend_thread) )
  199. {
  200. rt_kprintf("%-8s %04d %d:", m->parent.parent.name, m->entry, rt_list_len(&m->parent.suspend_thread));
  201. show_wait_queue(&(m->parent.suspend_thread));
  202. rt_kprintf("\n");
  203. }
  204. else
  205. {
  206. rt_kprintf("%-8s %04d %d\n", m->parent.parent.name, m->entry, rt_list_len(&m->parent.suspend_thread));
  207. }
  208. }
  209. return 0;
  210. }
  211. FINSH_FUNCTION_EXPORT(list_msgqueue, list message queue in system)
  212. #endif
  213. #ifdef RT_USING_MEMPOOL
  214. int list_mempool()
  215. {
  216. struct rt_mempool *mp;
  217. struct rt_list_node *list, *node;
  218. list = &rt_object_container[RT_Object_Class_MemPool].object_list;
  219. rt_kprintf("mempool block total free suspend thread\n");
  220. rt_kprintf("-------- ---- ---- ---- --------------\n");
  221. for (node = list->next; node != list; node = node->next)
  222. {
  223. mp = (struct rt_mempool*)rt_list_entry(node, struct rt_object, list);
  224. if (mp->suspend_thread_count > 0)
  225. {
  226. rt_kprintf("%-8s %04d %04d %04d %d:", mp->parent.name,
  227. mp->block_size, mp->block_total_count, mp->block_free_count,
  228. mp->suspend_thread_count);
  229. show_wait_queue(&(mp->suspend_thread));
  230. rt_kprintf("\n");
  231. }
  232. else
  233. {
  234. rt_kprintf("%-8s %04d %04d %04d %d\n", mp->parent.name,
  235. mp->block_size, mp->block_total_count, mp->block_free_count,
  236. mp->suspend_thread_count);
  237. }
  238. }
  239. return 0;
  240. }
  241. FINSH_FUNCTION_EXPORT(list_mempool, list memory pool in system)
  242. #endif
  243. int list_timer()
  244. {
  245. struct rt_timer *timer;
  246. struct rt_list_node *list, *node;
  247. list = &rt_object_container[RT_Object_Class_Timer].object_list;
  248. rt_kprintf("timer periodic timeout flag\n");
  249. rt_kprintf("-------- ---------- ---------- -----------\n");
  250. for (node = list->next; node != list; node = node->next)
  251. {
  252. timer = (struct rt_timer*)(rt_list_entry(node, struct rt_object, list));
  253. rt_kprintf("%-8s 0x%08x 0x%08x ", timer->parent.name, timer->init_tick, timer->timeout_tick);
  254. if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED) rt_kprintf("activated\n");
  255. else rt_kprintf("deactivated\n");
  256. }
  257. rt_kprintf("current tick:0x%08x\n", rt_tick_get());
  258. return 0;
  259. }
  260. FINSH_FUNCTION_EXPORT(list_timer, list timer in system)
  261. #ifdef RT_USING_DEVICE
  262. int list_device()
  263. {
  264. struct rt_device *device;
  265. struct rt_list_node *list, *node;
  266. const char *device_type_str[] =
  267. {
  268. "Character Device",
  269. "Block Device",
  270. "Network Interface",
  271. "MTD Device",
  272. "CAN",
  273. "RTC",
  274. "Unknown"
  275. };
  276. list = &rt_object_container[RT_Object_Class_Device].object_list;
  277. rt_kprintf("device type \n");
  278. rt_kprintf("-------- ---------- \n");
  279. for (node = list->next; node != list; node = node->next)
  280. {
  281. device = (struct rt_device*)(rt_list_entry(node, struct rt_object, list));
  282. rt_kprintf("%-8s %-8s \n", device->parent.name, device_type_str[device->type]);
  283. }
  284. return 0;
  285. }
  286. FINSH_FUNCTION_EXPORT(list_device, list device in system)
  287. #endif
  288. int list()
  289. {
  290. struct finsh_syscall_item* syscall_item;
  291. struct finsh_sysvar_item* sysvar_item;
  292. rt_kprintf("--Function List:\n");
  293. {
  294. struct finsh_syscall* index;
  295. for (index = _syscall_table_begin; index < _syscall_table_end; index ++)
  296. {
  297. #ifdef FINSH_USING_DESCRIPTION
  298. rt_kprintf("%-16s -- %s\n", index->name, index->desc);
  299. #else
  300. rt_kprintf("%s\n", index->name);
  301. #endif
  302. }
  303. }
  304. /* list syscall list */
  305. syscall_item = global_syscall_list;
  306. while (syscall_item != NULL)
  307. {
  308. rt_kprintf("[l] %s\n", syscall_item->syscall.name);
  309. syscall_item = syscall_item->next;
  310. }
  311. rt_kprintf("--Variable List:\n");
  312. {
  313. struct finsh_sysvar* index;
  314. for (index = _sysvar_table_begin; index < _sysvar_table_end; index ++)
  315. {
  316. #ifdef FINSH_USING_DESCRIPTION
  317. rt_kprintf("%-16s -- %s\n", index->name, index->desc);
  318. #else
  319. rt_kprintf("%s\n", index->name);
  320. #endif
  321. }
  322. }
  323. sysvar_item = global_sysvar_list;
  324. while (sysvar_item != NULL)
  325. {
  326. rt_kprintf("[l] %s\n", sysvar_item->sysvar.name);
  327. sysvar_item = sysvar_item->next;
  328. }
  329. return 0;
  330. }
  331. FINSH_FUNCTION_EXPORT(list, list all symbol in system)
  332. static int str_is_prefix(const char* prefix, const char* str)
  333. {
  334. while ((*prefix) && (*prefix == *str))
  335. {
  336. prefix ++;
  337. str ++;
  338. }
  339. if (*prefix == 0) return 0;
  340. return -1;
  341. }
  342. void list_prefix(char* prefix)
  343. {
  344. struct finsh_syscall_item* syscall_item;
  345. struct finsh_sysvar_item* sysvar_item;
  346. rt_uint16_t func_cnt, var_cnt;
  347. const char* name_ptr;
  348. func_cnt = 0;
  349. var_cnt = 0;
  350. name_ptr = RT_NULL;
  351. {
  352. struct finsh_syscall* index;
  353. for (index = _syscall_table_begin; index < _syscall_table_end; index ++)
  354. {
  355. if (str_is_prefix(prefix, index->name) == 0)
  356. {
  357. if (func_cnt == 0)
  358. rt_kprintf("--function:\n");
  359. func_cnt ++;
  360. /* set name_ptr */
  361. name_ptr = index->name;
  362. #ifdef FINSH_USING_DESCRIPTION
  363. rt_kprintf("%-16s -- %s\n", index->name, index->desc);
  364. #else
  365. rt_kprintf("%s\n", index->name);
  366. #endif
  367. }
  368. }
  369. }
  370. /* list syscall list */
  371. syscall_item = global_syscall_list;
  372. while (syscall_item != NULL)
  373. {
  374. if (str_is_prefix(prefix, syscall_item->syscall.name) == 0)
  375. {
  376. if (func_cnt == 0)
  377. rt_kprintf("--function:\n");
  378. func_cnt ++;
  379. /* set name_ptr */
  380. name_ptr = syscall_item->syscall.name;
  381. rt_kprintf("[l] %s\n", syscall_item->syscall.name);
  382. }
  383. syscall_item = syscall_item->next;
  384. }
  385. {
  386. struct finsh_sysvar* index;
  387. for (index = _sysvar_table_begin; index < _sysvar_table_end; index ++)
  388. {
  389. if (str_is_prefix(prefix, index->name) == 0)
  390. {
  391. if (var_cnt == 0)
  392. rt_kprintf("--variable:\n");
  393. var_cnt ++;
  394. /* set name ptr */
  395. name_ptr = index->name;
  396. #ifdef FINSH_USING_DESCRIPTION
  397. rt_kprintf("%-16s -- %s\n", index->name, index->desc);
  398. #else
  399. rt_kprintf("%s\n", index->name);
  400. #endif
  401. }
  402. }
  403. }
  404. sysvar_item = global_sysvar_list;
  405. while (sysvar_item != NULL)
  406. {
  407. if (str_is_prefix(prefix, sysvar_item->sysvar.name) == 0)
  408. {
  409. if (var_cnt == 0)
  410. rt_kprintf("--variable:\n");
  411. var_cnt ++;
  412. /* set name ptr */
  413. name_ptr = sysvar_item->sysvar.name;
  414. rt_kprintf("[l] %s\n", sysvar_item->sysvar.name);
  415. }
  416. sysvar_item = sysvar_item->next;
  417. }
  418. /* only one matched */
  419. if ((func_cnt + var_cnt) == 1)
  420. {
  421. rt_strncpy(prefix, name_ptr, strlen(name_ptr));
  422. }
  423. }
  424. #ifdef FINSH_USING_SYMTAB
  425. static int dummy = 0;
  426. FINSH_VAR_EXPORT(dummy, finsh_type_int, dummy variable for finsh)
  427. #endif