#include "usb_device.h"
#include <stdlib.h>
#include <stddef.h>
#include <stm32h747xx.h>
/* 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) {
}