spi_wrapper.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // SPDX-License-Identifier: Apache-2.0
  2. // Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #include "esp_check.h"
  16. #include "esp_log.h"
  17. #include "driver/spi_master.h"
  18. #include "os_wrapper.h"
  19. #include "transport_drv.h"
  20. #include "spi_wrapper.h"
  21. #include "driver/gpio.h"
  22. #ifdef CONFIG_IDF_TARGET_ESP32P4
  23. /* Enable workaround if got SPI Read Errors on ESP32-P4 due to caching */
  24. #define SPI_WORKAROUND (0)
  25. #else
  26. #define SPI_WORKAROUND (0)
  27. #endif
  28. #if SPI_WORKAROUND
  29. #include "esp_cache.h"
  30. #endif
  31. DEFINE_LOG_TAG(spi_wrapper);
  32. extern void * spi_handle;
  33. void * hosted_spi_init(void)
  34. {
  35. #ifdef CONFIG_IDF_TARGET_ESP32
  36. #define SENDER_HOST HSPI_HOST
  37. #else
  38. #define SENDER_HOST SPI2_HOST
  39. #endif
  40. esp_err_t ret;
  41. ESP_LOGI(TAG, "Transport: SPI, Mode:%u Freq:%uMHz TxQ:%u RxQ:%u\n GPIOs: MOSI:%u MISO:%u CLK:%u CS:%u HS:%u DR:%u SlaveReset:%u",
  42. H_SPI_MODE, H_SPI_INIT_CLK_MHZ, H_SPI_TX_Q, H_SPI_RX_Q,
  43. H_GPIO_MOSI_Pin, H_GPIO_MISO_Pin, H_GPIO_SCLK_Pin,
  44. H_GPIO_CS_Pin, H_GPIO_HANDSHAKE_Pin, H_GPIO_DATA_READY_Pin,
  45. H_GPIO_PIN_RESET_Pin);
  46. HOSTED_CREATE_HANDLE(spi_device_handle_t, spi_handle);
  47. assert(spi_handle);
  48. //Configuration for the SPI bus
  49. spi_bus_config_t buscfg={
  50. .mosi_io_num=H_GPIO_MOSI_Pin,
  51. .miso_io_num=H_GPIO_MISO_Pin,
  52. .sclk_io_num=H_GPIO_SCLK_Pin,
  53. .quadwp_io_num=-1,
  54. .quadhd_io_num=-1
  55. };
  56. //Configuration for the SPI device on the other side of the bus
  57. spi_device_interface_config_t devcfg={
  58. .command_bits=0,
  59. .address_bits=0,
  60. .dummy_bits=0,
  61. #ifdef CONFIG_IDF_TARGET_ESP32P4
  62. .clock_source = SPI_CLK_SRC_SPLL,
  63. #endif
  64. .clock_speed_hz=MHZ_TO_HZ(H_SPI_INIT_CLK_MHZ),
  65. .duty_cycle_pos=128, //50% duty cycle
  66. .mode=H_SPI_MODE,
  67. .spics_io_num=H_GPIO_CS_Pin,
  68. .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
  69. .queue_size=3
  70. };
  71. //Initialize the SPI bus and add the device we want to send stuff to.
  72. ret=spi_bus_initialize(SENDER_HOST, &buscfg, SPI_DMA_CH_AUTO);
  73. assert(ret==ESP_OK);
  74. ret=spi_bus_add_device(SENDER_HOST, &devcfg, spi_handle);
  75. assert(ret==ESP_OK);
  76. //Assume the slave is ready for the first transmission: if the slave started up before us, we will not detect
  77. //positive edge on the handshake line.
  78. gpio_set_drive_capability(H_GPIO_CS_Pin, GPIO_DRIVE_CAP_3);
  79. gpio_set_drive_capability(H_GPIO_SCLK_Pin, GPIO_DRIVE_CAP_3);
  80. return spi_handle;
  81. }
  82. int hosted_do_spi_transfer(void *trans)
  83. {
  84. spi_transaction_t t = {0};
  85. struct hosted_transport_context_t * spi_trans = trans;
  86. #if SPI_WORKAROUND
  87. /* this ensures RX DMA data in cache is sync to memory */
  88. assert(ESP_OK == esp_cache_msync((void *)spi_trans->rx_buf, spi_trans->tx_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
  89. #endif
  90. t.length=spi_trans->tx_buf_size*8;
  91. t.tx_buffer=spi_trans->tx_buf;
  92. t.rx_buffer=spi_trans->rx_buf;
  93. /* tell lower layer that we have manually aligned buffers for dma */
  94. t.flags |= SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL;
  95. return spi_device_transmit(*((spi_device_handle_t *)spi_handle), &t);
  96. }