fix incorrect data toggle when max packet size < 64
fix host buf_sel panic with "already available"
This commit is contained in:
@@ -46,7 +46,7 @@ static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) {
|
||||
#if TUSB_OPT_HOST_ENABLED
|
||||
static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep)
|
||||
{
|
||||
ep->last_buf = ep->len + ep->transfer_size == ep->total_len;
|
||||
ep->last_buf = (ep->len + ep->transfer_size == ep->total_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -126,8 +126,29 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep)
|
||||
|
||||
// PID
|
||||
val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
|
||||
|
||||
#if TUSB_OPT_DEVICE_ENABLED
|
||||
ep->next_pid ^= 1u;
|
||||
|
||||
#else
|
||||
// For Host (also device but since we dictate the endpoint size, following scenario does not occur)
|
||||
// Next PID depends on the number of packet in case wMaxPacketSize < 64 (e.g Interrupt Endpoint 8, or 12)
|
||||
// Special case with control status stage where PID is always DATA1
|
||||
if ( ep->transfer_size == 0 )
|
||||
{
|
||||
ep->next_pid ^= 1u;
|
||||
}else
|
||||
{
|
||||
uint32_t packet_count = 1 + ((ep->transfer_size - 1) / ep->wMaxPacketSize);
|
||||
|
||||
if ( packet_count & 0x01 )
|
||||
{
|
||||
ep->next_pid ^= 1u;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if TUSB_OPT_HOST_ENABLED
|
||||
// Is this the last buffer? Only really matters for host mode. Will trigger
|
||||
// the trans complete irq but also stop it polling. We only really care about
|
||||
@@ -143,6 +164,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep)
|
||||
// the next time the controller polls this dpram address
|
||||
_hw_endpoint_buffer_control_set_value32(ep, val);
|
||||
pico_trace("buffer control (0x%p) <- 0x%x\n", ep->buffer_control, val);
|
||||
//print_bufctrl16(val);
|
||||
}
|
||||
|
||||
|
||||
@@ -189,10 +211,14 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep)
|
||||
|
||||
#if TUSB_OPT_HOST_ENABLED
|
||||
// tag::host_buf_sel_fix[]
|
||||
// TODO need changes to support double buffering
|
||||
if (ep->buf_sel == 1)
|
||||
{
|
||||
// Host can erroneously write status to top half of buf_ctrl register
|
||||
buf_ctrl = buf_ctrl >> 16;
|
||||
|
||||
// update buf1 -> buf0 to prevent panic with "already available"
|
||||
*ep->buffer_control = buf_ctrl;
|
||||
}
|
||||
// Flip buf sel for host
|
||||
ep->buf_sel ^= 1u;
|
||||
|
||||
Reference in New Issue
Block a user