esp32-s2_dfu/src/portable/raspberrypi/rp2040/rp2040_usb.h

161 lines
4.5 KiB
C
Raw Normal View History

2021-01-20 02:52:07 +01:00
#ifndef RP2040_COMMON_H_
#define RP2040_COMMON_H_
#if defined(RP2040_USB_HOST_MODE) && defined(RP2040_USB_DEVICE_MODE)
#error TinyUSB device and host mode not supported at the same time
#endif
#include "common/tusb_common.h"
#include "pico.h"
#include "hardware/structs/usb.h"
#include "hardware/irq.h"
#include "hardware/resets.h"
#if defined(PICO_RP2040_USB_DEVICE_ENUMERATION_FIX) && !defined(TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX)
#define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX
#endif
#if false && !defined(NDEBUG)
#define pico_trace(format,args...) printf(format, ## args)
#else
#define pico_trace(format,...) ((void)0)
#endif
#if false && !defined(NDEBUG)
#define pico_info(format,args...) printf(format, ## args)
#else
#define pico_info(format,...) ((void)0)
#endif
#if false && !defined(NDEBUG)
#define pico_warn(format,args...) printf(format, ## args)
#else
#define pico_warn(format,...) ((void)0)
#endif
// Hardware information per endpoint
struct hw_endpoint
{
// Is this a valid struct
bool configured;
// Transfer direction (i.e. IN is rx for host but tx for device)
// allows us to common up transfer functions
bool rx;
uint8_t ep_addr;
uint8_t next_pid;
// Endpoint control register
io_rw_32 *endpoint_control;
// Buffer control register
io_rw_32 *buffer_control;
// Buffer pointer in usb dpram
uint8_t *hw_data_buf;
// Have we been stalled
bool stalled;
// Current transfer information
bool active;
uint16_t total_len;
uint16_t len;
2021-01-20 02:52:07 +01:00
// Amount of data with the hardware
uint16_t transfer_size;
2021-01-20 02:52:07 +01:00
// User buffer in main memory
uint8_t *user_buf;
// Data needed from EP descriptor
uint16_t wMaxPacketSize;
2021-01-20 02:52:07 +01:00
// Interrupt, bulk, etc
uint8_t transfer_type;
2021-02-26 08:05:08 +01:00
#if TUSB_OPT_HOST_ENABLED
// Only needed for host mode
bool last_buf;
// RP2040-E4: HOST BUG. Host will incorrect write status to top half of buffer
// control register when doing transfers > 1 packet
uint8_t buf_sel;
2021-01-20 02:52:07 +01:00
// Only needed for host
uint8_t dev_addr;
bool sent_setup;
// If interrupt endpoint
uint8_t interrupt_num;
#endif
2021-01-20 02:52:07 +01:00
};
void rp2040_usb_init(void);
void hw_endpoint_reset_transfer(struct hw_endpoint *ep);
void _hw_endpoint_xfer(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len, bool start);
void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep);
void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len);
void _hw_endpoint_xfer_sync(struct hw_endpoint *ep);
bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep);
void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask);
static inline uint32_t _hw_endpoint_buffer_control_get_value32(struct hw_endpoint *ep) {
return *ep->buffer_control;
}
static inline void _hw_endpoint_buffer_control_set_value32(struct hw_endpoint *ep, uint32_t value) {
return _hw_endpoint_buffer_control_update32(ep, 0, value);
}
static inline void _hw_endpoint_buffer_control_set_mask32(struct hw_endpoint *ep, uint32_t value) {
return _hw_endpoint_buffer_control_update32(ep, ~value, value);
}
static inline void _hw_endpoint_buffer_control_clear_mask32(struct hw_endpoint *ep, uint32_t value) {
return _hw_endpoint_buffer_control_update32(ep, ~value, 0);
}
static inline uintptr_t hw_data_offset(uint8_t *buf)
{
// Remove usb base from buffer pointer
return (uintptr_t)buf ^ (uintptr_t)usb_dpram;
}
extern const char *ep_dir_string[];
typedef union TU_ATTR_PACKED
{
uint16_t u16;
struct TU_ATTR_PACKED
{
uint16_t xfer_len : 10;
uint16_t available : 1;
uint16_t stall : 1;
uint16_t reset_bufsel : 1;
uint16_t data_toggle : 1;
uint16_t last_buf : 1;
uint16_t full : 1;
};
} rp2040_buffer_control_t;
TU_VERIFY_STATIC(sizeof(rp2040_buffer_control_t) == 2, "size is not correct");
static inline void print_bufctrl16(uint32_t __unused u16)
{
rp2040_buffer_control_t __unused bufctrl = {
.u16 = u16
};
TU_LOG(2, "len = %u, available = %u, stall = %u, reset = %u, toggle = %u, last = %u, full = %u\r\n",
bufctrl.xfer_len, bufctrl.available, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle, bufctrl.last_buf, bufctrl.full);
}
static inline void print_bufctrl32(uint32_t u32)
{
uint16_t u16;
u16 = u32 >> 16;
TU_LOG(2, "Buffer Control 1 0x%x: ", u16);
print_bufctrl16(u16);
u16 = u32 & 0x0000ffff;
TU_LOG(2, "Buffer Control 0 0x%x: ", u16);
print_bufctrl16(u16);
}
2021-01-20 02:52:07 +01:00
#endif