rt_kprintf.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Copyright (c) 2021, Meco Jianting Man <jiantingman@foxmail.com>
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-12-15 Meco Man first version
  9. */
  10. #include <rtthread.h>
  11. #include <rthw.h>
  12. #ifndef RT_USING_CONSOLE
  13. #error "Please enable console"
  14. #endif
  15. /**
  16. * This function will print a formatted string on system console (thread safe)
  17. *
  18. * @param fmt the format
  19. */
  20. #if (RTTHREAD_VERSION >= 40100) || (RTTHREAD_VERSION < 40000 && RTTHREAD_VERSION >= 30106)
  21. int rt_kprintf(const char *fmt, ...)
  22. #else
  23. void rt_kprintf(const char *fmt, ...)
  24. #endif
  25. {
  26. va_list args;
  27. rt_size_t length;
  28. rt_device_t console_dev;
  29. static char rt_console_buf[RT_CONSOLEBUF_SIZE];
  30. #if defined RT_USING_MUTEX || defined RT_USING_SEMAPHORE
  31. static unsigned char kprintf_init_flag = RT_FALSE;
  32. #if defined RT_USING_MUTEX
  33. static struct rt_mutex kprintf_mutex;
  34. #elif defined RT_USING_SEMAPHORE
  35. static struct rt_semaphore kprintf_sem;
  36. #endif /*defined RT_USING_MUTEX*/
  37. #endif /*defined RT_USING_MUTEX || defined RT_USING_SEMAPHORE*/
  38. if(rt_interrupt_get_nest() == 0u && rt_thread_self() != RT_NULL)
  39. {
  40. #if defined RT_USING_MUTEX || defined RT_USING_SEMAPHORE
  41. if(kprintf_init_flag == RT_FALSE)
  42. {
  43. #if defined RT_USING_MUTEX
  44. rt_mutex_init(&kprintf_mutex, "kprintf", RT_IPC_FLAG_FIFO);
  45. #elif defined RT_USING_SEMAPHORE
  46. rt_sem_init(&kprintf_sem, "kprintf", 1, RT_IPC_FLAG_FIFO);
  47. #endif /*defined RT_USING_MUTEX*/
  48. kprintf_init_flag = RT_TRUE;
  49. }
  50. #if defined RT_USING_MUTEX
  51. rt_mutex_take(&kprintf_mutex, RT_WAITING_FOREVER);
  52. #elif defined RT_USING_SEMAPHORE
  53. rt_sem_take(&kprintf_sem, RT_WAITING_FOREVER);
  54. #endif /*defined RT_USING_MUTEX*/
  55. #else
  56. rt_enter_critical();
  57. #endif /*defined RT_USING_MUTEX || defined RT_USING_SEMAPHORE*/
  58. }
  59. console_dev = rt_console_get_device();
  60. va_start(args, fmt);
  61. /* the return value of vsnprintf is the number of bytes that would be
  62. * written to buffer had if the size of the buffer been sufficiently
  63. * large excluding the terminating null byte. If the output string
  64. * would be larger than the rt_console_buf, we have to adjust the output
  65. * length. */
  66. length = rt_vsnprintf(rt_console_buf, sizeof(rt_console_buf) - 1, fmt, args);
  67. if (length > RT_CONSOLEBUF_SIZE - 1)
  68. length = RT_CONSOLEBUF_SIZE - 1;
  69. #ifdef RT_USING_DEVICE
  70. if (console_dev == RT_NULL)
  71. {
  72. rt_hw_console_output(rt_console_buf);
  73. }
  74. else
  75. {
  76. rt_uint16_t old_flag = console_dev->open_flag;
  77. console_dev->open_flag |= RT_DEVICE_FLAG_STREAM;
  78. rt_device_write(console_dev, 0, rt_console_buf, length);
  79. console_dev->open_flag = old_flag;
  80. }
  81. #else
  82. rt_hw_console_output(rt_console_buf);
  83. #endif /*RT_USING_DEVICE*/
  84. va_end(args);
  85. if(rt_interrupt_get_nest() == 0u &&
  86. #if defined RT_USING_MUTEX || defined RT_USING_SEMAPHORE
  87. kprintf_init_flag == RT_TRUE &&
  88. #endif
  89. rt_thread_self() != RT_NULL)
  90. {
  91. #if defined RT_USING_MUTEX || defined RT_USING_SEMAPHORE
  92. #if defined RT_USING_MUTEX
  93. rt_mutex_release(&kprintf_mutex);
  94. #elif defined RT_USING_SEMAPHORE
  95. rt_sem_release(&kprintf_sem);
  96. #endif /*defined RT_USING_MUTEX*/
  97. #else
  98. rt_exit_critical();
  99. #endif /*defined RT_USING_MUTEX || defined RT_USING_SEMAPHORE*/
  100. }
  101. #if (RTTHREAD_VERSION >= 40100) || (RTTHREAD_VERSION < 40000 && RTTHREAD_VERSION >= 30106)
  102. return length; /* the total number of printed characters */
  103. #endif
  104. }