169 lines
7.4 KiB
C
169 lines
7.4 KiB
C
#ifndef CORE_USB_USB_DRIVER
|
|
#define CORE_USB_USB_DRIVER
|
|
|
|
// #include "utils/gen_queue.h"
|
|
|
|
#include "usb_common_types.h"
|
|
|
|
// #define USBDBGMSG
|
|
|
|
#define USB_NUM_OF_ENDPOINTS (4)
|
|
|
|
#define USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS (64)
|
|
#define USB_MAX_FS_PCKT_SIZE_ISOCHRONOUS (1023)
|
|
|
|
#define USB_MIN_EP_FIFO_SIZE (64)
|
|
|
|
// Unfortunately this cannot be enabled, since the USB controller
|
|
// generates such enormous amounts of interrupts, so that no other
|
|
// task can run along the USB processing.
|
|
#define USB_EVENT_PROCESSING_IN_OS_THREAD (0)
|
|
|
|
#if USB_EVENT_PROCESSING_IN_OS_THREAD
|
|
#include <cmsis_os2.h>
|
|
#endif
|
|
|
|
// endpoint configuration structure
|
|
typedef struct {
|
|
uint16_t max_packet_size; // maximum packet size
|
|
bool8_t responding_NAK; // indicates if endpoint responds with NAK
|
|
uint8_t type; // endpoint type
|
|
uint8_t service_interval; // service interval
|
|
|
|
// calculated values
|
|
|
|
uint8_t is_configured; // the endpoint is in use
|
|
uint16_t fifo_address; // address in the FIFO
|
|
uint16_t fifo_size; // FIFO size
|
|
bool8_t auto_zlp; // automatically insert ZLP packets
|
|
bool8_t zlp_next; // indicates, that ZLP should be transmitted at the end of the current transfer (for IN endpoints)
|
|
bool8_t autoarm; // automatically arm endpoint (for OUT endpoints)
|
|
//bool8_t txp; // transfer in progress
|
|
} USBDRV_EpConfig;
|
|
|
|
typedef enum {
|
|
USB_FSM_INITIAL_WAIT_SPEEDNEG = 0, // initial state, right after reset, wait for speed negotiation, must be ZERO!
|
|
USB_FSM_SETUP_OPERATE, // ready to perform setup operations
|
|
} USBDRV_FsmState;
|
|
|
|
typedef enum {
|
|
USB_EVT_USB_RESET, // bus reset received
|
|
USB_EVT_SPEEDNEG_DONE, // linespeed negotiation (ST calls "enumeration") done
|
|
USB_EVT_RECEPTION_DONE, // received packet is waiting to be fetched from the Rx FIFO
|
|
USB_EVT_OUT_DONE, // something has happened on an OUT endpoint
|
|
USB_EVT_IN_DONE, // previously armed IN endpoint has finished packet transmission
|
|
} USBDRV_EventCode;
|
|
|
|
// endpoint event
|
|
typedef enum {
|
|
USB_EPEVT_IDLE = 0x00, // endpoint is IDLE
|
|
USB_EPEVT_ARMED, // endpoint is armed for transmission
|
|
USB_EPEVT_STALLED, // endpoint is stalled
|
|
USB_EPEVT_NAK // endpoint responds NAK regardless of FIFO level
|
|
} USBDRV_EndpointEvent;
|
|
|
|
// USB device state
|
|
typedef struct {
|
|
USBDRV_EpConfig ep_OUT[USB_NUM_OF_ENDPOINTS]; // OUT endpoint configs
|
|
USBDRV_EpConfig ep_IN[USB_NUM_OF_ENDPOINTS]; // IN endpoint configs
|
|
uint16_t rx_fifo_size; // Rx FIFO size in bytes
|
|
uint16_t state; // FSM state
|
|
uint8_t *rx_buf; // pointer to the receive buffer (this way declaration can be separated)
|
|
uint16_t rx_buf_level; // fill level of the rx buffer
|
|
uint8_t address; // device address
|
|
#if USB_EVENT_PROCESSING_IN_OS_THREAD
|
|
osMessageQueueId_t event_queue; // event queue
|
|
osThreadId_t th; // event processing thread
|
|
#endif
|
|
} USBDRV_GlobalState;
|
|
|
|
// USB received packet status
|
|
typedef enum { USB_PCKT_STATUS_GLOBAL_OUT_NAK = 0b0001,
|
|
USB_PCKT_STATUS_OUT_DATA_RECV = 0b0010,
|
|
USB_PCKT_STATUS_OUT_TRANSFER_CPLT = 0b0011,
|
|
USB_PCKT_STATUS_SETUP_CPLT = 0b0100,
|
|
USB_PCKT_STATUS_SETUP_DATA_RECV = 0b0110,
|
|
} USBDRV_PcktStatus;
|
|
|
|
#define USB_FLUSH_TX_FIFO_ALL (0b10000)
|
|
|
|
// event data
|
|
typedef union {
|
|
struct {
|
|
uint8_t pckt_status; // read packet status
|
|
uint8_t data_pid; // data PID
|
|
uint8_t byte_count; // byte count
|
|
uint8_t ep_num; // read endpoint number
|
|
} rx; // receive event data
|
|
} USBDRV_EventData;
|
|
|
|
// event compound for queueing
|
|
typedef struct {
|
|
uint32_t code; // event code
|
|
USBDRV_EventData data; // accompaining event data
|
|
} USBDRV_EventCompound;
|
|
|
|
// callback codes
|
|
typedef enum {
|
|
USB_CBC_OUT, // OUT done!
|
|
USB_CBC_IN_DONE, // IN done!
|
|
USB_CBC_IN_FIFOEMPTY, // could not serve IN request, since Tx FIFO was empty
|
|
} USBDRV_CallbackCode;
|
|
|
|
// callback compound
|
|
typedef struct {
|
|
uint8_t ep : 4; // endpoint number
|
|
uint8_t dir : 1; // direction
|
|
uint8_t code : 3; // event code
|
|
uint16_t size; // data size
|
|
const uint8_t *data; // data
|
|
} USBDRV_CallbackCompound;
|
|
|
|
typedef enum { UST_SETUP,
|
|
UST_DATA } USBDRV_ControlTfStage;
|
|
|
|
// ------------
|
|
|
|
void usbdrv_gpio_init(); // USB pin low level, early peripheral initialization
|
|
void usbdrv_init_global_state(); // initialize global state
|
|
void usbdrv_periph_init(); // initialize USB peripheral
|
|
void usbdrv_initial_ep0_setup(); // create an initial setup for EP0 in both directions
|
|
void usbdrv_power_and_connect(bool en); // connect to or disconnect from the bus
|
|
|
|
void usbdrv_init(); // initialize USB subsystem
|
|
void usbdrv_reset(); // reset USB subsystem
|
|
|
|
void usbdrv_preload_endpoint_config(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *cfg); // preload usb endpoint config
|
|
void usbdrv_clear_endpoint_config(); // clear endpoint config
|
|
void usbdrv_apply_endpoint_config(); // apply preloaded endpoint configuration
|
|
void usbdrv_build_fifo(); // build FIFO (compute addresses)
|
|
|
|
void usbdrv_fetch_endpoint_configuration(uint8_t config_index); // fetch endpoint configuration from descriptor dump
|
|
void usbdrv_configure_endpoint(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *cfg); // configure USB endpoint
|
|
void usbdrv_deconfigure_endpoint(uint8_t ep, uint8_t dir); // deconfigure USB endpoint
|
|
void usbdrv_stall_endpoint(uint8_t ep, uint8_t dir, bool stall); // stall endpoint
|
|
void usbdrv_set_global_NAK(uint8_t dir, bool en); // set global NAK
|
|
|
|
void usbdrv_flush_tx_fifo(uint8_t n); // flush specific or all Tx FIFOs
|
|
void usbdrv_flush_rx_fifo(); // flush the Rx FIFO
|
|
void usbdrv_set_rx_fifo_size(uint16_t size); // set Rx FIFO size
|
|
|
|
void usbdrv_fetch_received_data(uint8_t ep, uint16_t len); // fetch received data from RX FIFO to receive buffer
|
|
void usbdrv_process_rx_fifo_top(USBDRV_EventData *evt_data); // see what's on top of Rx FIFO
|
|
|
|
uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len); // write data to specific endpoint FIFO
|
|
#define USBDRV_ARM_IN_ZLP(ep) usbdrv_arm_IN_endpoint((ep), NULL, 0)
|
|
uint32_t usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size); // arm OUT endpoint, returned with the actual armed size (capped by the max packet size on that endpoint)
|
|
void usbdrv_autoarm_OUT_endpoint(uint8_t ep); // automatically re-arm OUT endpoint at the and of the current OUT transfer
|
|
void usbdrv_enable_autozlp(uint8_t ep, bool en); // enable or disable automatic ZLP appending to the transaction
|
|
|
|
bool usbdrv_get_endpoint_interrupt_flag(uint8_t ep, uint8_t dir); // get endpoint interrupt flag
|
|
|
|
void usbdrv_set_address(uint8_t addr); // set device address
|
|
|
|
void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data); // process USB event
|
|
void usbdrv_push_event(uint32_t evt_code, USBDRV_EventData *evt_data); // push event onto the event queue
|
|
void usbdrv_periodic_processing(); // call this to process incoming events
|
|
|
|
#endif /* CORE_USB_USB_DRIVER */
|