i2s_private.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #pragma once
  7. #include "freertos/FreeRTOS.h"
  8. #include "freertos/semphr.h"
  9. #include "freertos/queue.h"
  10. #include "soc/lldesc.h"
  11. #include "soc/soc_caps.h"
  12. #include "hal/i2s_hal.h"
  13. #include "driver/i2s_types.h"
  14. #if CONFIG_IDF_TARGET_ESP32
  15. #include "esp_clock_output.h"
  16. #endif
  17. #if SOC_GDMA_SUPPORTED
  18. #include "esp_private/gdma.h"
  19. #endif
  20. #include "esp_private/periph_ctrl.h"
  21. #include "esp_pm.h"
  22. #include "esp_err.h"
  23. #include "sdkconfig.h"
  24. #ifdef __cplusplus
  25. extern "C" {
  26. #endif
  27. // If ISR handler is allowed to run whilst cache is disabled,
  28. // Make sure all the code and related variables used by the handler are in the SRAM
  29. #if CONFIG_I2S_ISR_IRAM_SAFE
  30. #define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
  31. #define I2S_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
  32. #else
  33. #define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
  34. #define I2S_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
  35. #endif //CONFIG_I2S_ISR_IRAM_SAFE
  36. #define I2S_DMA_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA)
  37. #if SOC_PERIPH_CLK_CTRL_SHARED
  38. #define I2S_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
  39. #else
  40. #define I2S_CLOCK_SRC_ATOMIC()
  41. #endif
  42. #if !SOC_RCC_IS_INDEPENDENT
  43. #define I2S_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
  44. #else
  45. #define I2S_RCC_ATOMIC()
  46. #endif
  47. #define I2S_NULL_POINTER_CHECK(tag, p) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, tag, "input parameter '"#p"' is NULL")
  48. /**
  49. * @brief i2s channel state for checking if the operation in under right driver state
  50. */
  51. typedef enum {
  52. I2S_CHAN_STATE_REGISTER, /*!< i2s channel is registered (not initialized) */
  53. I2S_CHAN_STATE_READY, /*!< i2s channel is disabled (initialized) */
  54. I2S_CHAN_STATE_RUNNING, /*!< i2s channel is idling (initialized and enabled) */
  55. } i2s_state_t;
  56. /**
  57. * @brief Group of I2S callbacks
  58. * @note The callbacks are all running under ISR environment
  59. * @note When CONFIG_I2S_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
  60. * The variables used in the function should be in the SRAM as well.
  61. * @note Declare the internal type to remove the dependency of `i2s_common.h`
  62. */
  63. typedef struct {
  64. i2s_isr_callback_t on_recv; /**< Callback of data received event, only for rx channel
  65. * The event data includes DMA buffer address and size that just finished receiving data
  66. */
  67. i2s_isr_callback_t on_recv_q_ovf; /**< Callback of receiving queue overflowed event, only for rx channel
  68. * The event data includes buffer size that has been overwritten
  69. */
  70. i2s_isr_callback_t on_sent; /**< Callback of data sent event, only for tx channel
  71. * The event data includes DMA buffer address and size that just finished sending data
  72. */
  73. i2s_isr_callback_t on_send_q_ovf; /**< Callback of sending queue overflowed event, only for tx channel
  74. * The event data includes buffer size that has been overwritten
  75. */
  76. } i2s_event_callbacks_internal_t;
  77. /**
  78. * @brief i2s channel level configurations
  79. * @note It performs as channel handle
  80. */
  81. typedef struct {
  82. #if SOC_GDMA_SUPPORTED
  83. gdma_channel_handle_t dma_chan; /*!< gdma channel handle */
  84. #else
  85. intr_handle_t dma_chan; /*!< interrupt channel handle */
  86. #endif
  87. uint32_t desc_num; /*!< I2S DMA buffer number, it is also the number of DMA descriptor */
  88. uint32_t frame_num; /*!< I2S frame number in one DMA buffer. One frame means one-time sample data in all slots */
  89. uint32_t buf_size; /*!< dma buffer size */
  90. bool auto_clear; /*!< Set to auto clear DMA TX descriptor, i2s will always send zero automatically if no data to send */
  91. uint32_t rw_pos; /*!< reading/writing pointer position */
  92. void *curr_ptr; /*!< Pointer to current dma buffer */
  93. void *curr_desc; /*!< Pointer to current dma descriptor used for pre-load */
  94. lldesc_t **desc; /*!< dma descriptor array */
  95. uint8_t **bufs; /*!< dma buffer array */
  96. } i2s_dma_t;
  97. /**
  98. * @brief i2s controller level configurations
  99. * @note Both i2s rx and tx channel are under its control
  100. */
  101. typedef struct {
  102. i2s_port_t id; /*!< i2s port id */
  103. i2s_hal_context_t hal; /*!< hal context */
  104. uint32_t chan_occupancy; /*!< channel occupancy (rx/tx) */
  105. bool full_duplex; /*!< is full_duplex */
  106. i2s_chan_handle_t tx_chan; /*!< tx channel handler */
  107. i2s_chan_handle_t rx_chan; /*!< rx channel handler */
  108. int mclk; /*!< MCK out pin, shared by tx/rx*/
  109. #if CONFIG_IDF_TARGET_ESP32
  110. esp_clock_output_mapping_handle_t mclk_out_hdl; /*!< The handle of MCLK output signal */
  111. #endif
  112. } i2s_controller_t;
  113. struct i2s_channel_obj_t {
  114. /* Channel basic information */
  115. i2s_controller_t *controller; /*!< Parent pointer to controller object */
  116. i2s_comm_mode_t mode; /*!< i2s channel communication mode */
  117. i2s_role_t role; /*!< i2s role */
  118. i2s_dir_t dir; /*!< i2s channel direction */
  119. i2s_dma_t dma; /*!< i2s dma object */
  120. i2s_state_t state; /*!< i2s driver state. Ensuring the driver working in a correct sequence */
  121. /* Stored configurations */
  122. int intr_prio_flags;/*!< i2s interrupt priority flags */
  123. void *mode_info; /*!< Slot, clock and gpio information of each mode */
  124. #if SOC_I2S_SUPPORTS_APLL
  125. bool apll_en; /*!< Flag of wether APLL enabled */
  126. #endif
  127. uint32_t active_slot; /*!< Active slot number */
  128. uint32_t total_slot; /*!< Total slot number */
  129. /* Locks and queues */
  130. SemaphoreHandle_t mutex; /*!< Mutex semaphore for the channel operations */
  131. SemaphoreHandle_t binary; /*!< Binary semaphore for writing / reading / enabling / disabling */
  132. #if CONFIG_PM_ENABLE
  133. esp_pm_lock_handle_t pm_lock; /*!< Power management lock, to avoid apb clock frequency changes while i2s is working */
  134. #endif
  135. QueueHandle_t msg_queue; /*!< Message queue handler, used for transporting data between interrupt and read/write task */
  136. i2s_event_callbacks_internal_t callbacks; /*!< Callback functions */
  137. void *user_data; /*!< User data for callback functions */
  138. void (*start)(i2s_chan_handle_t); /*!< start tx/rx channel */
  139. void (*stop)(i2s_chan_handle_t); /*!< stop tx/rx channel */
  140. };
  141. /**
  142. * @brief i2s platform level configurations
  143. * @note All i2s controllers' resources are involved
  144. */
  145. typedef struct {
  146. portMUX_TYPE spinlock; /*!< Platform level lock */
  147. i2s_controller_t *controller[SOC_I2S_NUM]; /*!< Controller object */
  148. const char *comp_name[SOC_I2S_NUM]; /*!< The component name that occupied i2s controller */
  149. } i2s_platform_t;
  150. extern i2s_platform_t g_i2s; /*!< Global i2s instance for driver internal use */
  151. /**
  152. * @brief Initialize I2S DMA interrupt
  153. *
  154. * @param handle I2S channel handle
  155. * @param intr_flag I2S interrupt flags, `ESP_INTR_FLAG_XXX` defined in `esp_intr_alloc.h`
  156. * @return
  157. * - ESP_OK Initialize interrupt success
  158. * - ESP_ERR_INVALID_ARG Wrong port id or NULL pointer
  159. */
  160. esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag);
  161. /**
  162. * @brief Free I2S DMA descriptor and DMA buffer
  163. *
  164. * @param handle I2S channel handle
  165. * @return
  166. * - ESP_OK Free success
  167. * - ESP_ERR_INVALID_ARG NULL pointer
  168. */
  169. esp_err_t i2s_free_dma_desc(i2s_chan_handle_t handle);
  170. /**
  171. * @brief Allocate memory for I2S DMA descriptor and DMA buffer
  172. *
  173. * @param handle I2S channel handle
  174. * @param num Number of DMA descriptors
  175. * @param bufsize The DMA buffer size
  176. *
  177. * @return
  178. * - ESP_OK Allocate memory success
  179. * - ESP_ERR_INVALID_ARG NULL pointer or bufsize is too big
  180. * - ESP_ERR_NO_MEM No memory for DMA descriptor and DMA buffer
  181. */
  182. esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bufsize);
  183. /**
  184. * @brief Get DMA buffer size
  185. *
  186. * @param handle I2S channel handle
  187. * @param data_bit_width Data bit width in one slot
  188. * @param dma_frame_num Frame number in one DMA buffer
  189. *
  190. * @return
  191. * - DMA buffer size
  192. */
  193. uint32_t i2s_get_buf_size(i2s_chan_handle_t handle, uint32_t data_bit_width, uint32_t dma_frame_num);
  194. /**
  195. * @brief Get the frequency of the source clock
  196. *
  197. * @param clk_src clock source
  198. * @param mclk_freq_hz Expected mclk frequency in Hz
  199. * @return
  200. * - Actual source clock frequency
  201. */
  202. uint32_t i2s_get_source_clk_freq(i2s_clock_src_t clk_src, uint32_t mclk_freq_hz);
  203. /**
  204. * @brief Check gpio validity and attach to corresponding signal
  205. *
  206. * @param gpio GPIO number
  207. * @param signal_idx Signal index
  208. * @param is_input Is input gpio
  209. * @param is_invert Is invert gpio
  210. */
  211. void i2s_gpio_check_and_set(int gpio, uint32_t signal_idx, bool is_input, bool is_invert);
  212. /**
  213. * @brief Check gpio validity and output mclk signal
  214. *
  215. * @param id I2S port id
  216. * @param gpio_num GPIO number
  217. * @param clk_src The clock source of this I2S port
  218. * @param is_invert Is invert the GPIO
  219. * @return
  220. * - ESP_OK Set mclk output gpio success
  221. * - ESP_ERR_INVALID_ARG Invalid GPIO number
  222. */
  223. esp_err_t i2s_check_set_mclk(i2s_port_t id, int gpio_num, i2s_clock_src_t clk_src, bool is_invert);
  224. /**
  225. * @brief Attach data out signal and data in signal to a same gpio
  226. *
  227. * @param gpio GPIO number
  228. * @param out_sig_idx Data out signal index
  229. * @param in_sig_idx Data in signal index
  230. */
  231. void i2s_gpio_loopback_set(int gpio, uint32_t out_sig_idx, uint32_t in_sig_idx);
  232. #ifdef __cplusplus
  233. }
  234. #endif