Files
AC707N/SDK/apps/common/device/usb/usb_epbuf_manager.c
2025-12-03 11:12:34 +08:00

195 lines
5.3 KiB
C

#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".usb.data.bss")
#pragma data_seg(".usb.data")
#pragma code_seg(".usb.text")
#pragma const_seg(".usb.text.const")
#pragma str_literal_override(".usb.text.const")
#endif
#include "usb_config.h"
#include "init.h"
#include "app_config.h"
#include "lbuf.h"
#define LOG_TAG_CONST USB
#define LOG_TAG "[USB]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#if TCFG_USB_HOST_ENABLE || TCFG_USB_SLAVE_ENABLE
#ifndef USB_HW_20
#if (FUSB_MODE == 0)
#error "USB1.1 IP is not support high-speed mode"
#endif
#endif
#define USB_DMA_BUF_ALIGN (8)
//附加的字节数用于ep rx接收crc(占用4字节,dual buf则8字节)以及分配lbuf头信息
//占用。lbuf头结构体20字节,假设需要8对齐,需要占用24字节,另外分配出来的头+buf
//总长度也需要8对齐,in/out ep各调用1次所以要留2份。
#define TO_ALIGN(size, align) (((size) & ((align) - 1)) ? ((align) - ((size) & ((align) - 1))) : 0)
#define _APPEND(size, align, eps) ((size) + TO_ALIGN(size, align) + 24 * (eps) + 8)
#define APPEND(size, eps) _APPEND(size, USB_DMA_BUF_ALIGN, eps)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~ usb slave begin ~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#if TCFG_USB_SLAVE_MSD_ENABLE
#define MSD_DMA_SIZE APPEND(MAXP_SIZE_BULKOUT * 2, 1)
#else
#define MSD_DMA_SIZE 0
#endif
#if TCFG_USB_SLAVE_HID_ENABLE
#define HID_DMA_SIZE APPEND(64, 2)
#else
#define HID_DMA_SIZE 0
#endif
#if TCFG_USB_CUSTOM_HID_ENABLE
#define CUSTOM_HID_DMA_SIZE APPEND(64 * 2, 2)
#else
#define CUSTOM_HID_DMA_SIZE 0
#endif
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
#if USB_EP_PROTECT
#define AUDIO_SPK_DMA_SIZE APPEND(1024, 1)
#else
#define AUDIO_SPK_DMA_SIZE APPEND(192, 1)
#endif
#else
#define AUDIO_SPK_DMA_SIZE 0
#endif
#if TCFG_USB_SLAVE_AUDIO_MIC_ENABLE
#define AUDIO_MIC_DMA_SIZE APPEND(192, 1)
#else
#define AUDIO_MIC_DMA_SIZE 0
#endif
#if TCFG_USB_SLAVE_CDC_ENABLE
#if CDC_INTR_EP_ENABLE
#define CDC_DMA_SIZE APPEND(64 * 4, 3) //bulk: 64x2+64 + intr: 64
#else
#define CDC_DMA_SIZE APPEND(64 * 3, 2) //bulk: 64x2+64
#endif
#else
#define CDC_DMA_SIZE 0
#endif
#define USB_DEVICE_DMA_BUF_MAX_SIZE (HID_DMA_SIZE + AUDIO_SPK_DMA_SIZE + AUDIO_MIC_DMA_SIZE + MSD_DMA_SIZE + CDC_DMA_SIZE + CUSTOM_HID_DMA_SIZE)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~ usb slave end ~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~ usb host begin ~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#if TCFG_UDISK_ENABLE
#define H_MSD_DMA_SIZE APPEND(MAXP_SIZE_BULKOUT * 2 + MAXP_SIZE_BULKIN, 2)
#else
#define H_MSD_DMA_SIZE 0
#endif
#if TCFG_HID_HOST_ENABLE
#define H_HID_DMA_SIZE APPEND(64, 1)
#else
#define H_HID_DMA_SIZE 0
#endif
#if TCFG_AOA_ENABLE
#define H_AOA_DMA_SIZE APPEND(64 + 64, 2)
#else
#define H_AOA_DMA_SIZE 0
#endif
#if TCFG_ADB_ENABLE
#define H_ADB_DMA_SIZE APPEND(64 + 64, 2)
#else
#define H_ADB_DMA_SIZE 0
#endif
#if TCFG_HOST_AUDIO_ENABLE
#define H_AUDIO_DMA_SIZE APPEND(192 + 192, 2)
#else
#define H_AUDIO_DMA_SIZE 0
#endif
#define USB_HOST_DMA_BUF_MAX_SIZE (H_MSD_DMA_SIZE + H_HID_DMA_SIZE + H_AOA_DMA_SIZE + H_ADB_DMA_SIZE + H_AUDIO_DMA_SIZE)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~ usb host end ~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#ifndef USB_DMA_BUF_MAX_SIZE
#if (USB_DEVICE_DMA_BUF_MAX_SIZE >= USB_HOST_DMA_BUF_MAX_SIZE)
#define USB_DMA_BUF_MAX_SIZE USB_DEVICE_DMA_BUF_MAX_SIZE
#else
#define USB_DMA_BUF_MAX_SIZE USB_HOST_DMA_BUF_MAX_SIZE
#endif
#endif//USB_DMA_BUF_MAX_SIZE
static u8 ep0_dma_buffer[USB_MAX_HW_NUM][64 + 4] __attribute__((aligned(4)));
#if USB_EPBUF_ALLOC_USE_LBUF
//除了lbuf分配的每份buf之和,还有留一些给lbuf自身
static u8 usb_dma_buf[USB_DMA_BUF_MAX_SIZE + 48] SEC(.usb.data.bss.exchange) __attribute__((aligned(USB_DMA_BUF_ALIGN)));
struct lbuff_head *usb_dma_lbuf = NULL;
int usb_memory_init(void)
{
usb_dma_lbuf = lbuf_init(usb_dma_buf, sizeof(usb_dma_buf), USB_DMA_BUF_ALIGN, 0);
log_info("%s() total dma size %d @%x", __func__, sizeof(usb_dma_buf), usb_dma_buf);
return 0;
}
//early_initcall(usb_memory_init);
void *usb_epbuf_alloc(const usb_dev usb_id, u32 ep, u32 size)
{
if ((ep & 0xf) == 0) {
return ep0_dma_buffer[usb_id];
}
if (ep & USB_DIR_IN) {
size += 8; //fusb的rx,需要额外4字节存放接收的crc,使用ping-pong buffer就需要两份,即4 x 2
}
return lbuf_alloc(usb_dma_lbuf, size);
}
void usb_epbuf_free(const usb_dev usb_id, void *buf)
{
if (buf == ep0_dma_buffer[usb_id]) {
return;
}
lbuf_free(buf);
}
#else /* USB_EPBUF_ALLOC_USE_LBUF */
void *usb_epbuf_alloc(const usb_dev usb_id, u32 ep, u32 size)
{
if ((ep & 0xf) == 0) {
return ep0_dma_buffer[usb_id];
}
if (ep & USB_DIR_IN) {
size += 8; //fusb的rx,需要额外4字节存放接收的crc,使用ping-pong buffer就需要两份,即4 x 2
}
return dma_malloc(size);
}
void usb_epbuf_free(const usb_dev usb_id, void *buf)
{
if (buf == ep0_dma_buffer[usb_id]) {
return;
}
dma_free(buf);
}
#endif
#endif