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

60e864124ffe6c385a3cf779d8e87ea86b78c859 — Rutherther 4 months ago f4b4b64
feat: add rx data callback, increase tx fifo size
2 files changed, 44 insertions(+), 36 deletions(-)

M include/usb_device.h
M src/usb_device.c
M include/usb_device.h => include/usb_device.h +35 -2
@@ 38,6 38,29 @@ struct usb_class_header_t;
struct usb_device_t;
typedef struct usb_device_t usb_device_t;

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;
  uint8_t status_phase_start;
} packet_info_t;

/**
 * @struct usb_class_vtable_t
 * A vtable struct for usb class,


@@ 125,12 148,22 @@ typedef struct {
  void (*rxfifo_empty_callback)(usb_device_t* device, uint8_t endpoint);

/**
 * @brief Callback on transmission done - all data were sent from configured size.
 * @brief Callback on tx transmission done - all data were sent from configured size.
 * @param[in,out] device The usb device.
 * @param[in] endpoint The number of the endpoint.
 * @return Description
 */
  void (*transmit_done_callback)(usb_device_t* device, uint8_t endpoint);
  void (*tx_done_callback)(usb_device_t* device, uint8_t endpoint);

/**
 * @brief Callback on rx transmission done - all data were sent from configured size.
 * @param[in,out] device The usb device.
 * @param[in] endpoint The number of the endpoint.
 * @return Description
 */
  void (*rx_done_callback)(usb_device_t* device, uint8_t endpoint);

  void (*received_data_callback)(usb_device_t* device, packet_info_t* packet);

/**
 * @brief Callback on nak being effective.

M src/usb_device.c => src/usb_device.c +9 -34
@@ 130,29 130,6 @@ void usb_device_setup(void* device_ptr) {
  /* while (((device->core->GINTSTS) & USB_OTG_GINTSTS_ENUMDNE) == 0) {} */
}

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;
  uint8_t status_phase_start;
} packet_info_t;

task_result_t usb_handle_setup_command(usb_device_t *device, usb_setup_command_t* cmd) {
  task_result_t result = RES_ERROR;



@@ 459,7 436,7 @@ void usb_handle_rxflvl_int(usb_device_t *device) {
    if (packet_info.endpoint_num == 0) {
      usb_handle_rxflvl_control_int(device, &packet_info);
    } else {
      // TODO: ...
      device->vt.received_data_callback(device, &packet_info);
    }
  }



@@ 544,7 521,7 @@ void usb_handle_endpoint_in_int(usb_device_t* device) {
  if (interrupt_reg & USB_OTG_DIEPINT_XFRC) {
    // Transfer is completed.
    if (device->state == ENUMERATED) {
      device->vt.transmit_done_callback(device, ep_id);
      device->vt.rx_done_callback(device, ep_id);
    }

    if (ep_id == 0) {


@@ 606,10 583,10 @@ void usb_handle_endpoint_out_int(usb_device_t* device) {
    reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_B2BSTUP);
  }
  if (interrupt_reg & USB_OTG_DOEPINT_OTEPSPR) {
    // This is valid only for DATA phases where the host sends us data.
    // Those are not supported yet! After they are, here is the place to
    // set STALL or send zero length packet.
    // TODO: ack or stall the status phase?
    // TODO: is there someting to do? The data sending is usually handled prior
    //       to this, in handling of setup / data stages. Maybe it should be
    //       moved here instead, since it's possible other packet will be
    //       received in the meantime?
    reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_OTEPSPR);
  }
  if (interrupt_reg & USB_OTG_DOEPINT_OTEPDIS) {


@@ 633,7 610,7 @@ void usb_handle_endpoint_out_int(usb_device_t* device) {
    device->out[0].DOEPCTL = USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA;
    reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_XFRC);

    // TODO: handle data? - callback to device data handle?
    device->vt.rx_done_callback(device, ep_id);

    if (ep_id == 0) {
      usb_handle_setup(device, USB_GOT_ACK);


@@ 671,9 648,9 @@ void otg_hs_handler(void) {
    device->device->DIEPMSK |= USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPEACHMSK1_NAKM | USB_OTG_DIEPEACHMSK1_INEPNEM;

    // 512 bytes
    device->core->GRXFSIZ = 256 / 4;
    device->core->GRXFSIZ = 1024 / 4;
    // 64 bytes, beginning of ram
    device->core->DIEPTXF[0] = (0) << USB_OTG_TX0FSA_Pos | (128 / 4) << USB_OTG_TX0FD_Pos;
    device->core->DIEPTXF[0] = (0 << USB_OTG_DIEPTXF_INEPTXSA_Pos) | ((128 / 4) << USB_OTG_DIEPTXF_INEPTXFD_Pos);

    // 3 packets to receive as setup
    reg_write_bits_pos(&device->out->DOEPTSIZ, 3, USB_OTG_DOEPTSIZ_STUPCNT_Pos, 3);


@@ 691,7 668,6 @@ void otg_hs_handler(void) {
    // We do not need to know the speed, it can be either full speed or high
    // speed, both have maximum size 64 bytes. Only low speed or super high
    // speed would differ, but these are not supported!
    // TODO: does 0 mean 64 bits here??? This is NOT in the spec! It's in the spec only for out endpoint, not for the in one!!!
    reg_write_bits_pos(&device->in[0].DIEPCTL, 0, USB_OTG_DIEPCTL_MPSIZ_Pos, 0x7FFUL);

    device->in->DIEPCTL |= USB_OTG_DOEPCTL_SNAK;


@@ 728,7 704,6 @@ void otg_hs_handler(void) {
  }

  if (device->core->GINTSTS & (USB_OTG_GINTSTS_RXFLVL)) {
    // TODO
    usb_handle_rxflvl_int(device);
    return;
  }

Do not follow this link