<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>