tinyusb_console_be.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include <rtthread.h>
  2. #ifdef PKG_USING_AGILE_CONSOLE
  3. #ifdef PKG_AGILE_CONSOLE_USING_TINYUSB
  4. #include <stdint.h>
  5. #include <rtdevice.h>
  6. #include <agile_console.h>
  7. #include <tusb.h>
  8. ALIGN(RT_ALIGN_SIZE)
  9. static struct rt_semaphore _sem;
  10. static struct rt_timer _timer;
  11. static struct rt_ringbuffer _rb;
  12. static uint8_t _rb_buf[1024];
  13. static struct rt_thread _thread;
  14. static uint8_t _thread_stack[512];
  15. static struct agile_console_backend _console_backend = {0};
  16. static uint8_t _shield_flag = 0;
  17. static void console_backend_output(rt_device_t dev, const uint8_t *buf, int len)
  18. {
  19. if (_shield_flag)
  20. return;
  21. if (!tud_cdc_connected())
  22. return;
  23. rt_base_t level = rt_hw_interrupt_disable();
  24. if (dev->open_flag & RT_DEVICE_FLAG_STREAM) {
  25. while (len > 0) {
  26. if (*buf == '\n') {
  27. if (rt_ringbuffer_putchar(&_rb, '\r') == 0)
  28. break;
  29. }
  30. if (rt_ringbuffer_putchar(&_rb, *buf) == 0)
  31. break;
  32. ++buf;
  33. --len;
  34. }
  35. } else
  36. rt_ringbuffer_put(&_rb, buf, len);
  37. rt_hw_interrupt_enable(level);
  38. rt_sem_release(&_sem);
  39. }
  40. static int console_backend_read(rt_device_t dev, uint8_t *buf, int len)
  41. {
  42. if (_shield_flag)
  43. return 0;
  44. if (!tud_cdc_connected())
  45. return 0;
  46. if (!tud_cdc_available())
  47. return 0;
  48. return tud_cdc_read(buf, len);
  49. }
  50. static void timer_timeout(void *parameter)
  51. {
  52. if (_shield_flag)
  53. return;
  54. if (tud_cdc_available())
  55. agile_console_wakeup();
  56. }
  57. static void con_usb_output_entry(void *parameter)
  58. {
  59. rt_base_t level;
  60. rt_uint8_t *send_ptr = RT_NULL;
  61. int send_len;
  62. while (1) {
  63. do {
  64. level = rt_hw_interrupt_disable();
  65. send_len = rt_ringbuffer_peak(&_rb, &send_ptr);
  66. rt_hw_interrupt_enable(level);
  67. if (send_len > 0) {
  68. if (_shield_flag)
  69. continue;
  70. if (!tud_cdc_connected())
  71. continue;
  72. tud_cdc_write(send_ptr, send_len);
  73. tud_cdc_write_flush();
  74. }
  75. } while (send_len > 0);
  76. rt_sem_take(&_sem, RT_WAITING_FOREVER);
  77. rt_sem_control(&_sem, RT_IPC_CMD_RESET, RT_NULL);
  78. }
  79. }
  80. static int tinyusb_console_init(void)
  81. {
  82. rt_sem_init(&_sem, "con_usb", 0, RT_IPC_FLAG_FIFO);
  83. rt_timer_init(&_timer, "con_usb", timer_timeout, RT_NULL, 10, RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_PERIODIC);
  84. rt_timer_start(&_timer);
  85. rt_ringbuffer_init(&_rb, _rb_buf, sizeof(_rb_buf));
  86. _console_backend.output = console_backend_output;
  87. _console_backend.read = console_backend_read;
  88. agile_console_backend_register(&_console_backend);
  89. rt_thread_init(&_thread,
  90. "con_usb",
  91. con_usb_output_entry,
  92. RT_NULL,
  93. &_thread_stack[0],
  94. sizeof(_thread_stack),
  95. RT_THREAD_PRIORITY_MAX - 6,
  96. 100);
  97. rt_thread_startup(&_thread);
  98. return RT_EOK;
  99. }
  100. INIT_ENV_EXPORT(tinyusb_console_init);
  101. static int tinyusb_console_disable(void)
  102. {
  103. _shield_flag = 1;
  104. return RT_EOK;
  105. }
  106. MSH_CMD_EXPORT(tinyusb_console_disable, disable tinyusb console);
  107. static int tinyusb_console_enable(void)
  108. {
  109. _shield_flag = 0;
  110. tud_cdc_read_flush();
  111. return RT_EOK;
  112. }
  113. MSH_CMD_EXPORT(tinyusb_console_enable, enable tinyusb console);
  114. #endif /* PKG_AGILE_CONSOLE_USING_TINYUSB */
  115. #endif /* PKG_USING_AGILE_CONSOLE */