~ruther/stm32h747i-disco-usb-image-viewer

fd50dee1a73f27372392f528cda343b258e16f99 — Rutherther 5 months ago 3b7f816
feat: receive setup packets
2 files changed, 99 insertions(+), 28 deletions(-)

M include/usb_device.h
M src/usb_device.c
M include/usb_device.h => include/usb_device.h +20 -9
@@ 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)

M src/usb_device.c => src/usb_device.c +79 -19
@@ 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;
  }


Do not follow this link