cmd.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  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. rt_kprintf("%-8s %04d %d\n", m->parent.parent.name, m->entry, rt_list_len(&m->parent.suspend_thread));
  199. }
  200. return 0;
  201. }
  202. FINSH_FUNCTION_EXPORT(list_msgqueue, list message queue in system)
  203. #endif
  204. #ifdef RT_USING_MEMPOOL
  205. int list_mempool()
  206. {
  207. struct rt_mempool *mp;
  208. struct rt_list_node *list, *node;
  209. list = &rt_object_container[RT_Object_Class_MemPool].object_list;
  210. rt_kprintf("mempool block total free suspend thread\n");
  211. rt_kprintf("-------- ---- ---- ---- --------------\n");
  212. for (node = list->next; node != list; node = node->next)
  213. {
  214. mp = (struct rt_mempool*)rt_list_entry(node, struct rt_object, list);
  215. if (mp->suspend_thread_count > 0)
  216. {
  217. rt_kprintf("%-8s %04d %04d %04d %d:", mp->parent.name,
  218. mp->block_size, mp->block_total_count, mp->block_free_count,
  219. mp->suspend_thread_count);
  220. show_wait_queue(&(mp->suspend_thread));
  221. rt_kprintf("\n");
  222. }
  223. else
  224. {
  225. rt_kprintf("%-8s %04d %04d %04d %d\n", mp->parent.name,
  226. mp->block_size, mp->block_total_count, mp->block_free_count,
  227. mp->suspend_thread_count);
  228. }
  229. }
  230. return 0;
  231. }
  232. FINSH_FUNCTION_EXPORT(list_mempool, list memory pool in system)
  233. #endif
  234. int list_timer()
  235. {
  236. struct rt_timer *timer;
  237. struct rt_list_node *list, *node;
  238. list = &rt_object_container[RT_Object_Class_Timer].object_list;
  239. rt_kprintf("timer periodic timeout flag\n");
  240. rt_kprintf("-------- ---------- ---------- -----------\n");
  241. for (node = list->next; node != list; node = node->next)
  242. {
  243. timer = (struct rt_timer*)(rt_list_entry(node, struct rt_object, list));
  244. rt_kprintf("%-8s 0x%08x 0x%08x ", timer->parent.name, timer->init_tick, timer->timeout_tick);
  245. if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED) rt_kprintf("activated\n");
  246. else rt_kprintf("deactivated\n");
  247. }
  248. rt_kprintf("current tick:0x%08x\n", rt_tick_get());
  249. return 0;
  250. }
  251. FINSH_FUNCTION_EXPORT(list_timer, list timer in system)
  252. #ifdef RT_USING_DEVICE
  253. int list_device()
  254. {
  255. struct rt_device *device;
  256. struct rt_list_node *list, *node;
  257. const char *device_type_str[] =
  258. {
  259. "Character Device",
  260. "Block Device",
  261. "Network Interface",
  262. "MTD Device",
  263. "CAN",
  264. "RTC",
  265. "Unknown"
  266. };
  267. list = &rt_object_container[RT_Object_Class_Device].object_list;
  268. rt_kprintf("device type \n");
  269. rt_kprintf("-------- ---------- \n");
  270. for (node = list->next; node != list; node = node->next)
  271. {
  272. device = (struct rt_device*)(rt_list_entry(node, struct rt_object, list));
  273. rt_kprintf("%-8s %-8s \n", device->parent.name, device_type_str[device->type]);
  274. }
  275. return 0;
  276. }
  277. FINSH_FUNCTION_EXPORT(list_device, list device in system)
  278. #endif
  279. int list()
  280. {
  281. struct finsh_syscall_item* syscall_item;
  282. struct finsh_sysvar_item* sysvar_item;
  283. rt_kprintf("--Function List:\n");
  284. {
  285. struct finsh_syscall* index;
  286. for (index = _syscall_table_begin; index < _syscall_table_end; index ++)
  287. {
  288. #ifdef FINSH_USING_DESCRIPTION
  289. rt_kprintf("%-16s -- %s\n", index->name, index->desc);
  290. #else
  291. rt_kprintf("%s\n", index->name);
  292. #endif
  293. }
  294. }
  295. /* list syscall list */
  296. syscall_item = global_syscall_list;
  297. while (syscall_item != NULL)
  298. {
  299. rt_kprintf("[l] %s\n", syscall_item->syscall.name);
  300. syscall_item = syscall_item->next;
  301. }
  302. rt_kprintf("--Variable List:\n");
  303. {
  304. struct finsh_sysvar* index;
  305. for (index = _sysvar_table_begin; index < _sysvar_table_end; index ++)
  306. {
  307. #ifdef FINSH_USING_DESCRIPTION
  308. rt_kprintf("%-16s -- %s\n", index->name, index->desc);
  309. #else
  310. rt_kprintf("%s\n", index->name);
  311. #endif
  312. }
  313. }
  314. sysvar_item = global_sysvar_list;
  315. while (sysvar_item != NULL)
  316. {
  317. rt_kprintf("[l] %s\n", sysvar_item->sysvar.name);
  318. sysvar_item = sysvar_item->next;
  319. }
  320. return 0;
  321. }
  322. FINSH_FUNCTION_EXPORT(list, list all symbol in system)
  323. static int str_is_prefix(const char* prefix, const char* str)
  324. {
  325. while ((*prefix) && (*prefix == *str))
  326. {
  327. prefix ++;
  328. str ++;
  329. }
  330. if (*prefix == 0) return 0;
  331. return -1;
  332. }
  333. void list_prefix(char* prefix)
  334. {
  335. struct finsh_syscall_item* syscall_item;
  336. struct finsh_sysvar_item* sysvar_item;
  337. rt_uint16_t func_cnt, var_cnt;
  338. const char* name_ptr;
  339. func_cnt = 0;
  340. var_cnt = 0;
  341. name_ptr = RT_NULL;
  342. {
  343. struct finsh_syscall* index;
  344. for (index = _syscall_table_begin; index < _syscall_table_end; index ++)
  345. {
  346. if (str_is_prefix(prefix, index->name) == 0)
  347. {
  348. if (func_cnt == 0)
  349. rt_kprintf("--function:\n");
  350. func_cnt ++;
  351. /* set name_ptr */
  352. name_ptr = index->name;
  353. #ifdef FINSH_USING_DESCRIPTION
  354. rt_kprintf("%-16s -- %s\n", index->name, index->desc);
  355. #else
  356. rt_kprintf("%s\n", index->name);
  357. #endif
  358. }
  359. }
  360. }
  361. /* list syscall list */
  362. syscall_item = global_syscall_list;
  363. while (syscall_item != NULL)
  364. {
  365. if (str_is_prefix(prefix, syscall_item->syscall.name) == 0)
  366. {
  367. if (func_cnt == 0)
  368. rt_kprintf("--function:\n");
  369. func_cnt ++;
  370. /* set name_ptr */
  371. name_ptr = syscall_item->syscall.name;
  372. rt_kprintf("[l] %s\n", syscall_item->syscall.name);
  373. }
  374. syscall_item = syscall_item->next;
  375. }
  376. {
  377. struct finsh_sysvar* index;
  378. for (index = _sysvar_table_begin; index < _sysvar_table_end; index ++)
  379. {
  380. if (str_is_prefix(prefix, index->name) == 0)
  381. {
  382. if (var_cnt == 0)
  383. rt_kprintf("--variable:\n");
  384. var_cnt ++;
  385. /* set name ptr */
  386. name_ptr = index->name;
  387. #ifdef FINSH_USING_DESCRIPTION
  388. rt_kprintf("%-16s -- %s\n", index->name, index->desc);
  389. #else
  390. rt_kprintf("%s\n", index->name);
  391. #endif
  392. }
  393. }
  394. }
  395. sysvar_item = global_sysvar_list;
  396. while (sysvar_item != NULL)
  397. {
  398. if (str_is_prefix(prefix, sysvar_item->sysvar.name) == 0)
  399. {
  400. if (var_cnt == 0)
  401. rt_kprintf("--variable:\n");
  402. var_cnt ++;
  403. /* set name ptr */
  404. name_ptr = sysvar_item->sysvar.name;
  405. rt_kprintf("[l] %s\n", sysvar_item->sysvar.name);
  406. }
  407. sysvar_item = sysvar_item->next;
  408. }
  409. /* only one matched */
  410. if ((func_cnt + var_cnt) == 1)
  411. {
  412. rt_strncpy(prefix, name_ptr, strlen(name_ptr));
  413. }
  414. }
  415. #ifdef FINSH_USING_SYMTAB
  416. static int dummy = 0;
  417. FINSH_VAR_EXPORT(dummy, finsh_type_int, dummy variable for finsh)
  418. #endif