uart.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #include "kbf/uart.h"
  2. #include <string_view>
  3. #include <esp_log.h>
  4. #include <driver/uart.h>
  5. #include <freertos/FreeRTOS.h>
  6. #include <freertos/queue.h>
  7. #include "kbf.h"
  8. #include "kbf/macros.h"
  9. using std::string_view;
  10. using namespace kbf;
  11. UART::UART(int port, int baudRate) : port(port) {
  12. ESP_LOGI(TAG, "UART(%d, %d)", port, baudRate);
  13. if (isDriverInstalled(port)) {
  14. ABORT("UART driver already installed");
  15. }
  16. CHECK(uart_driver_install(port, BUFFER_SIZE, 0, 20, &queue, 0));
  17. uart_config_t config = {
  18. .baud_rate = baudRate,
  19. .data_bits = UART_DATA_8_BITS,
  20. .parity = UART_PARITY_DISABLE,
  21. .stop_bits = UART_STOP_BITS_1,
  22. .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
  23. .rx_flow_ctrl_thresh = 0,
  24. .source_clk = UART_SCLK_APB,
  25. };
  26. CHECK(uart_param_config(port, &config));
  27. CHECK(uart_set_pin(port, NO_CHANGE, NO_CHANGE, NO_CHANGE, NO_CHANGE));
  28. task = new rtos::Task("kbf_uart_" + std::to_string(port), taskFunc, this);
  29. }
  30. UART::~UART() {
  31. ESP_LOGI(TAG, "~UART()");
  32. esp_err_t err = uart_wait_tx_done(port, WAIT_ON_DESTROY);
  33. if (err == ESP_ERR_TIMEOUT) {
  34. ESP_LOGE(TAG, "UART TX not done! Data will be corrupted.");
  35. } else {
  36. CHECK_ABORT(err);
  37. }
  38. CHECK_ABORT(uart_driver_delete(port));
  39. }
  40. void UART::setPins(int rx, int tx, int rts, int cts) const {
  41. CHECK(uart_set_pin(port, rx, tx, rts, cts));
  42. }
  43. bool UART::isDriverInstalled(int port) {
  44. return uart_is_driver_installed(port);
  45. }
  46. void UART::write(const string &data) const {
  47. ESP_LOGD(TAG, "write(%s); len = %d", data.c_str(), data.size() + 1);
  48. auto len = uart_write_bytes(port, data.c_str(), data.size() + 1);
  49. if (len < 0) {
  50. ESP_LOGE(TAG, "uart_write_bytes returned %d", len);
  51. return;
  52. }
  53. if (len != data.length() + 1) {
  54. ESP_LOGE(TAG, "sent bytes < data.length()");
  55. throw kbf::exception::KBFError("UART buffering support not yet implemented");
  56. }
  57. }
  58. string UART::read() {
  59. ESP_LOGI(TAG, "read()");
  60. mutex.lock();
  61. buffer.clear();
  62. mutex.unlock();
  63. while (true) {
  64. // TODO this barely works; either use select or RTOS signals
  65. mutex.lock();
  66. if (!buffer.empty()) break;
  67. mutex.unlock();
  68. sleep(200); // FIXME keeps the tests from failing... *sad face*
  69. }
  70. return buffer;
  71. }
  72. void UART::waitFor(const string &signal) {
  73. while (read() != signal);
  74. }
  75. [[noreturn]] void UART::taskFunc(void *uartInstance) {
  76. auto uart = static_cast<UART *>(uartInstance);
  77. uart_event_t event;
  78. while (true) {
  79. if (xQueueReceive(uart->queue, &event, portMAX_DELAY) == pdFALSE) continue;
  80. ESP_LOGD(TAG, "event: %d", event.type);
  81. if (event.type == UART_DATA) {
  82. if (event.size > BUFFER_SIZE) {
  83. ESP_LOGE(TAG, "event size (%d) > buffer size (%d)", event.size, BUFFER_SIZE);
  84. throw kbf::exception::KBFError("fix me");
  85. }
  86. auto buf = new char[BUFFER_SIZE];
  87. int len = uart_read_bytes(uart->port, buf, event.size, portMAX_DELAY);
  88. if (len < 0) CHECK(len);
  89. ESP_LOGD(TAG, "read %d bytes", len);
  90. uart->mutex.lock();
  91. uart->buffer = buf;
  92. if (uart->onRead) uart->onRead(uart->buffer, *uart);
  93. uart->mutex.unlock();
  94. } else {
  95. ESP_LOGW(TAG, "unhandled event: %d", event.type);
  96. }
  97. }
  98. }