You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
10 KiB

3 years ago
  1. // Copyright 2020-2021 Espressif Systems (Shanghai) PTE 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. #include <stdio.h>
  14. #include <string.h>
  15. #include "esp_log.h"
  16. #include "freertos/FreeRTOS.h"
  17. #include "freertos/semphr.h"
  18. #include "driver/spi_master.h"
  19. #include "driver/spi_common.h"
  20. #include "spi_bus.h"
  21. typedef struct {
  22. spi_host_device_t host_id; /*!<spi device number */
  23. bool is_init;
  24. spi_bus_config_t conf; /*!<spi bus active configuration */
  25. } _spi_bus_t;
  26. typedef struct {
  27. spi_device_handle_t handle;
  28. spi_bus_handle_t spi_bus; /*!<spi bus handle */
  29. spi_device_interface_config_t conf; /*!<spi device active configuration */
  30. SemaphoreHandle_t mutex; /* mutex to achive device thread-safe*/
  31. } _spi_device_t;
  32. static const char *TAG = "spi_bus";
  33. static _spi_bus_t s_spi_bus[2];
  34. #define ESP_SPI_MUTEX_TICKS_TO_WAIT 2
  35. #define SPI_BUS_CHECK(a, str, ret) if(!(a)) { \
  36. ESP_LOGE(TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
  37. return (ret); \
  38. }
  39. #define SPI_BUS_CHECK_GOTO(a, str, lable) if(!(a)) { \
  40. ESP_LOGE(TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
  41. goto lable; \
  42. }
  43. #define SPI_DEVICE_MUTEX_TAKE(p_spi_dev, ret) if (!xSemaphoreTake((p_spi_dev)->mutex, ESP_SPI_MUTEX_TICKS_TO_WAIT)) { \
  44. ESP_LOGE(TAG, "spi device(%d) take mutex timeout, max wait = %d ticks", (int32_t)((p_spi_dev)->handle), ESP_SPI_MUTEX_TICKS_TO_WAIT); \
  45. return (ret); \
  46. }
  47. #define SPI_DEVICE_MUTEX_GIVE(p_spi_dev, ret) if (!xSemaphoreGive((p_spi_dev)->mutex)) { \
  48. ESP_LOGE(TAG, "spi device(%d) give mutex failed", (int32_t)((p_spi_dev)->handle)); \
  49. return (ret); \
  50. }
  51. spi_bus_handle_t spi_bus_create(spi_host_device_t host_id, const spi_config_t *bus_conf)
  52. {
  53. SPI_BUS_CHECK(SPI1_HOST < host_id && host_id <= SPI3_HOST, "Invalid spi host_id", NULL);
  54. uint8_t index = host_id - 1; //find related index
  55. spi_bus_config_t buscfg = {
  56. .miso_io_num = bus_conf->miso_io_num,
  57. .mosi_io_num = bus_conf->mosi_io_num,
  58. .sclk_io_num = bus_conf->sclk_io_num,
  59. .quadwp_io_num = -1,
  60. .quadhd_io_num = -1,
  61. .max_transfer_sz = bus_conf->max_transfer_sz,
  62. };
  63. #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0))
  64. esp_err_t ret = spi_bus_initialize(host_id, &buscfg, SPI_DMA_CH_AUTO);
  65. #else
  66. int dma_chan = host_id; //set dma channel equals to host_id by default
  67. esp_err_t ret = spi_bus_initialize(host_id, &buscfg, dma_chan);
  68. #endif
  69. SPI_BUS_CHECK(ESP_OK == ret, "spi bus create failed", NULL);
  70. s_spi_bus[index].host_id = host_id;
  71. memcpy(&s_spi_bus[index].conf, &buscfg, sizeof(spi_bus_config_t));
  72. s_spi_bus[index].is_init = true;
  73. ESP_LOGI(TAG, "SPI%d bus created", host_id + 1);
  74. return (spi_bus_handle_t)&s_spi_bus[index];
  75. }
  76. esp_err_t spi_bus_delete(spi_bus_handle_t *p_bus_handle)
  77. {
  78. SPI_BUS_CHECK((NULL != p_bus_handle) && (NULL != *p_bus_handle), "Handle error", ESP_ERR_INVALID_ARG);
  79. _spi_bus_t *spi_bus = (_spi_bus_t *)(*p_bus_handle);
  80. if (!spi_bus->is_init) {
  81. ESP_LOGW(TAG, "spi_bus%d has been de-inited", spi_bus->host_id);
  82. return ESP_ERR_INVALID_STATE;
  83. }
  84. esp_err_t ret = spi_bus_free(spi_bus->host_id);
  85. SPI_BUS_CHECK(ESP_OK == ret, "spi bus delete failed", ESP_FAIL);
  86. ESP_LOGI(TAG, "SPI%d bus delete", spi_bus->host_id + 1);
  87. memset(spi_bus, 0, sizeof(_spi_bus_t));
  88. *p_bus_handle = NULL;
  89. return ESP_OK;
  90. }
  91. spi_bus_device_handle_t spi_bus_device_create(spi_bus_device_handle_t bus_handle, const spi_device_config_t *device_conf)
  92. {
  93. SPI_BUS_CHECK(NULL != bus_handle, "Pointer error", NULL);
  94. _spi_bus_t *spi_bus = (_spi_bus_t *)bus_handle;
  95. _spi_device_t *spi_dev = malloc(sizeof(_spi_device_t));
  96. spi_device_interface_config_t devcfg = {
  97. .command_bits = 0,
  98. .address_bits = 0,
  99. .dummy_bits = 0,
  100. .clock_speed_hz = device_conf->clock_speed_hz,
  101. .duty_cycle_pos = 128, //50% duty cycle
  102. .mode = device_conf->mode,
  103. .spics_io_num = device_conf->cs_io_num,
  104. .cs_ena_posttrans = 3, //Keep the CS low 3 cycles after transaction, to stop slave from missing the last bit when CS has less propagation delay than CLK
  105. .queue_size = 3
  106. };
  107. esp_err_t ret = spi_bus_add_device(spi_bus->host_id, &devcfg, &spi_dev->handle);
  108. SPI_BUS_CHECK_GOTO(ESP_OK == ret, "add spi device failed", cleanup_device);
  109. spi_dev->mutex = xSemaphoreCreateMutex();
  110. SPI_BUS_CHECK_GOTO(NULL != spi_dev->mutex, "spi device create mutex failed", cleanup_device);
  111. spi_dev->spi_bus = bus_handle;
  112. memcpy(&spi_dev->conf, &devcfg, sizeof(spi_device_interface_config_t));
  113. ESP_LOGI(TAG, "SPI%d bus device added, CS=%d Mode=%u Speed=%d", spi_bus->host_id + 1, device_conf->cs_io_num, device_conf->mode, device_conf->clock_speed_hz);
  114. return (spi_bus_device_handle_t)spi_dev;
  115. cleanup_device:
  116. free(spi_dev);
  117. return NULL;
  118. }
  119. esp_err_t spi_bus_device_delete(spi_bus_device_handle_t *p_dev_handle)
  120. {
  121. SPI_BUS_CHECK((NULL != p_dev_handle) && (NULL != *p_dev_handle), "Pointer error", ESP_ERR_INVALID_ARG);
  122. _spi_device_t *spi_dev = (_spi_device_t *)(*p_dev_handle);
  123. _spi_bus_t *spi_bus = (_spi_bus_t *)(spi_dev->spi_bus);
  124. SPI_DEVICE_MUTEX_TAKE(spi_dev, ESP_FAIL);
  125. esp_err_t ret = spi_bus_remove_device(spi_dev->handle);
  126. SPI_DEVICE_MUTEX_GIVE(spi_dev, ESP_FAIL);
  127. SPI_BUS_CHECK(ESP_OK == ret, "spi bus delete device failed", ret);
  128. vSemaphoreDelete(spi_dev->mutex);
  129. ESP_LOGI(TAG, "SPI%d device removed, CS=%d", spi_bus->host_id + 1, spi_dev->conf.spics_io_num);
  130. free(spi_dev);
  131. *p_dev_handle = NULL;
  132. return ESP_OK;
  133. }
  134. /* this function should lable with inline*/
  135. inline static esp_err_t _spi_device_polling_transmit(spi_bus_device_handle_t dev_handle, spi_transaction_t *trans)
  136. {
  137. SPI_BUS_CHECK(NULL != dev_handle, "Pointer error", ESP_ERR_INVALID_ARG);
  138. _spi_device_t *spi_dev = (_spi_device_t *)(dev_handle);
  139. esp_err_t ret;
  140. SPI_DEVICE_MUTEX_TAKE(spi_dev, ESP_FAIL);
  141. ret = spi_device_polling_transmit(spi_dev->handle, trans);
  142. SPI_DEVICE_MUTEX_GIVE(spi_dev, ESP_FAIL);
  143. return ret;
  144. }
  145. esp_err_t spi_bus_transfer_byte(spi_bus_device_handle_t dev_handle, uint8_t data_out, uint8_t *data_in)
  146. {
  147. esp_err_t ret;
  148. spi_transaction_t trans = {
  149. .length = 8,
  150. .flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA,
  151. .tx_data = {
  152. [0] = data_out
  153. }
  154. };
  155. ret = _spi_device_polling_transmit(dev_handle, &trans);
  156. SPI_BUS_CHECK(ret == ESP_OK, "spi transfer byte failed", ret);
  157. if (data_in) {
  158. *data_in = trans.rx_data[0];
  159. }
  160. return ESP_OK;
  161. }
  162. esp_err_t spi_bus_transfer_bytes(spi_bus_device_handle_t dev_handle, const uint8_t *data_out, uint8_t *data_in, uint32_t data_len)
  163. {
  164. esp_err_t ret;
  165. #if 1
  166. #define MIN(a,b) (((a)<(b))?(a):(b))
  167. uint32_t remain = data_len;
  168. while (remain > 0) {
  169. uint32_t chunk_len = MIN(remain, 2048);
  170. spi_transaction_t trans = {
  171. .length = chunk_len * 8,
  172. .tx_buffer = NULL,
  173. .rx_buffer = NULL
  174. };
  175. if (data_out) {
  176. trans.tx_buffer = data_out+(data_len-remain);
  177. }
  178. if (data_in) {
  179. trans.rx_buffer = data_in+(data_len-remain);
  180. }
  181. ret = _spi_device_polling_transmit(dev_handle, &trans);
  182. SPI_BUS_CHECK(ret == ESP_OK, "spi transfer bytes failed", ret);
  183. remain -= chunk_len;
  184. }
  185. #else
  186. spi_transaction_t trans = {
  187. .length = data_len * 8,
  188. .tx_buffer = NULL,
  189. .rx_buffer = NULL
  190. };
  191. if (data_out) {
  192. trans.tx_buffer = data_out;
  193. }
  194. if (data_in) {
  195. trans.rx_buffer = data_in;
  196. }
  197. ret = _spi_device_polling_transmit(dev_handle, &trans);
  198. SPI_BUS_CHECK(ret == ESP_OK, "spi transfer bytes failed", ret);
  199. #endif
  200. return ESP_OK;
  201. }
  202. /**************************************** Public Functions (Low level)*********************************************/
  203. esp_err_t spi_bus_transmit_begin(spi_bus_device_handle_t dev_handle, spi_transaction_t *p_trans)
  204. {
  205. return _spi_device_polling_transmit(dev_handle, p_trans);
  206. }
  207. esp_err_t spi_bus_transfer_reg16(spi_bus_device_handle_t dev_handle, uint16_t data_out, uint16_t *data_in)
  208. {
  209. esp_err_t ret;
  210. spi_transaction_t trans = {
  211. .length = 16,
  212. .flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA,
  213. /* default MSB first */
  214. .tx_data = {
  215. [0] = (data_out >> 8) & 0xff,
  216. [1] = data_out & 0xff,
  217. }
  218. };
  219. ret = _spi_device_polling_transmit(dev_handle, &trans);
  220. SPI_BUS_CHECK(ret == ESP_OK, "spi transfer reg16 failed", ret);
  221. if (data_in) {
  222. *data_in = (trans.rx_data[0] << 8) | (trans.rx_data[1]);
  223. }
  224. return ESP_OK;
  225. }
  226. esp_err_t spi_bus_transfer_reg32(spi_bus_device_handle_t dev_handle, uint32_t data_out, uint32_t *data_in)
  227. {
  228. esp_err_t ret;
  229. spi_transaction_t trans = {
  230. .length = 32,
  231. .flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA,
  232. /* default MSB first */
  233. .tx_data = {
  234. [0] = (data_out >> 24) & 0xff,
  235. [1] = (data_out >> 16) & 0xff,
  236. [2] = (data_out >> 8) & 0xff,
  237. [3] = data_out & 0xff
  238. }
  239. };
  240. ret = _spi_device_polling_transmit(dev_handle, &trans);
  241. SPI_BUS_CHECK(ret == ESP_OK, "spi transfer reg32 failed", ret);
  242. if (data_in) {
  243. *data_in = (trans.rx_data[0] << 24) | (trans.rx_data[1] << 16) | (trans.rx_data[2] << 8) | (trans.rx_data[3]);
  244. }
  245. return ESP_OK;
  246. }