소스 검색

esplink: add ring buffer read/write functions to rv32 side

Add functions to read and write ring buffer data to/from the rv32
side. These are unconditionally atomic, at least for now, since
there is no task scheduler on the rv32 side.
H. Peter Anvin 2 년 전
부모
커밋
1b4255df8e

+ 0 - 1
esp32/max80/esplink.h

@@ -38,7 +38,6 @@ struct esplink_ptrs_dstr {
     size_t head;
 };
 
-
 struct esplink_timesync {
     struct esplink_timesync_buf {
 	uint16_t update;

BIN
esp32/output/max80.ino.bin


+ 2 - 2
fpga/max80.qpf

@@ -19,12 +19,12 @@
 #
 # Quartus Prime
 # Version 21.1.0 Build 842 10/21/2021 SJ Lite Edition
-# Date created = 18:01:47  May 25, 2022
+# Date created = 00:47:37  June 05, 2022
 #
 # -------------------------------------------------------------------------- #
 
 QUARTUS_VERSION = "21.1"
-DATE = "18:01:47  May 25, 2022"
+DATE = "00:47:37  June 05, 2022"
 
 # Revisions
 

BIN
fpga/output/bypass.jic


BIN
fpga/output/v1.fw


BIN
fpga/output/v1.jic


BIN
fpga/output/v1.rbf.gz


BIN
fpga/output/v1.rpd.gz


BIN
fpga/output/v1.sof


BIN
fpga/output/v1.svf.gz


BIN
fpga/output/v1.xsvf.gz


BIN
fpga/output/v2.fw


BIN
fpga/output/v2.jic


BIN
fpga/output/v2.rbf.gz


BIN
fpga/output/v2.rpd.gz


BIN
fpga/output/v2.sof


BIN
fpga/output/v2.svf.gz


BIN
fpga/output/v2.xsvf.gz


+ 1 - 1
rv32/checksum.h

@@ -1,4 +1,4 @@
 #ifndef CHECKSUM_H
 #define CHECKSUM_H
-#define SDRAM_SUM 0xbd6632a6
+#define SDRAM_SUM 0xa53dbdef
 #endif

+ 1 - 4
rv32/common.h

@@ -90,7 +90,4 @@ extern void run_test_image(void);
 extern void rom_flash_from_memory(void *, size_t);
 extern void rom_flash_from_sdcard(void);
 
-extern void esp_init(void);
-extern void esp_ota(const void *, size_t);
-
-#endif /* FW_H */
+#endif /* COMMON_H */

+ 100 - 1
rv32/esp.c

@@ -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);
 

+ 13 - 0
rv32/esplink.h

@@ -1 +1,14 @@
+#ifndef RV32_ESPLINK_H
+#define RV32_ESPLINK_H
+
+#include "compiler.h"
 #include "../esp32/max80/esplink.h"
+
+extern void esp_init(void);
+extern void esp_ota(const void *, size_t);
+extern size_t esp_rb_read(enum esplink_ringbuf_user ring,
+			  void *data, size_t len);
+extern size_t esp_rb_write(enum esplink_ringbuf_user ring,
+			   const void *data, size_t len);
+
+#endif /* RV32_ESPLINK_H */

+ 1 - 0
rv32/system.c

@@ -4,6 +4,7 @@
 #include "abcio.h"
 #include "sys.h"
 #include "console.h"
+#include "esplink.h"
 
 #define DEBUG     0
 #define MINITESTS 1