Generalization of USB transfer's error handling
No longer assumes EP0 for control transfer, in general HCD code. Some additional cleanup.
This commit is contained in:
parent
69cba46141
commit
c1ba580ae2
@ -16,4 +16,4 @@ created march-june 2014, JPEmbedded (info@jpembedded.eu)
|
|||||||
formatting for it, is therefore hardcoded into USBD
|
formatting for it, is therefore hardcoded into USBD
|
||||||
- Waiting for USB0 clock to leave IDLEST.Disable state, by nanosleep, was
|
- Waiting for USB0 clock to leave IDLEST.Disable state, by nanosleep, was
|
||||||
removed, as this should be implemented for all clocks in clkconf_set
|
removed, as this should be implemented for all clocks in clkconf_set
|
||||||
- Control transfers can only be performed with EP0
|
- Control transfers can only be performed with EP0
|
||||||
|
@ -673,6 +673,7 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
|
|||||||
/* Check response */
|
/* Check response */
|
||||||
if (EXIT_SUCCESS != d->check_error(d->private_data,
|
if (EXIT_SUCCESS != d->check_error(d->private_data,
|
||||||
HCD_TRANSFER_CONTROL,
|
HCD_TRANSFER_CONTROL,
|
||||||
|
ep,
|
||||||
HCD_DIRECTION_UNUSED))
|
HCD_DIRECTION_UNUSED))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
@ -696,6 +697,7 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
|
|||||||
if (EXIT_SUCCESS != d->check_error(
|
if (EXIT_SUCCESS != d->check_error(
|
||||||
d->private_data,
|
d->private_data,
|
||||||
HCD_TRANSFER_CONTROL,
|
HCD_TRANSFER_CONTROL,
|
||||||
|
ep,
|
||||||
HCD_DIRECTION_UNUSED))
|
HCD_DIRECTION_UNUSED))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
@ -746,6 +748,7 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
|
|||||||
/* Check response */
|
/* Check response */
|
||||||
if (EXIT_SUCCESS != d->check_error(d->private_data,
|
if (EXIT_SUCCESS != d->check_error(d->private_data,
|
||||||
HCD_TRANSFER_CONTROL,
|
HCD_TRANSFER_CONTROL,
|
||||||
|
ep,
|
||||||
HCD_DIRECTION_UNUSED))
|
HCD_DIRECTION_UNUSED))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
@ -760,6 +763,7 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
|
|||||||
/* Check response */
|
/* Check response */
|
||||||
if (EXIT_SUCCESS != d->check_error(d->private_data,
|
if (EXIT_SUCCESS != d->check_error(d->private_data,
|
||||||
HCD_TRANSFER_CONTROL,
|
HCD_TRANSFER_CONTROL,
|
||||||
|
ep,
|
||||||
HCD_DIRECTION_UNUSED))
|
HCD_DIRECTION_UNUSED))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
@ -851,6 +855,7 @@ hcd_data_transfer(hcd_device_state * this_device, hcd_datarequest * request)
|
|||||||
/* Check response */
|
/* Check response */
|
||||||
if (EXIT_SUCCESS != d->check_error(d->private_data,
|
if (EXIT_SUCCESS != d->check_error(d->private_data,
|
||||||
request->type,
|
request->type,
|
||||||
|
request->endpoint,
|
||||||
HCD_DIRECTION_IN))
|
HCD_DIRECTION_IN))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
@ -898,6 +903,7 @@ hcd_data_transfer(hcd_device_state * this_device, hcd_datarequest * request)
|
|||||||
/* Check response */
|
/* Check response */
|
||||||
if (EXIT_SUCCESS != d->check_error(d->private_data,
|
if (EXIT_SUCCESS != d->check_error(d->private_data,
|
||||||
request->type,
|
request->type,
|
||||||
|
request->endpoint,
|
||||||
HCD_DIRECTION_OUT))
|
HCD_DIRECTION_OUT))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ musb_read_fifo(void * cfg, void * output, int size, hcd_reg1 fifo_num)
|
|||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* musb_write_fifo *
|
* musb_write_fifo *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static void
|
static void
|
||||||
musb_write_fifo(void * cfg, void * input, int size, hcd_reg1 fifo_num)
|
musb_write_fifo(void * cfg, void * input, int size, hcd_reg1 fifo_num)
|
||||||
@ -524,9 +524,9 @@ musb_rx_stage(void * cfg, hcd_datarequest * request)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* TODO: One reusable FIFO, no double buffering */
|
/* TODO: One reusable FIFO, no double buffering */
|
||||||
/* TODO: With this, only one device can work at a time but it
|
/* TODO: With this, only one device/EP can work at a time. Should this
|
||||||
* may be impossible to have MUSB work reasonably with multiple
|
* be changed, hcd_device_wait/hcd_device_continue calls must be fixed
|
||||||
* EP interrupts anyway */
|
* accordingly to allow handling multiple EP interrupts */
|
||||||
/* Assign FIFO */
|
/* Assign FIFO */
|
||||||
HCD_WR2(r, MUSB_REG_RXFIFOADDR, MUSB_VAL_XXFIFOADDR_EP0_END);
|
HCD_WR2(r, MUSB_REG_RXFIFOADDR, MUSB_VAL_XXFIFOADDR_EP0_END);
|
||||||
HCD_WR1(r, MUSB_REG_RXFIFOSZ, MUSB_VAL_XXFIFOSZ_4096);
|
HCD_WR1(r, MUSB_REG_RXFIFOSZ, MUSB_VAL_XXFIFOSZ_4096);
|
||||||
@ -618,9 +618,9 @@ musb_tx_stage(void * cfg, hcd_datarequest * request)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* TODO: One reusable FIFO, no double buffering */
|
/* TODO: One reusable FIFO, no double buffering */
|
||||||
/* TODO: With this, only one device can work at a time but it
|
/* TODO: With this, only one device/EP can work at a time. Should this
|
||||||
* may be impossible to have MUSB work reasonably with multiple
|
* be changed, hcd_device_wait/hcd_device_continue calls must be fixed
|
||||||
* EP interrupts anyway */
|
* accordingly to allow handling multiple EP interrupts */
|
||||||
/* Assign FIFO */
|
/* Assign FIFO */
|
||||||
HCD_WR2(r, MUSB_REG_TXFIFOADDR, MUSB_VAL_XXFIFOADDR_EP0_END);
|
HCD_WR2(r, MUSB_REG_TXFIFOADDR, MUSB_VAL_XXFIFOADDR_EP0_END);
|
||||||
HCD_WR1(r, MUSB_REG_TXFIFOSZ, MUSB_VAL_XXFIFOSZ_4096);
|
HCD_WR1(r, MUSB_REG_TXFIFOSZ, MUSB_VAL_XXFIFOSZ_4096);
|
||||||
@ -781,15 +781,26 @@ musb_read_data(void * cfg, hcd_reg1 * buffer, hcd_reg1 ep_num)
|
|||||||
* musb_check_error *
|
* musb_check_error *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int
|
int
|
||||||
musb_check_error(void * cfg, hcd_transfer transfer, hcd_direction dir)
|
musb_check_error(void * cfg, hcd_transfer xfer, hcd_reg1 ep, hcd_direction dir)
|
||||||
{
|
{
|
||||||
|
/* Possible error handling schemes for MUSB */
|
||||||
|
typedef enum {
|
||||||
|
|
||||||
|
MUSB_INVALID_ERROR_CASE,
|
||||||
|
MUSB_EP0_ERROR_CASE,
|
||||||
|
MUSB_OUT_ERROR_CASE,
|
||||||
|
MUSB_IN_ERROR_CASE,
|
||||||
|
}
|
||||||
|
musb_error_case;
|
||||||
|
|
||||||
void * r;
|
void * r;
|
||||||
hcd_reg2 host_csr;
|
hcd_reg2 host_csr;
|
||||||
|
musb_error_case error_case;
|
||||||
|
|
||||||
DEBUG_DUMP;
|
DEBUG_DUMP;
|
||||||
|
|
||||||
/* TODO: ISO transfer */
|
/* TODO: ISO transfer */
|
||||||
USB_ASSERT(HCD_TRANSFER_ISOCHRONOUS != transfer,
|
USB_ASSERT(HCD_TRANSFER_ISOCHRONOUS != xfer,
|
||||||
"ISO transfer not supported");
|
"ISO transfer not supported");
|
||||||
|
|
||||||
r = ((musb_core_config *)cfg)->regs;
|
r = ((musb_core_config *)cfg)->regs;
|
||||||
@ -797,9 +808,28 @@ musb_check_error(void * cfg, hcd_transfer transfer, hcd_direction dir)
|
|||||||
/* Set EP and device address to be used in this command */
|
/* Set EP and device address to be used in this command */
|
||||||
musb_set_state((musb_core_config *)cfg);
|
musb_set_state((musb_core_config *)cfg);
|
||||||
|
|
||||||
/* TODO: More than one control EP? */
|
/* Resolve which error needs to be checked
|
||||||
/* In MUSB EP0 has it's own registers for error handling */
|
* so we can use proper MUSB registers */
|
||||||
if (HCD_TRANSFER_CONTROL == transfer) {
|
error_case = MUSB_INVALID_ERROR_CASE;
|
||||||
|
|
||||||
|
if (HCD_DEFAULT_EP == ep) {
|
||||||
|
if (HCD_TRANSFER_CONTROL == xfer)
|
||||||
|
/* EP0, control, any direction */
|
||||||
|
error_case = MUSB_EP0_ERROR_CASE;
|
||||||
|
} else {
|
||||||
|
if (HCD_TRANSFER_CONTROL != xfer) {
|
||||||
|
if (HCD_DIRECTION_OUT == dir)
|
||||||
|
/* EP>0, non-control, out */
|
||||||
|
error_case = MUSB_OUT_ERROR_CASE;
|
||||||
|
else if (HCD_DIRECTION_IN == dir)
|
||||||
|
/* EP>0, non-control, in */
|
||||||
|
error_case = MUSB_IN_ERROR_CASE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In MUSB, EP0 has it's own registers for error handling and it also
|
||||||
|
* seems to be the only way to handle errors for control transfers */
|
||||||
|
if (MUSB_EP0_ERROR_CASE == error_case) {
|
||||||
/* Get control status register */
|
/* Get control status register */
|
||||||
host_csr = HCD_RD2(r, MUSB_REG_HOST_CSR0);
|
host_csr = HCD_RD2(r, MUSB_REG_HOST_CSR0);
|
||||||
|
|
||||||
@ -828,10 +858,8 @@ musb_check_error(void * cfg, hcd_transfer transfer, hcd_direction dir)
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Non-control transfer error check,
|
if (MUSB_OUT_ERROR_CASE == error_case) {
|
||||||
* is based on transfer direction */
|
/* Get TX status register */
|
||||||
if (HCD_DIRECTION_OUT == dir) {
|
|
||||||
/* Get RX status register */
|
|
||||||
host_csr = HCD_RD2(r, MUSB_REG_HOST_TXCSR);
|
host_csr = HCD_RD2(r, MUSB_REG_HOST_TXCSR);
|
||||||
|
|
||||||
/* Check for common errors */
|
/* Check for common errors */
|
||||||
@ -859,7 +887,7 @@ musb_check_error(void * cfg, hcd_transfer transfer, hcd_direction dir)
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HCD_DIRECTION_IN == dir) {
|
if (MUSB_IN_ERROR_CASE == error_case) {
|
||||||
/* Get RX status register */
|
/* Get RX status register */
|
||||||
host_csr = HCD_RD2(r, MUSB_REG_HOST_RXCSR);
|
host_csr = HCD_RD2(r, MUSB_REG_HOST_RXCSR);
|
||||||
|
|
||||||
@ -888,6 +916,7 @@ musb_check_error(void * cfg, hcd_transfer transfer, hcd_direction dir)
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
USB_MSG("Invalid USB transfer 0x%X:0x%X", (int)transfer, (int)dir);
|
USB_MSG("Invalid USB transfer error check: 0x%X, 0x%X, 0x%X",
|
||||||
|
(int)xfer, (int)ep, (int)dir);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ void musb_out_data_stage(void *);
|
|||||||
void musb_in_status_stage(void *);
|
void musb_in_status_stage(void *);
|
||||||
void musb_out_status_stage(void *);
|
void musb_out_status_stage(void *);
|
||||||
int musb_read_data(void *, hcd_reg1 *, hcd_reg1);
|
int musb_read_data(void *, hcd_reg1 *, hcd_reg1);
|
||||||
int musb_check_error(void *, hcd_transfer, hcd_direction);
|
int musb_check_error(void *, hcd_transfer, hcd_reg1, hcd_direction);
|
||||||
|
|
||||||
|
|
||||||
#endif /* !_MUSB_CORE_H_ */
|
#endif /* !_MUSB_CORE_H_ */
|
||||||
|
@ -33,7 +33,8 @@ struct hcd_driver_state {
|
|||||||
void (*in_status_stage) (void *);
|
void (*in_status_stage) (void *);
|
||||||
void (*out_status_stage) (void *);
|
void (*out_status_stage) (void *);
|
||||||
int (*read_data) (void *, hcd_reg1 *, hcd_reg1);
|
int (*read_data) (void *, hcd_reg1 *, hcd_reg1);
|
||||||
int (*check_error) (void *, hcd_transfer, hcd_direction);
|
int (*check_error) (void *, hcd_transfer, hcd_reg1,
|
||||||
|
hcd_direction);
|
||||||
|
|
||||||
/* Controller's private data (like mapped registers) */
|
/* Controller's private data (like mapped registers) */
|
||||||
void * private_data;
|
void * private_data;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user