fpgasvc.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #include "common.h"
  2. #include "config.h"
  3. #include "fpga.h"
  4. #include <driver/gpio.h>
  5. #include <driver/spi_common.h>
  6. #include <driver/spi_master.h>
  7. #define PIN_FPGA_INT 9
  8. #define PIN_FPGA_CS 10
  9. #define PIN_FPGA_IO0 11
  10. #define PIN_FPGA_CLK 12
  11. #define PIN_FPGA_IO1 13
  12. #define FPGA_SPI_HOST FSPI /* SPI2 */
  13. #define FPGA_PRIORITY 3
  14. static spi_bus_config_t spi_bus_config = {
  15. .data0_io_num = PIN_FPGA_IO0,
  16. .data1_io_num = PIN_FPGA_IO1,
  17. .sclk_io_num = PIN_FPGA_CLK,
  18. .data2_io_num = -1,
  19. .data3_io_num = -1,
  20. .data4_io_num = -1,
  21. .data5_io_num = -1,
  22. .data6_io_num = -1,
  23. .data7_io_num = -1,
  24. .max_transfer_sz = 4096,
  25. .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_DUAL
  26. };
  27. static const spi_device_interface_config_t spi_device_interface_config = {
  28. .command_bits = 8,
  29. .address_bits = 32,
  30. .dummy_bits = 0,
  31. .mode = 0,
  32. .cs_ena_pretrans = 0,
  33. .cs_ena_posttrans = 0,
  34. .clock_speed_hz = SPI_MASTER_FREQ_40M,
  35. .spics_io_num = PIN_FPGA_CS,
  36. .flags = SPI_DEVICE_HALFDUPLEX,
  37. .queue_size = 4 /* Maybe? */
  38. };
  39. static spi_device_handle_t spi_handle;
  40. static TaskHandle_t fpga_task;
  41. static SemaphoreHandle_t spi_mutex;
  42. #define NOTIFY_INDEX 0
  43. static void ARDUINO_ISR_ATTR fpga_interrupt(void)
  44. {
  45. BaseType_t do_wakeup = pdFALSE;
  46. if (!fpga_task)
  47. return;
  48. xTaskNotifyIndexedFromISR(fpga_task, NOTIFY_INDEX, 1, eSetBits, &do_wakeup);
  49. if (do_wakeup)
  50. portYIELD_FROM_ISR(do_wakeup);
  51. }
  52. static void fpga_service_task(void *);
  53. int fpga_service_start(void)
  54. {
  55. esp_err_t err;
  56. pinMode(PIN_FPGA_INT, INPUT_PULLUP);
  57. if (!spi_mutex) {
  58. spi_mutex = xSemaphoreCreateMutex();
  59. if (!spi_mutex)
  60. goto failed;
  61. }
  62. xSemaphoreTake(spi_mutex, portMAX_DELAY);
  63. err = spi_bus_initialize(FPGA_SPI_HOST, &spi_bus_config, SPI_DMA_CH_AUTO);
  64. if (err)
  65. goto failed;
  66. err = spi_bus_add_device(FPGA_SPI_HOST, &spi_device_interface_config,
  67. &spi_handle);
  68. if (err)
  69. goto failed;
  70. /* Only device on this bus, so acquire it permanently */
  71. spi_device_acquire_bus(spi_handle, portMAX_DELAY);
  72. xSemaphoreGive(spi_mutex);
  73. if (!fpga_task) {
  74. if (xTaskCreate(fpga_service_task, "fpga_svc", 4096, NULL,
  75. FPGA_PRIORITY, &fpga_task) != pdPASS)
  76. goto failed;
  77. attachInterrupt(PIN_FPGA_INT, fpga_interrupt, FALLING);
  78. esp_register_shutdown_handler(fpga_service_stop);
  79. }
  80. /* All good! */
  81. printf("[FPGA] FPGA services started\n");
  82. return 0;
  83. failed:
  84. printf("[FPGA] Failed to initialize FPGA SPI bus\n");
  85. if (spi_mutex)
  86. xSemaphoreGive(spi_mutex);
  87. fpga_service_stop();
  88. return -1;
  89. }
  90. void fpga_service_stop(void)
  91. {
  92. if (spi_mutex) {
  93. xSemaphoreTake(spi_mutex, portMAX_DELAY);
  94. if (fpga_task) {
  95. esp_unregister_shutdown_handler(fpga_service_stop);
  96. detachInterrupt(PIN_FPGA_INT);
  97. vTaskDelete(fpga_task);
  98. fpga_task = NULL;
  99. }
  100. if (spi_handle) {
  101. spi_device_release_bus(spi_handle);
  102. spi_bus_remove_device(spi_handle);
  103. spi_bus_free(FPGA_SPI_HOST);
  104. spi_handle = NULL;
  105. }
  106. xSemaphoreGive(spi_mutex);
  107. }
  108. printf("[FPGA] FPGA services stopped\n");
  109. }
  110. #define FPGA_CMD_IRQ1 (1 << 0)
  111. #define FPGA_CMD_IRQ2 (2 << 0)
  112. #define FPGA_CMD_IRQ3 (3 << 0)
  113. #define FPGA_CMD_ACK1 (1 << 2)
  114. #define FPGA_CMD_ACK2 (2 << 2)
  115. #define FPGA_CMD_ACK3 (3 << 2)
  116. #define FPGA_CMD_WR (0 << 4)
  117. #define FPGA_CMD_RD (1 << 4)
  118. #define FPGA_HDR_ADDR 0x40000000
  119. static esp_err_t fpga_io(uint8_t cmd, uint32_t addr, void *data, size_t len)
  120. {
  121. spi_transaction_ext_t trans;
  122. esp_err_t err;
  123. memset(&trans, 0, sizeof trans);
  124. trans.base.flags =
  125. SPI_TRANS_MODE_DIO |
  126. SPI_TRANS_VARIABLE_DUMMY |
  127. SPI_TRANS_MULTILINE_CMD |
  128. SPI_TRANS_MULTILINE_ADDR;
  129. trans.command_bits = 8;
  130. trans.address_bits = 32;
  131. trans.base.cmd = cmd;
  132. trans.base.addr = addr;
  133. if (cmd & FPGA_CMD_RD) {
  134. trans.dummy_bits = 16; /* 16 cycles = 32 bits */
  135. trans.base.rx_buffer = data;
  136. trans.base.rxlength = len << 3;
  137. } else {
  138. trans.base.tx_buffer = data;
  139. trans.base.length = len << 3;
  140. }
  141. xSemaphoreTake(spi_mutex, portMAX_DELAY);
  142. err = spi_device_transmit(spi_handle, (spi_transaction_t *)&trans);
  143. xSemaphoreGive(spi_mutex);
  144. return err;
  145. }
  146. static void fpga_service_task(void *dummy)
  147. {
  148. (void)dummy;
  149. uint32_t head[8];
  150. while (1) {
  151. vTaskDelay(10 * configTICK_RATE_HZ);
  152. fpga_io(FPGA_CMD_RD|FPGA_CMD_ACK1, FPGA_HDR_ADDR,
  153. head, sizeof head);
  154. for (unsigned int i = 0; i < ARRAY_SIZE(head); i++) {
  155. printf("[FPGA] head[%u] = 0x%08x (%u)\n",
  156. i, head[i], head[i]);
  157. }
  158. }
  159. while (1) {
  160. while (!digitalRead(PIN_FPGA_INT)) {
  161. printf("[FPGA] FPGA signals ready\n");
  162. }
  163. /* Wait until an interrupt is received */
  164. xTaskNotifyWaitIndexed(NOTIFY_INDEX, 0, 1, NULL, portMAX_DELAY);
  165. }
  166. }