esp_uart_spinel_interface.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #pragma once
  7. #include "esp_err.h"
  8. #include "esp_openthread.h"
  9. #include "esp_openthread_types.h"
  10. #include "hal/uart_types.h"
  11. #include "lib/spinel/spinel_interface.hpp"
  12. #include "lib/hdlc/hdlc.hpp"
  13. #include "openthread/error.h"
  14. namespace esp {
  15. namespace openthread {
  16. /**
  17. * This class defines an UART interface to the Radio Co-processor (RCP).
  18. *
  19. */
  20. class UartSpinelInterface {
  21. public:
  22. /**
  23. * @brief This constructor of object.
  24. *
  25. * @param[in] callback Callback on frame received
  26. * @param[in] callback_context Callback context
  27. * @param[in] frame_buffer A reference to a `RxFrameBuffer` object.
  28. *
  29. */
  30. UartSpinelInterface(ot::Spinel::SpinelInterface::ReceiveFrameCallback callback, void *callback_context,
  31. ot::Spinel::SpinelInterface::RxFrameBuffer &frame_buffer);
  32. /**
  33. * @brief This destructor of the object.
  34. *
  35. */
  36. ~UartSpinelInterface(void);
  37. /**
  38. * @brief This method initializes the HDLC interface.
  39. *
  40. * @return
  41. * - ESP_OK on success
  42. * - ESP_ERR_NO_MEM if allocation has failed
  43. * - ESP_ERROR on failure
  44. */
  45. esp_err_t Init(const esp_openthread_uart_config_t &radio_uart_config);
  46. /**
  47. * @brief This method deinitializes the HDLC interface.
  48. *
  49. */
  50. esp_err_t Deinit(void);
  51. /**
  52. * @brief This method encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket.
  53. *
  54. * @note This is blocking call, i.e., if the socket is not writable, this method waits for it to become writable
  55. * for up to `kMaxWaitTime` interval.
  56. *
  57. * @param[in] frame A pointer to buffer containing the spinel frame to send.
  58. * @param[in] length The length (number of bytes) in the frame.
  59. *
  60. * @return
  61. * -OT_ERROR_NONE Successfully encoded and sent the spinel frame.
  62. * -OT_ERROR_NO_BUFS Insufficient buffer space available to encode the frame.
  63. * -OT_ERROR_FAILED Failed to send due to socket not becoming writable within `kMaxWaitTime`.
  64. *
  65. */
  66. otError SendFrame(const uint8_t *frame, uint16_t length);
  67. /**
  68. * This method waits for receiving part or all of spinel frame within specified timeout.
  69. *
  70. * @param[in] timeout_us The timeout value in microseconds.
  71. *
  72. * @return
  73. * -OT_ERROR_NONE Part or all of spinel frame is received.
  74. * -OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p timeout_us.
  75. *
  76. */
  77. otError WaitForFrame(uint64_t timeout_us);
  78. /**
  79. * This method performs uart processing to the RCP.
  80. *
  81. * @param[in] mainloop The mainloop context
  82. *
  83. */
  84. void Process(const void *mainloop);
  85. /**
  86. * This methods updates the mainloop context.
  87. *
  88. * @param[inout] mainloop The mainloop context.
  89. *
  90. */
  91. void Update(void *mainloop);
  92. /**
  93. * This methods registers the callback for RCP failure.
  94. *
  95. * @param[in] handler The RCP failure handler.
  96. *
  97. */
  98. void RegisterRcpFailureHandler(esp_openthread_rcp_failure_handler handler) { mRcpFailureHandler = handler; }
  99. /**
  100. * This method is called when RCP failure detected and resets internal states of the interface.
  101. *
  102. */
  103. otError HardwareReset(void);
  104. /**
  105. * This method is called when RCP is reset to recreate the connection with it.
  106. * Intentionally empty.
  107. *
  108. */
  109. otError ResetConnection(void) { return OT_ERROR_NONE; }
  110. private:
  111. enum {
  112. /**
  113. * Maximum spinel frame size.
  114. *
  115. */
  116. kMaxFrameSize = ot::Spinel::SpinelInterface::kMaxFrameSize,
  117. /**
  118. * Maximum wait time in Milliseconds for socket to become writable (see `SendFrame`).
  119. *
  120. */
  121. kMaxWaitTime = 2000,
  122. };
  123. esp_err_t InitUart(const esp_openthread_uart_config_t &radio_uart_config);
  124. esp_err_t DeinitUart(void);
  125. int TryReadAndDecode(void);
  126. otError WaitForWritable(void);
  127. otError Write(const uint8_t *frame, uint16_t length);
  128. esp_err_t TryRecoverUart(void);
  129. static void HandleHdlcFrame(void *context, otError error);
  130. void HandleHdlcFrame(otError error);
  131. ot::Spinel::SpinelInterface::ReceiveFrameCallback m_receiver_frame_callback;
  132. void *m_receiver_frame_context;
  133. ot::Spinel::SpinelInterface::RxFrameBuffer &m_receive_frame_buffer;
  134. ot::Hdlc::Decoder m_hdlc_decoder;
  135. uint8_t *m_uart_rx_buffer;
  136. esp_openthread_uart_config_t m_uart_config;
  137. int m_uart_fd;
  138. // Non-copyable, intentionally not implemented.
  139. UartSpinelInterface(const UartSpinelInterface &);
  140. UartSpinelInterface &operator=(const UartSpinelInterface &);
  141. esp_openthread_rcp_failure_handler mRcpFailureHandler;
  142. };
  143. } // namespace openthread
  144. } // namespace esp