laforge has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-e1-hardware/+/21715 )

Change subject: icE1usb fw: Expose error conditions from E1 driver
......................................................................

icE1usb fw: Expose error conditions from E1 driver

This will allow the USB interface code to report the errors to the
host PC.

Related: OS#4674
Change-Id: Iba3e00a2b28a2fef6dbd986bfc706c1619c3a3ed
---
M firmware/ice40-riscv/icE1usb/e1.c
M firmware/ice40-riscv/icE1usb/e1.h
M firmware/ice40-riscv/icE1usb/ice1usb_proto.h
M firmware/ice40-riscv/icE1usb/usb_desc_app.c
M firmware/ice40-riscv/icE1usb/usb_e1.c
5 files changed, 108 insertions(+), 4 deletions(-)

Approvals:
  Jenkins Builder: Verified
  tnt: Looks good to me, but someone else must approve
  laforge: Looks good to me, approved



diff --git a/firmware/ice40-riscv/icE1usb/e1.c 
b/firmware/ice40-riscv/icE1usb/e1.c
index 16c8c80..5e57480 100644
--- a/firmware/ice40-riscv/icE1usb/e1.c
+++ b/firmware/ice40-riscv/icE1usb/e1.c
@@ -232,6 +232,7 @@
                int in_flight;
                enum e1_pipe_state state;
        } tx;
+       struct e1_error_count errors;
 } g_e1;


@@ -360,6 +361,12 @@
        return e1f_valid_frames(&g_e1.rx.fifo);
 }

+const struct e1_error_count *
+e1_get_error_count(void)
+{
+       return &g_e1.errors;
+}
+
 void
 e1_poll(void)
 {
@@ -374,10 +381,12 @@
        if (e1_regs->rx.csr & E1_RX_SR_ALIGNED) {
                e1_platform_led_set(0, E1P_LED_GREEN, E1P_LED_ST_ON);
                led_color(0, 48, 0);
+               g_e1.errors.flags &= ~(E1_ERR_F_LOS|E1_ERR_F_ALIGN_ERR);
        } else {
                e1_platform_led_set(0, E1P_LED_GREEN, E1P_LED_ST_BLINK);
-               /* TODO: completely off if rx tick counter not incrementing */
                led_color(48, 0, 0);
+               g_e1.errors.flags |= E1_ERR_F_ALIGN_ERR;
+               /* TODO: completely off if rx tick counter not incrementing */
        }

        /* Recover any done TX BD */
@@ -390,8 +399,10 @@
        while ( (bd = e1_regs->rx.bd) & E1_BD_VALID ) {
                /* FIXME: CRC status ? */
                e1f_multiframe_write_commit(&g_e1.rx.fifo);
-               if ((bd & (E1_BD_CRC0 | E1_BD_CRC1)) != (E1_BD_CRC0 | 
E1_BD_CRC1))
+               if ((bd & (E1_BD_CRC0 | E1_BD_CRC1)) != (E1_BD_CRC0 | 
E1_BD_CRC1)) {
                        printf("b: %03x\n", bd);
+                       g_e1.errors.crc++;
+               }
                g_e1.rx.in_flight--;
        }

@@ -410,6 +421,7 @@
                if (!(e1_regs->rx.csr & E1_RX_SR_ALIGNED)) {
                        printf("[!] E1 rx misalign\n");
                        g_e1.rx.state = RECOVER;
+                       g_e1.errors.align++;
                }
        }

@@ -418,6 +430,7 @@
                if (e1_regs->rx.csr & E1_RX_SR_OVFL) {
                        printf("[!] E1 overflow %d\n", g_e1.rx.in_flight);
                        g_e1.rx.state = RECOVER;
+                       g_e1.errors.ovfl++;
                }
        }

@@ -449,6 +462,7 @@
                if (e1_regs->tx.csr & E1_TX_SR_UNFL) {
                        printf("[!] E1 underflow %d\n", g_e1.tx.in_flight);
                        g_e1.tx.state = RECOVER;
+                       g_e1.errors.unfl++;
                }
        }

diff --git a/firmware/ice40-riscv/icE1usb/e1.h 
b/firmware/ice40-riscv/icE1usb/e1.h
index fcd4284..8ba9838 100644
--- a/firmware/ice40-riscv/icE1usb/e1.h
+++ b/firmware/ice40-riscv/icE1usb/e1.h
@@ -14,6 +14,19 @@
 void e1_tx_config(uint16_t cr);
 void e1_rx_config(uint16_t cr);

+#define E1_ERR_F_ALIGN_ERR     0x01
+#define E1_ERR_F_LOS           0x02
+
+struct e1_error_count {
+       uint16_t crc;
+       uint16_t align;
+       uint16_t ovfl;
+       uint16_t unfl;
+       uint8_t flags;
+};
+
+const struct e1_error_count *e1_get_error_count(void);
+
 volatile uint8_t *e1_data_ptr(int mf, int frame, int ts);
 unsigned int e1_data_ofs(int mf, int frame, int ts);

diff --git a/firmware/ice40-riscv/icE1usb/ice1usb_proto.h 
b/firmware/ice40-riscv/icE1usb/ice1usb_proto.h
index 61e12ad..71f7236 100644
--- a/firmware/ice40-riscv/icE1usb/ice1usb_proto.h
+++ b/firmware/ice40-riscv/icE1usb/ice1usb_proto.h
@@ -75,3 +75,32 @@
 struct ice1usb_rx_config {
        uint8_t mode;           /*!< enum ice1usb_rx_mode */
 } __attribute__((packed));
+
+
+/***********************************************************************
+ * Interrupt Endpoint
+ ***********************************************************************/
+
+enum ice1usb_irq_type {
+       ICE1USB_IRQ_T_ERRCNT            = 1,
+};
+
+/* Ensue ro keep those in sync with e1.h */
+#define ICE1USB_ERR_F_ALIGN_ERR        0x01
+#define ICE1USB_ERR_F_LOS      0x02
+
+struct ice1usb_irq_err {
+       /* 16-bit little-endian counters */
+       uint16_t crc;
+       uint16_t align;
+       uint16_t ovfl;
+       uint16_t unfl;
+       uint8_t flags;
+} __attribute__((packed));
+
+struct ice1usb_irq {
+       uint8_t type;           /*!< enum ice1usb_irq_type */
+       union {
+               struct ice1usb_irq_err errors;
+       } u;
+} __attribute__((packed));
diff --git a/firmware/ice40-riscv/icE1usb/usb_desc_app.c 
b/firmware/ice40-riscv/icE1usb/usb_desc_app.c
index 9fe3968..153d70e 100644
--- a/firmware/ice40-riscv/icE1usb/usb_desc_app.c
+++ b/firmware/ice40-riscv/icE1usb/usb_desc_app.c
@@ -28,12 +28,14 @@
                        struct usb_ep_desc ep_data_in;
                        struct usb_ep_desc ep_data_out;
                        struct usb_ep_desc ep_fb;
+                       struct usb_ep_desc ep_interrupt;
                } __attribute__ ((packed)) off;
                struct {
                        struct usb_intf_desc intf;
                        struct usb_ep_desc ep_data_in;
                        struct usb_ep_desc ep_data_out;
                        struct usb_ep_desc ep_fb;
+                       struct usb_ep_desc ep_interrupt;
                } __attribute__ ((packed)) on;
        } __attribute__ ((packed)) e1;

@@ -79,7 +81,7 @@
                                .bDescriptorType        = USB_DT_INTF,
                                .bInterfaceNumber       = 0,
                                .bAlternateSetting      = 0,
-                               .bNumEndpoints          = 3,
+                               .bNumEndpoints          = 4,
                                .bInterfaceClass        = 0xff,
                                .bInterfaceSubClass     = 0xe1,
                                .bInterfaceProtocol     = 0x00,
@@ -109,6 +111,14 @@
                                .wMaxPacketSize         = 0,
                                .bInterval              = 3,
                        },
+                       .ep_interrupt = {
+                               .bLength                = sizeof(struct 
usb_ep_desc),
+                               .bDescriptorType        = USB_DT_EP,
+                               .bEndpointAddress       = 0x83,
+                               .bmAttributes           = 0x03,
+                               .wMaxPacketSize         = 10,
+                               .bInterval              = 3,
+                       },
                },
                .on = {
                        .intf = {
@@ -116,7 +126,7 @@
                                .bDescriptorType        = USB_DT_INTF,
                                .bInterfaceNumber       = 0,
                                .bAlternateSetting      = 1,
-                               .bNumEndpoints          = 3,
+                               .bNumEndpoints          = 4,
                                .bInterfaceClass        = 0xff,
                                .bInterfaceSubClass     = 0xe1,
                                .bInterfaceProtocol     = 0x00,
@@ -146,6 +156,14 @@
                                .wMaxPacketSize         = 8,
                                .bInterval              = 3,
                        },
+                       .ep_interrupt = {
+                               .bLength                = sizeof(struct 
usb_ep_desc),
+                               .bDescriptorType        = USB_DT_EP,
+                               .bEndpointAddress       = 0x83,
+                               .bmAttributes           = 0x03,
+                               .wMaxPacketSize         = 10,
+                               .bInterval              = 3,
+                       },
                },
        },
 #if 0
diff --git a/firmware/ice40-riscv/icE1usb/usb_e1.c 
b/firmware/ice40-riscv/icE1usb/usb_e1.c
index 0698de5..bbbb24e 100644
--- a/firmware/ice40-riscv/icE1usb/usb_e1.c
+++ b/firmware/ice40-riscv/icE1usb/usb_e1.c
@@ -25,6 +25,7 @@
        int in_bdi;             /* buffer descriptor index for IN EP */
        struct ice1usb_tx_config tx_cfg;
        struct ice1usb_rx_config rx_cfg;
+       struct e1_error_count last_err;
 } g_usb_e1;

 /* default configuration at power-up */
@@ -87,6 +88,29 @@
        if (!g_usb_e1.running)
                return;

+       /* EP3 IRQ */
+       if ((usb_ep_regs[3].in.bd[0].csr & USB_BD_STATE_MSK) != 
USB_BD_STATE_RDY_DATA) {
+               const struct e1_error_count *cur_err = e1_get_error_count();
+               if (memcmp(cur_err, &g_usb_e1.last_err, sizeof(*cur_err))) {
+                       struct ice1usb_irq errmsg = {
+                               .type = ICE1USB_IRQ_T_ERRCNT,
+                               .u = {
+                                       .errors = {
+                                               .crc = cur_err->crc,
+                                               .align = cur_err->align,
+                                               .ovfl = cur_err->ovfl,
+                                               .unfl = cur_err->unfl,
+                                               .flags = cur_err->flags,
+                                       }
+                               }
+                       };
+                       printf("E");
+                       usb_data_write(usb_ep_regs[3].in.bd[0].ptr, &errmsg, 
sizeof(errmsg));
+                       usb_ep_regs[3].in.bd[0].csr = USB_BD_STATE_RDY_DATA | 
USB_BD_LEN(sizeof(errmsg));
+                       g_usb_e1.last_err = *cur_err;
+               }
+       }
+
        /* EP2 IN */
        bdi = g_usb_e1.in_bdi;

@@ -213,6 +237,7 @@
        usb_ep_boot(intf, 0x01, true);
        usb_ep_boot(intf, 0x81, true);
        usb_ep_boot(intf, 0x82, true);
+       usb_ep_boot(intf, 0x83, true);

        return USB_FND_SUCCESS;
 }
@@ -274,6 +299,11 @@
        /* EP1 IN: Queue buffer */
        _usb_fill_feedback_ep();

+       /* EP3 IN: Interrupt */
+       usb_ep_regs[3].in.status = USB_EP_TYPE_INT;
+       usb_ep_regs[3].in.bd[0].ptr = 68;
+       usb_ep_regs[3].in.bd[0].csr = 0;
+
        return USB_FND_SUCCESS;
 }


--
To view, visit https://gerrit.osmocom.org/c/osmo-e1-hardware/+/21715
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-e1-hardware
Gerrit-Branch: master
Gerrit-Change-Id: Iba3e00a2b28a2fef6dbd986bfc706c1619c3a3ed
Gerrit-Change-Number: 21715
Gerrit-PatchSet: 8
Gerrit-Owner: laforge <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>
Gerrit-Reviewer: tnt <[email protected]>
Gerrit-MessageType: merged

Reply via email to