From cad5bd6501868f9532d5b4a227ca156f9c9d1d8e Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Thu, 16 Sep 2021 11:09:30 +0200 Subject: Added NRF52 support. --- build_rules | 9 ++ gpio/gpio.h | 217 ++++--------------------------------------------- gpio/gpio_nrf.h | 83 +++++++++++++++++++ gpio/gpio_stm32.h | 202 +++++++++++++++++++++++++++++++++++++++++++++ ld_scripts/nrf52840.ld | 6 ++ radio/radio.h | 115 ++++++++++++++++++++++++++ usb/usb.h | 5 ++ usb/usb_nrf.h | 187 ++++++++++++++++++++++++++++++++++++++++++ usb/usb_nrf_def.h | 97 ++++++++++++++++++++++ 9 files changed, 721 insertions(+), 200 deletions(-) create mode 100644 gpio/gpio_nrf.h create mode 100644 gpio/gpio_stm32.h create mode 100644 ld_scripts/nrf52840.ld create mode 100644 radio/radio.h create mode 100644 usb/usb_nrf.h create mode 100644 usb/usb_nrf_def.h diff --git a/build_rules b/build_rules index fc7fd75..ddc9647 100644 --- a/build_rules +++ b/build_rules @@ -109,12 +109,21 @@ def select_stm32(env, variant): print 'Unknown stm32 family: %s' % family Exit(1) +def select_nrf(env, variant): + if variant == 'nrf52840': + select_arm(env, 'cortex-m4f') + env.Append(CPPDEFINES = ['NRF52840']) + env['LINK_SCRIPT'] = 'nrf52840.ld' + def SelectMCU(env, mcu, variant_dir = None): mcu = mcu.lower() if mcu.startswith('stm32'): select_stm32(env, mcu) + elif mcu.startswith('nrf'): + select_nrf(env, mcu) + else: print 'Unknown MCU: %s' % mcu Exit(1) diff --git a/gpio/gpio.h b/gpio/gpio.h index 392b2f7..bb4201e 100644 --- a/gpio/gpio.h +++ b/gpio/gpio.h @@ -1,218 +1,25 @@ -#ifndef GPIO_H -#define GPIO_H - -#include - -struct GPIO_reg_t { - #if defined(STM32F1) - volatile uint32_t CRL; - volatile uint32_t CRH; - volatile uint32_t IDR; - volatile uint32_t ODR; - volatile uint32_t BSRR; - volatile uint32_t BRR; - volatile uint32_t LCKR; - #elif defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) - volatile uint32_t MODER; - volatile uint32_t OTYPER; - volatile uint32_t OSPEEDR; - volatile uint32_t PUPDR; - volatile uint32_t IDR; - volatile uint32_t ODR; - volatile uint32_t BSRR; - volatile uint32_t LCKR; - volatile uint32_t AFRL; - volatile uint32_t AFRH; - #endif -}; - -class GPIO_t { - public: - GPIO_reg_t& reg; - - class Pin { - private: - const GPIO_t& g; - int n; - - public: - constexpr Pin(const GPIO_t& gpio, int pin) : g(gpio), n(pin) {} - - enum Mode { - #if defined(STM32F1) - Input = 0x4, - InputPull = 0x8, - Output = 0x3, - AF = 0xb, - Analog = 0x0, - #elif defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) - Input, - Output, - AF, - Analog, - #endif - }; - - enum Type { - PushPull, - OpenDrain, - }; - - enum Pull { - PullNone, - PullUp, - PullDown, - }; - - enum Speed { - Low, - Medium, - Fast, - High, - }; - - void set_mode(Mode m) { - #if defined(STM32F1) - if(n < 8) { - g.reg.CRL = (g.reg.CRL & ~(0xf << (n * 4))) | m << (n * 4); - } else { - g.reg.CRH = (g.reg.CRH & ~(0xf << (n * 4 - 32))) | m << (n * 4 - 32); - } - #elif defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) - g.reg.MODER = (g.reg.MODER & ~(3 << (n * 2))) | m << (n * 2); - #endif - } - - void set_type(Type t) { - #if defined(STM32F1) - // TODO: Unified configure() method? - #elif defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) - if(t) { - g.reg.OTYPER |= 1 << n; - } else { - g.reg.OTYPER &= ~(1 << n); - } - #endif - } - - void set_pull(Pull p) { - #if defined(STM32F1) - // TODO: Unified configure() method? - #elif defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) - g.reg.PUPDR = (g.reg.PUPDR & ~(3 << (n * 2))) | p << (n * 2); - #endif - } - - void set_af(int af) { - #if defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) - if(n < 8) { - g.reg.AFRL = (g.reg.AFRL & ~(0xf << (n * 4))) | af << (n * 4); - } else { - g.reg.AFRH = (g.reg.AFRH & ~(0xf << (n * 4 - 32))) | af << (n * 4 - 32); - } - #endif - } - - void set_speed(Speed s) { - #if defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) - g.reg.OSPEEDR = (g.reg.OSPEEDR & ~(3 << (n * 2))) | s << (n * 2); - #endif - } - - void on() { - g.reg.BSRR = 1 << n; - } - - void off() { - g.reg.BSRR = 1 << 16 << n; - } - - void set(bool value) { - if(value) { - on(); - } else { - off(); - } - } - - bool get() { - return g.reg.IDR & (1 << n); - } - - void toggle() { - set(!(g.reg.ODR & (1 << n))); - } - }; - - class PinArray { - private: - const GPIO_t& g; - int f; - int l; - - constexpr uint32_t mask1() { - return ((2 << l) - 1) ^ ((1 << f) - 1); - } - - constexpr uint32_t mask2() { - return ((4 << (l * 2)) - 1) ^ ((1 << (f * 2)) - 1); - } - - public: - constexpr PinArray(const GPIO_t& gpio, int first, int last) : g(gpio), f(first), l(last) {} - - #if defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) - void set_mode(Pin::Mode m) { - g.reg.MODER = (g.reg.MODER & ~mask2()) | ((0x55555555 * m) & mask2()); - } - - void set_type(Pin::Type t) { - g.reg.OTYPER = (g.reg.OTYPER & ~mask2()) | ((0x55555555 * t) & mask2()); - } - - void set_pull(Pin::Pull p) { - g.reg.PUPDR = (g.reg.PUPDR & ~mask2()) | ((0x55555555 * p) & mask2()); - } - #endif - - void set(uint16_t value) { - value <<= f; - g.reg.BSRR = ((~value & mask1()) << 16) | (value & mask1()); - } - - uint16_t get() { - return (g.reg.IDR & mask1()) >> f; - } - }; - - constexpr GPIO_t(uint32_t reg_addr) : reg(*(GPIO_reg_t*)reg_addr) {} - - constexpr Pin operator[](int pin) { - return Pin(*this, pin); - } - - constexpr PinArray array(int first, int last) { - return PinArray(*this, first, last); - } -}; - -typedef GPIO_t::Pin Pin; -typedef GPIO_t::PinArray PinArray; +#ifndef LAKS_GPIO_GPIO_H +#define LAKS_GPIO_GPIO_H #if defined(STM32F1) +#include "gpio_stm32.h" static GPIO_t GPIOA(0x40010800); static GPIO_t GPIOB(0x40010c00); static GPIO_t GPIOC(0x40011000); static GPIO_t GPIOD(0x40011400); static GPIO_t GPIOE(0x40011800); + #elif defined(STM32F3) +#include "gpio_stm32.h" static GPIO_t GPIOA(0x48000000); static GPIO_t GPIOB(0x48000400); static GPIO_t GPIOC(0x48000800); static GPIO_t GPIOD(0x48000c00); static GPIO_t GPIOE(0x48001000); static GPIO_t GPIOF(0x48001400); + #elif defined(STM32F4) +#include "gpio_stm32.h" static GPIO_t GPIOA(0x40020000); static GPIO_t GPIOB(0x40020400); static GPIO_t GPIOC(0x40020800); @@ -222,19 +29,29 @@ static GPIO_t GPIOF(0x40021400); static GPIO_t GPIOG(0x40021800); static GPIO_t GPIOH(0x40021c00); static GPIO_t GPIOI(0x40022000); + #elif defined(STM32L0) +#include "gpio_stm32.h" static GPIO_t GPIOA(0x50000000); static GPIO_t GPIOB(0x50000400); static GPIO_t GPIOC(0x50000800); static GPIO_t GPIOD(0x50000c00); static GPIO_t GPIOH(0x50001c00); + #elif defined(STM32WB) +#include "gpio_stm32.h" static GPIO_t GPIOA(0x48000000); static GPIO_t GPIOB(0x48000400); static GPIO_t GPIOC(0x48000800); static GPIO_t GPIOD(0x48000c00); static GPIO_t GPIOE(0x48001000); static GPIO_t GPIOH(0x48001c00); + +#elif defined(NRF52840) +#include "gpio_nrf.h" +static GPIO_t P0(0x50000000); +static GPIO_t P1(0x50000300); + #endif #endif diff --git a/gpio/gpio_nrf.h b/gpio/gpio_nrf.h new file mode 100644 index 0000000..44c85f4 --- /dev/null +++ b/gpio/gpio_nrf.h @@ -0,0 +1,83 @@ +#ifndef LAKS_GPIO_GPIO_NRF_H +#define LAKS_GPIO_GPIO_NRF_H + +#include + +struct GPIO_reg_t { + uint32_t _reserved; + volatile uint32_t OUT; + volatile uint32_t OUTSET; + volatile uint32_t OUTCLR; + volatile uint32_t IN; + volatile uint32_t DIR; + volatile uint32_t DIRSET; + volatile uint32_t DIRCLR; + volatile uint32_t LATCH; + volatile uint32_t DETECTMODE; + uint32_t _reserved_1[118]; + volatile uint32_t PIN_CNF[32]; +}; + +class GPIO_t { + public: + GPIO_reg_t& reg; + + class Pin { + private: + const GPIO_t& g; + int n; + + public: + constexpr Pin(const GPIO_t& gpio, int pin) : g(gpio), n(pin) {} + + enum Mode { + Input, + Output, + }; + + void set_mode(Mode m) { + switch(m) { + case Input: + g.reg.DIRCLR = 1 << n; + break; + case Output: + g.reg.DIRSET = 1 << n; + break; + } + } + + void on() { + g.reg.OUTSET = 1 << n; + } + + void off() { + g.reg.OUTCLR = 1 << n; + } + + void set(bool value) { + if(value) { + on(); + } else { + off(); + } + } + + bool get() { + return g.reg.IN & (1 << n); + } + + void toggle() { + set(!(g.reg.OUT & (1 << n))); + } + }; + + constexpr GPIO_t(uint32_t reg_addr) : reg(*(GPIO_reg_t*)(reg_addr + 0x500)) {} + + constexpr Pin operator[](int pin) { + return Pin(*this, pin); + } +}; + +typedef GPIO_t::Pin Pin; + +#endif diff --git a/gpio/gpio_stm32.h b/gpio/gpio_stm32.h new file mode 100644 index 0000000..635bcc9 --- /dev/null +++ b/gpio/gpio_stm32.h @@ -0,0 +1,202 @@ +#ifndef LAKS_GPIO_GPIO_STM32_H +#define LAKS_GPIO_GPIO_STM32_H + +#include + +struct GPIO_reg_t { + #if defined(STM32F1) + volatile uint32_t CRL; + volatile uint32_t CRH; + volatile uint32_t IDR; + volatile uint32_t ODR; + volatile uint32_t BSRR; + volatile uint32_t BRR; + volatile uint32_t LCKR; + #elif defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) + volatile uint32_t MODER; + volatile uint32_t OTYPER; + volatile uint32_t OSPEEDR; + volatile uint32_t PUPDR; + volatile uint32_t IDR; + volatile uint32_t ODR; + volatile uint32_t BSRR; + volatile uint32_t LCKR; + volatile uint32_t AFRL; + volatile uint32_t AFRH; + #endif +}; + +class GPIO_t { + public: + GPIO_reg_t& reg; + + class Pin { + private: + const GPIO_t& g; + int n; + + public: + constexpr Pin(const GPIO_t& gpio, int pin) : g(gpio), n(pin) {} + + enum Mode { + #if defined(STM32F1) + Input = 0x4, + InputPull = 0x8, + Output = 0x3, + AF = 0xb, + Analog = 0x0, + #elif defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) + Input, + Output, + AF, + Analog, + #endif + }; + + enum Type { + PushPull, + OpenDrain, + }; + + enum Pull { + PullNone, + PullUp, + PullDown, + }; + + enum Speed { + Low, + Medium, + Fast, + High, + }; + + void set_mode(Mode m) { + #if defined(STM32F1) + if(n < 8) { + g.reg.CRL = (g.reg.CRL & ~(0xf << (n * 4))) | m << (n * 4); + } else { + g.reg.CRH = (g.reg.CRH & ~(0xf << (n * 4 - 32))) | m << (n * 4 - 32); + } + #elif defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) + g.reg.MODER = (g.reg.MODER & ~(3 << (n * 2))) | m << (n * 2); + #endif + } + + void set_type(Type t) { + #if defined(STM32F1) + // TODO: Unified configure() method? + #elif defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) + if(t) { + g.reg.OTYPER |= 1 << n; + } else { + g.reg.OTYPER &= ~(1 << n); + } + #endif + } + + void set_pull(Pull p) { + #if defined(STM32F1) + // TODO: Unified configure() method? + #elif defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) + g.reg.PUPDR = (g.reg.PUPDR & ~(3 << (n * 2))) | p << (n * 2); + #endif + } + + void set_af(int af) { + #if defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) + if(n < 8) { + g.reg.AFRL = (g.reg.AFRL & ~(0xf << (n * 4))) | af << (n * 4); + } else { + g.reg.AFRH = (g.reg.AFRH & ~(0xf << (n * 4 - 32))) | af << (n * 4 - 32); + } + #endif + } + + void set_speed(Speed s) { + #if defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) + g.reg.OSPEEDR = (g.reg.OSPEEDR & ~(3 << (n * 2))) | s << (n * 2); + #endif + } + + void on() { + g.reg.BSRR = 1 << n; + } + + void off() { + g.reg.BSRR = 1 << 16 << n; + } + + void set(bool value) { + if(value) { + on(); + } else { + off(); + } + } + + bool get() { + return g.reg.IDR & (1 << n); + } + + void toggle() { + set(!(g.reg.ODR & (1 << n))); + } + }; + + class PinArray { + private: + const GPIO_t& g; + int f; + int l; + + constexpr uint32_t mask1() { + return ((2 << l) - 1) ^ ((1 << f) - 1); + } + + constexpr uint32_t mask2() { + return ((4 << (l * 2)) - 1) ^ ((1 << (f * 2)) - 1); + } + + public: + constexpr PinArray(const GPIO_t& gpio, int first, int last) : g(gpio), f(first), l(last) {} + + #if defined(STM32F3) || defined(STM32F4) || defined(STM32L0) || defined(STM32WB) + void set_mode(Pin::Mode m) { + g.reg.MODER = (g.reg.MODER & ~mask2()) | ((0x55555555 * m) & mask2()); + } + + void set_type(Pin::Type t) { + g.reg.OTYPER = (g.reg.OTYPER & ~mask2()) | ((0x55555555 * t) & mask2()); + } + + void set_pull(Pin::Pull p) { + g.reg.PUPDR = (g.reg.PUPDR & ~mask2()) | ((0x55555555 * p) & mask2()); + } + #endif + + void set(uint16_t value) { + value <<= f; + g.reg.BSRR = ((~value & mask1()) << 16) | (value & mask1()); + } + + uint16_t get() { + return (g.reg.IDR & mask1()) >> f; + } + }; + + constexpr GPIO_t(uint32_t reg_addr) : reg(*(GPIO_reg_t*)reg_addr) {} + + constexpr Pin operator[](int pin) { + return Pin(*this, pin); + } + + constexpr PinArray array(int first, int last) { + return PinArray(*this, first, last); + } +}; + +typedef GPIO_t::Pin Pin; +typedef GPIO_t::PinArray PinArray; + +#endif diff --git a/ld_scripts/nrf52840.ld b/ld_scripts/nrf52840.ld new file mode 100644 index 0000000..7542734 --- /dev/null +++ b/ld_scripts/nrf52840.ld @@ -0,0 +1,6 @@ +MEMORY { + flash (rx) : org = 0x00000000, len = 1024k + ram (rwx) : org = 0x20000000, len = 256k +} + +INCLUDE "arm_flash_ram.ld" diff --git a/radio/radio.h b/radio/radio.h new file mode 100644 index 0000000..010db43 --- /dev/null +++ b/radio/radio.h @@ -0,0 +1,115 @@ +#ifndef LAKS_RADIO_RADIO_H +#define LAKS_RADIO_RADIO_H + +class RADIO_NRF_t { + private: + struct tasks_t { + volatile uint32_t TXEN; + volatile uint32_t RXEN; + volatile uint32_t START; + volatile uint32_t STOP; + volatile uint32_t DISABLE; + volatile uint32_t RSSISTART; + volatile uint32_t RSSISTOP; + volatile uint32_t BCSTART; + volatile uint32_t BCSTOP; + volatile uint32_t EDSTART; + volatile uint32_t EDSTOP; + volatile uint32_t CCASTART; + volatile uint32_t CCASTOP; + }; + + struct events_t { + volatile uint32_t READY; + volatile uint32_t ADDRESS; + volatile uint32_t PAYLOAD; + volatile uint32_t END; + volatile uint32_t DISABLED; + volatile uint32_t DEVMATCH; + volatile uint32_t DEVMISS; + volatile uint32_t RSSIEND; + uint32_t _reserved[2]; + volatile uint32_t BCMATCH; + uint32_t _reserved_1; + volatile uint32_t CRCOK; + volatile uint32_t CRCERROR; + volatile uint32_t FRAMESTART; + volatile uint32_t EDEND; + volatile uint32_t EDSTOPPED; + volatile uint32_t CCAIDLE; + volatile uint32_t CCABUSY; + volatile uint32_t CCASTOPPED; + volatile uint32_t RATEBOOST; + volatile uint32_t TXREADY; + volatile uint32_t RXREADY; + volatile uint32_t MHRMATCH; + uint32_t _reserved_2[3]; + volatile uint32_t PHYEND; + }; + + struct reg_t { + volatile uint32_t SHORTS; + uint32_t _reserved[63]; + volatile uint32_t INTEN; + volatile uint32_t INTENSET; + volatile uint32_t INTENCLR; + uint32_t _reserved_1[61]; + volatile uint32_t CRCSTATUS; + uint32_t _reserved_2; + volatile uint32_t RXMATCH; + volatile uint32_t RXCRC; + volatile uint32_t DAI; + volatile uint32_t PDUSTAT; + uint32_t _reserved_3[59]; + volatile uint32_t PACKETPTR; + volatile uint32_t FREQUENCY; + volatile uint32_t TXPOWER; + volatile uint32_t MODE; + volatile uint32_t PCNF0; + volatile uint32_t PCNF1; + volatile uint32_t BASE[2]; + volatile uint32_t PREFIX[2]; + volatile uint32_t TXADDRESS; + volatile uint32_t RXADDRESSES; + volatile uint32_t CRCCNF; + volatile uint32_t CRCPOLY; + volatile uint32_t CRCINIT; + uint32_t _reserved_4; + volatile uint32_t TIFS; + volatile uint32_t RSSISAMPLE; + uint32_t _reserved_5; + volatile uint32_t STATE; + volatile uint32_t DATAWHITEIV; + uint32_t _reserved_6[2]; + volatile uint32_t BCC; + uint32_t _reserved_7[39]; + volatile uint32_t DAB[8]; + volatile uint32_t DAP[8]; + volatile uint32_t DACNF; + volatile uint32_t MHRMATCHCONF; + volatile uint32_t MHRMATCHMAS; + uint32_t _reserved_8; + volatile uint32_t MODECNF0; + uint32_t _reserved_9[3]; + volatile uint32_t SFD; + volatile uint32_t EDCNT; + volatile uint32_t EDSAMPLE; + volatile uint32_t CCACTRL; + uint32_t _reserved_10[611]; + volatile uint32_t POWER; + }; + + public: + tasks_t& tasks; + events_t& events; + reg_t& reg; + + RADIO_NRF_t(uint32_t reg_addr) : + tasks(*(tasks_t*)(reg_addr + 0x0)), + events(*(events_t*)(reg_addr + 0x100)), + reg(*(reg_t*)(reg_addr + 0x200)) {} +}; + +static RADIO_NRF_t RADIO(0x40001000); + +#endif diff --git a/usb/usb.h b/usb/usb.h index e57867c..260af9f 100644 --- a/usb/usb.h +++ b/usb/usb.h @@ -22,6 +22,11 @@ static L0_USB_t USB(0x40005c00, 0x40006000); static L0_USB_t USB(0x40006800, 0x40006c00); +#elif defined(NRF52840) +#include "usb_nrf.h" + +static USB_NRF_t USBD(0x40027000); + #endif #endif diff --git a/usb/usb_nrf.h b/usb/usb_nrf.h new file mode 100644 index 0000000..16e40a1 --- /dev/null +++ b/usb/usb_nrf.h @@ -0,0 +1,187 @@ +#ifndef LAKS_USB_USB_NRF_H +#define LAKS_USB_USB_NRF_H + +#include "generic.h" +#include "usb_nrf_def.h" + +#include + +class USB_NRF : public USB_generic { + private: + USB_NRF_t& usb; + + uint32_t ep_in_busy; + + uint8_t buf_in[8][64]; + uint8_t buf_out[8][64]; + + protected: + virtual void hw_set_address(uint8_t addr) { + usb_rblog.log("SetAddress: %d", addr); + + // Do nothing, handled in hardware. + } + + 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; + + if(in || ep == 0) { + usb.reg_in[ep].PTR = (uint32_t)&buf_in[ep]; + usb.reg.EPINEN |= 1 << ep; + } + + if(!in) { + usb.reg_out[ep].PTR = (uint32_t)&buf_out[ep]; + + usb.reg.SIZE_EPOUT[ep] = 0; + usb.reg.EPOUTEN |= 1 << ep; + } + } + + virtual void hw_set_stall(uint8_t ep) { + if(ep == 0) { + usb.tasks.EP0STALL = 1; + } + } + + public: + USB_NRF(USB_NRF_t& usb_periph, desc_t dev, desc_t conf) : USB_generic(dev, conf), usb(usb_periph) {} + + void init() { + *(volatile uint32_t*)0x4006ec00 = 0x00009375; + *(volatile uint32_t*)0x4006ed14 = 0x00000003; + *(volatile uint32_t*)0x4006ec00 = 0x00009375; + + usb.reg.ENABLE = 1; + + while(!(usb.reg.EVENTCAUSE & (1 << 11))); + + usb.reg.EVENTCAUSE = 1 << 11; + + *(volatile uint32_t*)0x4006ec00 = 0x00009375; + *(volatile uint32_t*)0x4006ed14 = 0x00000000; + *(volatile uint32_t*)0x4006ec00 = 0x00009375; + + usb.reg.USBPULLUP = 1; + } + + void process() { + if(usb.events.USBRESET) { + usb.events.USBRESET = 0; + + usb_rblog.log("USB Reset"); + + handle_reset(); + return; + } + + if(usb.events.EP0SETUP) { + usb.events.EP0SETUP = 0; + + uint8_t setupbuf[8] = { + (uint8_t)usb.reg.BMREQUESTTYPE, + (uint8_t)usb.reg.BREQUEST, + (uint8_t)usb.reg.WVALUEL, + (uint8_t)usb.reg.WVALUEH, + (uint8_t)usb.reg.WINDEXL, + (uint8_t)usb.reg.WINDEXH, + (uint8_t)usb.reg.WLENGTHL, + (uint8_t)usb.reg.WLENGTHH, + }; + + handle_setup((uint32_t*)&setupbuf); + } + + if(usb.events.EP0DATADONE) { + // TODO: Support multi-packet data stages. + usb.events.EP0DATADONE = 0; + + usb_rblog.log("Control data IN done, ACKing status stage."); + + usb.tasks.EP0STATUS = 1; + } + + /* + for(uint32_t ep = 0; ep <= 7; ep++) { + if(usb.events.ENDEPIN[ep]) { + usb.events.ENDEPIN[ep] = 0; + + ep_in_busy &= ~(1 << ep); + } + } + */ + + if(usb.reg.EPDATASTATUS) { + for(uint32_t ep = 1; ep <= 7; ep++) { + if((usb.reg.EPDATASTATUS & ((1 << 16) << ep)) == 0) { + continue; + } + + usb_rblog.log("EPDATA, starting DMA on ep %d", ep); + + usb.reg.EPDATASTATUS = (1 << 16) << ep; + + usb.reg_out[ep].MAXCNT = usb.reg.SIZE_EPOUT[ep]; + usb.tasks.STARTEPOUT[ep] = 1; + } + } + + for(uint32_t ep = 0; ep <= 7; ep++) { + if(usb.events.ENDEPOUT[ep]) { + usb.events.ENDEPOUT[ep] = 0; + + handle_out(ep, usb.reg_out[ep].AMOUNT); + } + } + } + + virtual bool ep_ready(uint32_t ep) { + //if(usb.events.ENDEPIN[ep]) { + // usb.events.ENDEPIN[ep] = 0; + // ep_in_busy &= ~(1 << ep); + //} + + if(usb.reg.EPDATASTATUS & (1 << ep)) { + usb.reg.EPDATASTATUS = 1 << ep; + + ep_in_busy &= ~(1 << ep); + } + + return (ep_in_busy & (1 << ep)) == 0; + } + + virtual void write(uint32_t ep, uint32_t* bufp, uint32_t len) { + usb_rblog.log("Writing, ep=%d, len=%d", ep, len); + + if(ep == 0 && len == 0 && (usb.reg.BMREQUESTTYPE & 0x80) == 0) { + usb_rblog.log("EP0 status ACK"); + usb.tasks.EP0STATUS = 1; + return; + } + + memcpy(&buf_in[ep], bufp, len); + + usb.reg_in[ep].MAXCNT = len; + + usb.tasks.STARTEPIN[ep] = 1; + + ep_in_busy |= 1 << ep; + } + + virtual uint32_t read(uint32_t ep, uint32_t* bufp, uint32_t len) { + usb_rblog.log("Reading, ep=%d, len=%d", ep, len); + + if(len > usb.reg_out[ep].AMOUNT) { + len = usb.reg_out[ep].AMOUNT; + } + + memcpy(bufp, &buf_out[ep], len); + + return len; + } +}; + +#endif diff --git a/usb/usb_nrf_def.h b/usb/usb_nrf_def.h new file mode 100644 index 0000000..0d56807 --- /dev/null +++ b/usb/usb_nrf_def.h @@ -0,0 +1,97 @@ +#ifndef LAKS_USB_USB_NRF_DEF_H +#define LAKS_USB_USB_NRF_DEF_H + +#include + +class USB_NRF_t { + private: + struct tasks_t { + uint32_t _reserved; + volatile uint32_t STARTEPIN[8]; + volatile uint32_t STARTISOIN; + volatile uint32_t STARTEPOUT[8]; + volatile uint32_t STARTISOOUT; + volatile uint32_t EP0RCVOUT; + volatile uint32_t EP0STATUS; + volatile uint32_t EP0STALL; + volatile uint32_t DPDMDRIVE; + volatile uint32_t DPDMNODRIVE; + }; + + struct events_t { + volatile uint32_t USBRESET; + volatile uint32_t STARTED; + volatile uint32_t ENDEPIN[8]; + volatile uint32_t EP0DATADONE; + volatile uint32_t ENDISOIN; + volatile uint32_t ENDEPOUT[8]; + volatile uint32_t ENDISOOUT; + volatile uint32_t SOF; + volatile uint32_t USBEVENT; + volatile uint32_t EP0SETUP; + volatile uint32_t EPDATA; + }; + + struct reg_t { + volatile uint32_t SHORTS; + uint32_t _reserved[63]; + volatile uint32_t INTEN; + volatile uint32_t INTENSET; + volatile uint32_t INTENCLR; + uint32_t _reserved_1[61]; + volatile uint32_t EVENTCAUSE; + uint32_t _reserved_2[7]; + volatile uint32_t HALTED_EPIN[9]; + volatile uint32_t HALTED_EPOUT[9]; + volatile uint32_t EPSTATUS; + volatile uint32_t EPDATASTATUS; + volatile uint32_t USBADDR; + uint32_t _reserved_3[3]; + volatile uint32_t BMREQUESTTYPE; + volatile uint32_t BREQUEST; + volatile uint32_t WVALUEL; + volatile uint32_t WVALUEH; + volatile uint32_t WINDEXL; + volatile uint32_t WINDEXH; + volatile uint32_t WLENGTHL; + volatile uint32_t WLENGTHH; + volatile uint32_t SIZE_EPOUT[8]; + volatile uint32_t SIZE_ISOOUT; + uint32_t _reserved_4[15]; + volatile uint32_t ENABLE; + volatile uint32_t USBPULLUP; + volatile uint32_t DPDMVALUE; + volatile uint32_t DTOGGLE; + volatile uint32_t EPINEN; + volatile uint32_t EPOUTEN; + volatile uint32_t EPSTALL; + volatile uint32_t ISOSPLIT; + volatile uint32_t FRAMECNTR; + uint32_t _reserved_5[2]; + volatile uint32_t LOWPOWER; + volatile uint32_t ISOINCONFIG; + }; + + struct ep_reg_t { + volatile uint32_t PTR; + volatile uint32_t MAXCNT; + volatile uint32_t AMOUNT; + uint32_t _reserved[2]; + }; + + public: + tasks_t& tasks; + events_t& events; + reg_t& reg; + ep_reg_t* reg_in; + ep_reg_t* reg_out; + + USB_NRF_t(uint32_t reg_addr) : + tasks(*(tasks_t*)(reg_addr + 0x0)), + events(*(events_t*)(reg_addr + 0x100)), + reg(*(reg_t*)(reg_addr + 0x200)), + reg_in((ep_reg_t*)(reg_addr + 0x600)), + reg_out((ep_reg_t*)(reg_addr + 0x700)) {} +}; + +#endif -- cgit v1.2.3