spi_slave_hal_iram.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include "hal/spi_slave_hal.h"
  2. #include "hal/spi_ll.h"
  3. #include "soc/soc_caps.h"
  4. //This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
  5. #if SOC_GDMA_SUPPORTED
  6. #include "soc/gdma_struct.h"
  7. #include "hal/gdma_ll.h"
  8. #define spi_dma_ll_rx_reset(dev, chan) gdma_ll_rx_reset_channel(&GDMA, chan)
  9. #define spi_dma_ll_tx_reset(dev, chan) gdma_ll_tx_reset_channel(&GDMA, chan);
  10. #define spi_dma_ll_rx_start(dev, chan, addr) do {\
  11. gdma_ll_rx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\
  12. gdma_ll_rx_start(&GDMA, chan);\
  13. } while (0)
  14. #define spi_dma_ll_tx_start(dev, chan, addr) do {\
  15. gdma_ll_tx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\
  16. gdma_ll_tx_start(&GDMA, chan);\
  17. } while (0)
  18. #endif
  19. bool spi_slave_hal_usr_is_done(spi_slave_hal_context_t* hal)
  20. {
  21. return spi_ll_usr_is_done(hal->hw);
  22. }
  23. void spi_slave_hal_user_start(const spi_slave_hal_context_t *hal)
  24. {
  25. spi_ll_clear_int_stat(hal->hw); //clear int bit
  26. spi_ll_slave_user_start(hal->hw);
  27. }
  28. void spi_slave_hal_prepare_data(const spi_slave_hal_context_t *hal)
  29. {
  30. if (hal->use_dma) {
  31. //Fill DMA descriptors
  32. if (hal->rx_buffer) {
  33. lldesc_setup_link(hal->dmadesc_rx, hal->rx_buffer, ((hal->bitlen + 7) / 8), true);
  34. //reset dma inlink, this should be reset before spi related reset
  35. spi_dma_ll_rx_reset(hal->dma_in, hal->rx_dma_chan);
  36. spi_ll_dma_rx_fifo_reset(hal->dma_in);
  37. spi_ll_slave_reset(hal->hw);
  38. spi_ll_infifo_full_clr(hal->hw);
  39. spi_ll_dma_rx_enable(hal->hw, 1);
  40. spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, &hal->dmadesc_rx[0]);
  41. }
  42. if (hal->tx_buffer) {
  43. lldesc_setup_link(hal->dmadesc_tx, hal->tx_buffer, (hal->bitlen + 7) / 8, false);
  44. //reset dma outlink, this should be reset before spi related reset
  45. spi_dma_ll_tx_reset(hal->dma_out, hal->tx_dma_chan);
  46. spi_ll_dma_tx_fifo_reset(hal->dma_out);
  47. spi_ll_slave_reset(hal->hw);
  48. spi_ll_outfifo_empty_clr(hal->hw);
  49. spi_ll_dma_tx_enable(hal->hw, 1);
  50. spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, (&hal->dmadesc_tx[0]));
  51. }
  52. } else {
  53. //No DMA. Turn off SPI and copy data to transmit buffers.
  54. if (hal->tx_buffer) {
  55. spi_ll_slave_reset(hal->hw);
  56. spi_ll_write_buffer(hal->hw, hal->tx_buffer, hal->bitlen);
  57. }
  58. spi_ll_cpu_tx_fifo_reset(hal->hw);
  59. }
  60. spi_ll_slave_set_rx_bitlen(hal->hw, hal->bitlen);
  61. spi_ll_slave_set_tx_bitlen(hal->hw, hal->bitlen);
  62. #ifdef CONFIG_IDF_TARGET_ESP32
  63. //SPI Slave mode on ESP32 requires MOSI/MISO enable
  64. spi_ll_enable_mosi(hal->hw, (hal->rx_buffer == NULL) ? 0 : 1);
  65. spi_ll_enable_miso(hal->hw, (hal->tx_buffer == NULL) ? 0 : 1);
  66. #endif
  67. }
  68. void spi_slave_hal_store_result(spi_slave_hal_context_t *hal)
  69. {
  70. //when data of cur_trans->length are all sent, the slv_rdata_bit
  71. //will be the length sent-1 (i.e. cur_trans->length-1 ), otherwise
  72. //the length sent.
  73. hal->rcv_bitlen = spi_ll_slave_get_rcv_bitlen(hal->hw);
  74. if (hal->rcv_bitlen == hal->bitlen - 1) {
  75. hal->rcv_bitlen++;
  76. }
  77. if (!hal->use_dma && hal->rx_buffer) {
  78. //Copy result out
  79. spi_ll_read_buffer(hal->hw, hal->rx_buffer, hal->bitlen);
  80. }
  81. }
  82. uint32_t spi_slave_hal_get_rcv_bitlen(spi_slave_hal_context_t *hal)
  83. {
  84. return hal->rcv_bitlen;
  85. }
  86. bool spi_slave_hal_dma_need_reset(const spi_slave_hal_context_t *hal)
  87. {
  88. bool ret;
  89. ret = false;
  90. if (hal->use_dma && hal->rx_buffer) {
  91. int i;
  92. //In case CS goes high too soon, the transfer is aborted while the DMA channel still thinks it's going. This
  93. //leads to issues later on, so in that case we need to reset the channel. The state can be detected because
  94. //the DMA system doesn't give back the offending descriptor; the owner is still set to DMA.
  95. for (i = 0; hal->dmadesc_rx[i].eof == 0 && hal->dmadesc_rx[i].owner == 0; i++) {}
  96. if (hal->dmadesc_rx[i].owner) {
  97. ret = true;
  98. }
  99. }
  100. return ret;
  101. }