|
@@ -51,7 +51,7 @@ IRQHANDLER(esp,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;
|
|
@@ -62,6 +62,103 @@ void esp_ota(const void *data, size_t len)
|
|
|
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 = rb_desc[ring].ustr.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;
|
|
|
+}
|
|
|
+
|
|
|
void esp_init(void)
|
|
|
{
|
|
|
static char __dram_data esp_signature[] = "Hej tomtebuggar slå i glasen!";
|
|
@@ -78,6 +175,8 @@ void esp_init(void)
|
|
|
esplink_head.tsync = &tsync;
|
|
|
esplink_head.ota = &ota;
|
|
|
|
|
|
+ esplink_rb_init();
|
|
|
+
|
|
|
esplink_head.magic = ESPLINK_HEAD_MAGIC;
|
|
|
ESP_SPI_IRQ = (1 << EL_UIRQ_READY);
|
|
|
|