mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-17 05:32:55 +08:00
implement dcd_edpt_iso_alloc/dcd_edpt_iso_activate for musb. video_capture example with iso kind of work but not smoothly. audio example does not seems to work as expected
This commit is contained in:
parent
e345380723
commit
8fdd8d9a7b
@ -15,6 +15,7 @@ set(LD_FILE_Clang ${LD_FILE_GNU})
|
||||
set(CMAKE_SYSTEM_PROCESSOR cortex-m4 CACHE INTERNAL "System Processor")
|
||||
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
|
||||
set(JLINK_DEVICE max32690)
|
||||
set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -f target/max32690.cfg")
|
||||
|
||||
set(FAMILY_MCUS MAX32690 CACHE INTERNAL "")
|
||||
|
||||
|
@ -518,7 +518,8 @@
|
||||
#define TU_ATTR_FAST_FUNC
|
||||
#endif
|
||||
|
||||
#if defined(TUP_USBIP_DWC2) || defined(TUP_USBIP_FSDEV)
|
||||
// USBIP that support ISO alloc & activate API
|
||||
#if defined(TUP_USBIP_DWC2) || defined(TUP_USBIP_FSDEV) || defined(TUP_USBIP_MUSB)
|
||||
#define TUP_DCD_EDPT_ISO_ALLOC
|
||||
#endif
|
||||
|
||||
|
@ -157,10 +157,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc
|
||||
// required for multiple configuration support.
|
||||
void dcd_edpt_close_all (uint8_t rhport);
|
||||
|
||||
// Close an endpoint.
|
||||
// Since it is weak, caller must TU_ASSERT this function's existence before calling it.
|
||||
void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK;
|
||||
|
||||
// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
|
||||
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes);
|
||||
|
||||
@ -175,12 +171,19 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr);
|
||||
// This API never calls with control endpoints, since it is auto cleared when receiving setup packet
|
||||
void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr);
|
||||
|
||||
#ifdef TUP_DCD_EDPT_ISO_ALLOC
|
||||
// Allocate packet buffer used by ISO endpoints
|
||||
// Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering
|
||||
TU_ATTR_WEAK bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size);
|
||||
bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size);
|
||||
|
||||
// Configure and enable an ISO endpoint according to descriptor
|
||||
TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep);
|
||||
bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep);
|
||||
|
||||
#else
|
||||
// Close an endpoint.
|
||||
void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr);
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Event API (implemented by stack)
|
||||
|
@ -1418,6 +1418,10 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) {
|
||||
* In progress transfers on this EP may be delivered after this call.
|
||||
*/
|
||||
void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
|
||||
#ifdef TUP_DCD_EDPT_ISO_ALLOC
|
||||
(void) rhport; (void) ep_addr;
|
||||
// ISO alloc/activate Should be used instead
|
||||
#else
|
||||
rhport = _usbd_rhport;
|
||||
|
||||
TU_ASSERT(dcd_edpt_close, /**/);
|
||||
@ -1430,6 +1434,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
|
||||
_usbd_dev.ep_status[epnum][dir].stalled = 0;
|
||||
_usbd_dev.ep_status[epnum][dir].busy = 0;
|
||||
_usbd_dev.ep_status[epnum][dir].claimed = 0;
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1452,21 +1457,24 @@ void usbd_sof_enable(uint8_t rhport, sof_consumer_t consumer, bool en) {
|
||||
}
|
||||
|
||||
bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
|
||||
#ifdef TUP_DCD_EDPT_ISO_ALLOC
|
||||
rhport = _usbd_rhport;
|
||||
|
||||
TU_ASSERT(dcd_edpt_iso_alloc);
|
||||
TU_ASSERT(tu_edpt_number(ep_addr) < CFG_TUD_ENDPPOINT_MAX);
|
||||
|
||||
return dcd_edpt_iso_alloc(rhport, ep_addr, largest_packet_size);
|
||||
#else
|
||||
(void) rhport; (void) ep_addr; (void) largest_packet_size;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) {
|
||||
#ifdef TUP_DCD_EDPT_ISO_ALLOC
|
||||
rhport = _usbd_rhport;
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(desc_ep->bEndpointAddress);
|
||||
uint8_t const dir = tu_edpt_dir(desc_ep->bEndpointAddress);
|
||||
|
||||
TU_ASSERT(dcd_edpt_iso_activate);
|
||||
TU_ASSERT(epnum < CFG_TUD_ENDPPOINT_MAX);
|
||||
TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed));
|
||||
|
||||
@ -1474,6 +1482,10 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep)
|
||||
_usbd_dev.ep_status[epnum][dir].busy = 0;
|
||||
_usbd_dev.ep_status[epnum][dir].claimed = 0;
|
||||
return dcd_edpt_iso_activate(rhport, desc_ep);
|
||||
#else
|
||||
(void) rhport; (void) desc_ep;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -94,64 +94,71 @@ static dcd_data_t _dcd;
|
||||
// First 64 bytes are reserved for EP0
|
||||
static uint32_t alloced_fifo_bytes;
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void fifo_reset(musb_regs_t* musb, unsigned epnum, unsigned dir_in) {
|
||||
// ffsize is log2(mps) - 3 (round up)
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t hwfifo_byte2size(uint16_t nbytes) {
|
||||
uint8_t ffsize = 28 - tu_min8(28, __builtin_clz(nbytes));
|
||||
// round up to the next power of 2
|
||||
if ((8u << ffsize) < nbytes) {
|
||||
++ffsize;
|
||||
}
|
||||
|
||||
return ffsize;
|
||||
}
|
||||
|
||||
// index register is already set
|
||||
TU_ATTR_ALWAYS_INLINE static inline void hwfifo_reset(musb_regs_t* musb, unsigned epnum, unsigned dir_in) {
|
||||
(void) epnum;
|
||||
const uint8_t is_rx = 1 - dir_in;
|
||||
musb->index = epnum;
|
||||
musb->fifo_size[is_rx] = 0;
|
||||
musb->fifo_addr[is_rx] = 0;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool fifo_configure(musb_regs_t* musb, unsigned epnum, unsigned dir_in, unsigned mps) {
|
||||
// ffsize is log2(mps) - 3 (round up)
|
||||
uint8_t ffsize = 28 - tu_min8(28, __builtin_clz(mps));
|
||||
// round up to the next power of 2
|
||||
if ((8u << ffsize) < mps) {
|
||||
++ffsize;
|
||||
mps = 8 << ffsize;
|
||||
// index register is already set
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsigned epnum, unsigned dir_in, unsigned mps, bool double_packet) {
|
||||
(void) epnum;
|
||||
uint8_t ffsize = hwfifo_byte2size(mps);
|
||||
mps = 8 << ffsize; // round up to the next power of 2
|
||||
|
||||
if (double_packet) {
|
||||
ffsize |= MUSB_FIFOSZ_DOUBLE_PACKET;
|
||||
mps <<= 1;
|
||||
}
|
||||
|
||||
TU_ASSERT(alloced_fifo_bytes + mps <= MUSB_CFG_DYNAMIC_FIFO_SIZE);
|
||||
const uint8_t is_rx = 1 - dir_in;
|
||||
musb->index = epnum;
|
||||
|
||||
musb->fifo_addr[is_rx] = alloced_fifo_bytes / 8;
|
||||
musb->fifo_size[is_rx] = ffsize;
|
||||
|
||||
alloced_fifo_bytes += mps;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
TU_ATTR_ALWAYS_INLINE static inline void fifo_reset(musb_regs_t* musb, unsigned epnum, unsigned dir_in) {
|
||||
const uint8_t is_rx = 1 - dir_in;
|
||||
musb->index = epnum;
|
||||
|
||||
#if defined(TUP_USBIP_MUSB_ADI)
|
||||
// Analog have custom double buffered in csrh register, disable it
|
||||
musb->indexed_csr.maxp_csr[is_rx].csrh |= MUSB_CSRH_DISABLE_DOUBLE_PACKET(is_rx);
|
||||
#else
|
||||
// disable double bufeffered in extended register
|
||||
#endif
|
||||
// index register is already set
|
||||
TU_ATTR_ALWAYS_INLINE static inline void hwfifo_reset(musb_regs_t* musb, unsigned epnum, unsigned dir_in) {
|
||||
(void) musb; (void) epnum; (void) dir_in;
|
||||
// nothing to do for static FIFO
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool fifo_configure(musb_regs_t* musb, unsigned epnum, unsigned dir_in, unsigned mps) {
|
||||
(void) mps;
|
||||
// index register is already set
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsigned epnum, unsigned dir_in, unsigned mps,
|
||||
bool double_packet) {
|
||||
(void) epnum; (void) dir_in; (void) mps;
|
||||
|
||||
if (!double_packet) {
|
||||
#if defined(TUP_USBIP_MUSB_ADI)
|
||||
const uint8_t is_rx = 1 - dir_in;
|
||||
musb->index = epnum;
|
||||
|
||||
uint8_t csrh = 0;
|
||||
|
||||
#if defined(TUP_USBIP_MUSB_ADI)
|
||||
csrh = MUSB_CSRH_DISABLE_DOUBLE_PACKET(is_rx);
|
||||
#endif
|
||||
|
||||
#if MUSB_CFG_SHARED_FIFO
|
||||
if (dir_in) {
|
||||
csrh |= MUSB_CSRH_TX_MODE;
|
||||
musb->indexed_csr.maxp_csr[is_rx].csrh |= MUSB_CSRH_DISABLE_DOUBLE_PACKET(is_rx);
|
||||
#else
|
||||
if (is_rx) {
|
||||
musb->rx_doulbe_packet_disable |= 1u << epnum;
|
||||
} else {
|
||||
musb->tx_double_packet_disable |= 1u << epnum;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
musb->indexed_csr.maxp_csr[is_rx].csrh |= csrh;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -538,8 +545,9 @@ static void process_bus_reset(uint8_t rhport) {
|
||||
|
||||
/* Clear FIFO settings */
|
||||
for (unsigned i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) {
|
||||
fifo_reset(musb, i, 0);
|
||||
fifo_reset(musb, i, 1);
|
||||
musb->index = i;
|
||||
hwfifo_reset(musb, i, 0);
|
||||
hwfifo_reset(musb, i, 1);
|
||||
}
|
||||
dcd_event_bus_reset(rhport, (musb->power & MUSB_POWER_HSMODE) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, true);
|
||||
}
|
||||
@ -641,17 +649,18 @@ void dcd_sof_enable(uint8_t rhport, bool en)
|
||||
//--------------------------------------------------------------------+
|
||||
// Endpoint API
|
||||
//--------------------------------------------------------------------+
|
||||
// static void edpt_setup(musb_regs_t* musb, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_size){
|
||||
// const unsigned epn = tu_edpt_number(ep_addr);
|
||||
// const unsigned dir_in = tu_edpt_dir(ep_addr);
|
||||
// }
|
||||
|
||||
// Configure endpoint's registers according to descriptor
|
||||
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) {
|
||||
const unsigned ep_addr = ep_desc->bEndpointAddress;
|
||||
const unsigned epn = tu_edpt_number(ep_addr);
|
||||
const unsigned dir_in = tu_edpt_dir(ep_addr);
|
||||
const unsigned xfer = ep_desc->bmAttributes.xfer;
|
||||
const unsigned mps = tu_edpt_packet_size(ep_desc);
|
||||
|
||||
TU_ASSERT(epn < TUP_DCD_ENDPOINT_MAX);
|
||||
|
||||
pipe_state_t *pipe = &_dcd.pipe[dir_in][epn - 1];
|
||||
pipe->buf = NULL;
|
||||
pipe->length = 0;
|
||||
@ -659,11 +668,16 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) {
|
||||
|
||||
musb_regs_t* musb = MUSB_REGS(rhport);
|
||||
musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn);
|
||||
|
||||
const uint8_t is_rx = 1 - dir_in;
|
||||
musb_ep_maxp_csr_t* maxp_csr = &ep_csr->maxp_csr[is_rx];
|
||||
|
||||
maxp_csr->maxp = mps;
|
||||
maxp_csr->csrh = (xfer == TUSB_XFER_ISOCHRONOUS) ? MUSB_RXCSRH1_ISO : 0;
|
||||
maxp_csr->csrh = 0;
|
||||
#if MUSB_CFG_SHARED_FIFO
|
||||
if (dir_in) {
|
||||
maxp_csr->csrh |= MUSB_CSRH_TX_MODE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// flush and reset data toggle
|
||||
uint8_t csrl = MUSB_CSRL_CLEAR_DATA_TOGGLE(is_rx);
|
||||
@ -672,18 +686,65 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) {
|
||||
}
|
||||
maxp_csr->csrl = csrl;
|
||||
|
||||
TU_ASSERT(hwfifo_config(musb, epn, dir_in, mps, false));
|
||||
musb->intren_ep[is_rx] |= TU_BIT(epn);
|
||||
|
||||
fifo_configure(musb, epn, dir_in, mps);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
|
||||
// }
|
||||
//
|
||||
// bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) {
|
||||
// }
|
||||
bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
|
||||
const unsigned epn = tu_edpt_number(ep_addr);
|
||||
const unsigned dir_in = tu_edpt_dir(ep_addr);
|
||||
musb_regs_t* musb = MUSB_REGS(rhport);
|
||||
musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn);
|
||||
const uint8_t is_rx = 1 - dir_in;
|
||||
ep_csr->maxp_csr[is_rx].csrh = 0;
|
||||
return hwfifo_config(musb, epn, dir_in, largest_packet_size, true);
|
||||
}
|
||||
|
||||
bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc ) {
|
||||
const unsigned ep_addr = ep_desc->bEndpointAddress;
|
||||
const unsigned epn = tu_edpt_number(ep_addr);
|
||||
const unsigned dir_in = tu_edpt_dir(ep_addr);
|
||||
const unsigned mps = tu_edpt_packet_size(ep_desc);
|
||||
|
||||
unsigned const ie = musb_dcd_get_int_enable(rhport);
|
||||
musb_dcd_int_disable(rhport);
|
||||
|
||||
pipe_state_t *pipe = &_dcd.pipe[dir_in][epn - 1];
|
||||
pipe->buf = NULL;
|
||||
pipe->length = 0;
|
||||
pipe->remaining = 0;
|
||||
|
||||
musb_regs_t* musb = MUSB_REGS(rhport);
|
||||
musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn);
|
||||
const uint8_t is_rx = 1 - dir_in;
|
||||
musb_ep_maxp_csr_t* maxp_csr = &ep_csr->maxp_csr[is_rx];
|
||||
|
||||
maxp_csr->maxp = mps;
|
||||
maxp_csr->csrh |= MUSB_CSRH_ISO;
|
||||
#if MUSB_CFG_SHARED_FIFO
|
||||
if (dir_in) {
|
||||
maxp_csr->csrh |= MUSB_CSRH_TX_MODE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// flush fifo
|
||||
if (maxp_csr->csrl & MUSB_CSRL_PACKET_READY(is_rx)) {
|
||||
maxp_csr->csrl = MUSB_CSRL_FLUSH_FIFO(is_rx);
|
||||
}
|
||||
|
||||
#if MUSB_CFG_DYNAMIC_FIFO
|
||||
// fifo space is already allocated, keep the address and just change packet size
|
||||
musb->fifo_size[is_rx] = hwfifo_byte2size(mps) | MUSB_FIFOSZ_DOUBLE_PACKET;
|
||||
#endif
|
||||
|
||||
musb->intren_ep[is_rx] |= TU_BIT(epn);
|
||||
|
||||
if (ie) musb_dcd_int_enable(rhport);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dcd_edpt_close_all(uint8_t rhport)
|
||||
{
|
||||
@ -707,7 +768,7 @@ void dcd_edpt_close_all(uint8_t rhport)
|
||||
}
|
||||
maxp_csr->csrl = csrl;
|
||||
|
||||
fifo_reset(musb, i, 1-d);
|
||||
hwfifo_reset(musb, i, 1-d);
|
||||
}
|
||||
}
|
||||
|
||||
@ -718,38 +779,6 @@ void dcd_edpt_close_all(uint8_t rhport)
|
||||
if (ie) musb_dcd_int_enable(rhport);
|
||||
}
|
||||
|
||||
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
// FIXME: we should implement iso_alloc() and iso_activate()
|
||||
unsigned const epn = tu_edpt_number(ep_addr);
|
||||
unsigned const dir_in = tu_edpt_dir(ep_addr);
|
||||
musb_regs_t* musb = MUSB_REGS(rhport);
|
||||
musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn);
|
||||
unsigned const ie = musb_dcd_get_int_enable(rhport);
|
||||
musb_dcd_int_disable(rhport);
|
||||
if (dir_in) {
|
||||
musb->intr_txen &= ~TU_BIT(epn);
|
||||
ep_csr->tx_maxp = 0;
|
||||
ep_csr->tx_csrh = 0;
|
||||
if (ep_csr->tx_csrl & MUSB_TXCSRL1_TXRDY) {
|
||||
ep_csr->tx_csrl = MUSB_TXCSRL1_CLRDT | MUSB_TXCSRL1_FLUSH;
|
||||
} else {
|
||||
ep_csr->tx_csrl = MUSB_TXCSRL1_CLRDT;
|
||||
}
|
||||
} else {
|
||||
musb->intr_rxen &= ~TU_BIT(epn);
|
||||
ep_csr->rx_maxp = 0;
|
||||
ep_csr->rx_csrh = 0;
|
||||
if (ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY) {
|
||||
ep_csr->rx_csrl = MUSB_RXCSRL1_CLRDT | MUSB_RXCSRL1_FLUSH;
|
||||
} else {
|
||||
ep_csr->rx_csrl = MUSB_RXCSRL1_CLRDT;
|
||||
}
|
||||
}
|
||||
fifo_reset(musb, epn, dir_in);
|
||||
if (ie) musb_dcd_int_enable(rhport);
|
||||
}
|
||||
|
||||
// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
|
||||
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
{
|
||||
@ -771,7 +800,8 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c
|
||||
// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack
|
||||
// - optional, however, must be listed in usbd.c
|
||||
bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
|
||||
{
|
||||
(void)rhport;
|
||||
|
@ -51,11 +51,6 @@ const uintptr_t MUSB_BASES[] = { USB0_BASE };
|
||||
// Header supports both device and host modes. Only include what's necessary
|
||||
#if CFG_TUD_ENABLED
|
||||
|
||||
// Mapping of peripheral instances to port. Currently just 1.
|
||||
static USB0_Type* const musb_periph_inst[] = {
|
||||
USB0
|
||||
};
|
||||
|
||||
// Mapping of IRQ numbers to port. Currently just 1.
|
||||
static const IRQn_Type musb_irqs[] = {
|
||||
USB0_IRQn
|
||||
@ -87,142 +82,6 @@ static inline void musb_dcd_int_handler_enter(uint8_t rhport) {
|
||||
//Nothing to do for this part
|
||||
}
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
uint_fast16_t beg; /* offset of including first element */
|
||||
uint_fast16_t end; /* offset of excluding the last element */
|
||||
} free_block_t;
|
||||
|
||||
static inline free_block_t *find_containing_block(free_block_t *beg, free_block_t *end, uint_fast16_t addr) {
|
||||
free_block_t *cur = beg;
|
||||
for (; cur < end && ((addr < cur->beg) || (cur->end <= addr)); ++cur) ;
|
||||
return cur;
|
||||
}
|
||||
|
||||
static inline int update_free_block_list(free_block_t *blks, unsigned num, uint_fast16_t addr, uint_fast16_t size) {
|
||||
free_block_t *p = find_containing_block(blks, blks + num, addr);
|
||||
TU_ASSERT(p != blks + num, -2);
|
||||
if (p->beg == addr) {
|
||||
/* Shrink block */
|
||||
p->beg = addr + size;
|
||||
if (p->beg != p->end) return 0;
|
||||
/* remove block */
|
||||
free_block_t *end = blks + num;
|
||||
while (p + 1 < end) {
|
||||
*p = *(p + 1);
|
||||
++p;
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
/* Split into 2 blocks */
|
||||
free_block_t tmp = {
|
||||
.beg = addr + size,
|
||||
.end = p->end
|
||||
};
|
||||
p->end = addr;
|
||||
if (p->beg == p->end) {
|
||||
if (tmp.beg != tmp.end) {
|
||||
*p = tmp;
|
||||
return 0;
|
||||
}
|
||||
/* remove block */
|
||||
free_block_t *end = blks + num;
|
||||
while (p + 1 < end) {
|
||||
*p = *(p + 1);
|
||||
++p;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (tmp.beg == tmp.end) return 0;
|
||||
blks[num] = tmp;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned free_block_size(free_block_t const *blk) {
|
||||
return blk->end - blk->beg;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static inline void print_block_list(free_block_t const *blk, unsigned num)
|
||||
{
|
||||
TU_LOG1("*************\r\n");
|
||||
for (unsigned i = 0; i < num; ++i) {
|
||||
TU_LOG1(" Blk%u %u %u\r\n", i, blk->beg, blk->end);
|
||||
++blk;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define print_block_list(a,b)
|
||||
#endif
|
||||
|
||||
static unsigned find_free_memory(uint8_t rhport, uint_fast16_t size_in_log2_minus3)
|
||||
{
|
||||
free_block_t free_blocks[2 * (TUP_DCD_ENDPOINT_MAX - 1)];
|
||||
unsigned num_blocks = 1;
|
||||
|
||||
/* Initialize free memory block list */
|
||||
free_blocks[0].beg = 64 / 8;
|
||||
free_blocks[0].end = (4 << 10) / 8; /* 4KiB / 8 bytes */
|
||||
for (int i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) {
|
||||
uint_fast16_t addr;
|
||||
int num;
|
||||
musb_periph_inst[rhport]->EPIDX = i;
|
||||
addr = musb_periph_inst[rhport]->TXFIFOADD;
|
||||
if (addr) {
|
||||
unsigned sz = musb_periph_inst[rhport]->TXFIFOSZ;
|
||||
unsigned sft = (sz & USB_TXFIFOSZ_SIZE_M) + ((sz & USB_TXFIFOSZ_DPB) ? 1: 0);
|
||||
num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft);
|
||||
TU_ASSERT(-2 < num, 0);
|
||||
num_blocks += num;
|
||||
print_block_list(free_blocks, num_blocks);
|
||||
}
|
||||
addr = musb_periph_inst[rhport]->RXFIFOADD;
|
||||
if (addr) {
|
||||
unsigned sz = musb_periph_inst[rhport]->RXFIFOSZ;
|
||||
unsigned sft = (sz & USB_RXFIFOSZ_SIZE_M) + ((sz & USB_RXFIFOSZ_DPB) ? 1: 0);
|
||||
num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft);
|
||||
TU_ASSERT(-2 < num, 0);
|
||||
num_blocks += num;
|
||||
print_block_list(free_blocks, num_blocks);
|
||||
}
|
||||
}
|
||||
print_block_list(free_blocks, num_blocks);
|
||||
|
||||
/* Find the best fit memory block */
|
||||
uint_fast16_t size_in_8byte_unit = 1 << size_in_log2_minus3;
|
||||
free_block_t const *min = NULL;
|
||||
uint_fast16_t min_sz = 0xFFFFu;
|
||||
free_block_t const *end = &free_blocks[num_blocks];
|
||||
for (free_block_t const *cur = &free_blocks[0]; cur < end; ++cur) {
|
||||
uint_fast16_t sz = free_block_size(cur);
|
||||
if (sz < size_in_8byte_unit) continue;
|
||||
if (size_in_8byte_unit == sz) return cur->beg;
|
||||
if (sz < min_sz) min = cur;
|
||||
}
|
||||
TU_ASSERT(min, 0);
|
||||
return min->beg;
|
||||
}
|
||||
|
||||
|
||||
static inline void musb_dcd_setup_fifo(uint8_t rhport, unsigned epnum, unsigned dir_in, unsigned mps)
|
||||
{
|
||||
int size_in_log2_minus3 = 28 - TU_MIN(28, __CLZ((uint32_t)mps));
|
||||
if ((8u << size_in_log2_minus3) < mps) ++size_in_log2_minus3;
|
||||
unsigned addr = find_free_memory(rhport, size_in_log2_minus3);
|
||||
TU_ASSERT(addr,);
|
||||
|
||||
musb_periph_inst[rhport]->EPIDX = epnum;
|
||||
if (dir_in) {
|
||||
musb_periph_inst[rhport]->TXFIFOADD = addr;
|
||||
musb_periph_inst[rhport]->TXFIFOSZ = size_in_log2_minus3;
|
||||
} else {
|
||||
musb_periph_inst[rhport]->RXFIFOADD = addr;
|
||||
musb_periph_inst[rhport]->RXFIFOSZ = size_in_log2_minus3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CFG_TUD_ENABLED
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -338,6 +338,10 @@ TU_ATTR_ALWAYS_INLINE static inline musb_ep_csr_t* get_ep_csr(musb_regs_t* musb_
|
||||
// 0x13, 0x17: TX/RX CSRH
|
||||
#define MUSB_CSRH_DISABLE_DOUBLE_PACKET(_rx) (1u << 1)
|
||||
#define MUSB_CSRH_TX_MODE (1u << 5) // 1 = TX, 0 = RX. only relevant for SHARED FIFO
|
||||
#define MUSB_CSRH_ISO (1u << 6)
|
||||
|
||||
// 0x62, 0x63: TXFIFO_SZ, RXFIFO_SZ
|
||||
#define MUSB_FIFOSZ_DOUBLE_PACKET (1u << 4)
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
@ -417,58 +421,6 @@ TU_ATTR_ALWAYS_INLINE static inline musb_ep_csr_t* get_ep_csr(musb_regs_t* musb_
|
||||
#define MUSB_CCONF_TXEDMA 0x0002 // TX Early DMA Enable
|
||||
#define MUSB_CCONF_RXEDMA 0x0001 // TX Early DMA Enable
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// The following are defines for the bit fields in the MUSB_O_TXFIFOSZ register.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define MUSB_TXFIFOSZ_DPB 0x0010 // Double Packet Buffer Support
|
||||
#define MUSB_TXFIFOSZ_SIZE_M 0x000F // Max Packet Size
|
||||
#define MUSB_TXFIFOSZ_SIZE_8 0x0000 // 8
|
||||
#define MUSB_TXFIFOSZ_SIZE_16 0x0001 // 16
|
||||
#define MUSB_TXFIFOSZ_SIZE_32 0x0002 // 32
|
||||
#define MUSB_TXFIFOSZ_SIZE_64 0x0003 // 64
|
||||
#define MUSB_TXFIFOSZ_SIZE_128 0x0004 // 128
|
||||
#define MUSB_TXFIFOSZ_SIZE_256 0x0005 // 256
|
||||
#define MUSB_TXFIFOSZ_SIZE_512 0x0006 // 512
|
||||
#define MUSB_TXFIFOSZ_SIZE_1024 0x0007 // 1024
|
||||
#define MUSB_TXFIFOSZ_SIZE_2048 0x0008 // 2048
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// The following are defines for the bit fields in the MUSB_O_RXFIFOSZ register.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define MUSB_RXFIFOSZ_DPB 0x0010 // Double Packet Buffer Support
|
||||
#define MUSB_RXFIFOSZ_SIZE_M 0x000F // Max Packet Size
|
||||
#define MUSB_RXFIFOSZ_SIZE_8 0x0000 // 8
|
||||
#define MUSB_RXFIFOSZ_SIZE_16 0x0001 // 16
|
||||
#define MUSB_RXFIFOSZ_SIZE_32 0x0002 // 32
|
||||
#define MUSB_RXFIFOSZ_SIZE_64 0x0003 // 64
|
||||
#define MUSB_RXFIFOSZ_SIZE_128 0x0004 // 128
|
||||
#define MUSB_RXFIFOSZ_SIZE_256 0x0005 // 256
|
||||
#define MUSB_RXFIFOSZ_SIZE_512 0x0006 // 512
|
||||
#define MUSB_RXFIFOSZ_SIZE_1024 0x0007 // 1024
|
||||
#define MUSB_RXFIFOSZ_SIZE_2048 0x0008 // 2048
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// The following are defines for the bit fields in the MUSB_O_TXFIFOADD
|
||||
// register.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define MUSB_TXFIFOADD_ADDR_M 0x01FF // Transmit/Receive Start Address
|
||||
#define MUSB_TXFIFOADD_ADDR_S 0
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// The following are defines for the bit fields in the MUSB_O_RXFIFOADD
|
||||
// register.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define MUSB_RXFIFOADD_ADDR_M 0x01FF // Transmit/Receive Start Address
|
||||
#define MUSB_RXFIFOADD_ADDR_S 0
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// The following are defines for the bit fields in the MUSB_O_ULPIVBUSCTL
|
||||
|
Loading…
x
Reference in New Issue
Block a user