Unlike the AVR and CC1111 USB drivers, the STM usb driver queues IN
bytes in a local buffer instead of in the driver; this means that the
driver is queuing bytes while the previous IN packet is queued for the
host, which allows for overlapping execution.
It also means that when the local buffer is full, we must check to see
if the host has picked up the previous IN packet before trying to
queue another IN packet for transmission. This is done by always
waiting for the IN buffer to be ready before sending data.
Signed-off-by: Keith Packard <keithp@keithp.com>
/* Queue the current IN buffer for transmission */
static void
/* Queue the current IN buffer for transmission */
static void
{
_tx_dbg0("in_send start");
debug ("send %d\n", ao_usb_tx_count);
{
_tx_dbg0("in_send start");
debug ("send %d\n", ao_usb_tx_count);
+ while (ao_usb_in_pending)
+ ao_sleep(&ao_usb_in_pending);
+ if (ao_usb_tx_count != AO_USB_IN_SIZE)
+ ao_usb_in_flushed = 1;
ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count);
ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count;
ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count);
ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count;
- ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);
+ _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);
+ _tx_dbg0("in_send end");
}
/* Wait for a free IN buffer. Interrupts are blocked */
}
/* Wait for a free IN buffer. Interrupts are blocked */
* want to send an empty packet
*/
ao_arch_block_interrupts();
* want to send an empty packet
*/
ao_arch_block_interrupts();
- if (!ao_usb_in_flushed) {
- ao_usb_in_flushed = 1;
- /* Wait for an IN buffer to be ready */
- while (ao_usb_in_pending)
- ao_sleep(&ao_usb_in_pending);
- ao_usb_in_send();
+ while (!ao_usb_in_flushed) {
+ _tx_dbg0("flush top");
+ _ao_usb_in_send();
+ _tx_dbg0("flush end");
}
ao_arch_release_interrupts();
}
}
ao_arch_release_interrupts();
}