mirror of
https://github.com/hathach/tinyusb.git
synced 2025-02-14 09:39:50 +00:00
DA146xx: Allow transmitting of packets larger then 64 bytes
FIFO is limited to 64 bytes yet MCU is capable of transmitting larger packets provided that FIFO will be filled on the fly and USB_USB_TXCx_REG_USB_LAST_Msk bit is set after FIFO is filled with all the data that should be transmitted. This change allows to use FIFO level warning interrupt to fill FIFO. When DMA is available it will be used instead of interrupts. Some function names were changed to better reflect what each function does.
This commit is contained in:
parent
33a5081bd1
commit
d36bfddc30
@ -285,15 +285,12 @@ void tusb_vbus_changed(bool present)
|
||||
}
|
||||
}
|
||||
|
||||
static void transmit_packet(xfer_ctl_t * xfer)
|
||||
static void fill_tx_fifo(xfer_ctl_t * xfer)
|
||||
{
|
||||
int left_to_send;
|
||||
uint8_t const *src;
|
||||
EPx_REGS *regs = xfer->regs;
|
||||
uint32_t txc;
|
||||
|
||||
txc = USB_USB_TXC1_REG_USB_TX_EN_Msk | USB_USB_TXC1_REG_USB_IGN_ISOMSK_Msk;
|
||||
if (xfer->data1) txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk;
|
||||
uint8_t const epnum = tu_edpt_number(xfer->ep_addr);
|
||||
|
||||
src = &xfer->buffer[xfer->transferred];
|
||||
left_to_send = xfer->total_len - xfer->transferred;
|
||||
@ -310,22 +307,23 @@ static void transmit_packet(xfer_ctl_t * xfer)
|
||||
xfer->last_packet_size++;
|
||||
left_to_send--;
|
||||
}
|
||||
if (tu_edpt_number(xfer->ep_addr) != 0)
|
||||
if (epnum != 0)
|
||||
{
|
||||
if (left_to_send > 0)
|
||||
{
|
||||
// Max packet size is set to value greater then FIFO. Enable fifo level warning
|
||||
// to handle larger packets.
|
||||
txc |= USB_USB_TXC1_REG_USB_TFWL_Msk;
|
||||
regs->txc |= (3 << USB_USB_TXC1_REG_USB_TFWL_Pos);
|
||||
USB->USB_FWMSK_REG |= 1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_TXWARN31_Pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
xfer->regs->txc &= ~USB_USB_TXC1_REG_USB_TFWL_Msk;
|
||||
USB->USB_FWMSK_REG &= ~(1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_TXWARN31_Pos));
|
||||
// Whole packet already in fifo, no need to refill it later. Mark last.
|
||||
txc |= USB_USB_TXC1_REG_USB_LAST_Msk;
|
||||
regs->txc |= USB_USB_TXC1_REG_USB_LAST_Msk;
|
||||
}
|
||||
}
|
||||
// Enable transfer with correct interrupts enabled
|
||||
regs->txc = txc;
|
||||
}
|
||||
|
||||
static bool try_allocate_dma(uint8_t epnum, uint8_t dir)
|
||||
@ -387,6 +385,43 @@ static void start_rx_packet(xfer_ctl_t *xfer)
|
||||
xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk;
|
||||
}
|
||||
|
||||
static void start_tx_dma(void *src, volatile void *dst, uint16_t size)
|
||||
{
|
||||
// Setup SRC and DST registers
|
||||
TX_DMA_REGS->DMAx_A_START_REG = (uint32_t)src;
|
||||
TX_DMA_REGS->DMAx_B_START_REG = (uint32_t)dst;
|
||||
// Interrupt not needed
|
||||
TX_DMA_REGS->DMAx_INT_REG = size;
|
||||
TX_DMA_REGS->DMAx_LEN_REG = size - 1;
|
||||
TX_DMA_REGS->DMAx_CTRL_REG = TX_DMA_START;
|
||||
}
|
||||
|
||||
static void start_tx_packet(xfer_ctl_t *xfer)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(xfer->ep_addr);
|
||||
uint16_t remaining = xfer->total_len - xfer->transferred;
|
||||
uint16_t size = tu_min16(remaining, xfer->max_packet_size);
|
||||
EPx_REGS *regs = xfer->regs;
|
||||
|
||||
xfer->last_packet_size = 0;
|
||||
|
||||
regs->txc = USB_USB_TXC1_REG_USB_FLUSH_Msk;
|
||||
regs->txc = USB_USB_TXC1_REG_USB_IGN_ISOMSK_Msk;
|
||||
if (xfer->data1) xfer->regs->txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk;
|
||||
|
||||
if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE && try_allocate_dma(epnum, TUSB_DIR_IN))
|
||||
{
|
||||
// Whole packet will be put in FIFO by DMA. Set LAST bit before start.
|
||||
start_tx_dma(xfer->buffer + xfer->transferred, ®s->txd, size);
|
||||
regs->txc |= USB_USB_TXC1_REG_USB_LAST_Msk;
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_tx_fifo(xfer);
|
||||
}
|
||||
regs->txc |= USB_USB_TXC1_REG_USB_TX_EN_Msk;
|
||||
}
|
||||
|
||||
static void read_rx_fifo(xfer_ctl_t *xfer, uint16_t bytes_in_fifo)
|
||||
{
|
||||
EPx_REGS *regs = xfer->regs;
|
||||
@ -483,7 +518,7 @@ static void handle_ep0_tx(void)
|
||||
// Start from the beginning
|
||||
xfer->last_packet_size = 0;
|
||||
}
|
||||
transmit_packet(xfer);
|
||||
fill_tx_fifo(xfer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -570,14 +605,23 @@ static void handle_rx_ev(void)
|
||||
|
||||
static void handle_epx_tx_ev(xfer_ctl_t *xfer)
|
||||
{
|
||||
uint32_t usb_txs1_reg;
|
||||
uint8_t const epnum = tu_edpt_number(xfer->ep_addr);
|
||||
uint32_t txs;
|
||||
EPx_REGS *regs = xfer->regs;
|
||||
|
||||
usb_txs1_reg = regs->USB_TXS1_REG;
|
||||
txs = regs->txs;
|
||||
|
||||
if (GET_BIT(usb_txs1_reg, USB_USB_TXS1_REG_USB_TX_DONE))
|
||||
if (GET_BIT(txs, USB_USB_TXS1_REG_USB_TX_DONE))
|
||||
{
|
||||
if (GET_BIT(usb_txs1_reg, USB_USB_TXS1_REG_USB_ACK_STAT))
|
||||
if (_dcd.dma_ep[TUSB_DIR_IN] == epnum)
|
||||
{
|
||||
// Disable DMA and update last_packet_size with what DMA reported.
|
||||
TX_DMA_REGS->DMAx_CTRL_REG &= ~DMA_DMA1_CTRL_REG_DMA_ON_Msk;
|
||||
xfer->last_packet_size = TX_DMA_REGS->DMAx_IDX_REG + 1;
|
||||
// Release DMA to used by other endpoints.
|
||||
_dcd.dma_ep[TUSB_DIR_IN] = 0;
|
||||
}
|
||||
if (GET_BIT(txs, USB_USB_TXS1_REG_USB_ACK_STAT))
|
||||
{
|
||||
// ACK received, update transfer state and DATA0/1 bit
|
||||
xfer->transferred += xfer->last_packet_size;
|
||||
@ -590,12 +634,13 @@ static void handle_epx_tx_ev(xfer_ctl_t *xfer)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xfer->last_packet_size = 0;
|
||||
}
|
||||
transmit_packet(xfer);
|
||||
}
|
||||
if (txs & USB_USB_TXS1_REG_USB_TX_URUN_Msk)
|
||||
{
|
||||
TU_LOG1("EP %d FIFO underrun\n", epnum);
|
||||
}
|
||||
// Start next or repeated packet.
|
||||
start_tx_packet(xfer);
|
||||
}
|
||||
|
||||
static void handle_tx_ev(void)
|
||||
@ -665,9 +710,9 @@ static void handle_alt_ev(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_epx_tx_refill(uint8_t ep)
|
||||
static void handle_epx_tx_warn_ev(uint8_t ep)
|
||||
{
|
||||
transmit_packet(XFER_CTL_BASE(ep, TUSB_DIR_IN));
|
||||
fill_tx_fifo(XFER_CTL_BASE(ep, TUSB_DIR_IN));
|
||||
}
|
||||
|
||||
static void handle_fifo_warning(void)
|
||||
@ -675,11 +720,11 @@ static void handle_fifo_warning(void)
|
||||
uint32_t fifo_warning = USB->USB_FWEV_REG;
|
||||
|
||||
if (fifo_warning & 0x01)
|
||||
handle_epx_tx_refill(1);
|
||||
handle_epx_tx_warn_ev(1);
|
||||
if (fifo_warning & 0x02)
|
||||
handle_epx_tx_refill(2);
|
||||
handle_epx_tx_warn_ev(2);
|
||||
if (fifo_warning & 0x04)
|
||||
handle_epx_tx_refill(3);
|
||||
handle_epx_tx_warn_ev(3);
|
||||
if (fifo_warning & 0x10)
|
||||
handle_epx_rx_ev(1);
|
||||
if (fifo_warning & 0x20)
|
||||
@ -884,7 +929,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
|
||||
}
|
||||
else // IN
|
||||
{
|
||||
transmit_packet(xfer);
|
||||
start_tx_packet(xfer);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user