@@ 1,12 1,13 @@
+#include <stm32h747xx.h>
+#include "usb.h"
+
#ifndef USB_DEVICE_H
#define USB_DEVICE_H
-//
-#include <stm32h747xx.h>
-
typedef enum {
// error states first so they are lowest
CONTROL_ERROR = -4,
+ UNKNOWN_CONTROL_COMMAND = -4,
ERROR = -3,
UNKNOWN_INTERRUPT = -2,
OTG_ERROR = -1, // shouldn't happen, since otg is not used
@@ 20,23 21,33 @@ typedef enum {
} usb_device_state_t;
typedef struct {
+ volatile uint32_t data[128];
+} usb_fifo_t;
+
+typedef struct {
+ usb_device_descriptor_t device_descriptor;
+ usb_configuration_descriptor_t configuration_descriptor;
+ usb_interface_descriptor_t interface_descriptor;
+ usb_endpoint_descriptor_t endpoint_descriptors[8];
+} usb_class_t;
+
+typedef struct {
USB_OTG_GlobalTypeDef *core;
USB_OTG_DeviceTypeDef *device;
USB_OTG_OUTEndpointTypeDef *out;
USB_OTG_INEndpointTypeDef *in;
+ usb_fifo_t *fifos;
+
uint8_t endpoint_count;
+ usb_class_t class;
+
usb_device_state_t state;
+ usb_setup_command_t received_setup_command;
} usb_device_t;
-struct usb_configuration_t;
-
-typedef struct {
-
-} usb_class_t;
-
// has configuration etc
#define USB_DEVICE_SIZE sizeof(usb_device_t)
@@ 1,4 1,5 @@
#include "usb_device.h"
+#include "usb.h"
#include <stdlib.h>
#include <stddef.h>
#include <stm32h747xx.h>
@@ 20,6 21,7 @@ void* usb_device_init(void* peripheral_address, usb_class_t* class, void* buffer
device->device = peripheral_address + USB_OTG_DEVICE_BASE;
device->out = peripheral_address + USB_OTG_OUT_ENDPOINT_BASE;
device->in = peripheral_address + USB_OTG_IN_ENDPOINT_BASE;
+ device->fifos = (usb_fifo_t*)(((uint8_t*)device->core) + USB_OTG_FIFO_BASE);
device->endpoint_count = 8;
// TODO: clarify how this should work...
@@ 112,26 114,83 @@ void usb_device_setup(void* device_ptr) {
/* while (((device->core->GINTSTS) & USB_OTG_GINTSTS_ENUMDNE) == 0) {} */
}
-void usb_handle_control_interrupt(usb_device_t *device) {
- uint32_t daint = device->device->DAINT;
+void usb_handle_endpoint_int(usb_device_t* device) {
+ device->core->GRXSTSP;
+ device->core->GRXFSIZ;
+}
- if (daint & (1 << USB_OTG_DAINT_IEPINT_Pos)) {
- // in (that means sending data)
- } else if (daint & (1 << USB_OTG_DAINT_OEPINT_Pos)) {
- // out (that means receiving data)
- } else {
- device->state = CONTROL_ERROR;
+typedef enum {
+ PACKET_GLOBAL_OUT_NAK = 1,
+ PACKET_OUT_DATA_PACKET_RCVD = 2,
+ PACKET_OUT_TRANSFER_COMPLETED = 3,
+ PACKET_SETUP_TRANSACTION_COMPLETED = 4,
+ PACKET_SETUP_DATA_PACKET_RECEIVED = 6,
+} packet_status_t;
+
+typedef enum {
+ DATA0 = 0,
+ DATA1 = 1,
+ DATA2 = 2,
+ MDATA = 3
+} packet_dpid_t;
+
+typedef struct {
+ packet_status_t packet_status;
+ packet_dpid_t dpid;
+ uint8_t byte_count;
+ uint8_t endpoint_num;
+} packet_info_t;
+
+void usb_handle_rxflvl_control_int(usb_device_t *device,
+ packet_info_t *packet_info) {
+ uint32_t dummy;
+ uint8_t data[64];
+ uint32_t *fifo = device->fifos[0].data;
+
+ if (packet_info->packet_status == PACKET_SETUP_TRANSACTION_COMPLETED) {
+
+ } else if (packet_info->packet_status == PACKET_SETUP_DATA_PACKET_RECEIVED) {
+ /* dummy = *fifo; // internal info */
+ // SAVE data
+ usb_generic_read((uint8_t*)&device->received_setup_command, 8, fifo);
+
+ // 00000000010000000000000000000000
+ // 00000000101010000000000000000000
+
+ dummy = *fifo; // the last that will trigger another interrupt
+ } else if (packet_info->byte_count != 0) {
+ usb_generic_read(data, packet_info->byte_count, fifo);
}
}
-void usb_handle_endpoint_interrupt(usb_device_t* device) {
- // TODO
-
- if ((device->state < ENUMERATED) || (device->device->DAINT & ((1 << USB_OTG_DAINT_IEPINT_Pos) | (1 << USB_OTG_DAINT_OEPINT_Pos)))) {
- usb_handle_control_interrupt(device);
- } else {
- // new data received, put it to application level?.
+void usb_handle_rxflvl_int(usb_device_t *device) {
+ // Disable the interrupt
+ reg_clear_bits(&device->core->GINTMSK, USB_OTG_GINTMSK_RXFLVLM);
+
+ /* uint32_t rx_data; */
+ /* while ((rx_data = device->core->GRXSTSP) != 0) { */
+ while (device->core->GINTSTS & USB_OTG_GINTSTS_RXFLVL) {
+ uint32_t status_data = device->core->GRXSTSP;
+
+ /* uint8_t status_phase_start = reg_read_bits_pos(&status_data, USB_OTG_GRXSTSP_STSPHST); */
+ packet_info_t packet_info = {
+ .packet_status = (packet_status_t)reg_read_bits_pos(&status_data, USB_OTG_GRXSTSP_PKTSTS_Pos, 0xF),
+ .dpid = (packet_dpid_t)reg_read_bits_pos(&status_data, USB_OTG_GRXSTSP_DPID_Pos, 0x3),
+ .byte_count = reg_read_bits_pos(&status_data, USB_OTG_GRXSTSP_BCNT_Pos, 0x7FF),
+ .endpoint_num = reg_read_bits_pos(&status_data, USB_OTG_GRXSTSP_EPNUM_Pos, 0xF),
+ };
+
+ if (packet_info.endpoint_num == 0) {
+ usb_handle_rxflvl_control_int(device, &packet_info);
+ } else {
+ // TODO: ...
+ }
}
+
+ // Read info about the endoint etc.
+
+ // Re-enable the interrupt
+ reg_set_bits(&device->core->GINTMSK, USB_OTG_GINTMSK_RXFLVLM);
}
// NOTE: this is irq handler
@@ 145,11 204,10 @@ void otg_hs_handler(void) {
reg_set_bits(&device->device->DOEPMSK, USB_OTG_GINTMSK_IEPINT | USB_OTG_GINTMSK_OEPINT);
// TODO: should this be done for ep 0 as well?
- for (int ep = 1; ep < device->endpoint_count; ep++) {
+ for (int ep = 0; ep < device->endpoint_count; ep++) {
USB_OTG_OUTEndpointTypeDef *out = device->out + ep;
out->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
}
-
device->device->DAINTMSK |= 1 << USB_OTG_DAINTMSK_IEPM_Pos;
device->device->DAINTMSK |= 1 << USB_OTG_DAINTMSK_OEPM_Pos;
@@ 180,6 238,8 @@ void otg_hs_handler(void) {
// speed would differ, but these are not supported!
reg_write_bits_pos(&device->in->DIEPCTL, 64, USB_OTG_DIEPCTL_MPSIZ_Pos, 0x7FFUL);
+ device->out->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
+
device->state = RESET_DONE;
// clear it
reg_set_bits(&device->core->GINTSTS, USB_OTG_GINTSTS_ENUMDNE);
@@ 211,13 271,13 @@ void otg_hs_handler(void) {
// Setup, data...
if (device->core->GINTSTS & (USB_OTG_GINTSTS_OEPINT | USB_OTG_GINTSTS_IEPINT)) {
// TODO
- usb_handle_endpoint_interrupt(device);
+ usb_handle_endpoint_int(device);
return;
}
if (device->core->GINTSTS & (USB_OTG_GINTSTS_RXFLVL)) {
// TODO
- usb_handle_endpoint_interrupt(device);
+ usb_handle_rxflvl_int(device);
return;
}