#include "usb_device.h" #include #include #include /* USB_OTG_GlobalTypeDef */ usb_device_t* usb1_device; void* usb_device_init(void* peripheral_address, usb_class_t* class, void* buffer) { if (buffer == NULL) { buffer = (void*)malloc(sizeof(usb_device_t)); } usb_device_t* device = (usb_device_t*)buffer; device->core = peripheral_address; device->device = peripheral_address + USB_OTG_DEVICE_BASE; usb1_device = device; return device; } void usb_device_reset(void* device_ptr) { usb_device_t* device = (usb_device_t*)device_ptr; while ((device->core->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0); device->core->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; while (device->core->GRSTCTL & USB_OTG_GRSTCTL_CSRST); while ((device->core->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0); } void usb_device_clear_interrupts(void* device_ptr) { usb_device_t* device = (usb_device_t*)device_ptr; device->core->GINTSTS = 0; // clear interrupts // for other interrupts the rx queue has to be read } void usb_device_setup(void* device_ptr) { RCC->AHB1ENR |= RCC_AHB1ENR_USB1OTGHSEN | RCC_AHB1ENR_USB1OTGHSULPIEN; volatile uint32_t dummy; dummy = RCC->AHB1ENR; dummy = RCC->AHB1ENR; NVIC_SetPriority(OTG_FS_IRQn, 2); NVIC_EnableIRQ(OTG_FS_IRQn); // 1. core initialization usb_device_t* device = (usb_device_t*)device_ptr; RCC->AHB1ENR |= RCC_AHB1ENR_USB1OTGHSULPIEN | RCC_AHB1ENR_USB1OTGHSEN; /* PWR->CR3 |= PWR_CR3_USBREGEN; */ /* while ((PWR->CR3 & PWR_CR3_USB33RDY) == 0); */ device->core->GCCFG |= USB_OTG_GCCFG_PWRDWN; device->core->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; // global interrupt mask // rx fifo non empty // periodic tx fifo empty level usb_device_clear_interrupts(device_ptr); device->core->GAHBCFG = USB_OTG_GAHBCFG_GINT | USB_OTG_GAHBCFG_TXFELVL | USB_OTG_GAHBCFG_HBSTLEN_2; // hnp capable, srp capable, otg hs timeout, usb turnaround // TODO: based on enumeration speed set TOCAL - fs timeout calibration device->core->GUSBCFG = USB_OTG_GUSBCFG_FDMOD | USB_OTG_GUSBCFG_ULPIEVBUSI | USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_TRDT_3 | USB_OTG_GUSBCFG_TRDT_2; // unmask otg interrupt mask device->core->GINTMSK |= USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_MMISM; // device initialization // descdma, device speed, non-zero-length status out handshake, periodic frame interval device->device->DCFG = 0; // TODO device threshold control register IF DMA usb_device_reset(device_ptr); // sdis bit device->device->DCTL = ~(USB_OTG_DCTL_SDIS); // unmask interrupts usb reset, enumeration done, early suspend, usb suspend, sof device->core->GINTMSK |= USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_RSTDEM | USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ESUSPM | USB_OTG_GINTMSK_SOFM; // wait for usbrst interrupt - the reset while (((device->core->GINTSTS) & USB_OTG_GINTSTS_USBRST) == 0) {} // wait for enumdne interrupt - end of reset while (((device->core->GINTSTS) & USB_OTG_GINTSTS_ENUMDNE) == 0) {} } void otg_hs_handler(void) { }