log_backend_uart.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * Copyright (c) 2018 Nordic Semiconductor ASA
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <logging/log_backend.h>
  7. #include <logging/log_core.h>
  8. #include <logging/log_msg.h>
  9. #include <logging/log_output.h>
  10. #include <logging/log_output_dict.h>
  11. #include <logging/log_backend_std.h>
  12. #include <device.h>
  13. #include <drivers/uart.h>
  14. #include <sys/__assert.h>
  15. /* Fixed size to avoid auto-added trailing '\0'.
  16. * Used if CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY_HEX.
  17. */
  18. static const char LOG_HEX_SEP[10] = "##ZLOGV1##";
  19. static const struct device *uart_dev;
  20. static int char_out(uint8_t *data, size_t length, void *ctx)
  21. {
  22. ARG_UNUSED(ctx);
  23. for (size_t i = 0; i < length; i++) {
  24. #if defined(CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY_HEX)
  25. char c;
  26. uint8_t x;
  27. /* upper 8-bit */
  28. x = data[i] >> 4;
  29. (void)hex2char(x, &c);
  30. uart_poll_out(uart_dev, c);
  31. /* lower 8-bit */
  32. x = data[i] & 0x0FU;
  33. (void)hex2char(x, &c);
  34. uart_poll_out(uart_dev, c);
  35. #else
  36. uart_poll_out(uart_dev, data[i]);
  37. #endif
  38. }
  39. return length;
  40. }
  41. static uint8_t uart_output_buf;
  42. LOG_OUTPUT_DEFINE(log_output_uart, char_out, &uart_output_buf, 1);
  43. static void put(const struct log_backend *const backend,
  44. struct log_msg *msg)
  45. {
  46. uint32_t flag = IS_ENABLED(CONFIG_LOG_BACKEND_UART_SYST_ENABLE) ?
  47. LOG_OUTPUT_FLAG_FORMAT_SYST : 0;
  48. log_backend_std_put(&log_output_uart, flag, msg);
  49. }
  50. static void process(const struct log_backend *const backend,
  51. union log_msg2_generic *msg)
  52. {
  53. uint32_t flags = log_backend_std_get_flags();
  54. if (IS_ENABLED(CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY)) {
  55. log_dict_output_msg2_process(&log_output_uart,
  56. &msg->log, flags);
  57. } else {
  58. log_output_msg2_process(&log_output_uart, &msg->log, flags);
  59. }
  60. }
  61. static void log_backend_uart_init(struct log_backend const *const backend)
  62. {
  63. uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
  64. __ASSERT_NO_MSG(device_is_ready(uart_dev));
  65. if (IS_ENABLED(CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY_HEX)) {
  66. /* Print a separator so the output can be fed into
  67. * log parser directly. This is useful when capturing
  68. * from UART directly where there might be other output
  69. * (e.g. bootloader).
  70. */
  71. for (int i = 0; i < sizeof(LOG_HEX_SEP); i++) {
  72. uart_poll_out(uart_dev, LOG_HEX_SEP[i]);
  73. }
  74. }
  75. }
  76. static void panic(struct log_backend const *const backend)
  77. {
  78. log_backend_std_panic(&log_output_uart);
  79. }
  80. static void dropped(const struct log_backend *const backend, uint32_t cnt)
  81. {
  82. ARG_UNUSED(backend);
  83. if (IS_ENABLED(CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY)) {
  84. log_dict_output_dropped_process(&log_output_uart, cnt);
  85. } else {
  86. log_backend_std_dropped(&log_output_uart, cnt);
  87. }
  88. }
  89. static void sync_string(const struct log_backend *const backend,
  90. struct log_msg_ids src_level, uint32_t timestamp,
  91. const char *fmt, va_list ap)
  92. {
  93. uint32_t flag = IS_ENABLED(CONFIG_LOG_BACKEND_UART_SYST_ENABLE) ?
  94. LOG_OUTPUT_FLAG_FORMAT_SYST : 0;
  95. log_backend_std_sync_string(&log_output_uart, flag, src_level,
  96. timestamp, fmt, ap);
  97. }
  98. static void sync_hexdump(const struct log_backend *const backend,
  99. struct log_msg_ids src_level, uint32_t timestamp,
  100. const char *metadata, const uint8_t *data, uint32_t length)
  101. {
  102. uint32_t flag = IS_ENABLED(CONFIG_LOG_BACKEND_UART_SYST_ENABLE) ?
  103. LOG_OUTPUT_FLAG_FORMAT_SYST : 0;
  104. log_backend_std_sync_hexdump(&log_output_uart, flag, src_level,
  105. timestamp, metadata, data, length);
  106. }
  107. const struct log_backend_api log_backend_uart_api = {
  108. .process = IS_ENABLED(CONFIG_LOG2) ? process : NULL,
  109. .put = IS_ENABLED(CONFIG_LOG_MODE_DEFERRED) ? put : NULL,
  110. .put_sync_string = IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE) ?
  111. sync_string : NULL,
  112. .put_sync_hexdump = IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE) ?
  113. sync_hexdump : NULL,
  114. .panic = panic,
  115. .init = log_backend_uart_init,
  116. .dropped = IS_ENABLED(CONFIG_LOG_IMMEDIATE) ? NULL : dropped,
  117. };
  118. LOG_BACKEND_DEFINE(log_backend_uart, log_backend_uart_api, true);