flatUSB/driver/stm32/usb_drv.h
Epagris 2a69c57225 - basic docs added
- doxygen styling added
- CDC -> ACM refactor
- type refactoring
- examples categorized
- flatUSB_config.h examples added
2024-11-16 21:53:01 +01:00

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 */