fpgasvc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. #include "common.h"
  2. #include "config.h"
  3. #include "fpga.h"
  4. #include "esplink.h"
  5. #include "xmalloc.h"
  6. #include <driver/gpio.h>
  7. #include <driver/spi_common.h>
  8. #include <driver/spi_master.h>
  9. #define PIN_FPGA_INT 9
  10. #define PIN_FPGA_CS 10
  11. #define PIN_FPGA_IO0 11
  12. #define PIN_FPGA_CLK 12
  13. #define PIN_FPGA_IO1 13
  14. #define FPGA_SPI_HOST FSPI /* SPI2 */
  15. #define FPGA_PRIORITY 3
  16. #define FPGA_SVC_STACK 4096
  17. static spi_bus_config_t spi_bus_config = {
  18. .data0_io_num = PIN_FPGA_IO0,
  19. .data1_io_num = PIN_FPGA_IO1,
  20. .sclk_io_num = PIN_FPGA_CLK,
  21. .data2_io_num = -1,
  22. .data3_io_num = -1,
  23. .data4_io_num = -1,
  24. .data5_io_num = -1,
  25. .data6_io_num = -1,
  26. .data7_io_num = -1,
  27. .max_transfer_sz = 4096,
  28. .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_DUAL
  29. };
  30. #define FPGA_IOV_MAX 4
  31. static void ARDUINO_ISR_ATTR spi_callback(spi_transaction_t *);
  32. static const spi_device_interface_config_t spi_device_interface_config = {
  33. .command_bits = 8,
  34. .address_bits = 32,
  35. .dummy_bits = 0,
  36. .mode = 0,
  37. .cs_ena_pretrans = 0,
  38. .cs_ena_posttrans = 0,
  39. .clock_speed_hz = SPI_MASTER_FREQ_40M,
  40. .spics_io_num = PIN_FPGA_CS,
  41. .flags = SPI_DEVICE_HALFDUPLEX,
  42. .queue_size = FPGA_IOV_MAX,
  43. .post_cb = spi_callback
  44. };
  45. static spi_device_handle_t spi_handle;
  46. static TaskHandle_t fpga_task;
  47. static SemaphoreHandle_t spi_mutex;
  48. static EventGroupHandle_t spi_done_evgroup;
  49. static volatile bool spi_abort_all;
  50. #define NOTIFY_INDEX 0
  51. #define NOTIFY_FPGA (1 << 0)
  52. #define NOTIFY_ENABLE (1 << 1)
  53. #define NOTIFY_DISABLE (1 << 2)
  54. #if 0
  55. #define NOTIFY_SPI (1 << 3)
  56. #define NOTIFY_RINGBUF (1 << 4)
  57. #endif
  58. static uint32_t notify_poll_for(uint32_t flags)
  59. {
  60. return ulTaskNotifyValueClearIndexed(NULL, NOTIFY_INDEX, flags);
  61. }
  62. /* This supports multiple flags set */
  63. static uint32_t notify_wait_for(uint32_t flags)
  64. {
  65. uint32_t notify_value;
  66. /* Already received? Might already have been waited for... */
  67. notify_value = notify_poll_for(flags);
  68. while (!(notify_value & flags)) {
  69. xTaskNotifyWaitIndexed(NOTIFY_INDEX, 0, flags,
  70. &notify_value, portMAX_DELAY);
  71. }
  72. return notify_value;
  73. }
  74. static void ARDUINO_ISR_ATTR fpga_notify_from_isr(uint32_t flags)
  75. {
  76. BaseType_t wakeup = pdFALSE;
  77. if (xTaskNotifyIndexedFromISR(fpga_task, NOTIFY_INDEX, flags, eSetBits,
  78. &wakeup) != pdFAIL)
  79. portYIELD_FROM_ISR(wakeup);
  80. }
  81. static void fpga_notify_from_task(uint32_t flags)
  82. {
  83. xTaskNotifyIndexed(fpga_task, NOTIFY_INDEX, flags, eSetBits);
  84. }
  85. static void ARDUINO_ISR_ATTR fpga_interrupt(void)
  86. {
  87. fpga_notify_from_isr(NOTIFY_FPGA);
  88. }
  89. static void ARDUINO_ISR_ATTR spi_callback(spi_transaction_t *t)
  90. {
  91. size_t flags = (size_t)t->user;
  92. if (!flags)
  93. return;
  94. BaseType_t wakeup = pdFALSE;
  95. if (xEventGroupSetBitsFromISR(spi_done_evgroup, (size_t)t->user,
  96. &wakeup) != pdFAIL)
  97. portYIELD_FROM_ISR(wakeup);
  98. }
  99. static void fpga_service_task(void *);
  100. static EventGroupHandle_t fpga_service_evgroup;
  101. void fpga_service_enable(bool on)
  102. {
  103. uint32_t flag = on ? NOTIFY_ENABLE : NOTIFY_DISABLE;
  104. fpga_notify_from_task(flag);
  105. xEventGroupWaitBits(fpga_service_evgroup, flag, 0, pdTRUE, portMAX_DELAY);
  106. }
  107. esp_err_t fpga_service_init(void)
  108. {
  109. esp_err_t err;
  110. pinMode(PIN_FPGA_INT, INPUT);
  111. setenv_bool("status.max80.fpga", false);
  112. fpga_service_evgroup = null_check(xEventGroupCreate());
  113. spi_mutex = null_check(xSemaphoreCreateRecursiveMutex());
  114. spi_done_evgroup = null_check(xEventGroupCreate());
  115. /* The ordering here attempts to avoid race conditions... */
  116. if (xTaskCreate(fpga_service_task, "fpga_svc", FPGA_SVC_STACK, NULL,
  117. FPGA_PRIORITY, &fpga_task) != pdPASS)
  118. return ESP_FAIL;
  119. esplink_init();
  120. xEventGroupSetBits(fpga_service_evgroup, NOTIFY_DISABLE);
  121. return ESP_OK;
  122. }
  123. static bool fpga_link_enable(void)
  124. {
  125. esp_err_t err;
  126. if (spi_handle)
  127. return true; /* Already started */
  128. xEventGroupClearBits(fpga_service_evgroup, NOTIFY_DISABLE);
  129. err = spi_bus_initialize(FPGA_SPI_HOST, &spi_bus_config, SPI_DMA_CH_AUTO);
  130. if (err)
  131. goto init_fail;
  132. err = spi_bus_add_device(FPGA_SPI_HOST, &spi_device_interface_config,
  133. &spi_handle);
  134. if (err)
  135. goto free_bus_fail;
  136. /* Only device on this bus, so acquire it permanently */
  137. err = spi_device_acquire_bus(spi_handle, portMAX_DELAY);
  138. if (err)
  139. goto release_bus_fail;
  140. xEventGroupClearBits(spi_done_evgroup, EVENT_ALL_BITS);
  141. pinMode(PIN_FPGA_INT, INPUT);
  142. attachInterrupt(PIN_FPGA_INT, fpga_interrupt, FALLING);
  143. xEventGroupSetBits(fpga_service_evgroup, NOTIFY_ENABLE);
  144. xSemaphoreGiveRecursive(spi_mutex);
  145. fpga_notify_from_task(NOTIFY_FPGA); /* In case FPGA_INT was already low */
  146. goto done;
  147. release_bus_fail:
  148. spi_bus_remove_device(spi_handle);
  149. spi_handle = NULL;
  150. free_bus_fail:
  151. spi_bus_free(FPGA_SPI_HOST);
  152. init_fail:
  153. xEventGroupSetBits(fpga_service_evgroup, NOTIFY_DISABLE);
  154. done:
  155. return !err;
  156. }
  157. static void fpga_link_disable(void)
  158. {
  159. if (!spi_handle)
  160. return; /* Already stopped */
  161. xEventGroupClearBits(fpga_service_evgroup, NOTIFY_ENABLE);
  162. xSemaphoreTakeRecursive(spi_mutex, portMAX_DELAY);
  163. detachInterrupt(PIN_FPGA_INT);
  164. spi_device_release_bus(spi_handle);
  165. spi_bus_remove_device(spi_handle);
  166. spi_bus_free(FPGA_SPI_HOST);
  167. spi_handle = NULL;
  168. xEventGroupSetBits(fpga_service_evgroup, NOTIFY_DISABLE);
  169. }
  170. static bool fpga_online(void)
  171. {
  172. struct esplink_head head;
  173. fpga_io_read(FPGA_CMD_ACK(EL_UIRQ_READY), ESPLINK_HDR_ADDR,
  174. &head, sizeof head);
  175. if (head.magic != ESPLINK_HEAD_MAGIC || head.hlen <= 8) {
  176. printf("[FPGA] Bad header received, magic = 0x%08x len = %u\n",
  177. head.magic, head.hlen);
  178. return false;
  179. }
  180. if (unlikely(head.hlen < sizeof head)) {
  181. /* Clear any fields not provided */
  182. memset((char *)&head + head.hlen, 0, sizeof head - head.hlen);
  183. }
  184. printf("[FPGA] Ready, board = %u.%u fixes %02x fpga %u\n",
  185. head.board.major, head.board.minor,
  186. head.board.fixes, head.board.fpga);
  187. if (((size_t)head.signature_len - 1) >= 127)
  188. return false;
  189. char signature_string[head.signature_len+1];
  190. fpga_io_read(0, head.signature,
  191. signature_string, head.signature_len);
  192. signature_string[head.signature_len] = '\0';
  193. fpga_io_write(0, (char *)head.signature + 9, "GUBBAR", 6);
  194. printf("[FPGA] online, signature \"%s\"\n", signature_string);
  195. esplink_start(&head);
  196. setenv_bool("status.max80.fpga", true);
  197. xSemaphoreGiveRecursive(spi_mutex);
  198. return true;
  199. }
  200. static void fpga_offline(void)
  201. {
  202. xSemaphoreTakeRecursive(spi_mutex, portMAX_DELAY);
  203. setenv_bool("status.max80.fpga", false);
  204. esplink_start(NULL); /* Stop esplink */
  205. }
  206. esp_err_t fpga_iov(const struct fpga_iov *iov, size_t niov)
  207. {
  208. spi_transaction_ext_t trans[FPGA_IOV_MAX];
  209. size_t ntrans = 0;
  210. if (niov > FPGA_IOV_MAX)
  211. return ESP_ERR_INVALID_ARG;
  212. for (size_t i = 0; i < niov; i++) {
  213. const struct fpga_iov *iv = &iov[i];
  214. if (!iv->len && !(iv->cmd & FPGA_CMD_NULL))
  215. continue;
  216. spi_transaction_ext_t *t = &trans[ntrans];
  217. memset(t, 0, sizeof *t);
  218. t->base.flags =
  219. SPI_TRANS_MODE_DIO |
  220. SPI_TRANS_VARIABLE_DUMMY |
  221. SPI_TRANS_MULTILINE_CMD |
  222. SPI_TRANS_MULTILINE_ADDR;
  223. t->base.cmd = iv->cmd;
  224. t->base.addr = iv->iaddr;
  225. if (iv->cmd & FPGA_CMD_RD) {
  226. t->base.rxlength = iv->len << 3;
  227. t->base.rx_buffer = iv->rdata;
  228. /* Emulate partial word read by adding dummy bits for offset */
  229. t->dummy_bits = 16 + ((iv->iaddr & 3) << 2);
  230. if (iv->cmd & FPGA_CMD_STATUS) {
  231. /*
  232. * Include the status "dummy" bits
  233. * THIS REQUIRES THE REMOTE ADDRESS TO BE 32-BIT ALIGNED
  234. */
  235. t->base.rxlength += 32;
  236. t->dummy_bits -= 16;
  237. }
  238. } else {
  239. t->base.length = iv->len << 3;
  240. t->base.tx_buffer = iv->wdata;
  241. }
  242. ntrans++;
  243. }
  244. if (!ntrans)
  245. return ESP_OK;
  246. esp_err_t err = ESP_OK;
  247. xSemaphoreTakeRecursive(spi_mutex, portMAX_DELAY);
  248. if (!spi_handle) {
  249. err = ESP_FAIL;
  250. goto fail;
  251. }
  252. xEventGroupClearBits(spi_done_evgroup, EVENT_ALL_BITS);
  253. size_t tbit = 1;
  254. for (size_t i = 0; i < ntrans; i++) {
  255. spi_transaction_ext_t *t = &trans[i];
  256. t->base.user = (void *)tbit;
  257. err = spi_device_queue_trans(spi_handle, &t->base, portMAX_DELAY);
  258. if (err) {
  259. ntrans = i;
  260. break;
  261. }
  262. tbit <<= 1;
  263. }
  264. if (likely(ntrans)) {
  265. xEventGroupWaitBits(spi_done_evgroup, tbit-1, pdTRUE, pdTRUE,
  266. portMAX_DELAY);
  267. while (ntrans--) {
  268. /* This is insanely stupid to have to do when not needed */
  269. spi_transaction_t *tp;
  270. spi_device_get_trans_result(spi_handle, &tp, 0);
  271. }
  272. }
  273. fail:
  274. xSemaphoreGiveRecursive(spi_mutex);
  275. return err;
  276. }
  277. esp_err_t fpga_io_write(unsigned int cmd, const void *addr,
  278. const void *data, size_t len)
  279. {
  280. struct fpga_iov iov;
  281. iov.cmd = cmd | ~FPGA_CMD_RD;
  282. iov.addr = addr;
  283. iov.wdata = data;
  284. iov.len = len;
  285. return fpga_iov(&iov, 1);
  286. }
  287. esp_err_t fpga_io_read(unsigned int cmd, const void *addr,
  288. void *data, size_t len)
  289. {
  290. struct fpga_iov iov;
  291. iov.cmd = cmd | FPGA_CMD_RD;
  292. iov.addr = addr;
  293. iov.rdata = data;
  294. iov.len = len;
  295. return fpga_iov(&iov, 1);
  296. }
  297. /*
  298. * Get status in polling mode (small transaction, < 256 CPU cycles).
  299. * cmd typically would be IRQ/ACK bits.
  300. */
  301. uint32_t fpga_io_status(unsigned int cmd)
  302. {
  303. spi_transaction_t trans;
  304. memset(&trans, 0, sizeof trans);
  305. trans.flags =
  306. SPI_TRANS_MODE_DIO |
  307. SPI_TRANS_MULTILINE_CMD |
  308. SPI_TRANS_MULTILINE_ADDR |
  309. SPI_TRANS_USE_RXDATA;
  310. trans.cmd = cmd | FPGA_CMD_RD;
  311. trans.addr = 0;
  312. trans.rxlength = 32;
  313. esp_err_t err = ESP_OK;
  314. xSemaphoreTakeRecursive(spi_mutex, portMAX_DELAY);
  315. err = spi_device_polling_transmit(spi_handle, &trans);
  316. xSemaphoreGiveRecursive(spi_mutex);
  317. return err ? 0 : *(const uint32_t *)trans.rx_data;
  318. }
  319. static void fpga_service_task(void *dummy)
  320. {
  321. (void)dummy;
  322. uint32_t status;
  323. bool fpga_initialized = false;
  324. enum fpga_state {
  325. FPGA_DISABLED, /* FPGA services disabled */
  326. FPGA_OFFLINE, /* FPGA services enabled, waiting for FPGA */
  327. FPGA_ONLINE /* FPGA services active */
  328. } fpga_state = FPGA_DISABLED;
  329. fputs("[FPGA] Starting FPGA services task\n", stdout);
  330. while (1) {
  331. uint32_t notifiers, status;
  332. switch (fpga_state) {
  333. case FPGA_DISABLED:
  334. notifiers = notify_wait_for(NOTIFY_ENABLE);
  335. if ((notifiers & NOTIFY_ENABLE) && fpga_link_enable()) {
  336. fputs("[FPGA] Enabling FPGA services\n", stdout);
  337. fpga_state = FPGA_OFFLINE;
  338. }
  339. break;
  340. case FPGA_OFFLINE:
  341. status = fpga_io_status(FPGA_CMD_ACK(EL_UIRQ_READY)|
  342. FPGA_CMD_IRQ(EL_DIRQ_HELLO));
  343. printf("[FPGA] FPGA status flags = 0x%08x\n", status);
  344. if ((status & 0xf031) == 0x9030) {
  345. if (fpga_online())
  346. fpga_state = FPGA_ONLINE;
  347. } else if (digitalRead(PIN_FPGA_INT)) {
  348. notifiers = notify_wait_for(NOTIFY_FPGA|NOTIFY_DISABLE);
  349. }
  350. break;
  351. case FPGA_ONLINE:
  352. notifiers = notify_wait_for(NOTIFY_FPGA|NOTIFY_DISABLE);
  353. if (notifiers & NOTIFY_DISABLE) {
  354. fpga_offline();
  355. break;
  356. }
  357. while (!digitalRead(PIN_FPGA_INT)) {
  358. status = fpga_io_status(0);
  359. if ((status & 0xf031) != 0x9010) {
  360. fpga_offline();
  361. printf("[FPGA] FPGA offline, status = 0x%08x\n", status);
  362. fpga_state = FPGA_OFFLINE;
  363. break;
  364. }
  365. if (status & 0x40)
  366. esplink_poll();
  367. if (status & 0x80) {
  368. fputs("[FPGA] invalid upstream interrupt 3\n", stdout);
  369. fpga_io_status(FPGA_CMD_ACK(3));
  370. }
  371. }
  372. break;
  373. }
  374. if (notifiers & NOTIFY_DISABLE) {
  375. fputs("[FPGA] Disabling FPGA services\n", stdout);
  376. fpga_link_disable();
  377. fpga_state = FPGA_DISABLED;
  378. }
  379. }
  380. }