<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-e1-hardware/+/21715">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Jenkins Builder: Verified
tnt: Looks good to me, but someone else must approve
laforge: Looks good to me, approved
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">icE1usb fw: Expose error conditions from E1 driver<br><br>This will allow the USB interface code to report the errors to the<br>host PC.<br><br>Related: OS#4674<br>Change-Id: Iba3e00a2b28a2fef6dbd986bfc706c1619c3a3ed<br>---<br>M firmware/ice40-riscv/icE1usb/e1.c<br>M firmware/ice40-riscv/icE1usb/e1.h<br>M firmware/ice40-riscv/icE1usb/ice1usb_proto.h<br>M firmware/ice40-riscv/icE1usb/usb_desc_app.c<br>M firmware/ice40-riscv/icE1usb/usb_e1.c<br>5 files changed, 108 insertions(+), 4 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/firmware/ice40-riscv/icE1usb/e1.c b/firmware/ice40-riscv/icE1usb/e1.c</span><br><span>index 16c8c80..5e57480 100644</span><br><span>--- a/firmware/ice40-riscv/icE1usb/e1.c</span><br><span>+++ b/firmware/ice40-riscv/icE1usb/e1.c</span><br><span>@@ -232,6 +232,7 @@</span><br><span> int in_flight;</span><br><span> enum e1_pipe_state state;</span><br><span> } tx;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct e1_error_count errors;</span><br><span> } g_e1;</span><br><span> </span><br><span> </span><br><span>@@ -360,6 +361,12 @@</span><br><span> return e1f_valid_frames(&g_e1.rx.fifo);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+const struct e1_error_count *</span><br><span style="color: hsl(120, 100%, 40%);">+e1_get_error_count(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return &g_e1.errors;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void</span><br><span> e1_poll(void)</span><br><span> {</span><br><span>@@ -374,10 +381,12 @@</span><br><span> if (e1_regs->rx.csr & E1_RX_SR_ALIGNED) {</span><br><span> e1_platform_led_set(0, E1P_LED_GREEN, E1P_LED_ST_ON);</span><br><span> led_color(0, 48, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ g_e1.errors.flags &= ~(E1_ERR_F_LOS|E1_ERR_F_ALIGN_ERR);</span><br><span> } else {</span><br><span> e1_platform_led_set(0, E1P_LED_GREEN, E1P_LED_ST_BLINK);</span><br><span style="color: hsl(0, 100%, 40%);">- /* TODO: completely off if rx tick counter not incrementing */</span><br><span> led_color(48, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ g_e1.errors.flags |= E1_ERR_F_ALIGN_ERR;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: completely off if rx tick counter not incrementing */</span><br><span> }</span><br><span> </span><br><span> /* Recover any done TX BD */</span><br><span>@@ -390,8 +399,10 @@</span><br><span> while ( (bd = e1_regs->rx.bd) & E1_BD_VALID ) {</span><br><span> /* FIXME: CRC status ? */</span><br><span> e1f_multiframe_write_commit(&g_e1.rx.fifo);</span><br><span style="color: hsl(0, 100%, 40%);">- if ((bd & (E1_BD_CRC0 | E1_BD_CRC1)) != (E1_BD_CRC0 | E1_BD_CRC1))</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((bd & (E1_BD_CRC0 | E1_BD_CRC1)) != (E1_BD_CRC0 | E1_BD_CRC1)) {</span><br><span> printf("b: %03x\n", bd);</span><br><span style="color: hsl(120, 100%, 40%);">+ g_e1.errors.crc++;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> g_e1.rx.in_flight--;</span><br><span> }</span><br><span> </span><br><span>@@ -410,6 +421,7 @@</span><br><span> if (!(e1_regs->rx.csr & E1_RX_SR_ALIGNED)) {</span><br><span> printf("[!] E1 rx misalign\n");</span><br><span> g_e1.rx.state = RECOVER;</span><br><span style="color: hsl(120, 100%, 40%);">+ g_e1.errors.align++;</span><br><span> }</span><br><span> }</span><br><span> </span><br><span>@@ -418,6 +430,7 @@</span><br><span> if (e1_regs->rx.csr & E1_RX_SR_OVFL) {</span><br><span> printf("[!] E1 overflow %d\n", g_e1.rx.in_flight);</span><br><span> g_e1.rx.state = RECOVER;</span><br><span style="color: hsl(120, 100%, 40%);">+ g_e1.errors.ovfl++;</span><br><span> }</span><br><span> }</span><br><span> </span><br><span>@@ -449,6 +462,7 @@</span><br><span> if (e1_regs->tx.csr & E1_TX_SR_UNFL) {</span><br><span> printf("[!] E1 underflow %d\n", g_e1.tx.in_flight);</span><br><span> g_e1.tx.state = RECOVER;</span><br><span style="color: hsl(120, 100%, 40%);">+ g_e1.errors.unfl++;</span><br><span> }</span><br><span> }</span><br><span> </span><br><span>diff --git a/firmware/ice40-riscv/icE1usb/e1.h b/firmware/ice40-riscv/icE1usb/e1.h</span><br><span>index fcd4284..8ba9838 100644</span><br><span>--- a/firmware/ice40-riscv/icE1usb/e1.h</span><br><span>+++ b/firmware/ice40-riscv/icE1usb/e1.h</span><br><span>@@ -14,6 +14,19 @@</span><br><span> void e1_tx_config(uint16_t cr);</span><br><span> void e1_rx_config(uint16_t cr);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define E1_ERR_F_ALIGN_ERR 0x01</span><br><span style="color: hsl(120, 100%, 40%);">+#define E1_ERR_F_LOS 0x02</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct e1_error_count {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t crc;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t align;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t ovfl;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t unfl;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t flags;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const struct e1_error_count *e1_get_error_count(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> volatile uint8_t *e1_data_ptr(int mf, int frame, int ts);</span><br><span> unsigned int e1_data_ofs(int mf, int frame, int ts);</span><br><span> </span><br><span>diff --git a/firmware/ice40-riscv/icE1usb/ice1usb_proto.h b/firmware/ice40-riscv/icE1usb/ice1usb_proto.h</span><br><span>index 61e12ad..71f7236 100644</span><br><span>--- a/firmware/ice40-riscv/icE1usb/ice1usb_proto.h</span><br><span>+++ b/firmware/ice40-riscv/icE1usb/ice1usb_proto.h</span><br><span>@@ -75,3 +75,32 @@</span><br><span> struct ice1usb_rx_config {</span><br><span> uint8_t mode; /*!< enum ice1usb_rx_mode */</span><br><span> } __attribute__((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * Interrupt Endpoint</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum ice1usb_irq_type {</span><br><span style="color: hsl(120, 100%, 40%);">+ ICE1USB_IRQ_T_ERRCNT = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Ensue ro keep those in sync with e1.h */</span><br><span style="color: hsl(120, 100%, 40%);">+#define ICE1USB_ERR_F_ALIGN_ERR 0x01</span><br><span style="color: hsl(120, 100%, 40%);">+#define ICE1USB_ERR_F_LOS 0x02</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ice1usb_irq_err {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 16-bit little-endian counters */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t crc;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t align;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t ovfl;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t unfl;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t flags;</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ice1usb_irq {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t type; /*!< enum ice1usb_irq_type */</span><br><span style="color: hsl(120, 100%, 40%);">+ union {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ice1usb_irq_err errors;</span><br><span style="color: hsl(120, 100%, 40%);">+ } u;</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__((packed));</span><br><span>diff --git a/firmware/ice40-riscv/icE1usb/usb_desc_app.c b/firmware/ice40-riscv/icE1usb/usb_desc_app.c</span><br><span>index 9fe3968..153d70e 100644</span><br><span>--- a/firmware/ice40-riscv/icE1usb/usb_desc_app.c</span><br><span>+++ b/firmware/ice40-riscv/icE1usb/usb_desc_app.c</span><br><span>@@ -28,12 +28,14 @@</span><br><span> struct usb_ep_desc ep_data_in;</span><br><span> struct usb_ep_desc ep_data_out;</span><br><span> struct usb_ep_desc ep_fb;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct usb_ep_desc ep_interrupt;</span><br><span> } __attribute__ ((packed)) off;</span><br><span> struct {</span><br><span> struct usb_intf_desc intf;</span><br><span> struct usb_ep_desc ep_data_in;</span><br><span> struct usb_ep_desc ep_data_out;</span><br><span> struct usb_ep_desc ep_fb;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct usb_ep_desc ep_interrupt;</span><br><span> } __attribute__ ((packed)) on;</span><br><span> } __attribute__ ((packed)) e1;</span><br><span> </span><br><span>@@ -79,7 +81,7 @@</span><br><span> .bDescriptorType = USB_DT_INTF,</span><br><span> .bInterfaceNumber = 0,</span><br><span> .bAlternateSetting = 0,</span><br><span style="color: hsl(0, 100%, 40%);">- .bNumEndpoints = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bNumEndpoints = 4,</span><br><span> .bInterfaceClass = 0xff,</span><br><span> .bInterfaceSubClass = 0xe1,</span><br><span> .bInterfaceProtocol = 0x00,</span><br><span>@@ -109,6 +111,14 @@</span><br><span> .wMaxPacketSize = 0,</span><br><span> .bInterval = 3,</span><br><span> },</span><br><span style="color: hsl(120, 100%, 40%);">+ .ep_interrupt = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .bLength = sizeof(struct usb_ep_desc),</span><br><span style="color: hsl(120, 100%, 40%);">+ .bDescriptorType = USB_DT_EP,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bEndpointAddress = 0x83,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bmAttributes = 0x03,</span><br><span style="color: hsl(120, 100%, 40%);">+ .wMaxPacketSize = 10,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bInterval = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span> },</span><br><span> .on = {</span><br><span> .intf = {</span><br><span>@@ -116,7 +126,7 @@</span><br><span> .bDescriptorType = USB_DT_INTF,</span><br><span> .bInterfaceNumber = 0,</span><br><span> .bAlternateSetting = 1,</span><br><span style="color: hsl(0, 100%, 40%);">- .bNumEndpoints = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bNumEndpoints = 4,</span><br><span> .bInterfaceClass = 0xff,</span><br><span> .bInterfaceSubClass = 0xe1,</span><br><span> .bInterfaceProtocol = 0x00,</span><br><span>@@ -146,6 +156,14 @@</span><br><span> .wMaxPacketSize = 8,</span><br><span> .bInterval = 3,</span><br><span> },</span><br><span style="color: hsl(120, 100%, 40%);">+ .ep_interrupt = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .bLength = sizeof(struct usb_ep_desc),</span><br><span style="color: hsl(120, 100%, 40%);">+ .bDescriptorType = USB_DT_EP,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bEndpointAddress = 0x83,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bmAttributes = 0x03,</span><br><span style="color: hsl(120, 100%, 40%);">+ .wMaxPacketSize = 10,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bInterval = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span> },</span><br><span> },</span><br><span> #if 0</span><br><span>diff --git a/firmware/ice40-riscv/icE1usb/usb_e1.c b/firmware/ice40-riscv/icE1usb/usb_e1.c</span><br><span>index 0698de5..bbbb24e 100644</span><br><span>--- a/firmware/ice40-riscv/icE1usb/usb_e1.c</span><br><span>+++ b/firmware/ice40-riscv/icE1usb/usb_e1.c</span><br><span>@@ -25,6 +25,7 @@</span><br><span> int in_bdi; /* buffer descriptor index for IN EP */</span><br><span> struct ice1usb_tx_config tx_cfg;</span><br><span> struct ice1usb_rx_config rx_cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct e1_error_count last_err;</span><br><span> } g_usb_e1;</span><br><span> </span><br><span> /* default configuration at power-up */</span><br><span>@@ -87,6 +88,29 @@</span><br><span> if (!g_usb_e1.running)</span><br><span> return;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* EP3 IRQ */</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((usb_ep_regs[3].in.bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) {</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct e1_error_count *cur_err = e1_get_error_count();</span><br><span style="color: hsl(120, 100%, 40%);">+ if (memcmp(cur_err, &g_usb_e1.last_err, sizeof(*cur_err))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ice1usb_irq errmsg = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .type = ICE1USB_IRQ_T_ERRCNT,</span><br><span style="color: hsl(120, 100%, 40%);">+ .u = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .errors = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .crc = cur_err->crc,</span><br><span style="color: hsl(120, 100%, 40%);">+ .align = cur_err->align,</span><br><span style="color: hsl(120, 100%, 40%);">+ .ovfl = cur_err->ovfl,</span><br><span style="color: hsl(120, 100%, 40%);">+ .unfl = cur_err->unfl,</span><br><span style="color: hsl(120, 100%, 40%);">+ .flags = cur_err->flags,</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("E");</span><br><span style="color: hsl(120, 100%, 40%);">+ usb_data_write(usb_ep_regs[3].in.bd[0].ptr, &errmsg, sizeof(errmsg));</span><br><span style="color: hsl(120, 100%, 40%);">+ usb_ep_regs[3].in.bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(sizeof(errmsg));</span><br><span style="color: hsl(120, 100%, 40%);">+ g_usb_e1.last_err = *cur_err;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* EP2 IN */</span><br><span> bdi = g_usb_e1.in_bdi;</span><br><span> </span><br><span>@@ -213,6 +237,7 @@</span><br><span> usb_ep_boot(intf, 0x01, true);</span><br><span> usb_ep_boot(intf, 0x81, true);</span><br><span> usb_ep_boot(intf, 0x82, true);</span><br><span style="color: hsl(120, 100%, 40%);">+ usb_ep_boot(intf, 0x83, true);</span><br><span> </span><br><span> return USB_FND_SUCCESS;</span><br><span> }</span><br><span>@@ -274,6 +299,11 @@</span><br><span> /* EP1 IN: Queue buffer */</span><br><span> _usb_fill_feedback_ep();</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* EP3 IN: Interrupt */</span><br><span style="color: hsl(120, 100%, 40%);">+ usb_ep_regs[3].in.status = USB_EP_TYPE_INT;</span><br><span style="color: hsl(120, 100%, 40%);">+ usb_ep_regs[3].in.bd[0].ptr = 68;</span><br><span style="color: hsl(120, 100%, 40%);">+ usb_ep_regs[3].in.bd[0].csr = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return USB_FND_SUCCESS;</span><br><span> }</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-e1-hardware/+/21715">change 21715</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-e1-hardware/+/21715"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-e1-hardware </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Iba3e00a2b28a2fef6dbd986bfc706c1619c3a3ed </div>
<div style="display:none"> Gerrit-Change-Number: 21715 </div>
<div style="display:none"> Gerrit-PatchSet: 8 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: tnt <tnt@246tNt.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>