tnt has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-e1-hardware/+/26841 )
Change subject: icE1usb fw: Add multi-port support in USB code ......................................................................
icE1usb fw: Add multi-port support in USB code
Signed-off-by: Sylvain Munaut tnt@246tNt.com Change-Id: I134410b542461c34339baa8d9120a5c86fc35d46 --- M firmware/ice40-riscv/icE1usb/fw_app.c M firmware/ice40-riscv/icE1usb/usb_desc_app.c M firmware/ice40-riscv/icE1usb/usb_desc_ids.h M firmware/ice40-riscv/icE1usb/usb_e1.c M firmware/ice40-riscv/icE1usb/usb_e1.h M firmware/ice40-riscv/icE1usb/usb_str_app.txt 6 files changed, 225 insertions(+), 82 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-e1-hardware refs/changes/41/26841/1
diff --git a/firmware/ice40-riscv/icE1usb/fw_app.c b/firmware/ice40-riscv/icE1usb/fw_app.c index 3340f4a..55218b8 100644 --- a/firmware/ice40-riscv/icE1usb/fw_app.c +++ b/firmware/ice40-riscv/icE1usb/fw_app.c @@ -102,6 +102,7 @@
/* Start */ e1_init(0, 0, 0); + e1_init(1, 0, 0); led_state(true); usb_connect();
@@ -151,7 +152,9 @@ usb_poll();
/* E1 poll */ - e1_poll(0); - usb_e1_run(); + for (int port=0; port<2; port++) { + e1_poll(port); + usb_e1_run(port); + } } } diff --git a/firmware/ice40-riscv/icE1usb/usb_desc_app.c b/firmware/ice40-riscv/icE1usb/usb_desc_app.c index 663be0b..22a81d3 100644 --- a/firmware/ice40-riscv/icE1usb/usb_desc_app.c +++ b/firmware/ice40-riscv/icE1usb/usb_desc_app.c @@ -39,7 +39,7 @@ struct usb_ep_desc ep_fb; struct usb_ep_desc ep_interrupt; } __attribute__ ((packed)) on; - } __attribute__ ((packed)) e1; + } __attribute__ ((packed)) e1[2];
/* CDC */ #if 0 @@ -71,7 +71,7 @@ .bmAttributes = 0x80, .bMaxPower = 0x32, /* 100 mA */ }, - .e1 = { + .e1[0] = { .off = { .intf = { .bLength = sizeof(struct usb_intf_desc), @@ -103,7 +103,7 @@ .bInterfaceClass = 0xff, .bInterfaceSubClass = 0xe1, .bInterfaceProtocol = 0x00, - .iInterface = 5, + .iInterface = 6, }, .ep_data_in = { .bLength = sizeof(struct usb_ep_desc), @@ -139,6 +139,74 @@ }, }, }, + .e1[1] = { + .off = { + .intf = { + .bLength = sizeof(struct usb_intf_desc), + .bDescriptorType = USB_DT_INTF, + .bInterfaceNumber = USB_INTF_E1(1), + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xe1, + .bInterfaceProtocol = 0x00, + .iInterface = 7, + }, + .ep_interrupt = { + .bLength = sizeof(struct usb_ep_desc), + .bDescriptorType = USB_DT_EP, + .bEndpointAddress = USB_EP_E1_INT(1), + .bmAttributes = 0x03, + .wMaxPacketSize = 10, + .bInterval = 4, /* every 4 ms */ + }, + }, + .on = { + .intf = { + .bLength = sizeof(struct usb_intf_desc), + .bDescriptorType = USB_DT_INTF, + .bInterfaceNumber = USB_INTF_E1(1), + .bAlternateSetting = 1, + .bNumEndpoints = 4, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xe1, + .bInterfaceProtocol = 0x00, + .iInterface = 8, + }, + .ep_data_in = { + .bLength = sizeof(struct usb_ep_desc), + .bDescriptorType = USB_DT_EP, + .bEndpointAddress = USB_EP_E1_IN(1), + .bmAttributes = 0x05, + .wMaxPacketSize = 292, + .bInterval = 1, + }, + .ep_data_out = { + .bLength = sizeof(struct usb_ep_desc), + .bDescriptorType = USB_DT_EP, + .bEndpointAddress = USB_EP_E1_OUT(1), + .bmAttributes = 0x05, + .wMaxPacketSize = 292, + .bInterval = 1, + }, + .ep_fb = { + .bLength = sizeof(struct usb_ep_desc), + .bDescriptorType = USB_DT_EP, + .bEndpointAddress = USB_EP_E1_FB(1), + .bmAttributes = 0x11, + .wMaxPacketSize = 3, + .bInterval = 3, /* every 2^(3-1) = 4 ms */ + }, + .ep_interrupt = { + .bLength = sizeof(struct usb_ep_desc), + .bDescriptorType = USB_DT_EP, + .bEndpointAddress = USB_EP_E1_INT(1), + .bmAttributes = 0x03, + .wMaxPacketSize = 10, + .bInterval = 4, /* every 4 ms */ + }, + }, + }, #if 0 .cdc = { .intf_ctl = { @@ -150,7 +218,7 @@ .bInterfaceClass = USB_CLS_CDC_CONTROL, .bInterfaceSubClass = USB_CDC_SCLS_ACM, .bInterfaceProtocol = 0x00, - .iInterface = 6, + .iInterface = 9, }, .cdc_hdr = { .bLength = sizeof(struct usb_cdc_hdr_desc), @@ -188,7 +256,7 @@ .bInterfaceClass = USB_CLS_CDC_DATA, .bInterfaceSubClass = 0x00, .bInterfaceProtocol = 0x00, - .iInterface = 7, + .iInterface = 10, }, .ep_data_out = { .bLength = sizeof(struct usb_ep_desc), @@ -218,7 +286,7 @@ .bInterfaceClass = 0xfe, .bInterfaceSubClass = 0x01, .bInterfaceProtocol = 0x01, - .iInterface = 8, + .iInterface = 11, }, .func = { .bLength = sizeof(struct usb_dfu_func_desc), diff --git a/firmware/ice40-riscv/icE1usb/usb_desc_ids.h b/firmware/ice40-riscv/icE1usb/usb_desc_ids.h index 2247f84..00dbb34 100644 --- a/firmware/ice40-riscv/icE1usb/usb_desc_ids.h +++ b/firmware/ice40-riscv/icE1usb/usb_desc_ids.h @@ -8,8 +8,8 @@ #pragma once
#define USB_INTF_E1(p) (0 + (p)) -#define USB_INTF_DFU 1 -#define USB_INTF_NUM 2 +#define USB_INTF_DFU 2 +#define USB_INTF_NUM 3
#define USB_EP_E1_IN(p) (0x82 + (3 * (p))) #define USB_EP_E1_OUT(p) (0x01 + (3 * (p))) diff --git a/firmware/ice40-riscv/icE1usb/usb_e1.c b/firmware/ice40-riscv/icE1usb/usb_e1.c index 75811c2..a18ebe4 100644 --- a/firmware/ice40-riscv/icE1usb/usb_e1.c +++ b/firmware/ice40-riscv/icE1usb/usb_e1.c @@ -16,17 +16,20 @@ #include "e1.h" #include "misc.h" #include "usb_desc_ids.h" +#include "utils.h"
#include "ice1usb_proto.h"
-struct { +struct usb_e1_state { bool running; /* are we running (transceiving USB data)? */ int out_bdi; /* buffer descriptor index for OUT EP */ 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; +}; + +static struct usb_e1_state g_usb_e1[2];
/* default configuration at power-up */ static const struct ice1usb_tx_config tx_cfg_default = { @@ -47,8 +50,29 @@ return (ep & 0x80) ? &usb_ep_regs[ep & 0x1f].in : &usb_ep_regs[ep & 0x1f].out; }
+static struct usb_e1_state * +_get_state(int port) +{ + if ((port < 0) || (port > 1)) + panic("_get_state invalid port %d", port); + return &g_usb_e1[port]; +} + +static int +_ifnum2port(uint8_t bInterfaceNumber) +{ + switch (bInterfaceNumber) { + case USB_INTF_E1(0): return 0; + case USB_INTF_E1(1): return 1; + default: + /* Don't panic since this will be handled as USB STALL */ + return -1; + } +} + + static void -_usb_fill_feedback_ep(void) +_usb_fill_feedback_ep(int port) { static uint16_t ticks_prev = 0; uint16_t ticks; @@ -57,41 +81,42 @@ volatile struct usb_ep *ep_regs;
/* Compute real E1 tick count (with safety against bad values) */ - ticks = e1_tick_read(0); + ticks = e1_tick_read(port); val = (ticks - ticks_prev) & 0xffff; ticks_prev = ticks; if ((val < 7168) | (val > 9216)) val = 8192;
/* Bias depending on TX fifo level */ - level = e1_tx_level(0); + level = e1_tx_level(port); if (level < (3 * 16)) val += 256; else if (level > (8 * 16)) val -= 256;
/* Prepare buffer */ - ep_regs = _get_ep_regs(USB_EP_E1_FB(0)); + ep_regs = _get_ep_regs(USB_EP_E1_FB(port)); usb_data_write(ep_regs->bd[0].ptr, &val, 4); ep_regs->bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(3); }
void -usb_e1_run(void) +usb_e1_run(int port) { + struct usb_e1_state *usb_e1 = _get_state(port); volatile struct usb_ep *ep_regs; int bdi;
- if (!g_usb_e1.running) + if (!usb_e1->running) return;
/* Interrupt endpoint */ - ep_regs = _get_ep_regs(USB_EP_E1_INT(0)); + ep_regs = _get_ep_regs(USB_EP_E1_INT(port));
if ((ep_regs->bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) { - const struct e1_error_count *cur_err = e1_get_error_count(0); - if (memcmp(cur_err, &g_usb_e1.last_err, sizeof(*cur_err))) { + const struct e1_error_count *cur_err = e1_get_error_count(port); + if (memcmp(cur_err, &usb_e1->last_err, sizeof(*cur_err))) { struct ice1usb_irq errmsg = { .type = ICE1USB_IRQ_T_ERRCNT, .u = { @@ -107,13 +132,13 @@ printf("E"); usb_data_write(ep_regs->bd[0].ptr, &errmsg, sizeof(errmsg)); ep_regs->bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(sizeof(errmsg)); - g_usb_e1.last_err = *cur_err; + usb_e1->last_err = *cur_err; } }
/* Data IN endpoint */ - ep_regs = _get_ep_regs(USB_EP_E1_IN(0)); - bdi = g_usb_e1.in_bdi; + ep_regs = _get_ep_regs(USB_EP_E1_IN(port)); + bdi = usb_e1->in_bdi;
while ((ep_regs->bd[bdi].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) { @@ -126,7 +151,7 @@ puts("Err EP IN\n");
/* Get some data from E1 */ - int n = e1_rx_level(0); + int n = e1_rx_level(port);
if (n > 32) n = 9; @@ -135,7 +160,7 @@ else if (!n) break;
- n = e1_rx_need_data(0, (ptr >> 2) + 1, n, &pos); + n = e1_rx_need_data(port, (ptr >> 2) + 1, n, &pos);
/* Write header: currently version and pos (mfr/fr number) */ hdr = (0 << 28) | (pos & 0xff); @@ -146,12 +171,12 @@
/* Next BDI */ bdi ^= 1; - g_usb_e1.in_bdi = bdi; + usb_e1->in_bdi = bdi; }
/* Data OUT endpoint */ - ep_regs = _get_ep_regs(USB_EP_E1_OUT(0)); - bdi = g_usb_e1.out_bdi; + ep_regs = _get_ep_regs(USB_EP_E1_OUT(port)); + bdi = usb_e1->out_bdi;
while ((ep_regs->bd[bdi].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) { @@ -171,7 +196,7 @@ /* Empty data into the FIFO */ int n = ((int)(csr & USB_BD_LEN_MSK) - 6) / 32; if (n > 0) - e1_tx_feed_data(0, (ptr >> 2) + 1, n); + e1_tx_feed_data(port, (ptr >> 2) + 1, n);
refill: /* Refill it */ @@ -179,7 +204,7 @@
/* Next BDI */ bdi ^= 1; - g_usb_e1.out_bdi = bdi; + usb_e1->out_bdi = bdi;
static int x = 0; if ((x++ & 0xff) == 0xff) @@ -187,11 +212,11 @@ }
/* Feedback endpoint */ - ep_regs = _get_ep_regs(USB_EP_E1_FB(0)); + ep_regs = _get_ep_regs(USB_EP_E1_FB(port));
if ((ep_regs->bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) { - _usb_fill_feedback_ep(); + _usb_fill_feedback_ep(port); } }
@@ -204,24 +229,28 @@ if (!conf) return USB_FND_SUCCESS;
- intf = usb_desc_find_intf(conf, USB_INTF_E1(0), 0, NULL); - if (!intf) - return USB_FND_ERROR; + for (int port=0; port<2; port++) + { + intf = usb_desc_find_intf(conf, USB_INTF_E1(port), 0, NULL); + if (!intf) + return USB_FND_ERROR;
- printf("e1 set_conf %08x\n", intf); + printf("e1 set_conf[%d] %08x\n", port, intf);
- usb_ep_boot(intf, USB_EP_E1_IN(0), true); - usb_ep_boot(intf, USB_EP_E1_OUT(0), true); - usb_ep_boot(intf, USB_EP_E1_FB(0), false); - usb_ep_boot(intf, USB_EP_E1_INT(0), false); + usb_ep_boot(intf, USB_EP_E1_IN(port), true); + usb_ep_boot(intf, USB_EP_E1_OUT(port), true); + usb_ep_boot(intf, USB_EP_E1_FB(port), false); + usb_ep_boot(intf, USB_EP_E1_INT(port), false); + }
return USB_FND_SUCCESS; }
-static void _perform_tx_config(void) +static void _perform_tx_config(int port) { - const struct ice1usb_tx_config *cfg = &g_usb_e1.tx_cfg; - e1_tx_config(0, + struct usb_e1_state *usb_e1 = _get_state(port); + const struct ice1usb_tx_config *cfg = &usb_e1->tx_cfg; + e1_tx_config(port, ((cfg->mode & 3) << 1) | ((cfg->timing & 1) << 3) | ((cfg->alarm & 1) << 4) | @@ -229,10 +258,11 @@ ); }
-static void _perform_rx_config(void) +static void _perform_rx_config(int port) { - const struct ice1usb_rx_config *cfg = &g_usb_e1.rx_cfg; - e1_rx_config(0, + struct usb_e1_state *usb_e1 = _get_state(port); + const struct ice1usb_rx_config *cfg = &usb_e1->rx_cfg; + e1_rx_config(port, (cfg->mode << 1) ); } @@ -241,50 +271,60 @@ _e1_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel) { volatile struct usb_ep *ep_regs; + struct usb_e1_state *usb_e1; + int port;
- /* Validity checks */ + /* Is it for E1 interface ? */ if ((base->bInterfaceClass != 0xff) || (base->bInterfaceSubClass != 0xe1)) return USB_FND_CONTINUE;
+ /* Get matching port (if any) */ + port = _ifnum2port(base->bInterfaceNumber); + if (port < 0) + return USB_FND_ERROR; + + usb_e1 = _get_state(port); + + /* Valid setting ? */ if (sel->bAlternateSetting > 1) return USB_FND_ERROR;
/* Don't do anything if no change */ - if (g_usb_e1.running == (sel->bAlternateSetting != 0)) + if (usb_e1->running == (sel->bAlternateSetting != 0)) return USB_FND_SUCCESS;
- g_usb_e1.running = (sel->bAlternateSetting != 0); + usb_e1->running = (sel->bAlternateSetting != 0);
/* Reconfigure the endpoints */ - usb_ep_reconf(sel, USB_EP_E1_IN(0)); - usb_ep_reconf(sel, USB_EP_E1_OUT(0)); - usb_ep_reconf(sel, USB_EP_E1_FB(0)); - usb_ep_reconf(sel, USB_EP_E1_INT(0)); + usb_ep_reconf(sel, USB_EP_E1_IN(port)); + usb_ep_reconf(sel, USB_EP_E1_OUT(port)); + usb_ep_reconf(sel, USB_EP_E1_FB(port)); + usb_ep_reconf(sel, USB_EP_E1_INT(port));
/* Update E1 and USB state */ - switch (g_usb_e1.running) { + switch (usb_e1->running) { case false: /* Disable E1 rx/tx */ - e1_init(0, 0, 0); + e1_init(port, 0, 0); break;
case true: /* Reset and Re-Enable E1 */ - e1_init(0, 0, 0); - _perform_rx_config(); - _perform_tx_config(); + e1_init(port, 0, 0); + _perform_rx_config(port); + _perform_tx_config(port);
/* Reset BDI */ - g_usb_e1.in_bdi = 0; - g_usb_e1.out_bdi = 0; + usb_e1->in_bdi = 0; + usb_e1->out_bdi = 0;
/* EP OUT: Queue two buffers */ - ep_regs = _get_ep_regs(USB_EP_E1_FB(0)); + ep_regs = _get_ep_regs(USB_EP_E1_OUT(port)); ep_regs->bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(292); ep_regs->bd[1].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(292);
/* EP Feedback: Pre-fill */ - _usb_fill_feedback_ep(); + _usb_fill_feedback_ep(port);
break; } @@ -295,10 +335,22 @@ static enum usb_fnd_resp _e1_get_intf(const struct usb_intf_desc *base, uint8_t *alt) { + struct usb_e1_state *usb_e1; + int port; + + /* Is it for E1 interface ? */ if ((base->bInterfaceClass != 0xff) || (base->bInterfaceSubClass != 0xe1)) return USB_FND_CONTINUE;
- *alt = g_usb_e1.running ? 1 : 0; + /* Get matching port (if any) */ + port = _ifnum2port(base->bInterfaceNumber); + if (port < 0) + return USB_FND_ERROR; + + usb_e1 = _get_state(port); + + /* Return current alt-setting */ + *alt = usb_e1->running ? 1 : 0;
return USB_FND_SUCCESS; } @@ -307,10 +359,13 @@ _set_tx_mode_done(struct usb_xfer *xfer) { const struct ice1usb_tx_config *cfg = (const struct ice1usb_tx_config *) xfer->data; - printf("set_tx_mode %02x%02x%02x%02x\r\n", + struct usb_ctrl_req *req = xfer->cb_ctx; + int port = _ifnum2port(req->wIndex); + struct usb_e1_state *usb_e1 = _get_state(port); + printf("set_tx_mode[%d] %02x%02x%02x%02x\r\n", port, xfer->data[0], xfer->data[1], xfer->data[2], xfer->data[3]); - g_usb_e1.tx_cfg = *cfg; - _perform_tx_config(); + usb_e1->tx_cfg = *cfg; + _perform_tx_config(port); return true; }
@@ -318,9 +373,12 @@ _set_rx_mode_done(struct usb_xfer *xfer) { const struct ice1usb_rx_config *cfg = (const struct ice1usb_rx_config *) xfer->data; - printf("set_rx_mode %02x\r\n", xfer->data[0]); - g_usb_e1.rx_cfg = *cfg; - _perform_rx_config(); + struct usb_ctrl_req *req = xfer->cb_ctx; + int port = _ifnum2port(req->wIndex); + struct usb_e1_state *usb_e1 = _get_state(port); + printf("set_rx_mode[%d] %02x\r\n", port, xfer->data[0]); + usb_e1->rx_cfg = *cfg; + _perform_rx_config(port); return true; }
@@ -328,8 +386,17 @@ static enum usb_fnd_resp _e1_ctrl_req_intf(struct usb_ctrl_req *req, struct usb_xfer *xfer) { - unsigned int i; + struct usb_e1_state *usb_e1; + int port;
+ /* Get matching port (if any) */ + port = _ifnum2port(req->wIndex); + if (port < 0) + return USB_FND_CONTINUE; + + usb_e1 = _get_state(port); + + /* Process request */ switch (req->bRequest) { case ICE1USB_INTF_GET_CAPABILITIES: /* no optional capabilities yet */ @@ -345,7 +412,7 @@ case ICE1USB_INTF_GET_TX_CFG: if (req->wLength < sizeof(struct ice1usb_tx_config)) return USB_FND_ERROR; - memcpy(xfer->data, &g_usb_e1.tx_cfg, sizeof(struct ice1usb_tx_config)); + memcpy(xfer->data, &usb_e1->tx_cfg, sizeof(struct ice1usb_tx_config)); xfer->len = sizeof(struct ice1usb_tx_config); break; case ICE1USB_INTF_SET_RX_CFG: @@ -358,7 +425,7 @@ case ICE1USB_INTF_GET_RX_CFG: if (req->wLength < sizeof(struct ice1usb_rx_config)) return USB_FND_ERROR; - memcpy(xfer->data, &g_usb_e1.rx_cfg, sizeof(struct ice1usb_rx_config)); + memcpy(xfer->data, &usb_e1->rx_cfg, sizeof(struct ice1usb_rx_config)); xfer->len = sizeof(struct ice1usb_rx_config); break; default: @@ -396,8 +463,6 @@ case USB_REQ_RCPT_DEV: return _e1_ctrl_req_dev(req, xfer); case USB_REQ_RCPT_INTF: - if (req->wIndex != USB_INTF_E1(0)) - return USB_FND_CONTINUE; return _e1_ctrl_req_intf(req, xfer); case USB_REQ_RCPT_EP: case USB_REQ_RCPT_OTHER: @@ -417,8 +482,12 @@ void usb_e1_init(void) { - memset(&g_usb_e1, 0x00, sizeof(g_usb_e1)); - g_usb_e1.tx_cfg = tx_cfg_default; - g_usb_e1.rx_cfg = rx_cfg_default; + for (int i=0; i<2; i++) { + struct usb_e1_state *usb_e1 = _get_state(i); + memset(usb_e1, 0x00, sizeof(struct usb_e1_state)); + usb_e1->tx_cfg = tx_cfg_default; + usb_e1->rx_cfg = rx_cfg_default; + } + usb_register_function_driver(&_e1_drv); } diff --git a/firmware/ice40-riscv/icE1usb/usb_e1.h b/firmware/ice40-riscv/icE1usb/usb_e1.h index a573b38..06723ea 100644 --- a/firmware/ice40-riscv/icE1usb/usb_e1.h +++ b/firmware/ice40-riscv/icE1usb/usb_e1.h @@ -7,5 +7,5 @@
#pragma once
-void usb_e1_run(void); +void usb_e1_run(int port); void usb_e1_init(void); diff --git a/firmware/ice40-riscv/icE1usb/usb_str_app.txt b/firmware/ice40-riscv/icE1usb/usb_str_app.txt index 10887d3..3aa6b4a 100644 --- a/firmware/ice40-riscv/icE1usb/usb_str_app.txt +++ b/firmware/ice40-riscv/icE1usb/usb_str_app.txt @@ -2,7 +2,10 @@ osmocom icE1usb Main -E1 -Console (control) -Console (data) +E1 port 0 (disabled) +E1 port 0 +E1 port 1 (disabled) +E1 port 1 +GPS (CDC control) +GPS (CDC data) DFU runtime
laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-e1-hardware/+/26841 )
Change subject: icE1usb fw: Add multi-port support in USB code ......................................................................
Patch Set 1:
so will you keep your slightly different-than-osmocom codign style for this project? If so, we should probably remove the linter for this project.
tnt has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-e1-hardware/+/26841 )
Change subject: icE1usb fw: Add multi-port support in USB code ......................................................................
Patch Set 1:
Patch Set 1:
so will you keep your slightly different-than-osmocom codign style for this project? If so, we should probably remove the linter for this project.
Yes. Not sure if it's possible to disable only some of the options.
Mostly it's the brace position which I put for whatever looks better (which depends on the surounding code, I don't like when code isn't "aerated"), and the '=' in for loops.
laforge has removed a vote from this change. ( https://gerrit.osmocom.org/c/osmo-e1-hardware/+/26841 )
Change subject: icE1usb fw: Add multi-port support in USB code ......................................................................
Removed Verified-1 by Jenkins Builder (1000002)
laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-e1-hardware/+/26841 )
Change subject: icE1usb fw: Add multi-port support in USB code ......................................................................
Patch Set 1: Verified+1 Code-Review+1
so will you keep your slightly different-than-osmocom codign style for this project? If so, we should probably remove the linter for this project.
Yes. Not sure if it's possible to disable only some of the options.
Mostly it's the brace position which I put for whatever looks better (which depends on the surounding code, I don't like when code isn't "aerated"), and the '=' in for loops.
see https://gerrit.osmocom.org/c/osmo-ci/+/26858 and https://osmocom.org/issues/5399
laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-e1-hardware/+/26841 )
Change subject: icE1usb fw: Add multi-port support in USB code ......................................................................
Patch Set 1: Code-Review+2
laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-e1-hardware/+/26841 )
Change subject: icE1usb fw: Add multi-port support in USB code ......................................................................
icE1usb fw: Add multi-port support in USB code
Signed-off-by: Sylvain Munaut tnt@246tNt.com Change-Id: I134410b542461c34339baa8d9120a5c86fc35d46 --- M firmware/ice40-riscv/icE1usb/fw_app.c M firmware/ice40-riscv/icE1usb/usb_desc_app.c M firmware/ice40-riscv/icE1usb/usb_desc_ids.h M firmware/ice40-riscv/icE1usb/usb_e1.c M firmware/ice40-riscv/icE1usb/usb_e1.h M firmware/ice40-riscv/icE1usb/usb_str_app.txt 6 files changed, 225 insertions(+), 82 deletions(-)
Approvals: laforge: Looks good to me, approved; Verified
diff --git a/firmware/ice40-riscv/icE1usb/fw_app.c b/firmware/ice40-riscv/icE1usb/fw_app.c index 3340f4a..55218b8 100644 --- a/firmware/ice40-riscv/icE1usb/fw_app.c +++ b/firmware/ice40-riscv/icE1usb/fw_app.c @@ -102,6 +102,7 @@
/* Start */ e1_init(0, 0, 0); + e1_init(1, 0, 0); led_state(true); usb_connect();
@@ -151,7 +152,9 @@ usb_poll();
/* E1 poll */ - e1_poll(0); - usb_e1_run(); + for (int port=0; port<2; port++) { + e1_poll(port); + usb_e1_run(port); + } } } diff --git a/firmware/ice40-riscv/icE1usb/usb_desc_app.c b/firmware/ice40-riscv/icE1usb/usb_desc_app.c index 663be0b..22a81d3 100644 --- a/firmware/ice40-riscv/icE1usb/usb_desc_app.c +++ b/firmware/ice40-riscv/icE1usb/usb_desc_app.c @@ -39,7 +39,7 @@ struct usb_ep_desc ep_fb; struct usb_ep_desc ep_interrupt; } __attribute__ ((packed)) on; - } __attribute__ ((packed)) e1; + } __attribute__ ((packed)) e1[2];
/* CDC */ #if 0 @@ -71,7 +71,7 @@ .bmAttributes = 0x80, .bMaxPower = 0x32, /* 100 mA */ }, - .e1 = { + .e1[0] = { .off = { .intf = { .bLength = sizeof(struct usb_intf_desc), @@ -103,7 +103,7 @@ .bInterfaceClass = 0xff, .bInterfaceSubClass = 0xe1, .bInterfaceProtocol = 0x00, - .iInterface = 5, + .iInterface = 6, }, .ep_data_in = { .bLength = sizeof(struct usb_ep_desc), @@ -139,6 +139,74 @@ }, }, }, + .e1[1] = { + .off = { + .intf = { + .bLength = sizeof(struct usb_intf_desc), + .bDescriptorType = USB_DT_INTF, + .bInterfaceNumber = USB_INTF_E1(1), + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xe1, + .bInterfaceProtocol = 0x00, + .iInterface = 7, + }, + .ep_interrupt = { + .bLength = sizeof(struct usb_ep_desc), + .bDescriptorType = USB_DT_EP, + .bEndpointAddress = USB_EP_E1_INT(1), + .bmAttributes = 0x03, + .wMaxPacketSize = 10, + .bInterval = 4, /* every 4 ms */ + }, + }, + .on = { + .intf = { + .bLength = sizeof(struct usb_intf_desc), + .bDescriptorType = USB_DT_INTF, + .bInterfaceNumber = USB_INTF_E1(1), + .bAlternateSetting = 1, + .bNumEndpoints = 4, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xe1, + .bInterfaceProtocol = 0x00, + .iInterface = 8, + }, + .ep_data_in = { + .bLength = sizeof(struct usb_ep_desc), + .bDescriptorType = USB_DT_EP, + .bEndpointAddress = USB_EP_E1_IN(1), + .bmAttributes = 0x05, + .wMaxPacketSize = 292, + .bInterval = 1, + }, + .ep_data_out = { + .bLength = sizeof(struct usb_ep_desc), + .bDescriptorType = USB_DT_EP, + .bEndpointAddress = USB_EP_E1_OUT(1), + .bmAttributes = 0x05, + .wMaxPacketSize = 292, + .bInterval = 1, + }, + .ep_fb = { + .bLength = sizeof(struct usb_ep_desc), + .bDescriptorType = USB_DT_EP, + .bEndpointAddress = USB_EP_E1_FB(1), + .bmAttributes = 0x11, + .wMaxPacketSize = 3, + .bInterval = 3, /* every 2^(3-1) = 4 ms */ + }, + .ep_interrupt = { + .bLength = sizeof(struct usb_ep_desc), + .bDescriptorType = USB_DT_EP, + .bEndpointAddress = USB_EP_E1_INT(1), + .bmAttributes = 0x03, + .wMaxPacketSize = 10, + .bInterval = 4, /* every 4 ms */ + }, + }, + }, #if 0 .cdc = { .intf_ctl = { @@ -150,7 +218,7 @@ .bInterfaceClass = USB_CLS_CDC_CONTROL, .bInterfaceSubClass = USB_CDC_SCLS_ACM, .bInterfaceProtocol = 0x00, - .iInterface = 6, + .iInterface = 9, }, .cdc_hdr = { .bLength = sizeof(struct usb_cdc_hdr_desc), @@ -188,7 +256,7 @@ .bInterfaceClass = USB_CLS_CDC_DATA, .bInterfaceSubClass = 0x00, .bInterfaceProtocol = 0x00, - .iInterface = 7, + .iInterface = 10, }, .ep_data_out = { .bLength = sizeof(struct usb_ep_desc), @@ -218,7 +286,7 @@ .bInterfaceClass = 0xfe, .bInterfaceSubClass = 0x01, .bInterfaceProtocol = 0x01, - .iInterface = 8, + .iInterface = 11, }, .func = { .bLength = sizeof(struct usb_dfu_func_desc), diff --git a/firmware/ice40-riscv/icE1usb/usb_desc_ids.h b/firmware/ice40-riscv/icE1usb/usb_desc_ids.h index 2247f84..00dbb34 100644 --- a/firmware/ice40-riscv/icE1usb/usb_desc_ids.h +++ b/firmware/ice40-riscv/icE1usb/usb_desc_ids.h @@ -8,8 +8,8 @@ #pragma once
#define USB_INTF_E1(p) (0 + (p)) -#define USB_INTF_DFU 1 -#define USB_INTF_NUM 2 +#define USB_INTF_DFU 2 +#define USB_INTF_NUM 3
#define USB_EP_E1_IN(p) (0x82 + (3 * (p))) #define USB_EP_E1_OUT(p) (0x01 + (3 * (p))) diff --git a/firmware/ice40-riscv/icE1usb/usb_e1.c b/firmware/ice40-riscv/icE1usb/usb_e1.c index 75811c2..a18ebe4 100644 --- a/firmware/ice40-riscv/icE1usb/usb_e1.c +++ b/firmware/ice40-riscv/icE1usb/usb_e1.c @@ -16,17 +16,20 @@ #include "e1.h" #include "misc.h" #include "usb_desc_ids.h" +#include "utils.h"
#include "ice1usb_proto.h"
-struct { +struct usb_e1_state { bool running; /* are we running (transceiving USB data)? */ int out_bdi; /* buffer descriptor index for OUT EP */ 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; +}; + +static struct usb_e1_state g_usb_e1[2];
/* default configuration at power-up */ static const struct ice1usb_tx_config tx_cfg_default = { @@ -47,8 +50,29 @@ return (ep & 0x80) ? &usb_ep_regs[ep & 0x1f].in : &usb_ep_regs[ep & 0x1f].out; }
+static struct usb_e1_state * +_get_state(int port) +{ + if ((port < 0) || (port > 1)) + panic("_get_state invalid port %d", port); + return &g_usb_e1[port]; +} + +static int +_ifnum2port(uint8_t bInterfaceNumber) +{ + switch (bInterfaceNumber) { + case USB_INTF_E1(0): return 0; + case USB_INTF_E1(1): return 1; + default: + /* Don't panic since this will be handled as USB STALL */ + return -1; + } +} + + static void -_usb_fill_feedback_ep(void) +_usb_fill_feedback_ep(int port) { static uint16_t ticks_prev = 0; uint16_t ticks; @@ -57,41 +81,42 @@ volatile struct usb_ep *ep_regs;
/* Compute real E1 tick count (with safety against bad values) */ - ticks = e1_tick_read(0); + ticks = e1_tick_read(port); val = (ticks - ticks_prev) & 0xffff; ticks_prev = ticks; if ((val < 7168) | (val > 9216)) val = 8192;
/* Bias depending on TX fifo level */ - level = e1_tx_level(0); + level = e1_tx_level(port); if (level < (3 * 16)) val += 256; else if (level > (8 * 16)) val -= 256;
/* Prepare buffer */ - ep_regs = _get_ep_regs(USB_EP_E1_FB(0)); + ep_regs = _get_ep_regs(USB_EP_E1_FB(port)); usb_data_write(ep_regs->bd[0].ptr, &val, 4); ep_regs->bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(3); }
void -usb_e1_run(void) +usb_e1_run(int port) { + struct usb_e1_state *usb_e1 = _get_state(port); volatile struct usb_ep *ep_regs; int bdi;
- if (!g_usb_e1.running) + if (!usb_e1->running) return;
/* Interrupt endpoint */ - ep_regs = _get_ep_regs(USB_EP_E1_INT(0)); + ep_regs = _get_ep_regs(USB_EP_E1_INT(port));
if ((ep_regs->bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) { - const struct e1_error_count *cur_err = e1_get_error_count(0); - if (memcmp(cur_err, &g_usb_e1.last_err, sizeof(*cur_err))) { + const struct e1_error_count *cur_err = e1_get_error_count(port); + if (memcmp(cur_err, &usb_e1->last_err, sizeof(*cur_err))) { struct ice1usb_irq errmsg = { .type = ICE1USB_IRQ_T_ERRCNT, .u = { @@ -107,13 +132,13 @@ printf("E"); usb_data_write(ep_regs->bd[0].ptr, &errmsg, sizeof(errmsg)); ep_regs->bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(sizeof(errmsg)); - g_usb_e1.last_err = *cur_err; + usb_e1->last_err = *cur_err; } }
/* Data IN endpoint */ - ep_regs = _get_ep_regs(USB_EP_E1_IN(0)); - bdi = g_usb_e1.in_bdi; + ep_regs = _get_ep_regs(USB_EP_E1_IN(port)); + bdi = usb_e1->in_bdi;
while ((ep_regs->bd[bdi].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) { @@ -126,7 +151,7 @@ puts("Err EP IN\n");
/* Get some data from E1 */ - int n = e1_rx_level(0); + int n = e1_rx_level(port);
if (n > 32) n = 9; @@ -135,7 +160,7 @@ else if (!n) break;
- n = e1_rx_need_data(0, (ptr >> 2) + 1, n, &pos); + n = e1_rx_need_data(port, (ptr >> 2) + 1, n, &pos);
/* Write header: currently version and pos (mfr/fr number) */ hdr = (0 << 28) | (pos & 0xff); @@ -146,12 +171,12 @@
/* Next BDI */ bdi ^= 1; - g_usb_e1.in_bdi = bdi; + usb_e1->in_bdi = bdi; }
/* Data OUT endpoint */ - ep_regs = _get_ep_regs(USB_EP_E1_OUT(0)); - bdi = g_usb_e1.out_bdi; + ep_regs = _get_ep_regs(USB_EP_E1_OUT(port)); + bdi = usb_e1->out_bdi;
while ((ep_regs->bd[bdi].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) { @@ -171,7 +196,7 @@ /* Empty data into the FIFO */ int n = ((int)(csr & USB_BD_LEN_MSK) - 6) / 32; if (n > 0) - e1_tx_feed_data(0, (ptr >> 2) + 1, n); + e1_tx_feed_data(port, (ptr >> 2) + 1, n);
refill: /* Refill it */ @@ -179,7 +204,7 @@
/* Next BDI */ bdi ^= 1; - g_usb_e1.out_bdi = bdi; + usb_e1->out_bdi = bdi;
static int x = 0; if ((x++ & 0xff) == 0xff) @@ -187,11 +212,11 @@ }
/* Feedback endpoint */ - ep_regs = _get_ep_regs(USB_EP_E1_FB(0)); + ep_regs = _get_ep_regs(USB_EP_E1_FB(port));
if ((ep_regs->bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) { - _usb_fill_feedback_ep(); + _usb_fill_feedback_ep(port); } }
@@ -204,24 +229,28 @@ if (!conf) return USB_FND_SUCCESS;
- intf = usb_desc_find_intf(conf, USB_INTF_E1(0), 0, NULL); - if (!intf) - return USB_FND_ERROR; + for (int port=0; port<2; port++) + { + intf = usb_desc_find_intf(conf, USB_INTF_E1(port), 0, NULL); + if (!intf) + return USB_FND_ERROR;
- printf("e1 set_conf %08x\n", intf); + printf("e1 set_conf[%d] %08x\n", port, intf);
- usb_ep_boot(intf, USB_EP_E1_IN(0), true); - usb_ep_boot(intf, USB_EP_E1_OUT(0), true); - usb_ep_boot(intf, USB_EP_E1_FB(0), false); - usb_ep_boot(intf, USB_EP_E1_INT(0), false); + usb_ep_boot(intf, USB_EP_E1_IN(port), true); + usb_ep_boot(intf, USB_EP_E1_OUT(port), true); + usb_ep_boot(intf, USB_EP_E1_FB(port), false); + usb_ep_boot(intf, USB_EP_E1_INT(port), false); + }
return USB_FND_SUCCESS; }
-static void _perform_tx_config(void) +static void _perform_tx_config(int port) { - const struct ice1usb_tx_config *cfg = &g_usb_e1.tx_cfg; - e1_tx_config(0, + struct usb_e1_state *usb_e1 = _get_state(port); + const struct ice1usb_tx_config *cfg = &usb_e1->tx_cfg; + e1_tx_config(port, ((cfg->mode & 3) << 1) | ((cfg->timing & 1) << 3) | ((cfg->alarm & 1) << 4) | @@ -229,10 +258,11 @@ ); }
-static void _perform_rx_config(void) +static void _perform_rx_config(int port) { - const struct ice1usb_rx_config *cfg = &g_usb_e1.rx_cfg; - e1_rx_config(0, + struct usb_e1_state *usb_e1 = _get_state(port); + const struct ice1usb_rx_config *cfg = &usb_e1->rx_cfg; + e1_rx_config(port, (cfg->mode << 1) ); } @@ -241,50 +271,60 @@ _e1_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel) { volatile struct usb_ep *ep_regs; + struct usb_e1_state *usb_e1; + int port;
- /* Validity checks */ + /* Is it for E1 interface ? */ if ((base->bInterfaceClass != 0xff) || (base->bInterfaceSubClass != 0xe1)) return USB_FND_CONTINUE;
+ /* Get matching port (if any) */ + port = _ifnum2port(base->bInterfaceNumber); + if (port < 0) + return USB_FND_ERROR; + + usb_e1 = _get_state(port); + + /* Valid setting ? */ if (sel->bAlternateSetting > 1) return USB_FND_ERROR;
/* Don't do anything if no change */ - if (g_usb_e1.running == (sel->bAlternateSetting != 0)) + if (usb_e1->running == (sel->bAlternateSetting != 0)) return USB_FND_SUCCESS;
- g_usb_e1.running = (sel->bAlternateSetting != 0); + usb_e1->running = (sel->bAlternateSetting != 0);
/* Reconfigure the endpoints */ - usb_ep_reconf(sel, USB_EP_E1_IN(0)); - usb_ep_reconf(sel, USB_EP_E1_OUT(0)); - usb_ep_reconf(sel, USB_EP_E1_FB(0)); - usb_ep_reconf(sel, USB_EP_E1_INT(0)); + usb_ep_reconf(sel, USB_EP_E1_IN(port)); + usb_ep_reconf(sel, USB_EP_E1_OUT(port)); + usb_ep_reconf(sel, USB_EP_E1_FB(port)); + usb_ep_reconf(sel, USB_EP_E1_INT(port));
/* Update E1 and USB state */ - switch (g_usb_e1.running) { + switch (usb_e1->running) { case false: /* Disable E1 rx/tx */ - e1_init(0, 0, 0); + e1_init(port, 0, 0); break;
case true: /* Reset and Re-Enable E1 */ - e1_init(0, 0, 0); - _perform_rx_config(); - _perform_tx_config(); + e1_init(port, 0, 0); + _perform_rx_config(port); + _perform_tx_config(port);
/* Reset BDI */ - g_usb_e1.in_bdi = 0; - g_usb_e1.out_bdi = 0; + usb_e1->in_bdi = 0; + usb_e1->out_bdi = 0;
/* EP OUT: Queue two buffers */ - ep_regs = _get_ep_regs(USB_EP_E1_FB(0)); + ep_regs = _get_ep_regs(USB_EP_E1_OUT(port)); ep_regs->bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(292); ep_regs->bd[1].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(292);
/* EP Feedback: Pre-fill */ - _usb_fill_feedback_ep(); + _usb_fill_feedback_ep(port);
break; } @@ -295,10 +335,22 @@ static enum usb_fnd_resp _e1_get_intf(const struct usb_intf_desc *base, uint8_t *alt) { + struct usb_e1_state *usb_e1; + int port; + + /* Is it for E1 interface ? */ if ((base->bInterfaceClass != 0xff) || (base->bInterfaceSubClass != 0xe1)) return USB_FND_CONTINUE;
- *alt = g_usb_e1.running ? 1 : 0; + /* Get matching port (if any) */ + port = _ifnum2port(base->bInterfaceNumber); + if (port < 0) + return USB_FND_ERROR; + + usb_e1 = _get_state(port); + + /* Return current alt-setting */ + *alt = usb_e1->running ? 1 : 0;
return USB_FND_SUCCESS; } @@ -307,10 +359,13 @@ _set_tx_mode_done(struct usb_xfer *xfer) { const struct ice1usb_tx_config *cfg = (const struct ice1usb_tx_config *) xfer->data; - printf("set_tx_mode %02x%02x%02x%02x\r\n", + struct usb_ctrl_req *req = xfer->cb_ctx; + int port = _ifnum2port(req->wIndex); + struct usb_e1_state *usb_e1 = _get_state(port); + printf("set_tx_mode[%d] %02x%02x%02x%02x\r\n", port, xfer->data[0], xfer->data[1], xfer->data[2], xfer->data[3]); - g_usb_e1.tx_cfg = *cfg; - _perform_tx_config(); + usb_e1->tx_cfg = *cfg; + _perform_tx_config(port); return true; }
@@ -318,9 +373,12 @@ _set_rx_mode_done(struct usb_xfer *xfer) { const struct ice1usb_rx_config *cfg = (const struct ice1usb_rx_config *) xfer->data; - printf("set_rx_mode %02x\r\n", xfer->data[0]); - g_usb_e1.rx_cfg = *cfg; - _perform_rx_config(); + struct usb_ctrl_req *req = xfer->cb_ctx; + int port = _ifnum2port(req->wIndex); + struct usb_e1_state *usb_e1 = _get_state(port); + printf("set_rx_mode[%d] %02x\r\n", port, xfer->data[0]); + usb_e1->rx_cfg = *cfg; + _perform_rx_config(port); return true; }
@@ -328,8 +386,17 @@ static enum usb_fnd_resp _e1_ctrl_req_intf(struct usb_ctrl_req *req, struct usb_xfer *xfer) { - unsigned int i; + struct usb_e1_state *usb_e1; + int port;
+ /* Get matching port (if any) */ + port = _ifnum2port(req->wIndex); + if (port < 0) + return USB_FND_CONTINUE; + + usb_e1 = _get_state(port); + + /* Process request */ switch (req->bRequest) { case ICE1USB_INTF_GET_CAPABILITIES: /* no optional capabilities yet */ @@ -345,7 +412,7 @@ case ICE1USB_INTF_GET_TX_CFG: if (req->wLength < sizeof(struct ice1usb_tx_config)) return USB_FND_ERROR; - memcpy(xfer->data, &g_usb_e1.tx_cfg, sizeof(struct ice1usb_tx_config)); + memcpy(xfer->data, &usb_e1->tx_cfg, sizeof(struct ice1usb_tx_config)); xfer->len = sizeof(struct ice1usb_tx_config); break; case ICE1USB_INTF_SET_RX_CFG: @@ -358,7 +425,7 @@ case ICE1USB_INTF_GET_RX_CFG: if (req->wLength < sizeof(struct ice1usb_rx_config)) return USB_FND_ERROR; - memcpy(xfer->data, &g_usb_e1.rx_cfg, sizeof(struct ice1usb_rx_config)); + memcpy(xfer->data, &usb_e1->rx_cfg, sizeof(struct ice1usb_rx_config)); xfer->len = sizeof(struct ice1usb_rx_config); break; default: @@ -396,8 +463,6 @@ case USB_REQ_RCPT_DEV: return _e1_ctrl_req_dev(req, xfer); case USB_REQ_RCPT_INTF: - if (req->wIndex != USB_INTF_E1(0)) - return USB_FND_CONTINUE; return _e1_ctrl_req_intf(req, xfer); case USB_REQ_RCPT_EP: case USB_REQ_RCPT_OTHER: @@ -417,8 +482,12 @@ void usb_e1_init(void) { - memset(&g_usb_e1, 0x00, sizeof(g_usb_e1)); - g_usb_e1.tx_cfg = tx_cfg_default; - g_usb_e1.rx_cfg = rx_cfg_default; + for (int i=0; i<2; i++) { + struct usb_e1_state *usb_e1 = _get_state(i); + memset(usb_e1, 0x00, sizeof(struct usb_e1_state)); + usb_e1->tx_cfg = tx_cfg_default; + usb_e1->rx_cfg = rx_cfg_default; + } + usb_register_function_driver(&_e1_drv); } diff --git a/firmware/ice40-riscv/icE1usb/usb_e1.h b/firmware/ice40-riscv/icE1usb/usb_e1.h index a573b38..06723ea 100644 --- a/firmware/ice40-riscv/icE1usb/usb_e1.h +++ b/firmware/ice40-riscv/icE1usb/usb_e1.h @@ -7,5 +7,5 @@
#pragma once
-void usb_e1_run(void); +void usb_e1_run(int port); void usb_e1_init(void); diff --git a/firmware/ice40-riscv/icE1usb/usb_str_app.txt b/firmware/ice40-riscv/icE1usb/usb_str_app.txt index 10887d3..3aa6b4a 100644 --- a/firmware/ice40-riscv/icE1usb/usb_str_app.txt +++ b/firmware/ice40-riscv/icE1usb/usb_str_app.txt @@ -2,7 +2,10 @@ osmocom icE1usb Main -E1 -Console (control) -Console (data) +E1 port 0 (disabled) +E1 port 0 +E1 port 1 (disabled) +E1 port 1 +GPS (CDC control) +GPS (CDC data) DFU runtime