esp.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #include "compiler.h"
  2. #include "common.h"
  3. #include "io.h"
  4. #include "console.h"
  5. #include "esp.h"
  6. #include "boardinfo_fpga.h"
  7. #include "config.h"
  8. struct esplink_head __esplink_head esplink_head;
  9. static volatile __esplink struct esplink_timesync tsync;
  10. static volatile __esplink struct esplink_ota ota;
  11. volatile __esplink char board_info_esp[BOARDINFO_SIZE];
  12. IRQHANDLER(esp,0)
  13. {
  14. uint32_t irqstatus = ESP_CPU_IRQ;
  15. ESP_CPU_IRQ_CLR = irqstatus;
  16. con_printf("[ESP] ESP link IRQ, status = %08x\n", irqstatus);
  17. if (irqstatus & (1 << EL_DIRQ_UNDERRUN)) {
  18. con_printf("[ESP] ESP link memory underrun!!\n");
  19. ESP_SPI_IRQ = (1 << EL_UIRQ_READY); /* Block writes, reinitialize! */
  20. return;
  21. }
  22. if (irqstatus & (1 << EL_DIRQ_TIME)) {
  23. if (tsync.set.update) {
  24. SYSCLOCK_TICK_HOLD = tsync.set.tick;
  25. SYSCLOCK_DATETIME = tsync.set.td;
  26. tsync.set.update = 0;
  27. do_write_rtc = true;
  28. } else {
  29. tsync.get.td = SYSCLOCK_DATETIME;
  30. tsync.get.tick = SYSCLOCK_TICK_HOLD;
  31. ESP_SPI_IRQ_SET = 1 << EL_UIRQ_TIME;
  32. }
  33. }
  34. if (irqstatus & (1 << EL_DIRQ_BOARDINFO))
  35. do_update_boardinfo = true;
  36. if (irqstatus & (1 << EL_DIRQ_HELLO)) {
  37. con_printf("[ESP] Got hello, sending ready...\n");
  38. /* Hello, are you there? Yes, I'm here, and you can write data now */
  39. ESP_SPI_IRQ_SET = (1 << EL_UIRQ_READY)|(1 << EL_UIRQ_WREN);
  40. }
  41. if (irqstatus & (1 << EL_DIRQ_CONFIG))
  42. do_update_config = true;
  43. /*
  44. * Check to see if we got hello after an OTA process was completed
  45. * or aborted; ESP will send EL_DIRQ_DONE to wake us up.
  46. */
  47. if (!(ESP_SPI_IRQ & (1 << EL_UIRQ_OTA))) {
  48. ota.data = NULL;
  49. ota.len = 0;
  50. }
  51. }
  52. void esp_ota(const void *data, size_t len)
  53. {
  54. mask_irq(ESP_IRQ);
  55. ota.data = data;
  56. ota.len = len;
  57. ESP_SPI_IRQ_SET = 1 << EL_UIRQ_OTA;
  58. unmask_irq(ESP_IRQ);
  59. while (ota.data)
  60. waitfor(ESP_IRQ);
  61. }
  62. #define RINGBUF_BUF_SIZE 4096 /* Must be a power of 2 */
  63. static __esplink uint8_t rb_buf[EL_RB_COUNT][2][RINGBUF_BUF_SIZE];
  64. static __esplink struct esplink_ringbuf_desc rb_desc[EL_RB_COUNT];
  65. static volatile __esplink struct esplink_ptrs_dstr rb_dstr[EL_RB_COUNT];
  66. static volatile __esplink struct esplink_ptrs_ustr rb_ustr[EL_RB_COUNT];
  67. static void esplink_rb_init(void)
  68. {
  69. unsigned int i;
  70. for (i = 0; i < EL_RB_COUNT; i++) {
  71. rb_desc[i].dstr.start = rb_buf[i][0];
  72. rb_desc[i].dstr.size = RINGBUF_BUF_SIZE;
  73. rb_desc[i].ustr.start = rb_buf[i][1];
  74. rb_desc[i].ustr.size = RINGBUF_BUF_SIZE;
  75. }
  76. esplink_head.rb.desc = rb_desc;
  77. esplink_head.rb.dstr = (void *)rb_dstr;
  78. esplink_head.rb.ustr = (void *)rb_ustr;
  79. esplink_head.rb.count = EL_RB_COUNT;
  80. }
  81. /*
  82. * Read and write from ring buffers. These are atomic only; on failure
  83. * returns the amount of data/space available, but does NOT advance
  84. * any pointers nor copy any data.
  85. */
  86. size_t esp_rb_read(enum esplink_ringbuf_user ring, void *data, size_t len)
  87. {
  88. const size_t size = rb_desc[ring].dstr.size;
  89. const size_t sizemask = size - 1;
  90. const uint8_t * const base = rb_desc[ring].dstr.start;
  91. size_t head = rb_ustr[ring].head;
  92. size_t tail = rb_dstr[ring].tail;
  93. size_t avail = (head - tail) & sizemask;
  94. uint8_t *p = data;
  95. size_t xlen = len;
  96. if (!len)
  97. return 0;
  98. if (avail < xlen)
  99. return avail;
  100. if (tail + xlen > size) {
  101. size_t left = size - tail;
  102. memcpy(p, base + tail, left);
  103. p += left;
  104. xlen -= left;
  105. tail = 0;
  106. }
  107. memcpy(p, base + tail, xlen);
  108. tail = (tail + xlen) & sizemask;
  109. rb_dstr[ring].tail = tail;
  110. ESP_SPI_IRQ_SET = 1 << EL_UIRQ_RINGBUF;
  111. return len;
  112. }
  113. size_t esp_rb_write(enum esplink_ringbuf_user ring,
  114. const void *data, size_t len)
  115. {
  116. const size_t size = RINGBUF_BUF_SIZE;
  117. const size_t sizemask = size - 1;
  118. uint8_t * const base = rb_desc[ring].ustr.start;
  119. size_t tail = rb_ustr[ring].tail;
  120. size_t head = rb_dstr[ring].head;
  121. size_t avail = (tail - head - 1) & sizemask;
  122. const uint8_t *p = data;
  123. size_t xlen = len;
  124. if (!len)
  125. return 0;
  126. if (avail < xlen)
  127. return avail;
  128. if (head + xlen > size) {
  129. size_t left = size - head;
  130. memcpy(base + head, p, left);
  131. p += left;
  132. xlen -= left;
  133. head = 0;
  134. }
  135. memcpy(base + head, p, xlen);
  136. head = (head + xlen) & sizemask;
  137. rb_dstr[ring].head = head;
  138. ESP_SPI_IRQ_SET = 1 << EL_UIRQ_RINGBUF;
  139. return len;
  140. }
  141. /*
  142. * Faster/simpler versions for reading/writing a single byte at a time;
  143. * esp_rb_getc() returns -1 if the ring is empty.
  144. *
  145. * esp_rb_putc() returns -1 on failure, otherwise the number of
  146. * bytes still free in the ring (a nonnegative number.)
  147. */
  148. __hot int esp_rb_getc(enum esplink_ringbuf_user ring)
  149. {
  150. const size_t size = RINGBUF_BUF_SIZE;
  151. const size_t sizemask = size - 1;
  152. const uint8_t * const base = rb_desc[ring].dstr.start;
  153. size_t head = rb_ustr[ring].head;
  154. size_t tail = rb_dstr[ring].tail;
  155. int data;
  156. if (tail == head)
  157. return -1; /* Buffer empty */
  158. data = base[tail];
  159. tail = (tail + 1) & sizemask;
  160. rb_dstr[ring].tail = tail;
  161. ESP_SPI_IRQ_SET = 1 << EL_UIRQ_RINGBUF;
  162. return data;
  163. }
  164. __hot int esp_rb_putc(enum esplink_ringbuf_user ring, uint8_t data)
  165. {
  166. const size_t size = RINGBUF_BUF_SIZE;
  167. const size_t sizemask = size - 1;
  168. uint8_t * const base = rb_desc[ring].ustr.start;
  169. size_t tail = rb_ustr[ring].tail;
  170. size_t head = rb_dstr[ring].head;
  171. int avail = (tail - head - 1) & sizemask;
  172. if (avail--) {
  173. base[head] = data;
  174. head = (head + 1) & sizemask;
  175. rb_dstr[ring].head = head;
  176. ESP_SPI_IRQ_SET = 1 << EL_UIRQ_RINGBUF;
  177. }
  178. return avail;
  179. }
  180. __hot enum ringbuf_status esp_rb_status(enum esplink_ringbuf_user ring)
  181. {
  182. const size_t size = RINGBUF_BUF_SIZE;
  183. const size_t sizemask = size - 1;
  184. const size_t utail = rb_ustr[ring].tail;
  185. const size_t dhead = rb_ustr[ring].head;
  186. const size_t uhead = rb_dstr[ring].head;
  187. const size_t dtail = rb_dstr[ring].tail;
  188. enum ringbuf_status status = RB_CONNECTED;
  189. if (dhead != dtail)
  190. status |= RB_RXDATA;
  191. if ((utail - uhead - 1) & sizemask)
  192. status |= RB_TXFREE;
  193. return status;
  194. }
  195. void esp_init(void)
  196. {
  197. static char __dram_data esp_signature[] = "Hej tomtebuggar slå i glasen!";
  198. ESP_CPU_IRQ = 0;
  199. ESP_SPI_IRQ = 0;
  200. memset(&esplink_head, 0, sizeof esplink_head);
  201. esplink_head.hlen = sizeof esplink_head;
  202. esplink_head.board.cfg = SYS_BOARDCFG;
  203. memcpy(esplink_head.signature, esp_signature, sizeof esp_signature);
  204. esplink_head.board_info = &board_info_raw;
  205. esplink_head.tsync = &tsync;
  206. esplink_head.ota = &ota;
  207. esplink_head.cfg.buf = config_buf;
  208. esplink_head.cfg.buflen = sizeof config_buf;
  209. esplink_rb_init();
  210. esplink_head.magic = ESPLINK_HEAD_MAGIC;
  211. ESP_SPI_IRQ = (1 << EL_UIRQ_READY);
  212. unmask_irq(ESP_IRQ);
  213. }