summaryrefslogtreecommitdiff
path: root/usb
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2023-05-01 00:50:55 +0200
committerVegard Storheil Eriksen <zyp@jvnv.net>2023-05-01 00:50:55 +0200
commitd381db5b1f6a7d7897056adb84ea24f18f2dd0b8 (patch)
tree411568025c0aa101bd3241416ce192ae9c2a9ab1 /usb
parent3eb114c680a63274948700c653dfc263d182171a (diff)
usb: Update code for stm32_usb and add support for v3.
Diffstat (limited to 'usb')
-rw-r--r--usb/SConscript9
-rw-r--r--usb/f1_usb.h174
-rw-r--r--usb/f1_usb_def.h35
-rw-r--r--usb/l0_usb.h174
-rw-r--r--usb/l0_usb_def.h37
-rw-r--r--usb/stm32_usb.h212
-rw-r--r--usb/stm32_usb_def.h71
7 files changed, 292 insertions, 420 deletions
diff --git a/usb/SConscript b/usb/SConscript
index 81d84d4..d000a82 100644
--- a/usb/SConscript
+++ b/usb/SConscript
@@ -14,6 +14,15 @@ if 'dwc_otg' in periph:
'args': [data['offset']],
})
+if 'stm32_usb' in periph:
+ headers.append('stm32_usb.h')
+ for name, data in periph['stm32_usb'].items():
+ instances.append({
+ 'type': 'STM32_USB_t<STM32_USB_reg_%s_t>' % data['type'],
+ 'name': name,
+ 'args': [data['offset'], data['buf_offset']],
+ })
+
env.Jinja2('usb.h', '../templates/periph_instances.h.j2', headers = headers, instances = instances)
Return()
diff --git a/usb/f1_usb.h b/usb/f1_usb.h
deleted file mode 100644
index 8510bb9..0000000
--- a/usb/f1_usb.h
+++ /dev/null
@@ -1,174 +0,0 @@
-#ifndef F1_USB_H
-#define F1_USB_H
-
-#include "generic.h"
-#include "f1_usb_def.h"
-
-class USB_f1 : public USB_generic {
- private:
- F1_USB_t& usb;
-
- uint32_t setupbuf[16];
-
- uint32_t buf_end;
-
- uint8_t pending_addr;
-
- protected:
- virtual void hw_set_address(uint8_t addr) {
- usb_rblog.log("SetAddress: %d", addr);
-
- pending_addr = addr;
- }
-
- virtual void hw_conf_ep(uint8_t ep, EPType type, uint32_t size) {
- usb_rblog.log("Configuring EP%02x: size=%d", ep, size);
-
- uint8_t in = ep & 0x80;
- ep &= 0x7f;
-
- uint32_t old_epr = usb.reg.EPR[ep];
- //uint32_t new_epr = 0x3220;
- uint32_t new_epr = 0x8080 | ((type == EPType::Bulk ? 0 : type == EPType::Control ? 1 : type == EPType::Isochronous ? 2 : 3) << 9) | ep;
-
- if(in || ep == 0) {
- usb.bufd[ep].ADDR_TX = buf_end;
- buf_end += size;
-
- new_epr |= (old_epr & 0x0070) ^ 0x0020;
- }
-
- if(!in) {
- usb.bufd[ep].ADDR_RX = buf_end;
- buf_end += size;
- usb.bufd[ep].COUNT_RX = 0x8000 | (1 << 10);
-
- new_epr |= (old_epr & 0x7000) ^ 0x3000;
- }
-
- usb.reg.EPR[ep] = new_epr;
-
- usb_rblog.log("EPR: old=%04x, new=%04x", old_epr, usb.reg.EPR[ep]);
- }
-
- virtual void hw_set_stall(uint8_t ep) {
- usb_rblog.log("Setting stall on EP %d", ep);
-
- usb.reg.EPR[ep] = (usb.reg.EPR[ep] & 0x878f) | 0x2030;
-
- //otg.dev_iep_reg[ep].DIEPCTL |= (1 << 21);
- }
-
- public:
- USB_f1(F1_USB_t& usb_periph, desc_t dev, desc_t conf) : USB_generic(dev, conf), usb(usb_periph) {}
-
- void init() {
- usb.reg.CNTR = 3;
- Time::sleep(10);
- usb.reg.CNTR = 1;
- Time::sleep(10);
- // Exit power down mode.
- usb.reg.CNTR = 0;
- }
-
- void process() {
- uint32_t istr = usb.reg.ISTR;
-
- if(istr & (1 << 10)) {
- usb_rblog.log("USB Reset");
-
- buf_end = 0x40;
-
- usb.reg.DADDR = 0x80;
-
- handle_reset();
-
- usb.reg.ISTR = ~(1 << 10);
-
- return;
- }
-
- if(istr & (1 << 15)) {
- usb_rblog.log("USB Transfer: %02x", istr & 0x1f);
-
- uint32_t ep = istr & 0xf;
- uint32_t dir = istr & 0x10;
-
- usb_rblog.log("EPR%d: %04x", ep, usb.reg.EPR[ep]);
-
- if(dir) {
- // RX.
-
- usb_rblog.log("RXBUF: ADDR: %04x, COUNT: %04x", usb.bufd[ep].ADDR_RX, usb.bufd[ep].COUNT_RX);
-
- uint32_t len = usb.bufd[ep].COUNT_RX & 0x03ff;
-
- if(usb.reg.EPR[ep] & (1 << 11)) {
- usb_rblog.log("SETUP packet received");
-
- read(0, setupbuf, 8);
-
- handle_setup(setupbuf);
-
- } else {
- usb_rblog.log("OUT packet received");
-
- handle_out(ep, len);
- }
-
- //usb.reg.EPR[ep] = 0x9280;
- //usb.reg.EPR[ep] &= 0x078f;
-
- usb.reg.EPR[ep] = (usb.reg.EPR[ep] & 0x078f) | 0x1000;
- } else {
- // TX.
-
- usb_rblog.log("TXBUF: ADDR: %04x, COUNT: %04x", usb.bufd[ep].ADDR_TX, usb.bufd[ep].COUNT_TX);
-
- if(pending_addr) {
- usb_rblog.log("Actually changing addr to: %d", pending_addr);
-
- usb.reg.DADDR = 0x80 | pending_addr;
-
- pending_addr = 0;
- }
-
- usb.reg.EPR[ep] &= 0x870f;
- }
- usb_rblog.log("Leaving: EPR%d: %04x", ep, usb.reg.EPR[ep]);
- }
- }
-
- virtual bool ep_ready(uint32_t ep) {
- return (usb.reg.EPR[ep] & 0x30) == 0x20;
- }
-
- virtual void write(uint32_t ep, uint32_t* bufp, uint32_t len) {
- usb_rblog.log("Writing, ep=%d, len=%d", ep, len);
-
- uint16_t* p = (uint16_t*)bufp;
- uint32_t base = usb.bufd[ep].ADDR_TX >> 1;
-
- for(uint32_t i = 0; i < len; i += 2) {
- usb.buf[base + (i >> 1)] = *p++;
- }
-
- usb.bufd[ep].COUNT_TX = len;
- usb.reg.EPR[ep] = (usb.reg.EPR[ep] & 0x870f) | 0x0010;
- }
-
- virtual uint32_t read(uint32_t ep, uint32_t* bufp, uint32_t len) {
- usb_rblog.log("Reading, ep=%d, len=%d", ep, len);
-
- uint16_t* p = (uint16_t*)bufp;
- uint32_t base = usb.bufd[ep].ADDR_RX >> 1;
-
- for(uint32_t i = 0; i < len; i += 2) {
- *p++ = uint16_t(usb.buf[base + (i >> 1)]);
- }
-
- return len;
- }
-};
-
-#endif
diff --git a/usb/f1_usb_def.h b/usb/f1_usb_def.h
deleted file mode 100644
index 0e42f6f..0000000
--- a/usb/f1_usb_def.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef F1_USB_DEF_H
-#define F1_USB_DEF_H
-
-#include <stdint.h>
-
-class F1_USB_t {
- private:
- struct F1_USB_reg_t {
- volatile uint32_t EPR[16];
- volatile uint32_t CNTR;
- volatile uint32_t ISTR;
- volatile uint32_t FNR;
- volatile uint32_t DADDR;
- volatile uint32_t BTABLE;
- };
-
- struct F1_USB_bufd_t {
- volatile uint32_t ADDR_TX;
- volatile uint32_t COUNT_TX;
- volatile uint32_t ADDR_RX;
- volatile uint32_t COUNT_RX;
- };
-
- public:
- F1_USB_reg_t& reg;
- F1_USB_bufd_t* bufd;
- volatile uint32_t* buf;
-
- F1_USB_t(uint32_t reg_addr, uint32_t buf_addr) :
- reg(*(F1_USB_reg_t*)reg_addr),
- bufd((F1_USB_bufd_t*)buf_addr),
- buf((volatile uint32_t*)buf_addr) {}
-};
-
-#endif
diff --git a/usb/l0_usb.h b/usb/l0_usb.h
deleted file mode 100644
index 243f19b..0000000
--- a/usb/l0_usb.h
+++ /dev/null
@@ -1,174 +0,0 @@
-#ifndef L0_USB_H
-#define L0_USB_H
-
-#include "generic.h"
-#include "l0_usb_def.h"
-
-class USB_l0 : public USB_generic {
- private:
- L0_USB_t& usb;
-
- uint32_t setupbuf[16];
-
- uint32_t buf_end;
-
- uint8_t pending_addr;
-
- protected:
- virtual void hw_set_address(uint8_t addr) {
- usb_rblog.log("SetAddress: %d", addr);
-
- pending_addr = addr;
- }
-
- virtual void hw_conf_ep(uint8_t ep, EPType type, uint32_t size) {
- usb_rblog.log("Configuring EP%02x: size=%d", ep, size);
-
- uint8_t in = ep & 0x80;
- ep &= 0x7f;
-
- uint32_t old_epr = usb.reg.EPR[ep];
- //uint32_t new_epr = 0x3220;
- uint32_t new_epr = 0x8080 | ((type == EPType::Bulk ? 0 : type == EPType::Control ? 1 : type == EPType::Isochronous ? 2 : 3) << 9) | ep;
-
- if(in || ep == 0) {
- usb.bufd[ep].ADDR_TX = buf_end;
- buf_end += size;
-
- new_epr |= (old_epr & 0x0070) ^ 0x0020;
- }
-
- if(!in) {
- usb.bufd[ep].ADDR_RX = buf_end;
- buf_end += size;
- usb.bufd[ep].COUNT_RX = 0x8000 | (1 << 10);
-
- new_epr |= (old_epr & 0x7000) ^ 0x3000;
- }
-
- usb.reg.EPR[ep] = new_epr;
-
- usb_rblog.log("EPR: old=%04x, new=%04x", old_epr, usb.reg.EPR[ep]);
- }
-
- virtual void hw_set_stall(uint8_t ep) {
- usb_rblog.log("Setting stall on EP %d", ep);
-
- usb.reg.EPR[ep] = (usb.reg.EPR[ep] & 0x878f) | 0x2030;
-
- //otg.dev_iep_reg[ep].DIEPCTL |= (1 << 21);
- }
-
- public:
- USB_l0(L0_USB_t& usb_periph, desc_t dev, desc_t conf) : USB_generic(dev, conf), usb(usb_periph) {}
-
- void init() {
- usb.reg.CNTR = 3;
- Time::sleep(10);
- usb.reg.CNTR = 1;
- Time::sleep(10);
- // Exit power down mode.
- usb.reg.CNTR = 0;
- }
-
- void process() {
- uint32_t istr = usb.reg.ISTR;
-
- if(istr & (1 << 10)) {
- usb_rblog.log("USB Reset");
-
- buf_end = 0x40;
-
- usb.reg.DADDR = 0x80;
-
- handle_reset();
-
- usb.reg.ISTR = ~(1 << 10);
-
- return;
- }
-
- if(istr & (1 << 15)) {
- usb_rblog.log("USB Transfer: %02x", istr & 0x1f);
-
- uint32_t ep = istr & 0xf;
- uint32_t dir = istr & 0x10;
-
- usb_rblog.log("EPR%d: %04x", ep, usb.reg.EPR[ep]);
-
- if(dir) {
- // RX.
-
- usb_rblog.log("RXBUF: ADDR: %04x, COUNT: %04x", usb.bufd[ep].ADDR_RX, usb.bufd[ep].COUNT_RX);
-
- uint32_t len = usb.bufd[ep].COUNT_RX & 0x03ff;
-
- if(usb.reg.EPR[ep] & (1 << 11)) {
- usb_rblog.log("SETUP packet received");
-
- read(0, setupbuf, 8);
-
- handle_setup(setupbuf);
-
- } else {
- usb_rblog.log("OUT packet received");
-
- handle_out(ep, len);
- }
-
- //usb.reg.EPR[ep] = 0x9280;
- //usb.reg.EPR[ep] &= 0x078f;
-
- usb.reg.EPR[ep] = (usb.reg.EPR[ep] & 0x078f) | 0x1000;
- } else {
- // TX.
-
- usb_rblog.log("TXBUF: ADDR: %04x, COUNT: %04x", usb.bufd[ep].ADDR_TX, usb.bufd[ep].COUNT_TX);
-
- if(pending_addr) {
- usb_rblog.log("Actually changing addr to: %d", pending_addr);
-
- usb.reg.DADDR = 0x80 | pending_addr;
-
- pending_addr = 0;
- }
-
- usb.reg.EPR[ep] &= 0x870f;
- }
- usb_rblog.log("Leaving: EPR%d: %04x", ep, usb.reg.EPR[ep]);
- }
- }
-
- virtual bool ep_ready(uint32_t ep) {
- return (usb.reg.EPR[ep] & 0x30) == 0x20;
- }
-
- virtual void write(uint32_t ep, uint32_t* bufp, uint32_t len) {
- usb_rblog.log("Writing, ep=%d, len=%d", ep, len);
-
- uint16_t* p = (uint16_t*)bufp;
- uint32_t base = usb.bufd[ep].ADDR_TX >> 1;
-
- for(uint32_t i = 0; i < len; i += 2) {
- usb.buf[base + (i >> 1)] = *p++;
- }
-
- usb.bufd[ep].COUNT_TX = len;
- usb.reg.EPR[ep] = (usb.reg.EPR[ep] & 0x870f) | 0x0010;
- }
-
- virtual uint32_t read(uint32_t ep, uint32_t* bufp, uint32_t len) {
- usb_rblog.log("Reading, ep=%d, len=%d", ep, len);
-
- uint16_t* p = (uint16_t*)bufp;
- uint32_t base = usb.bufd[ep].ADDR_RX >> 1;
-
- for(uint32_t i = 0; i < len; i += 2) {
- *p++ = uint16_t(usb.buf[base + (i >> 1)]);
- }
-
- return len;
- }
-};
-
-#endif
diff --git a/usb/l0_usb_def.h b/usb/l0_usb_def.h
deleted file mode 100644
index b9d8d10..0000000
--- a/usb/l0_usb_def.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef L0_USB_DEF_H
-#define L0_USB_DEF_H
-
-#include <stdint.h>
-
-class L0_USB_t {
- private:
- struct L0_USB_reg_t {
- volatile uint32_t EPR[16];
- volatile uint32_t CNTR;
- volatile uint32_t ISTR;
- volatile uint32_t FNR;
- volatile uint32_t DADDR;
- volatile uint32_t BTABLE;
- volatile uint32_t LPMCSR;
- volatile uint32_t BCDR;
- };
-
- struct L0_USB_bufd_t {
- volatile uint16_t ADDR_TX;
- volatile uint16_t COUNT_TX;
- volatile uint16_t ADDR_RX;
- volatile uint16_t COUNT_RX;
- };
-
- public:
- L0_USB_reg_t& reg;
- L0_USB_bufd_t* bufd;
- volatile uint16_t* buf;
-
- L0_USB_t(uint32_t reg_addr, uint32_t buf_addr) :
- reg(*(L0_USB_reg_t*)reg_addr),
- bufd((L0_USB_bufd_t*)buf_addr),
- buf((volatile uint16_t*)buf_addr) {}
-};
-
-#endif
diff --git a/usb/stm32_usb.h b/usb/stm32_usb.h
new file mode 100644
index 0000000..7be6a7c
--- /dev/null
+++ b/usb/stm32_usb.h
@@ -0,0 +1,212 @@
+#pragma once
+
+#include "generic.h"
+#include "stm32_usb_def.h"
+
+#include <type_traits>
+
+template <typename T>
+class STM32_USB_drv : public USB_generic {
+ private:
+ const STM32_USB_t<T>& usb;
+
+ uint32_t setupbuf[16];
+
+ uint32_t buf_end;
+
+ uint8_t pending_addr;
+
+ protected:
+ virtual void hw_set_address(uint8_t addr) {
+ usb_rblog.log("SetAddress: %d", addr);
+
+ pending_addr = addr;
+ }
+
+ virtual void hw_conf_ep(uint8_t ep, EPType type, uint32_t size) {
+ usb_rblog.log("Configuring EP%02x: size=%d", ep, size);
+
+ uint8_t in = ep & 0x80;
+ ep &= 0x7f;
+
+ uint32_t old_epr = usb->EPR[ep];
+ //uint32_t new_epr = 0x3220;
+ uint32_t new_epr = 0x8080 | ((type == EPType::Bulk ? 0 : type == EPType::Control ? 1 : type == EPType::Isochronous ? 2 : 3) << 9) | ep;
+
+ if(in || ep == 0) {
+ if constexpr (std::is_same_v<T, STM32_USB_reg_v3_t>) {
+ usb.bufd[ep].TXRXBD = buf_end;
+ } else {
+ usb.bufd[ep].ADDR_TX = buf_end;
+ }
+ buf_end += size;
+
+ new_epr |= (old_epr & 0x0070) ^ 0x0020;
+ }
+
+ if(!in) {
+ if constexpr (std::is_same_v<T, STM32_USB_reg_v3_t>) {
+ usb.bufd[ep].RXTXBD = (1 << 31) | (1 << 26) | buf_end;
+ } else {
+ usb.bufd[ep].ADDR_RX = buf_end;
+ usb.bufd[ep].COUNT_RX = (1 << 15) | (1 << 10);
+ }
+ buf_end += size;
+
+ new_epr |= (old_epr & 0x7000) ^ 0x3000;
+ }
+
+ usb->EPR[ep] = new_epr;
+
+ usb_rblog.log("EPR: old=%04x, new=%04x", old_epr, usb->EPR[ep]);
+ }
+
+ virtual void hw_set_stall(uint8_t ep) {
+ usb_rblog.log("Setting stall on EP %d", ep);
+
+ usb->EPR[ep] = (usb->EPR[ep] & 0x878f) | 0x2030;
+
+ //otg.dev_iep_reg[ep].DIEPCTL |= (1 << 21);
+ }
+
+ public:
+ STM32_USB_drv(const STM32_USB_t<T>& usb_periph, desc_t dev, desc_t conf) : USB_generic(dev, conf), usb(usb_periph) {}
+
+ void init() {
+ usb->CNTR = 3;
+ //Time::sleep(10);
+ usb->CNTR = 1;
+ //Time::sleep(10);
+ // Exit power down mode.
+ usb->CNTR = 0;
+ }
+
+ void process() {
+ uint32_t istr = usb->ISTR;
+
+ if(istr & (1 << 10)) {
+ usb_rblog.log("USB Reset");
+
+ buf_end = 0x40;
+
+ usb->DADDR = 0x80;
+
+ handle_reset();
+
+ usb->ISTR = ~(1 << 10);
+
+ return;
+ }
+
+ if(istr & (1 << 15)) {
+ usb_rblog.log("USB Transfer: %02x", istr & 0x1f);
+
+ uint32_t ep = istr & 0xf;
+ uint32_t dir = istr & 0x10;
+
+ usb_rblog.log("EPR%d: %04x", ep, usb->EPR[ep]);
+
+ if(dir) {
+ // RX.
+
+ uint32_t len;
+ if constexpr (std::is_same_v<T, STM32_USB_reg_v3_t>) {
+ usb_rblog.log("RXBUF: RXTXBD: %08x", usb.bufd[ep].RXTXBD);
+ len = (usb.bufd[ep].RXTXBD >> 16) & 0x03ff;
+ } else {
+ usb_rblog.log("RXBUF: ADDR: %04x, COUNT: %04x", usb.bufd[ep].ADDR_RX, usb.bufd[ep].COUNT_RX);
+ len = usb.bufd[ep].COUNT_RX & 0x03ff;
+ }
+
+ if(usb->EPR[ep] & (1 << 11)) {
+ usb_rblog.log("SETUP packet received");
+
+ read(0, setupbuf, 8);
+
+ handle_setup(setupbuf);
+
+ } else {
+ usb_rblog.log("OUT packet received");
+
+ handle_out(ep, len);
+ }
+
+ //usb->EPR[ep] = 0x9280;
+ //usb->EPR[ep] &= 0x078f;
+
+ usb->EPR[ep] = (usb->EPR[ep] & 0x078f) | 0x1000;
+ } else {
+ // TX.
+
+ if constexpr (std::is_same_v<T, STM32_USB_reg_v3_t>) {
+ usb_rblog.log("TXBUF: TXRXBD: %08x", usb.bufd[ep].TXRXBD);
+ } else {
+ usb_rblog.log("TXBUF: ADDR: %04x, COUNT: %04x", usb.bufd[ep].ADDR_TX, usb.bufd[ep].COUNT_TX);
+ }
+
+ if(pending_addr) {
+ usb_rblog.log("Actually changing addr to: %d", pending_addr);
+
+ usb->DADDR = 0x80 | pending_addr;
+
+ pending_addr = 0;
+ }
+
+ usb->EPR[ep] &= 0x870f;
+ }
+ usb_rblog.log("Leaving: EPR%d: %04x", ep, usb->EPR[ep]);
+ }
+ }
+
+ virtual bool ep_ready(uint32_t ep) {
+ return (usb->EPR[ep] & 0x30) == 0x20;
+ }
+
+ virtual void write(uint32_t ep, uint32_t* bufp, uint32_t len) {
+ usb_rblog.log("Writing, ep=%d, len=%d", ep, len);
+
+ if constexpr (std::is_same_v<T, STM32_USB_reg_v3_t>) {
+ uint32_t base = (usb.bufd[ep].TXRXBD & 0xffff) >> 2;
+
+ for(uint32_t i = 0; i < len; i += 4) {
+ usb.buf[base + (i >> 2)] = *bufp++;
+ }
+
+ usb.bufd[ep].TXRXBD = (len << 16) | (usb.bufd[ep].TXRXBD & 0xffff);
+
+ } else {
+ uint16_t* p = (uint16_t*)bufp;
+ uint32_t base = usb.bufd[ep].ADDR_TX >> 1;
+
+ for(uint32_t i = 0; i < len; i += 2) {
+ usb.buf[base + (i >> 1)] = *p++;
+ }
+
+ usb.bufd[ep].COUNT_TX = len;
+ }
+
+ usb->EPR[ep] = (usb->EPR[ep] & 0x870f) | 0x0010;
+ }
+
+ virtual uint32_t read(uint32_t ep, uint32_t* bufp, uint32_t len) {
+ usb_rblog.log("Reading, ep=%d, len=%d", ep, len);
+
+ if constexpr (std::is_same_v<T, STM32_USB_reg_v3_t>) {
+ uint32_t base = (usb.bufd[ep].RXTXBD & 0xffff) >> 2;
+
+ for(uint32_t i = 0; i < len; i += 4) {
+ *bufp++ = usb.buf[base + (i >> 2)];
+ }
+
+ } else {
+ uint16_t* p = (uint16_t*)bufp;
+ uint32_t base = usb.bufd[ep].ADDR_RX >> 1;
+
+ for(uint32_t i = 0; i < len; i += 2) {
+ *p++ = uint16_t(usb.buf[base + (i >> 1)]);
+ }
+ }
+
+ return len;
+ }
+};
diff --git a/usb/stm32_usb_def.h b/usb/stm32_usb_def.h
new file mode 100644
index 0000000..5fdd2ff
--- /dev/null
+++ b/usb/stm32_usb_def.h
@@ -0,0 +1,71 @@
+#pragma once
+
+#include <mmio/mmio.h>
+
+struct STM32_USB_reg_v1_t {
+ volatile uint32_t EPR[16];
+ volatile uint32_t CNTR;
+ volatile uint32_t ISTR;
+ volatile uint32_t FNR;
+ volatile uint32_t DADDR;
+ volatile uint32_t BTABLE;
+
+ struct bufd_t {
+ volatile uint32_t ADDR_TX;
+ volatile uint32_t COUNT_TX;
+ volatile uint32_t ADDR_RX;
+ volatile uint32_t COUNT_RX;
+ };
+
+ using buf_t = volatile uint32_t;
+};
+
+struct STM32_USB_reg_v2_t {
+ volatile uint32_t EPR[16];
+ volatile uint32_t CNTR;
+ volatile uint32_t ISTR;
+ volatile uint32_t FNR;
+ volatile uint32_t DADDR;
+ volatile uint32_t BTABLE;
+ volatile uint32_t LPMCSR;
+ volatile uint32_t BCDR;
+
+ struct bufd_t {
+ volatile uint16_t ADDR_TX;
+ volatile uint16_t COUNT_TX;
+ volatile uint16_t ADDR_RX;
+ volatile uint16_t COUNT_RX;
+ };
+
+ using buf_t = volatile uint16_t;
+};
+
+struct STM32_USB_reg_v3_t {
+ volatile uint32_t EPR[16];
+ volatile uint32_t CNTR;
+ volatile uint32_t ISTR;
+ volatile uint32_t FNR;
+ volatile uint32_t DADDR;
+ uint32_t _reserved;
+ volatile uint32_t LPMCSR;
+ volatile uint32_t BCDR;
+
+ struct bufd_t {
+ volatile uint32_t TXRXBD;
+ volatile uint32_t RXTXBD;
+ };
+
+ using buf_t = volatile uint32_t;
+};
+
+template <typename T>
+class STM32_USB_t : public mmio_ptr<T> {
+ public:
+ mmio_ptr<typename T::bufd_t> bufd;
+ mmio_ptr<typename T::buf_t> buf;
+
+ constexpr STM32_USB_t(uint32_t reg_addr, uint32_t buf_addr) :
+ mmio_ptr<T>(reg_addr),
+ bufd(buf_addr),
+ buf(buf_addr) {}
+};