- doxygen styling added - CDC -> ACM refactor - type refactoring - examples categorized - flatUSB_config.h examples added
335 lines
9.2 KiB
C
335 lines
9.2 KiB
C
#ifndef STM32_USB_DRV
|
|
#define STM32_USB_DRV
|
|
|
|
#include "common_defs.h"
|
|
|
|
#include "../../usb_common_types.h"
|
|
|
|
#include "../../usb_driver_common.h"
|
|
|
|
// number of supported endpoints
|
|
#define USB_NUM_OF_ENDPOINTS (6) // set it to the maximum that this type of module can support
|
|
|
|
// non isochronous transfers
|
|
#define USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS (64)
|
|
#define USB_MAX_HS_PCKT_SIZE_NON_ISOCHRONOUS (512)
|
|
|
|
// isochronous transfers
|
|
#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 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)
|
|
} 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;
|
|
|
|
// ------------
|
|
|
|
/**
|
|
* Fully initialize USB driver.
|
|
*/
|
|
void usbdrv_init();
|
|
|
|
/**
|
|
* Reset USB driver.
|
|
*/
|
|
void usbdrv_reset();
|
|
|
|
/**
|
|
* Init driver's global state.
|
|
*/
|
|
void usbdrv_init_global_state();
|
|
|
|
/**
|
|
* Initialize driver interface.
|
|
*/
|
|
void usbdrv_init_intf();
|
|
|
|
/**
|
|
* USB peripheral initialization.
|
|
*
|
|
* @param reset only perform an after-reset reinitialization
|
|
*/
|
|
void usbdrv_periph_init(bool reset);
|
|
|
|
/**
|
|
* Flush specific TX FIFO.
|
|
*
|
|
* @param n index of the TX FIFO
|
|
*/
|
|
void usbdrv_flush_tx_fifo(uint8_t n);
|
|
|
|
/**
|
|
* Flush all RX FIFOs.
|
|
*/
|
|
void usbdrv_flush_rx_fifo();
|
|
|
|
/**
|
|
* Power down or up the USB peripheral. Also control built-in transciever.
|
|
*
|
|
* @param en power on/off
|
|
*/
|
|
void usbdrv_power_and_connect(bool en);
|
|
|
|
/**
|
|
* Configure USB Endpoint.
|
|
*
|
|
* @param ep index of the endpoint
|
|
* @param dir direction of the endpoint to be configured
|
|
* @param cfg pointer to the configuration details
|
|
*/
|
|
void usbdrv_configure_endpoint(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *cfg);
|
|
|
|
/**
|
|
* Deconfigure a specific USB Endpoint.
|
|
*
|
|
* @param ep index of the endpoint
|
|
* @param dir direction of the endpoint to be deconfigured
|
|
*/
|
|
void usbdrv_deconfigure_endpoint(uint8_t ep, uint8_t dir);
|
|
|
|
/**
|
|
* Stall a particular USB Endpoint.
|
|
*
|
|
* @param ep index of the endpoint to be stalled
|
|
* @param dir direction of the endpoint
|
|
* @param stall enable/disable stalling
|
|
*/
|
|
void usbdrv_stall_endpoint(uint8_t ep, uint8_t dir, bool stall);
|
|
|
|
/**
|
|
* Implement or rescind responding NAK globally in the chosen direction.
|
|
*
|
|
* @param dir communication direction
|
|
* @param en enable/disable NAK responses
|
|
*/
|
|
void usbdrv_set_global_NAK(uint8_t dir, bool en);
|
|
|
|
/**
|
|
* Fetch data corresponding to a single Endpoint.
|
|
*
|
|
* @param ep index of endpoint
|
|
* @param len maximum length of data to be fetched
|
|
*/
|
|
void usbdrv_fetch_received_data(uint8_t ep, uint16_t len);
|
|
|
|
/**
|
|
* Setup and prepare Endpoint to transfer data towards the host.
|
|
* May be called multiple times in a single transmission, since
|
|
* large messages do not have to fit into a single buffer.
|
|
*
|
|
* @param ep index of the Endpoint
|
|
* @param data pointer to the data
|
|
* @param len length of the data to be read
|
|
* @return number of bytes read from the data buffer
|
|
*/
|
|
uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len);
|
|
|
|
/**
|
|
* Prepare Endpoint to expect data reception from the host.
|
|
*
|
|
* @param ep index of the Endpoint
|
|
* @param size expected reception length
|
|
* @return message length that the endpoint can support during next reception
|
|
*/
|
|
uint32_t usbdrv_arm_OUT_endpoint(uint8_t ep, uint16_t size);
|
|
|
|
/**
|
|
* Enable or disable OUT Endpoint auto arming.
|
|
* Right after a transaction completes the USB core
|
|
* automatically prepares the endpoint for the next
|
|
* reception if this feature is enabled.
|
|
*
|
|
* @param ep index of the Endpoint
|
|
*/
|
|
void usbdrv_autoarm_OUT_endpoint(uint8_t ep);
|
|
|
|
/**
|
|
* Mask or unmask Endpoint interrupt generation.
|
|
*
|
|
* @param ep index of the Endpoint
|
|
* @param dir direction of the Endpoint
|
|
* @param en enable/disable interrupt
|
|
*/
|
|
void usbdrv_enable_endpoint_interrupt(uint8_t ep, uint8_t dir, bool en);
|
|
|
|
/**
|
|
* Set the shared FIFO size for all receptions.
|
|
* (Shared among all OUT endpoints.)
|
|
* Size of multiple of 4 are recommended. Values
|
|
* not obeying this will be rounded up.
|
|
*
|
|
* @param size FIFO size in BYTES
|
|
*/
|
|
void usbdrv_set_rx_fifo_size(uint16_t size);
|
|
|
|
/**
|
|
* Preload Endpoint config. Do not write configuration
|
|
* to the hardware right away, just buffer them in.
|
|
*
|
|
* @param ep index of the Endpoint
|
|
* @param dir direction of the Endpint
|
|
* @param cfg pointer to Endpoint configuration
|
|
*/
|
|
void usbdrv_preload_endpoint_config(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *cfg);
|
|
|
|
/**
|
|
* Clear ALL Endpoints' preload configurations.
|
|
* Does NOT clear configuration in the hardware!
|
|
*/
|
|
void usbdrv_clear_endpoint_config();
|
|
|
|
/**
|
|
* Apply preloaded Endpoint configuration, write
|
|
* Endpoint config to the hardware.
|
|
*/
|
|
void usbdrv_apply_endpoint_config();
|
|
|
|
/**
|
|
* Select a specific configuration from the descriptor
|
|
* dump, preload Endpoint settings and finally apply them.
|
|
*
|
|
* @param config_index configuration index
|
|
*/
|
|
void usbdrv_fetch_endpoint_configuration(uint8_t config_index);
|
|
|
|
/**
|
|
* Construct FIFO considering configured Endpoints.
|
|
*/
|
|
void usbdrv_build_fifo();
|
|
|
|
/**
|
|
* Apply an initial EP0 setup.
|
|
*/
|
|
void usbdrv_initial_ep0_setup();
|
|
|
|
/**
|
|
* Set USB device address.
|
|
*
|
|
* @param addr device address
|
|
*/
|
|
void usbdrv_set_address(uint8_t addr);
|
|
|
|
/**
|
|
* Get driver interface.
|
|
*
|
|
* @return pointer to the driver interface
|
|
*/
|
|
UsbDrv_DrvIntf *usbdrv_get_intf();
|
|
|
|
/**
|
|
* Register callback for IN transaction complete.
|
|
*
|
|
* @param ep index of the Endpoint
|
|
* @param cb pointer to the callback function
|
|
*/
|
|
void usbdrv_register_IN_complete_cb(uint8_t ep, UsbDrv_IN_cb cb);
|
|
|
|
/**
|
|
* Get Endpoint interrupt flag.
|
|
*
|
|
* @param ep index of the Endpoint
|
|
* @param dir direction of the Endpoint
|
|
* @return flag was set
|
|
*/
|
|
bool usbdrv_get_endpoint_interrupt_flag(uint8_t ep, uint8_t dir);
|
|
|
|
/**
|
|
* Process data on the RX FIFO top.
|
|
*
|
|
* @param evt_data pointer to event data target area
|
|
*/
|
|
void usbdrv_process_rx_fifo_top(USBDRV_EventData *evt_data);
|
|
|
|
/**
|
|
* Get the address table.
|
|
*
|
|
* @return immutable pointer to the address table
|
|
*/
|
|
const char *usbdrv_get_fifo_addr_table();
|
|
|
|
#endif /* STM32_USB_DRV */
|