Skip to content

Commit 0164f2f

Browse files
thenguyenyfKhiemNguyenT
authored andcommitted
hal: renesas: ra: fix control transfer handling for r_usb_device
This commit to update control transfer flow to properly handle: - Send ZLP when last data is at packet boundary - Start the status stage only when received the reversed direction token Signed-off-by: The Nguyen <[email protected]>
1 parent 69c3df1 commit 0164f2f

File tree

2 files changed

+636
-558
lines changed

2 files changed

+636
-558
lines changed

drivers/ra/fsp/src/r_usb_device/r_usb_device.c

Lines changed: 83 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@
6060
/***********************************************************************************************************************
6161
* Typedef definitions
6262
**********************************************************************************************************************/
63+
typedef enum e_usb_control_stage
64+
{
65+
USB_CONTROL_STAGE_IDLE = 0,
66+
USB_CONTROL_STAGE_SETUP = 0,
67+
USB_CONTROL_STAGE_DATA = 1,
68+
USB_CONTROL_STAGE_STATUS = 2,
69+
USB_CONTROL_STAGE_ERROR = 3,
70+
} usb_control_stage_t;
71+
6372
typedef struct st_pipe_state
6473
{
6574
void * buf; /* the start address of a transfer data buffer */
@@ -85,8 +94,9 @@ static inline uint32_t get_first_bit1_offset (uint32_t s) {
8594
return __builtin_ctz(s);
8695
}
8796

88-
static inline uint16_t get_edpt_packet_size(usbd_instance_ctrl_t * const p_ctrl,
89-
usbd_desc_endpoint_t const * p_desc_ep);
97+
static usb_control_stage_t dcp_get_current_stage(usbd_instance_ctrl_t * p_ctrl);
98+
static inline uint16_t get_edpt_packet_size(usbd_instance_ctrl_t * const p_ctrl,
99+
usbd_desc_endpoint_t const * p_desc_ep);
90100
static uint32_t find_pipe(usbd_instance_ctrl_t * const p_ctrl, uint32_t xfer_type);
91101
static inline volatile uint16_t * get_pipectr(usbd_instance_ctrl_t * const p_ctrl, uint32_t num);
92102
static volatile void * get_pipetre(usbd_instance_ctrl_t * const p_ctrl, uint32_t num);
@@ -1133,9 +1143,11 @@ static inline fsp_err_t process_pipe0_xfer (usbd_instance_ctrl_t * const p_ctrl,
11331143
bool hs_module = USB_IS_USBHS(p_ctrl->p_cfg->module_number);
11341144
volatile uint16_t * cfifosel = hs_module ? &R_USB_HS0->CFIFOSEL : &R_USB_FS0->CFIFOSEL;
11351145
volatile uint16_t * dcpctr = hs_module ? &R_USB_HS0->DCPCTR : &R_USB_FS0->DCPCTR;
1146+
volatile uint16_t * cfifoctr = hs_module ? &R_USB_HS0->CFIFOCTR : &R_USB_FS0->CFIFOCTR;
11361147
#else
11371148
volatile uint16_t * cfifosel = &R_USB_FS0->CFIFOSEL;
11381149
volatile uint16_t * dcpctr = &R_USB_FS0->DCPCTR;
1150+
volatile uint16_t * cfifoctr = &R_USB_FS0->CFIFOCTR;
11391151
#endif
11401152

11411153
const uint8_t dir = USB_GET_EP_DIR(ep_addr);
@@ -1174,7 +1186,17 @@ static inline fsp_err_t process_pipe0_xfer (usbd_instance_ctrl_t * const p_ctrl,
11741186
{
11751187
/* ZLP */
11761188
pipe->buf = NULL;
1177-
*dcpctr = R_USB_DCPCTR_CCPL_Msk | R_USB_PIPE_CTR_PID_BUF;
1189+
1190+
if (USB_CONTROL_STAGE_STATUS == dcp_get_current_stage(p_ctrl))
1191+
{
1192+
/* perform status stage */
1193+
*dcpctr = R_USB_DCPCTR_CCPL_Msk | R_USB_PIPE_CTR_PID_BUF;
1194+
}
1195+
else
1196+
{
1197+
/* notice that this is the end of data stage */
1198+
*cfifoctr |= R_USB_CFIFOCTR_BVAL_Msk;
1199+
}
11781200
}
11791201

11801202
return FSP_SUCCESS;
@@ -1891,6 +1913,44 @@ static inline uint16_t get_active_bit_intsts0 (usbd_instance_ctrl_t * p_ctrl)
18911913
return intsts0;
18921914
}
18931915

1916+
static usb_control_stage_t dcp_get_current_stage (usbd_instance_ctrl_t * p_ctrl)
1917+
{
1918+
uint16_t intsts0 = get_active_bit_intsts0(p_ctrl);
1919+
usb_control_stage_t stage;
1920+
1921+
switch (intsts0 & R_USB_INTSTS0_CTSQ_Msk)
1922+
{
1923+
case R_USB_INTSTS0_CTSQ_CTRL_IDLE:
1924+
{
1925+
stage = USB_CONTROL_STAGE_IDLE;
1926+
break;
1927+
}
1928+
1929+
case R_USB_INTSTS0_CTSQ_CTRL_RDATA:
1930+
case R_USB_INTSTS0_CTSQ_CTRL_WDATA:
1931+
{
1932+
stage = USB_CONTROL_STAGE_DATA;
1933+
break;
1934+
}
1935+
1936+
case R_USB_INTSTS0_CTSQ_CTRL_RSTATUS:
1937+
case R_USB_INTSTS0_CTSQ_CTRL_WSTATUS:
1938+
case R_USB_INTSTS0_CTSQ_CTRL_WSTATUS_NODATA:
1939+
{
1940+
stage = USB_CONTROL_STAGE_STATUS;
1941+
break;
1942+
}
1943+
1944+
default:
1945+
{
1946+
stage = USB_CONTROL_STAGE_ERROR;
1947+
break;
1948+
}
1949+
}
1950+
1951+
return stage;
1952+
}
1953+
18941954
static inline void process_vbus_changed (usbd_instance_ctrl_t * p_ctrl, uint16_t intsts0)
18951955
{
18961956
usbd_event_t event;
@@ -2128,15 +2188,27 @@ void usb_device_isr (void)
21282188
/* Control transfer stage changes */
21292189
if (intsts0 & R_USB_INTSTS0_CTRT_Msk)
21302190
{
2131-
if (intsts0 & R_USB_INTSTS0_CTSQ_CTRL_RDATA)
2191+
switch (intsts0 & R_USB_INTSTS0_CTSQ_Msk)
21322192
{
2133-
/* A setup packet has been received. */
2134-
process_setup_packet(p_ctrl);
2135-
}
2136-
else if (0 == (intsts0 & R_USB_INTSTS0_CTSQ_Msk))
2137-
{
2138-
/* A ZLP has been sent/received. */
2139-
process_status_completion(p_ctrl);
2193+
case R_USB_INTSTS0_CTSQ_CTRL_RDATA:
2194+
case R_USB_INTSTS0_CTSQ_CTRL_WDATA:
2195+
case R_USB_INTSTS0_CTSQ_CTRL_WSTATUS_NODATA:
2196+
{
2197+
process_setup_packet(p_ctrl);
2198+
break;
2199+
}
2200+
2201+
case R_USB_INTSTS0_CTSQ_CTRL_IDLE:
2202+
{
2203+
/* A ZLP has been sent/received. */
2204+
process_status_completion(p_ctrl);
2205+
break;
2206+
}
2207+
2208+
default:
2209+
{
2210+
break;
2211+
}
21402212
}
21412213
}
21422214

0 commit comments

Comments
 (0)