sysrq.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * Copyright (c) 2017 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief Magic System Request Key Hacks
  9. *
  10. */
  11. #include <kernel.h>
  12. #include <drivers/uart.h>
  13. #include <soc.h>
  14. struct sysrq_key_op {
  15. char key;
  16. char reserved[3];
  17. void (*handler)(int);
  18. char *help_msg;
  19. char *action_msg;
  20. };
  21. static bool b_sysrq_in;
  22. #if CONFIG_KERNEL_SHOW_STACK
  23. extern void show_stack(void);
  24. static void sysrq_handle_show_stack(int key)
  25. {
  26. show_stack();
  27. }
  28. #endif
  29. static void sysrq_handle_change_jtag(int key)
  30. {
  31. jtag_set();
  32. b_sysrq_in = false;
  33. }
  34. #if defined(CONFIG_INIT_STACKS) && defined(CONFIG_THREAD_STACK_INFO) && defined(CONFIG_THREAD_MONITOR)
  35. static void sysrq_stack_dump(const struct k_thread *thread, void *user_data)
  36. {
  37. unsigned int pcnt;
  38. size_t unused;
  39. size_t size = thread->stack_info.size;
  40. const char *tname;
  41. int ret;
  42. ret = k_thread_stack_space_get(thread, &unused);
  43. if (ret) {
  44. printk("Unable to determine unused stack size (%d)\n", ret);
  45. return;
  46. }
  47. tname = k_thread_name_get((struct k_thread *)thread);
  48. /* Calculate the real size reserved for the stack */
  49. pcnt = ((size - unused) * 100U) / size;
  50. printk("%p %-10s (real size %u):\tunused %u\tusage %u / %u (%u %%)\n",
  51. thread,
  52. tname ? tname : "NA",
  53. size, unused, size - unused, size, pcnt);
  54. }
  55. static void sysrq_handle_stack_dump(int key)
  56. {
  57. k_thread_foreach(sysrq_stack_dump, NULL);
  58. }
  59. #endif
  60. static const struct sysrq_key_op sysrq_key_table[] = {
  61. #ifdef CONFIG_KERNEL_SHOW_STACK
  62. {
  63. .key = 't',
  64. .handler = sysrq_handle_show_stack,
  65. .help_msg = "show-thread-states(t)",
  66. .action_msg = "Show State:",
  67. },
  68. #endif
  69. {
  70. .key = 'j',
  71. .handler = sysrq_handle_change_jtag,
  72. .help_msg = "change jtag to grp1 (j)",
  73. .action_msg = "jtag:",
  74. },
  75. #if defined(CONFIG_INIT_STACKS) && defined(CONFIG_THREAD_STACK_INFO) && defined(CONFIG_THREAD_MONITOR)
  76. {
  77. .key = 's',
  78. .handler = sysrq_handle_stack_dump,
  79. .help_msg = "show thread stack usage (s)",
  80. .action_msg = "stack usage:",
  81. },
  82. #endif
  83. };
  84. /* magic sysrq key: CTLR + 'b' 'r' 'e' 'a' 'k' */
  85. static const char sysrq_breakbuf[] = {0x02, 0x12, 0x05, 0x01, 0x0b};
  86. static uint8_t sysrq_break_idx;
  87. static void (*sysrq_user_handler)(const struct device * port, char c);
  88. void sysrq_register_user_handler(void (*callback)(const struct device * port, char c))
  89. {
  90. sysrq_user_handler = callback;
  91. }
  92. static struct sysrq_key_op* sysrq_get_key_op(char key)
  93. {
  94. int i, cnt;
  95. cnt = ARRAY_SIZE(sysrq_key_table);
  96. for (i = 0; i < cnt; i++) {
  97. if (key == sysrq_key_table[i].key) {
  98. return (struct sysrq_key_op*)&sysrq_key_table[i];
  99. }
  100. }
  101. return NULL;
  102. }
  103. static void sysrq_print_help(void)
  104. {
  105. int i;
  106. printk("HELP : quit(q) \n");
  107. for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) {
  108. printk("%s \n", sysrq_key_table[i].help_msg);
  109. }
  110. printk("\n");
  111. }
  112. extern void printk_dma_switch(int sw_dma);
  113. static void handle_sysrq_main(const struct device * port)
  114. {
  115. struct sysrq_key_op* op_p;
  116. char key;
  117. #ifdef CONFIG_ACTIONS_PRINTK_DMA
  118. printk_dma_switch(0);
  119. #endif
  120. b_sysrq_in = true;
  121. while(b_sysrq_in) {
  122. printk("Wait SYSRQ Key:\n");
  123. sysrq_print_help();
  124. uart_poll_in(port, &key);
  125. if (key == 'q') {
  126. printk("sysrq: exit\n");
  127. break;
  128. }
  129. op_p = sysrq_get_key_op(key);
  130. if (op_p) {
  131. printk("%s\n", op_p->action_msg);
  132. op_p->handler(key);
  133. } else {
  134. sysrq_print_help();
  135. }
  136. }
  137. #ifdef CONFIG_ACTIONS_PRINTK_DMA
  138. printk_dma_switch(1);
  139. #endif
  140. }
  141. extern void handle_sysrq_tool_main(const struct device * port, int key_size);
  142. void uart_handle_sysrq_char(const struct device * port, char c)
  143. {
  144. if (c == sysrq_breakbuf[sysrq_break_idx]) {
  145. sysrq_break_idx++;
  146. if (sysrq_break_idx == sizeof(sysrq_breakbuf)) {
  147. sysrq_break_idx = 0;
  148. handle_sysrq_main(port);
  149. uart_fifo_read(port, (uint8_t*)&c, 1); //clr irq
  150. }
  151. } else {
  152. sysrq_break_idx = 0;
  153. }
  154. if (sysrq_user_handler){
  155. sysrq_user_handler(port, c);
  156. }
  157. }
  158. #if !defined(CONFIG_SHELL) && defined(CONFIG_UART_CONSOLE_ON_DEV_NAME)
  159. static const struct device *uart_sysrq_dev;
  160. static void uart_sysrq_isr(const struct device *unused, void *user_data)
  161. {
  162. uint8_t byte;
  163. while (uart_irq_update(uart_sysrq_dev) &&
  164. uart_irq_is_pending(uart_sysrq_dev)) {
  165. if (!uart_irq_rx_ready(uart_sysrq_dev)) {
  166. continue;
  167. }
  168. if(uart_fifo_read(uart_sysrq_dev, &byte, 1) < 0)
  169. break;
  170. uart_handle_sysrq_char(uart_sysrq_dev, byte);
  171. }
  172. }
  173. static int uart_sysrq_init(const struct device *arg)
  174. {
  175. ARG_UNUSED(arg);
  176. uart_sysrq_dev = device_get_binding(CONFIG_UART_CONSOLE_ON_DEV_NAME);
  177. if(uart_sysrq_dev== NULL){
  178. printk("sysrq uart dev err\n");
  179. return -1;
  180. }
  181. uart_irq_callback_set(uart_sysrq_dev, uart_sysrq_isr);
  182. uart_irq_rx_enable(uart_sysrq_dev);
  183. printk("uart_sysrq_init\n");
  184. return 0;
  185. }
  186. SYS_INIT(uart_sysrq_init, APPLICATION, 10);
  187. #endif