esp_uart_spinel_interface.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // Copyright 2021 Espressif Systems (Shanghai) CO LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License
  13. #pragma once
  14. #include "esp_err.h"
  15. #include "esp_openthread.h"
  16. #include "esp_openthread_types.h"
  17. #include "hal/uart_types.h"
  18. #include "lib/spinel/spinel_interface.hpp"
  19. namespace esp {
  20. namespace openthread {
  21. /**
  22. * This class defines an UART interface to the Radio Co-processor (RCP).
  23. *
  24. */
  25. class UartSpinelInterface {
  26. public:
  27. /**
  28. * @brief This constructor of object.
  29. *
  30. * @param[in] callback Callback on frame received
  31. * @param[in] callback_context Callback context
  32. * @param[in] frame_buffer A reference to a `RxFrameBuffer` object.
  33. *
  34. */
  35. UartSpinelInterface(ot::Spinel::SpinelInterface::ReceiveFrameCallback callback,
  36. void *callback_context,
  37. ot::Spinel::SpinelInterface::RxFrameBuffer &frame_buffer);
  38. /**
  39. * @brief This destructor of the object.
  40. *
  41. */
  42. ~UartSpinelInterface(void);
  43. /**
  44. * @brief This method initializes the HDLC interface.
  45. *
  46. * @return
  47. * - ESP_OK on success
  48. * - ESP_ERR_NO_MEM if allocation has failed
  49. * - ESP_ERROR on failure
  50. */
  51. esp_err_t Init(const esp_openthread_uart_config_t &radio_uart_config);
  52. /**
  53. * @brief This method deinitializes the HDLC interface.
  54. *
  55. */
  56. esp_err_t Deinit(void);
  57. /**
  58. * @brief This method encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket.
  59. *
  60. * @note This is blocking call, i.e., if the socket is not writable, this method waits for it to become writable for
  61. * up to `kMaxWaitTime` interval.
  62. *
  63. * @param[in] frame A pointer to buffer containing the spinel frame to send.
  64. * @param[in] length The length (number of bytes) in the frame.
  65. *
  66. * @return
  67. * -OT_ERROR_NONE Successfully encoded and sent the spinel frame.
  68. * -OT_ERROR_NO_BUFS Insufficient buffer space available to encode the frame.
  69. * -OT_ERROR_FAILED Failed to send due to socket not becoming writable within `kMaxWaitTime`.
  70. *
  71. */
  72. otError SendFrame(const uint8_t *frame, uint16_t length);
  73. /**
  74. * This method waits for receiving part or all of spinel frame within specified timeout.
  75. *
  76. * @param[in] timeout_us The timeout value in microseconds.
  77. *
  78. * @return
  79. * -OT_ERROR_NONE Part or all of spinel frame is received.
  80. * -OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p timeout_us.
  81. *
  82. */
  83. otError WaitForFrame(uint64_t timeout_us);
  84. /**
  85. * This method performs uart processing to the RCP.
  86. *
  87. * @param[in] mainloop The mainloop context
  88. *
  89. */
  90. void Process(const esp_openthread_mainloop_context_t &mainloop);
  91. /**
  92. * This methods updates the mainloop context.
  93. *
  94. * @param[inout] mainloop The mainloop context.
  95. *
  96. */
  97. void Update(esp_openthread_mainloop_context_t &mainloop);
  98. private:
  99. enum {
  100. /**
  101. * Maximum spinel frame size.
  102. *
  103. */
  104. kMaxFrameSize = ot::Spinel::SpinelInterface::kMaxFrameSize,
  105. /**
  106. * Maximum wait time in Milliseconds for socket to become writable (see `SendFrame`).
  107. *
  108. */
  109. kMaxWaitTime = 2000,
  110. };
  111. esp_err_t InitUart(const esp_openthread_uart_config_t &radio_uart_config);
  112. esp_err_t DeinitUart(void);
  113. int TryReadAndDecode(void);
  114. otError WaitForWritable(void);
  115. otError Write(const uint8_t *frame, uint16_t length);
  116. esp_err_t TryRecoverUart(void);
  117. static void HandleHdlcFrame(void *context, otError error);
  118. void HandleHdlcFrame(otError error);
  119. ot::Spinel::SpinelInterface::ReceiveFrameCallback m_receiver_frame_callback;
  120. void *m_receiver_frame_context;
  121. ot::Spinel::SpinelInterface::RxFrameBuffer &m_receive_frame_buffer;
  122. ot::Hdlc::Decoder m_hdlc_decoder;
  123. uint8_t *m_uart_rx_buffer;
  124. esp_openthread_uart_config_t m_uart_config;
  125. int m_uart_fd;
  126. // Non-copyable, intentionally not implemented.
  127. UartSpinelInterface(const UartSpinelInterface &);
  128. UartSpinelInterface &operator=(const UartSpinelInterface &);
  129. };
  130. } // namespace openthread
  131. } // namespace esp