[feat] add pc software for test usb device

This commit is contained in:
zhji 2025-03-30 21:34:42 +08:00
parent 6f891c902f
commit 821307d4c2
4 changed files with 105 additions and 14 deletions

View File

@ -44,17 +44,7 @@ extern "C" {
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
/** int usb_is_configured(void);
* @brief Given an endpoint configuration, returns true if the endpoint
* is transmitting data to the host (i.e. is an IN endpoint)
*
* @param ep, the endpoint configuration
* @return true
* @return false
*/
static inline int ep_is_tx(struct usb_endpoint_configuration *ep) {
return ep->descriptor->bEndpointAddress & USB_DIR_IN;
}
void usb_start_transfer(struct usb_endpoint_configuration *ep, uint8_t *buf, uint16_t len); void usb_start_transfer(struct usb_endpoint_configuration *ep, uint8_t *buf, uint16_t len);
void usb_device_init(struct usb_device_configuration *dev_config); void usb_device_init(struct usb_device_configuration *dev_config);
struct usb_endpoint_configuration *usb_get_endpoint_configuration(uint8_t addr); struct usb_endpoint_configuration *usb_get_endpoint_configuration(uint8_t addr);

View File

@ -12,13 +12,19 @@ static volatile int configured = 0;
// Global data buffer for EP0 // Global data buffer for EP0
static uint8_t ep0_buf[64]; static uint8_t ep0_buf[64];
int usb_is_configured(void)
{
return configured;
}
/** /**
* @brief Take a buffer pointer located in the USB RAM and return as an offset of the RAM. * @brief Take a buffer pointer located in the USB RAM and return as an offset of the RAM.
* *
* @param buf * @param buf
* @return uint32_t * @return uint32_t
*/ */
static inline uint32_t usb_buffer_offset(volatile uint8_t *buf) { static inline uint32_t usb_buffer_offset(volatile uint8_t *buf)
{
return (uint32_t) buf ^ (uint32_t) usb_dpram; return (uint32_t) buf ^ (uint32_t) usb_dpram;
} }
@ -97,6 +103,19 @@ uint8_t usb_prepare_string_descriptor(const unsigned char *str)
return bLength; return bLength;
} }
/**
* @brief Given an endpoint configuration, returns true if the endpoint
* is transmitting data to the host (i.e. is an IN endpoint)
*
* @param ep, the endpoint configuration
* @return true
* @return false
*/
static inline int ep_is_tx(struct usb_endpoint_configuration *ep)
{
return ep->descriptor->bEndpointAddress & USB_DIR_IN;
}
/** /**
* @brief Starts a transfer on a given endpoint. * @brief Starts a transfer on a given endpoint.
* *
@ -304,7 +323,8 @@ void usb_handle_setup_packet(void)
* *
* @param ep, the endpoint to notify. * @param ep, the endpoint to notify.
*/ */
static void usb_handle_ep_buff_done(struct usb_endpoint_configuration *ep) { static void usb_handle_ep_buff_done(struct usb_endpoint_configuration *ep)
{
uint32_t buffer_control = *ep->buffer_control; uint32_t buffer_control = *ep->buffer_control;
// Get the transfer length for this endpoint // Get the transfer length for this endpoint
uint16_t len = buffer_control & USB_BUF_CTRL_LEN_MASK; uint16_t len = buffer_control & USB_BUF_CTRL_LEN_MASK;

View File

@ -12,6 +12,8 @@ extern void ep0_out_handler(uint8_t *buf, uint16_t len);
void ep1_out_handler(uint8_t *buf, uint16_t len) void ep1_out_handler(uint8_t *buf, uint16_t len)
{ {
printf("RX %d bytes from host\n", len); printf("RX %d bytes from host\n", len);
buf[len] = 0;
printf("received data: %s\r\n", buf);
// Send data back to host // Send data back to host
struct usb_endpoint_configuration *ep = usb_get_endpoint_configuration(EP2_IN_ADDR); struct usb_endpoint_configuration *ep = usb_get_endpoint_configuration(EP2_IN_ADDR);
usb_start_transfer(ep, buf, len); usb_start_transfer(ep, buf, len);
@ -165,11 +167,16 @@ int main(void)
system_init(); system_init();
usb_device_init(&dev_config); usb_device_init(&dev_config);
while (usb_is_configured() == 0);
printf("enumed time: %ld\r\n", (uint32_t)timer_count_read());
// Get ready to rx from host
usb_start_transfer(usb_get_endpoint_configuration(EP1_OUT_ADDR), NULL, 64);
time_start = timer_count_read(); time_start = timer_count_read();
while (1) { while (1) {
time_stop = timer_count_read(); time_stop = timer_count_read();
if (time_stop - time_start > 3000 * 1000) { if (time_stop - time_start > 30 * 1000 * 1000) {
usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
reset_unreset_blocks_wait(RESETS_BLOCK_USBCTRL); reset_unreset_blocks_wait(RESETS_BLOCK_USBCTRL);
printf("time 1s, stop USB\r\n"); printf("time 1s, stop USB\r\n");

View File

@ -0,0 +1,74 @@
import usb.core
import usb.util
# USB设备参数
VENDOR_ID = 0x0000 # 替换为实际的VID
PRODUCT_ID = 0x0001 # 替换为实际的PID
OUT_ENDPOINT = 0x01 # EP1 OUT端点
IN_ENDPOINT = 0x82 # EP2 IN端点 (注意: IN端点通常最高位设为1)
MAX_FIFO_SIZE = 64 # 最大FIFO长度
def find_usb_device():
"""查找并返回指定的USB设备"""
dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)
if dev is None:
raise ValueError("设备未找到请检查连接或VID/PID")
return dev
def configure_device(dev):
"""配置USB设备"""
# 如果是Linux可能需要先detach内核驱动
# if dev.is_kernel_driver_active(0):
# dev.detach_kernel_driver(0)
# 设置配置
dev.set_configuration()
# 获取配置
cfg = dev.get_active_configuration()
intf = cfg[(0,0)]
print("设备配置成功")
return dev
def send_data(dev, data):
"""向OUT端点发送数据"""
if len(data) > MAX_FIFO_SIZE:
raise ValueError(f"数据长度超过最大FIFO大小({MAX_FIFO_SIZE}字节)")
# 发送数据到EP1 OUT
bytes_written = dev.write(OUT_ENDPOINT, data)
print(f"发送成功: {bytes_written} 字节")
return bytes_written
def receive_data(dev, max_length=MAX_FIFO_SIZE):
"""从IN端点接收数据"""
# 从EP2 IN读取数据
data = dev.read(IN_ENDPOINT, max_length)
print(f"接收成功: {len(data)} 字节")
return data
def main():
try:
# 查找并配置设备
dev = find_usb_device()
dev = configure_device(dev)
# 示例数据发送
test_data = b"Hello USB Device!" # 测试数据
send_data(dev, test_data)
# 示例数据接收
received_data = receive_data(dev)
print("接收到的数据:", received_data)
except usb.core.USBError as e:
print(f"USB错误: {e}")
except Exception as e:
print(f"错误: {e}")
finally:
# 释放设备
usb.util.dispose_resources(dev)
if __name__ == "__main__":
main()