Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance dcd rusb2, support ra2a1 pipe number scheme #2588

Merged
merged 5 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions hw/bsp/ra/boards/ra2a1_ek/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
extern "C" {
#endif

#define LED1 BSP_IO_PORT_01_PIN_06
#define LED1 BSP_IO_PORT_02_PIN_05
#define LED_STATE_ON 1

#define SW1 BSP_IO_PORT_01_PIN_05
#define SW1 BSP_IO_PORT_02_PIN_06
#define BUTTON_STATE_ACTIVE 0

static const ioport_pin_cfg_t board_pin_cfg[] = {
Expand Down
3 changes: 3 additions & 0 deletions hw/bsp/ra/family.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,11 @@ BSP_DONT_REMOVE BSP_PLACE_IN_SECTION(BSP_SECTION_APPLICATION_VECTORS)
const fsp_vector_t g_vector_table[BSP_ICU_VECTOR_MAX_ENTRIES] = {
[0] = usbfs_interrupt_handler, /* USBFS INT (USBFS interrupt) */
[1] = usbfs_resume_handler, /* USBFS RESUME (USBFS resume interrupt) */

#ifndef BSP_MCU_GROUP_RA2A1
[2] = usbfs_d0fifo_handler, /* USBFS FIFO 0 (DMA transfer request 0) */
[3] = usbfs_d1fifo_handler, /* USBFS FIFO 1 (DMA transfer request 1) */
#endif

#ifdef BOARD_HAS_USB_HIGHSPEED
[4] = usbhs_interrupt_handler, /* USBHS INT (USBHS interrupt) */
Expand Down
3 changes: 3 additions & 0 deletions hw/bsp/ra/vector_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ extern "C" {
/* ISR prototypes */
void usbfs_interrupt_handler(void);
void usbfs_resume_handler(void);

#ifndef BSP_MCU_GROUP_RA2A1
void usbfs_d0fifo_handler(void);
void usbfs_d1fifo_handler(void);
#endif

#ifdef BOARD_HAS_USB_HIGHSPEED
void usbhs_interrupt_handler(void);
Expand Down
130 changes: 50 additions & 80 deletions src/portable/renesas/rusb2/dcd_rusb2.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,29 +57,22 @@
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
enum {
PIPE_COUNT = 10,
};

/* Start of definition of packed structs (used by the CCRX toolchain) */
TU_ATTR_PACKED_BEGIN
TU_ATTR_BIT_FIELD_ORDER_BEGIN

typedef struct TU_ATTR_PACKED
{
typedef struct {
void *buf; /* the start address of a transfer data buffer */
uint16_t length; /* the number of bytes in the buffer */
uint16_t remaining; /* the number of bytes remaining in the buffer */
struct {
uint32_t ep : 8; /* an assigned endpoint address */
uint32_t ff : 1; /* `buf` is TU_FUFO or POD */
uint32_t : 0;
};
} pipe_state_t;

TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain)
TU_ATTR_BIT_FIELD_ORDER_END
uint8_t ep; /* an assigned endpoint address */
kkitayam marked this conversation as resolved.
Show resolved Hide resolved
uint8_t ff; /* `buf` is TU_FUFO or POD */
} pipe_state_t;

typedef struct
{
pipe_state_t pipe[10];
pipe_state_t pipe[PIPE_COUNT];
uint8_t ep[2][16]; /* a lookup table for a pipe index from an endpoint address */
} dcd_data_t;

Expand All @@ -89,70 +82,60 @@ static dcd_data_t _dcd;
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+

// Transfer conditions specifiable for each pipe:
// - Pipe 0: Control transfer with 64-byte single buffer
// - Pipes 1 and 2: Bulk isochronous transfer continuous transfer mode with programmable buffer size up
// to 2 KB and optional double buffer
// - Pipes 3 to 5: Bulk transfer continuous transfer mode with programmable buffer size up to 2 KB and
// optional double buffer
// - Pipes 6 to 9: Interrupt transfer with 64-byte single buffer
enum {
PIPE_1ST_BULK = 3,
PIPE_1ST_INTERRUPT = 6,
PIPE_COUNT = 10,
};

static unsigned find_pipe(unsigned xfer)
{
switch (xfer) {
case TUSB_XFER_ISOCHRONOUS:
for (int i = 1; i < PIPE_1ST_BULK; ++i) {
if (0 == _dcd.pipe[i].ep) return i;
}
break;

case TUSB_XFER_BULK:
for (int i = PIPE_1ST_BULK; i < PIPE_1ST_INTERRUPT; ++i) {
if (0 == _dcd.pipe[i].ep) return i;
}
for (int i = 1; i < PIPE_1ST_BULK; ++i) {
if (0 == _dcd.pipe[i].ep) return i;
}
break;
// Transfer conditions specifiable for each pipe for most MCUs
// - Pipe 0: Control transfer with 64-byte single buffer
// - Pipes 1 and 2: Bulk or ISO
// - Pipes 3 to 5: Bulk
// - Pipes 6 to 9: Interrupt
//
// Note: for small mcu such as
// - RA2A1: only pipe 4-7 are available, and no support for ISO
static unsigned find_pipe(unsigned xfer_type) {
hathach marked this conversation as resolved.
Show resolved Hide resolved
#if defined(BSP_MCU_GROUP_RA2A1)
const uint8_t pipe_idx_arr[4][2] = {
{ 0, 0 }, // Control
{ 0, 0 }, // Isochronous not supported
{ 4, 5 }, // Bulk
{ 6, 7 }, // Interrupt
};
#else
const uint8_t pipe_idx_arr[4][2] = {
{ 0, 0 }, // Control
{ 1, 2 }, // Isochronous
{ 1, 5 }, // Bulk
{ 6, 9 }, // Interrupt
};
#endif

case TUSB_XFER_INTERRUPT:
for (int i = PIPE_1ST_INTERRUPT; i < PIPE_COUNT; ++i) {
if (0 == _dcd.pipe[i].ep) return i;
}
break;
// find backward since only pipe 1, 2 support ISO
const uint8_t idx_first = pipe_idx_arr[xfer_type][0];
const uint8_t idx_last = pipe_idx_arr[xfer_type][1];

default:
/* No support for control transfer */
break;
for (int i = idx_last; i >= idx_first; i--) {
if (0 == _dcd.pipe[i].ep) return i;
}

return 0;
}

static volatile uint16_t* get_pipectr(rusb2_reg_t *rusb, unsigned num)
{
static volatile uint16_t* get_pipectr(rusb2_reg_t *rusb, unsigned num) {
if (num) {
return (volatile uint16_t*)&(rusb->PIPE_CTR[num - 1]);
} else {
return (volatile uint16_t*)&(rusb->DCPCTR);
}
}

static volatile reg_pipetre_t* get_pipetre(rusb2_reg_t *rusb, unsigned num)
{
static volatile reg_pipetre_t* get_pipetre(rusb2_reg_t *rusb, unsigned num) {
volatile reg_pipetre_t* tre = NULL;
if ((1 <= num) && (num <= 5)) {
tre = (volatile reg_pipetre_t*)&(rusb->PIPE_TR[num - 1].E);
}
return tre;
}

static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr)
{
static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr) {
rusb2_reg_t *rusb = RUSB2_REG(rhport);
const unsigned epn = tu_edpt_number(ep_addr);

Expand All @@ -165,19 +148,16 @@ static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr)
}
}

static uint16_t edpt0_max_packet_size(rusb2_reg_t* rusb)
{
static uint16_t edpt0_max_packet_size(rusb2_reg_t* rusb) {
return rusb->DCPMAXP_b.MXPS;
}

static uint16_t edpt_max_packet_size(rusb2_reg_t *rusb, unsigned num)
{
static uint16_t edpt_max_packet_size(rusb2_reg_t *rusb, unsigned num) {
rusb->PIPESEL = num;
return rusb->PIPEMAXP;
}

static inline void pipe_wait_for_ready(rusb2_reg_t * rusb, unsigned num)
{
static inline void pipe_wait_for_ready(rusb2_reg_t * rusb, unsigned num) {
while ( rusb->D0FIFOSEL_b.CURPIPE != num ) {}
while ( !rusb->D0FIFOCTR_b.FRDY ) {}
}
Expand Down Expand Up @@ -835,7 +815,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
}

rusb->PIPECFG = cfg;
rusb->BRDYSTS = 0x1FFu ^ TU_BIT(num);
rusb->BRDYSTS = 0x3FFu ^ TU_BIT(num);
hathach marked this conversation as resolved.
Show resolved Hide resolved
rusb->BRDYENB |= TU_BIT(num);

if (dir || (xfer != TUSB_XFER_BULK)) {
Expand Down Expand Up @@ -1022,23 +1002,13 @@ void dcd_int_handler(uint8_t rhport)
// Buffer ready
if ( is0 & RUSB2_INTSTS0_BRDY_Msk ) {
const unsigned m = rusb->BRDYENB;
unsigned s = rusb->BRDYSTS & m;
const unsigned s = rusb->BRDYSTS & m;
/* clear active bits (don't write 0 to already cleared bits according to the HW manual) */
rusb->BRDYSTS = ~s;
while (s) {
#if defined(__CCRX__)
static const int Mod37BitPosition[] = {
-1, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4,
7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5,
20, 8, 19, 18
};

const unsigned num = Mod37BitPosition[(-s & s) % 37];
#else
const unsigned num = __builtin_ctz(s);
#endif
process_pipe_brdy(rhport, num);
s &= ~TU_BIT(num);
for (unsigned p = 0; p < PIPE_COUNT; ++p) {
hathach marked this conversation as resolved.
Show resolved Hide resolved
if (tu_bit_test(s, p)) {
process_pipe_brdy(rhport, p);
}
}
}
}
Expand Down
75 changes: 29 additions & 46 deletions src/portable/renesas/rusb2/hcd_rusb2.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
enum {
PIPE_COUNT = 10,
};

TU_ATTR_PACKED_BEGIN
TU_ATTR_BIT_FIELD_ORDER_BEGIN
Expand Down Expand Up @@ -75,7 +78,7 @@ TU_ATTR_BIT_FIELD_ORDER_END
typedef struct
{
bool need_reset; /* The device has not been reset after connection. */
pipe_state_t pipe[10];
pipe_state_t pipe[PIPE_COUNT];
uint8_t ep[4][2][15]; /* a lookup table for a pipe index from an endpoint address */
uint8_t ctl_mps[5]; /* EP0 max packet size for each device */
} hcd_data_t;
Expand All @@ -86,46 +89,30 @@ typedef struct
static hcd_data_t _hcd;

// TODO merged with DCD
// Transfer conditions specifiable for each pipe:
// Transfer conditions specifiable for each pipe for most MCUs
// - Pipe 0: Control transfer with 64-byte single buffer
// - Pipes 1 and 2: Bulk isochronous transfer continuous transfer mode with programmable buffer size up
// to 2 KB and optional double buffer
// - Pipes 3 to 5: Bulk transfer continuous transfer mode with programmable buffer size up to 2 KB and
// optional double buffer
// - Pipes 6 to 9: Interrupt transfer with 64-byte single buffer
enum {
PIPE_1ST_BULK = 3,
PIPE_1ST_INTERRUPT = 6,
PIPE_COUNT = 10,
};

static unsigned find_pipe(unsigned xfer) {
switch ( xfer ) {
case TUSB_XFER_ISOCHRONOUS:
for (int i = 1; i < PIPE_1ST_BULK; ++i) {
if ( 0 == _hcd.pipe[i].ep ) return i;
}
break;

case TUSB_XFER_BULK:
for (int i = PIPE_1ST_BULK; i < PIPE_1ST_INTERRUPT; ++i) {
if ( 0 == _hcd.pipe[i].ep ) return i;
}
for (int i = 1; i < PIPE_1ST_BULK; ++i) {
if ( 0 == _hcd.pipe[i].ep ) return i;
}
break;
// - Pipes 1 and 2: Bulk or ISO
// - Pipes 3 to 5: Bulk
// - Pipes 6 to 9: Interrupt
//
// Note: for small mcu such as
// - RA2A1: only pipe 4-7 are available, and no support for ISO
static unsigned find_pipe(unsigned xfer_type) {
const uint8_t pipe_idx_arr[4][2] = {
{ 0, 0 }, // Control
{ 1, 2 }, // Isochronous
{ 1, 5 }, // Bulk
{ 6, 9 }, // Interrupt
};

case TUSB_XFER_INTERRUPT:
for (int i = PIPE_1ST_INTERRUPT; i < PIPE_COUNT; ++i) {
if ( 0 == _hcd.pipe[i].ep ) return i;
}
break;
// find backward since only pipe 1, 2 support ISO
const uint8_t idx_first = pipe_idx_arr[xfer_type][0];
const uint8_t idx_last = pipe_idx_arr[xfer_type][1];

default:
/* No support for control transfer */
break;
for (int i = idx_last; i >= idx_first; i--) {
if (0 == _hcd.pipe[i].ep) return i;
}

return 0;
}

Expand Down Expand Up @@ -718,7 +705,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
}

rusb->PIPECFG = cfg;
rusb->BRDYSTS = 0x1FFu ^ TU_BIT(num);
rusb->BRDYSTS = 0x3FFu ^ TU_BIT(num);
rusb->NRDYENB |= TU_BIT(num);
rusb->BRDYENB |= TU_BIT(num);

Expand Down Expand Up @@ -846,14 +833,10 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) {
unsigned s = rusb->BRDYSTS & m;
/* clear active bits (don't write 0 to already cleared bits according to the HW manual) */
rusb->BRDYSTS = ~s;
while (s) {
#if defined(__CCRX__)
const unsigned num = Mod37BitPosition[(-s & s) % 37];
#else
const unsigned num = __builtin_ctz(s);
#endif
process_pipe_brdy(rhport, num);
s &= ~TU_BIT(num);
for (unsigned p = 0; p < PIPE_COUNT; ++p) {
if (tu_bit_test(s, p)) {
process_pipe_brdy(rhport, p);
}
}
}
}
Expand Down
Loading