diff options
author | Vegard Storheil Eriksen <zyp@jvnv.net> | 2023-05-01 00:50:55 +0200 |
---|---|---|
committer | Vegard Storheil Eriksen <zyp@jvnv.net> | 2023-05-01 00:50:55 +0200 |
commit | d381db5b1f6a7d7897056adb84ea24f18f2dd0b8 (patch) | |
tree | 411568025c0aa101bd3241416ce192ae9c2a9ab1 | |
parent | 3eb114c680a63274948700c653dfc263d182171a (diff) |
usb: Update code for stm32_usb and add support for v3.
-rw-r--r-- | usb/SConscript | 9 | ||||
-rw-r--r-- | usb/f1_usb.h | 174 | ||||
-rw-r--r-- | usb/f1_usb_def.h | 35 | ||||
-rw-r--r-- | usb/l0_usb.h | 174 | ||||
-rw-r--r-- | usb/l0_usb_def.h | 37 | ||||
-rw-r--r-- | usb/stm32_usb.h | 212 | ||||
-rw-r--r-- | usb/stm32_usb_def.h | 71 |
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) {} +}; |