123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- #include "compiler.h"
- #include "common.h"
- #include "io.h"
- #include "console.h"
- #include "esp.h"
- #include "boardinfo_fpga.h"
- struct esplink_head __esplink_head esplink_head;
- static volatile __esplink struct esplink_timesync tsync;
- static volatile __esplink struct esplink_ota ota;
- volatile __esplink char board_info_esp[BOARDINFO_SIZE];
- IRQHANDLER(esp,0)
- {
- uint32_t irqstatus = ESP_CPU_IRQ;
- ESP_CPU_IRQ_CLR = irqstatus;
- if (irqstatus & (1 << EL_DIRQ_UNDERRUN)) {
- con_printf("[ESP] ESP link memory underrun!!\n");
- ESP_SPI_IRQ = (1 << EL_UIRQ_READY); /* Block writes, reinitialize! */
- return;
- }
- if (irqstatus & (1 << EL_DIRQ_TIME)) {
- if (tsync.set.update) {
- SYSCLOCK_TICK_HOLD = tsync.set.tick;
- SYSCLOCK_DATETIME = tsync.set.td;
- tsync.set.update = 0;
- do_write_rtc = true;
- } else {
- tsync.get.td = SYSCLOCK_DATETIME;
- tsync.get.tick = SYSCLOCK_TICK_HOLD;
- ESP_SPI_IRQ_SET = 1 << EL_UIRQ_TIME;
- }
- }
- if (irqstatus & (1 << EL_DIRQ_BOARDINFO))
- do_update_boardinfo = true;
- if (irqstatus & (1 << EL_DIRQ_HELLO)) {
- con_printf("[ESP] Got hello, sending ready...\n");
- /* Hello, are you there? Yes, I'm here, and you can write data now */
- ESP_SPI_IRQ_SET = (1 << EL_UIRQ_READY)|(1 << EL_UIRQ_WREN);
- }
- /*
- * Check to see if we got hello after an OTA process was completed
- * or aborted; ESP will send EL_DIRQ_DONE to wake us up.
- */
- if (!(ESP_SPI_IRQ & (1 << EL_UIRQ_OTA))) {
- ota.data = NULL;
- ota.len = 0;
- }
- }
- void esp_ota(const void *data, size_t len)
- {
- mask_irq(ESP_IRQ);
- ota.data = data;
- ota.len = len;
- ESP_SPI_IRQ_SET = 1 << EL_UIRQ_OTA;
- unmask_irq(ESP_IRQ);
- while (ota.data)
- waitfor(ESP_IRQ);
- }
- #define RINGBUF_BUF_SIZE 4096 /* Must be a power of 2 */
- static __esplink uint8_t rb_buf[EL_RB_COUNT][2][RINGBUF_BUF_SIZE];
- static __esplink struct esplink_ringbuf_desc rb_desc[EL_RB_COUNT];
- static volatile __esplink struct esplink_ptrs_dstr rb_dstr[EL_RB_COUNT];
- static volatile __esplink struct esplink_ptrs_ustr rb_ustr[EL_RB_COUNT];
- static void esplink_rb_init(void)
- {
- unsigned int i;
- for (i = 0; i < EL_RB_COUNT; i++) {
- rb_desc[i].dstr.start = rb_buf[i][0];
- rb_desc[i].dstr.size = RINGBUF_BUF_SIZE;
- rb_desc[i].ustr.start = rb_buf[i][1];
- rb_desc[i].ustr.size = RINGBUF_BUF_SIZE;
- }
- esplink_head.rb.desc = rb_desc;
- esplink_head.rb.dstr = (void *)rb_dstr;
- esplink_head.rb.ustr = (void *)rb_ustr;
- esplink_head.rb.count = EL_RB_COUNT;
- }
- /*
- * Read and write from ring buffers. These are atomic only; on failure
- * returns the amount of data/space available, but does NOT advance
- * any pointers nor copy any data.
- */
- size_t esp_rb_read(enum esplink_ringbuf_user ring, void *data, size_t len)
- {
- const size_t size = rb_desc[ring].dstr.size;
- const size_t sizemask = size - 1;
- const uint8_t * const base = rb_desc[ring].dstr.start;
- size_t head = rb_ustr[ring].head;
- size_t tail = rb_dstr[ring].tail;
- size_t avail = (head - tail) & sizemask;
- uint8_t *p = data;
- size_t xlen = len;
- if (!len)
- return 0;
- if (avail < xlen)
- return avail;
- if (tail + xlen > size) {
- size_t left = size - tail;
- memcpy(p, base + tail, left);
- p += left;
- xlen -= left;
- tail = 0;
- }
- memcpy(p, base + tail, xlen);
- tail = (tail + xlen) & sizemask;
- rb_dstr[ring].tail = tail;
- ESP_SPI_IRQ_SET = 1 << EL_UIRQ_RINGBUF;
- return len;
- }
- size_t esp_rb_write(enum esplink_ringbuf_user ring,
- const void *data, size_t len)
- {
- const size_t size = RINGBUF_BUF_SIZE;
- const size_t sizemask = size - 1;
- uint8_t * const base = rb_desc[ring].ustr.start;
- size_t tail = rb_ustr[ring].tail;
- size_t head = rb_dstr[ring].head;
- size_t avail = (tail - head - 1) & sizemask;
- const uint8_t *p = data;
- size_t xlen = len;
- if (!len)
- return 0;
- if (avail < xlen)
- return avail;
- if (head + xlen > size) {
- size_t left = size - head;
- memcpy(base + head, p, left);
- p += left;
- xlen -= left;
- head = 0;
- }
- memcpy(base + head, p, xlen);
- head = (head + xlen) & sizemask;
- rb_dstr[ring].head = head;
- ESP_SPI_IRQ_SET = 1 << EL_UIRQ_RINGBUF;
- return len;
- }
- /*
- * Faster/simpler versions for reading/writing a single byte at a time;
- * esp_rb_getc() returns -1 if the ring is empty.
- *
- * esp_rb_putc() returns -1 on failure, otherwise the number of
- * bytes still free in the ring (a nonnegative number.)
- */
- __hot int esp_rb_getc(enum esplink_ringbuf_user ring)
- {
- const size_t size = RINGBUF_BUF_SIZE;
- const size_t sizemask = size - 1;
- const uint8_t * const base = rb_desc[ring].dstr.start;
- size_t head = rb_ustr[ring].head;
- size_t tail = rb_dstr[ring].tail;
- int data;
- if (tail == head)
- return -1; /* Buffer empty */
- data = base[tail];
- tail = (tail + 1) & sizemask;
- rb_dstr[ring].tail = tail;
- ESP_SPI_IRQ_SET = 1 << EL_UIRQ_RINGBUF;
- return data;
- }
- __hot int esp_rb_putc(enum esplink_ringbuf_user ring, uint8_t data)
- {
- const size_t size = RINGBUF_BUF_SIZE;
- const size_t sizemask = size - 1;
- uint8_t * const base = rb_desc[ring].ustr.start;
- size_t tail = rb_ustr[ring].tail;
- size_t head = rb_dstr[ring].head;
- int avail = (tail - head - 1) & sizemask;
- if (avail--) {
- base[head] = data;
- head = (head + 1) & sizemask;
- rb_dstr[ring].head = head;
- ESP_SPI_IRQ_SET = 1 << EL_UIRQ_RINGBUF;
- }
- return avail;
- }
- __hot enum ringbuf_status esp_rb_status(enum esplink_ringbuf_user ring)
- {
- const size_t size = RINGBUF_BUF_SIZE;
- const size_t sizemask = size - 1;
- const size_t utail = rb_ustr[ring].tail;
- const size_t dhead = rb_ustr[ring].head;
- const size_t uhead = rb_dstr[ring].head;
- const size_t dtail = rb_dstr[ring].tail;
- enum ringbuf_status status = RB_CONNECTED;
- if (dhead != dtail)
- status |= RB_RXDATA;
- if ((utail - uhead - 1) & sizemask)
- status |= RB_TXFREE;
- return status;
- }
- void esp_init(void)
- {
- static char __dram_data esp_signature[] = "Hej tomtebuggar slå i glasen!";
- ESP_CPU_IRQ = 0;
- ESP_SPI_IRQ = 0;
- memset(&esplink_head, 0, sizeof esplink_head);
- esplink_head.hlen = sizeof esplink_head;
- esplink_head.board.cfg = SYS_BOARDCFG;
- memcpy(esplink_head.signature, esp_signature, sizeof esp_signature);
- esplink_head.board_info = &board_info_raw;
- esplink_head.tsync = &tsync;
- esplink_head.ota = &ota;
- esplink_rb_init();
- esplink_head.magic = ESPLINK_HEAD_MAGIC;
- ESP_SPI_IRQ = (1 << EL_UIRQ_READY);
- unmask_irq(ESP_IRQ);
- }
|