mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-17 05:32:55 +08:00
more multiple ports update
This commit is contained in:
parent
95b77a0e73
commit
1eefc2b3ef
@ -63,22 +63,11 @@
|
||||
// MACRO TYPEDEF CONSTANT ENUM
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/* LINK core registers */
|
||||
#if defined(__CCRX__)
|
||||
#define RUSB2 ((rusb2_reg_t __evenaccess*) RUSB2_REG_BASE)
|
||||
#elif defined(__RX__)
|
||||
#define RUSB2 ((rusb2_reg_t*) RUSB2_REG_BASE)
|
||||
#elif (CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE)
|
||||
#define RUSB2 ((R_USB_HS0_Type*)R_USB_HS0_BASE)
|
||||
#else
|
||||
#define RUSB2 ((R_USB_FS0_Type*)R_USB_FS0_BASE)
|
||||
#endif
|
||||
|
||||
/* 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 TU_ATTR_PACKED _ccrx_evenaccess {
|
||||
union {
|
||||
struct {
|
||||
uint16_t : 8;
|
||||
@ -186,52 +175,53 @@ static unsigned find_pipe(unsigned xfer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static volatile uint16_t* get_pipectr(unsigned num)
|
||||
static volatile uint16_t* get_pipectr(rusb2_reg_t *rusb, unsigned num)
|
||||
{
|
||||
if (num) {
|
||||
return (volatile uint16_t*)&(RUSB2->PIPE_CTR[num - 1]);
|
||||
return (volatile uint16_t*)&(rusb->PIPE_CTR[num - 1]);
|
||||
} else {
|
||||
return (volatile uint16_t*)&(RUSB2->DCPCTR);
|
||||
return (volatile uint16_t*)&(rusb->DCPCTR);
|
||||
}
|
||||
}
|
||||
|
||||
static volatile reg_pipetre_t* get_pipetre(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*)&(RUSB2->PIPE_TR[num - 1].E);
|
||||
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)
|
||||
{
|
||||
(void)rhport;
|
||||
rusb2_reg_t *rusb = RUSB2_REG(rhport);
|
||||
const unsigned epn = tu_edpt_number(ep_addr);
|
||||
|
||||
if (epn) {
|
||||
const unsigned dir = tu_edpt_dir(ep_addr);
|
||||
const unsigned num = _dcd.ep[dir][epn];
|
||||
return get_pipectr(num);
|
||||
return get_pipectr(rusb, num);
|
||||
} else {
|
||||
return get_pipectr(0);
|
||||
return get_pipectr(rusb, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned edpt0_max_packet_size(void)
|
||||
static uint16_t edpt0_max_packet_size(rusb2_reg_t* rusb)
|
||||
{
|
||||
return RUSB2->DCPMAXP_b.MXPS;
|
||||
return rusb->DCPMAXP_b.MXPS;
|
||||
}
|
||||
|
||||
static unsigned edpt_max_packet_size(unsigned num)
|
||||
static uint16_t edpt_max_packet_size(rusb2_reg_t *rusb, unsigned num)
|
||||
{
|
||||
RUSB2->PIPESEL = num;
|
||||
return RUSB2->PIPEMAXP;
|
||||
rusb->PIPESEL = num;
|
||||
return rusb->PIPEMAXP;
|
||||
}
|
||||
|
||||
static inline void pipe_wait_for_ready(unsigned num)
|
||||
static inline void pipe_wait_for_ready(rusb2_reg_t * rusb, unsigned num)
|
||||
{
|
||||
while (RUSB2->D0FIFOSEL_b.CURPIPE != num) ;
|
||||
while (!RUSB2->D0FIFOCTR_b.FRDY) ;
|
||||
while ( rusb->D0FIFOSEL_b.CURPIPE != num ) {}
|
||||
while ( !rusb->D0FIFOCTR_b.FRDY ) {}
|
||||
}
|
||||
|
||||
static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len)
|
||||
@ -284,61 +274,70 @@ static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigne
|
||||
ops[dir].tu_fifo_advance(f, total_len - rem);
|
||||
}
|
||||
|
||||
static bool pipe0_xfer_in(void)
|
||||
static bool pipe0_xfer_in(rusb2_reg_t* rusb)
|
||||
{
|
||||
pipe_state_t *pipe = &_dcd.pipe[0];
|
||||
const unsigned rem = pipe->remaining;
|
||||
|
||||
if (!rem) {
|
||||
pipe->buf = NULL;
|
||||
return true;
|
||||
}
|
||||
const unsigned mps = edpt0_max_packet_size();
|
||||
const unsigned len = TU_MIN(mps, rem);
|
||||
|
||||
const uint16_t mps = edpt0_max_packet_size(rusb);
|
||||
const uint16_t len = tu_min16(mps, rem);
|
||||
void *buf = pipe->buf;
|
||||
|
||||
if (len) {
|
||||
if (pipe->ff) {
|
||||
pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&RUSB2->CFIFO, len, TUSB_DIR_IN);
|
||||
pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len, TUSB_DIR_IN);
|
||||
} else {
|
||||
pipe_write_packet(buf, (volatile void*)&RUSB2->CFIFO, len);
|
||||
pipe_write_packet(buf, (volatile void*)&rusb->CFIFO, len);
|
||||
pipe->buf = (uint8_t*)buf + len;
|
||||
}
|
||||
}
|
||||
|
||||
if (len < mps) {
|
||||
RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
|
||||
rusb->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
|
||||
}
|
||||
|
||||
pipe->remaining = rem - len;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool pipe0_xfer_out(void)
|
||||
static bool pipe0_xfer_out(rusb2_reg_t* rusb)
|
||||
{
|
||||
pipe_state_t *pipe = &_dcd.pipe[0];
|
||||
const unsigned rem = pipe->remaining;
|
||||
|
||||
const unsigned mps = edpt0_max_packet_size();
|
||||
const unsigned vld = RUSB2->CFIFOCTR_b.DTLN;
|
||||
const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
|
||||
const uint16_t mps = edpt0_max_packet_size(rusb);
|
||||
const uint16_t vld = rusb->CFIFOCTR_b.DTLN;
|
||||
const uint16_t len = tu_min16(tu_min16(rem, mps), vld);
|
||||
void *buf = pipe->buf;
|
||||
|
||||
if (len) {
|
||||
if (pipe->ff) {
|
||||
pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&RUSB2->CFIFO, len, TUSB_DIR_OUT);
|
||||
pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len, TUSB_DIR_OUT);
|
||||
} else {
|
||||
pipe_read_packet(buf, (volatile void*)&RUSB2->CFIFO, len);
|
||||
pipe_read_packet(buf, (volatile void*)&rusb->CFIFO, len);
|
||||
pipe->buf = (uint8_t*)buf + len;
|
||||
}
|
||||
}
|
||||
|
||||
if (len < mps) {
|
||||
RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
|
||||
rusb->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
|
||||
}
|
||||
|
||||
pipe->remaining = rem - len;
|
||||
if ((len < mps) || (rem == len)) {
|
||||
pipe->buf = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool pipe_xfer_in(unsigned num)
|
||||
static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num)
|
||||
{
|
||||
pipe_state_t *pipe = &_dcd.pipe[num];
|
||||
const unsigned rem = pipe->remaining;
|
||||
@ -348,119 +347,141 @@ static bool pipe_xfer_in(unsigned num)
|
||||
return true;
|
||||
}
|
||||
|
||||
RUSB2->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
|
||||
const unsigned mps = edpt_max_packet_size(num);
|
||||
pipe_wait_for_ready(num);
|
||||
const unsigned len = TU_MIN(rem, mps);
|
||||
rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
|
||||
const uint16_t mps = edpt_max_packet_size(rusb, num);
|
||||
pipe_wait_for_ready(rusb, num);
|
||||
const uint16_t len = tu_min16(rem, mps);
|
||||
void *buf = pipe->buf;
|
||||
|
||||
if (len) {
|
||||
if (pipe->ff) {
|
||||
pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&RUSB2->D0FIFO, len, TUSB_DIR_IN);
|
||||
pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len, TUSB_DIR_IN);
|
||||
} else {
|
||||
pipe_write_packet(buf, (volatile void*)&RUSB2->D0FIFO, len);
|
||||
pipe_write_packet(buf, (volatile void*)&rusb->D0FIFO, len);
|
||||
pipe->buf = (uint8_t*)buf + len;
|
||||
}
|
||||
}
|
||||
|
||||
if (len < mps) {
|
||||
RUSB2->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
|
||||
rusb->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
|
||||
}
|
||||
RUSB2->D0FIFOSEL = 0;
|
||||
while (RUSB2->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
|
||||
|
||||
rusb->D0FIFOSEL = 0;
|
||||
while (rusb->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
|
||||
|
||||
pipe->remaining = rem - len;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool pipe_xfer_out(unsigned num)
|
||||
static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num)
|
||||
{
|
||||
pipe_state_t *pipe = &_dcd.pipe[num];
|
||||
const unsigned rem = pipe->remaining;
|
||||
const uint16_t rem = pipe->remaining;
|
||||
|
||||
RUSB2->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT;
|
||||
const unsigned mps = edpt_max_packet_size(num);
|
||||
pipe_wait_for_ready(num);
|
||||
const unsigned vld = RUSB2->D0FIFOCTR_b.DTLN;
|
||||
const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
|
||||
rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT;
|
||||
const uint16_t mps = edpt_max_packet_size(rusb, num);
|
||||
pipe_wait_for_ready(rusb, num);
|
||||
|
||||
const uint16_t vld = rusb->D0FIFOCTR_b.DTLN;
|
||||
const uint16_t len = tu_min16(tu_min16(rem, mps), vld);
|
||||
void *buf = pipe->buf;
|
||||
|
||||
if (len) {
|
||||
if (pipe->ff) {
|
||||
pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&RUSB2->D0FIFO, len, TUSB_DIR_OUT);
|
||||
pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len, TUSB_DIR_OUT);
|
||||
} else {
|
||||
pipe_read_packet(buf, (volatile void*)&RUSB2->D0FIFO, len);
|
||||
pipe_read_packet(buf, (volatile void*)&rusb->D0FIFO, len);
|
||||
pipe->buf = (uint8_t*)buf + len;
|
||||
}
|
||||
}
|
||||
|
||||
if (len < mps) {
|
||||
RUSB2->D0FIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
|
||||
rusb->D0FIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
|
||||
}
|
||||
RUSB2->D0FIFOSEL = 0;
|
||||
while (RUSB2->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
|
||||
|
||||
rusb->D0FIFOSEL = 0;
|
||||
while (rusb->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
|
||||
|
||||
pipe->remaining = rem - len;
|
||||
if ((len < mps) || (rem == len)) {
|
||||
pipe->buf = NULL;
|
||||
return NULL != buf;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void process_setup_packet(uint8_t rhport)
|
||||
{
|
||||
uint16_t setup_packet[4];
|
||||
if (0 == (RUSB2->INTSTS0 & RUSB2_INTSTS0_VALID_Msk)) return;
|
||||
RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
|
||||
setup_packet[0] = tu_le16toh(RUSB2->USBREQ);
|
||||
setup_packet[1] = RUSB2->USBVAL;
|
||||
setup_packet[2] = RUSB2->USBINDX;
|
||||
setup_packet[3] = RUSB2->USBLENG;
|
||||
RUSB2->INTSTS0 = ~((uint16_t)RUSB2_INTSTS0_VALID_Msk);
|
||||
rusb2_reg_t* rusb = RUSB2_REG(rhport);
|
||||
if (0 == (rusb->INTSTS0 & RUSB2_INTSTS0_VALID_Msk)) return;
|
||||
|
||||
rusb->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
|
||||
uint16_t setup_packet[4] = {
|
||||
tu_htole16(rusb->USBREQ),
|
||||
tu_htole16(rusb->USBVAL),
|
||||
tu_htole16(rusb->USBINDX),
|
||||
tu_htole16(rusb->USBLENG)
|
||||
};
|
||||
|
||||
rusb->INTSTS0 = ~((uint16_t) RUSB2_INTSTS0_VALID_Msk);
|
||||
dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet[0], true);
|
||||
}
|
||||
|
||||
static void process_status_completion(uint8_t rhport)
|
||||
{
|
||||
rusb2_reg_t* rusb = RUSB2_REG(rhport);
|
||||
uint8_t ep_addr;
|
||||
/* Check the data stage direction */
|
||||
if (RUSB2->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) {
|
||||
if (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) {
|
||||
/* IN transfer. */
|
||||
ep_addr = tu_edpt_addr(0, TUSB_DIR_IN);
|
||||
} else {
|
||||
/* OUT transfer. */
|
||||
ep_addr = tu_edpt_addr(0, TUSB_DIR_OUT);
|
||||
}
|
||||
|
||||
dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true);
|
||||
}
|
||||
|
||||
static bool process_pipe0_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
|
||||
static bool process_pipe0_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
|
||||
{
|
||||
/* configure fifo direction and access unit settings */
|
||||
if (ep_addr) { /* IN, 2 bytes */
|
||||
RUSB2->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT |
|
||||
(TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
|
||||
while (!(RUSB2->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) ;
|
||||
} else { /* OUT, a byte */
|
||||
RUSB2->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT;
|
||||
while (RUSB2->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ;
|
||||
if ( ep_addr ) {
|
||||
/* IN, 2 bytes */
|
||||
rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT |
|
||||
(TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
|
||||
while ( !(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ) {}
|
||||
} else {
|
||||
/* OUT, a byte */
|
||||
rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT;
|
||||
while ( rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE ) {}
|
||||
}
|
||||
|
||||
pipe_state_t *pipe = &_dcd.pipe[0];
|
||||
pipe->ff = buffer_type;
|
||||
pipe->length = total_bytes;
|
||||
pipe->remaining = total_bytes;
|
||||
if (total_bytes) {
|
||||
pipe->buf = buffer;
|
||||
if (ep_addr) { /* IN */
|
||||
TU_ASSERT(RUSB2->DCPCTR_b.BSTS && (RUSB2->USBREQ & 0x80));
|
||||
pipe0_xfer_in();
|
||||
|
||||
if ( total_bytes ) {
|
||||
pipe->buf = buffer;
|
||||
if ( ep_addr ) {
|
||||
/* IN */
|
||||
TU_ASSERT(rusb->DCPCTR_b.BSTS && (rusb->USBREQ & 0x80));
|
||||
pipe0_xfer_in(rusb);
|
||||
}
|
||||
RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_BUF;
|
||||
rusb->DCPCTR = RUSB2_PIPE_CTR_PID_BUF;
|
||||
} else {
|
||||
/* ZLP */
|
||||
pipe->buf = NULL;
|
||||
RUSB2->DCPCTR = RUSB2_DCPCTR_CCPL_Msk | RUSB2_PIPE_CTR_PID_BUF;
|
||||
pipe->buf = NULL;
|
||||
rusb->DCPCTR = RUSB2_DCPCTR_CCPL_Msk | RUSB2_PIPE_CTR_PID_BUF;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool process_pipe_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
|
||||
static bool process_pipe_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
|
||||
{
|
||||
const unsigned epn = tu_edpt_number(ep_addr);
|
||||
const unsigned dir = tu_edpt_dir(ep_addr);
|
||||
@ -473,49 +494,55 @@ static bool process_pipe_xfer(int buffer_type, uint8_t ep_addr, void* buffer, ui
|
||||
pipe->buf = buffer;
|
||||
pipe->length = total_bytes;
|
||||
pipe->remaining = total_bytes;
|
||||
if (dir) { /* IN */
|
||||
|
||||
if (dir) {
|
||||
/* IN */
|
||||
if (total_bytes) {
|
||||
pipe_xfer_in(num);
|
||||
} else { /* ZLP */
|
||||
RUSB2->D0FIFOSEL = num;
|
||||
pipe_wait_for_ready(num);
|
||||
RUSB2->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
|
||||
RUSB2->D0FIFOSEL = 0;
|
||||
while (RUSB2->D0FIFOSEL_b.CURPIPE) ; /* if CURPIPE bits changes, check written value */
|
||||
pipe_xfer_in(rusb, num);
|
||||
} else {
|
||||
/* ZLP */
|
||||
rusb->D0FIFOSEL = num;
|
||||
pipe_wait_for_ready(rusb, num);
|
||||
rusb->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
|
||||
rusb->D0FIFOSEL = 0;
|
||||
/* if CURPIPE bits changes, check written value */
|
||||
while (rusb->D0FIFOSEL_b.CURPIPE) {}
|
||||
}
|
||||
} else {
|
||||
#if defined(__CCRX__)
|
||||
__evenaccess volatile reg_pipetre_t *pt = get_pipetre(num);
|
||||
#else
|
||||
volatile reg_pipetre_t *pt = get_pipetre(num);
|
||||
#endif
|
||||
// OUT
|
||||
volatile reg_pipetre_t *pt = get_pipetre(rusb, num);
|
||||
|
||||
if (pt) {
|
||||
const unsigned mps = edpt_max_packet_size(num);
|
||||
volatile uint16_t *ctr = get_pipectr(num);
|
||||
const uint16_t mps = edpt_max_packet_size(rusb, num);
|
||||
volatile uint16_t *ctr = get_pipectr(rusb, num);
|
||||
|
||||
if (*ctr & 0x3) *ctr = RUSB2_PIPE_CTR_PID_NAK;
|
||||
|
||||
pt->TRE = TU_BIT(8);
|
||||
pt->TRN = (total_bytes + mps - 1) / mps;
|
||||
pt->TRENB = 1;
|
||||
*ctr = RUSB2_PIPE_CTR_PID_BUF;
|
||||
}
|
||||
}
|
||||
// TU_LOG1("X %x %d %d\r\n", ep_addr, total_bytes, buffer_type);
|
||||
|
||||
// TU_LOG2("X %x %d %d\r\n", ep_addr, total_bytes, buffer_type);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool process_edpt_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
|
||||
static bool process_edpt_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
|
||||
{
|
||||
const unsigned epn = tu_edpt_number(ep_addr);
|
||||
if (0 == epn) {
|
||||
return process_pipe0_xfer(buffer_type, ep_addr, buffer, total_bytes);
|
||||
return process_pipe0_xfer(rusb, buffer_type, ep_addr, buffer, total_bytes);
|
||||
} else {
|
||||
return process_pipe_xfer(buffer_type, ep_addr, buffer, total_bytes);
|
||||
return process_pipe_xfer(rusb, buffer_type, ep_addr, buffer, total_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void process_pipe0_bemp(uint8_t rhport)
|
||||
{
|
||||
bool completed = pipe0_xfer_in();
|
||||
rusb2_reg_t* rusb = RUSB2_REG(rhport);
|
||||
bool completed = pipe0_xfer_in(rusb);
|
||||
if (completed) {
|
||||
pipe_state_t *pipe = &_dcd.pipe[0];
|
||||
dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN),
|
||||
@ -525,17 +552,20 @@ static void process_pipe0_bemp(uint8_t rhport)
|
||||
|
||||
static void process_pipe_brdy(uint8_t rhport, unsigned num)
|
||||
{
|
||||
rusb2_reg_t* rusb = RUSB2_REG(rhport);
|
||||
pipe_state_t *pipe = &_dcd.pipe[num];
|
||||
const unsigned dir = tu_edpt_dir(pipe->ep);
|
||||
bool completed;
|
||||
|
||||
if (dir) { /* IN */
|
||||
completed = pipe_xfer_in(num);
|
||||
if (dir) {
|
||||
/* IN */
|
||||
completed = pipe_xfer_in(rusb, num);
|
||||
} else {
|
||||
// OUT
|
||||
if (num) {
|
||||
completed = pipe_xfer_out(num);
|
||||
completed = pipe_xfer_out(rusb, num);
|
||||
} else {
|
||||
completed = pipe0_xfer_out();
|
||||
completed = pipe0_xfer_out(rusb);
|
||||
}
|
||||
}
|
||||
if (completed) {
|
||||
@ -606,8 +636,10 @@ static void process_bus_reset(uint8_t rhport)
|
||||
|
||||
static void process_set_address(uint8_t rhport)
|
||||
{
|
||||
const uint32_t addr = RUSB2->USBADDR & 0xFF;
|
||||
rusb2_reg_t* rusb = RUSB2_REG(rhport);
|
||||
const uint32_t addr = rusb->USBADDR & 0xFF;
|
||||
if (!addr) return;
|
||||
|
||||
const tusb_control_request_t setup_packet = {
|
||||
#if defined(__CCRX__)
|
||||
.bmRequestType = { 0 }, /* Note: CCRX needs the braces over this struct member */
|
||||
@ -618,8 +650,9 @@ static void process_set_address(uint8_t rhport)
|
||||
.wValue = addr,
|
||||
.wIndex = 0,
|
||||
.wLength = 0,
|
||||
};
|
||||
dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet, true);
|
||||
};
|
||||
|
||||
dcd_event_setup_received(rhport, (const uint8_t *) &setup_packet, true);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
@ -704,7 +737,7 @@ void dcd_init(uint8_t rhport)
|
||||
rusb->INTSTS0 = 0;
|
||||
rusb->INTENB0 = RUSB2_INTSTS0_VBINT_Msk | RUSB2_INTSTS0_BRDY_Msk | RUSB2_INTSTS0_BEMP_Msk |
|
||||
RUSB2_INTSTS0_DVST_Msk | RUSB2_INTSTS0_CTRT_Msk | (USE_SOF ? RUSB2_INTSTS0_SOFR_Msk : 0) |
|
||||
RUSB2_INTSTS0_RESM_Msk | RUSB2_INTSTS0_NRDY_Msk;
|
||||
RUSB2_INTSTS0_RESM_Msk;
|
||||
rusb->BEMPENB = 1;
|
||||
rusb->BRDYENB = 1;
|
||||
|
||||
@ -766,33 +799,43 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
|
||||
{
|
||||
(void)rhport;
|
||||
|
||||
rusb2_reg_t * rusb = RUSB2_REG(rhport);
|
||||
const unsigned ep_addr = ep_desc->bEndpointAddress;
|
||||
const unsigned epn = tu_edpt_number(ep_addr);
|
||||
const unsigned dir = tu_edpt_dir(ep_addr);
|
||||
const unsigned xfer = ep_desc->bmAttributes.xfer;
|
||||
|
||||
const unsigned mps = tu_edpt_packet_size(ep_desc);
|
||||
if (xfer == TUSB_XFER_ISOCHRONOUS && mps > 256) {
|
||||
/* USBa supports up to 256 bytes */
|
||||
return false;
|
||||
|
||||
if (xfer == TUSB_XFER_ISOCHRONOUS) {
|
||||
// Fullspeed ISO is limit to 256 bytes
|
||||
if ( !is_highspeed(rhport) && mps > 256) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned num = find_pipe(xfer);
|
||||
if (!num) return false;
|
||||
TU_ASSERT(num);
|
||||
|
||||
_dcd.pipe[num].ep = ep_addr;
|
||||
_dcd.ep[dir][epn] = num;
|
||||
|
||||
/* setup pipe */
|
||||
dcd_int_disable(rhport);
|
||||
#if (CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE)
|
||||
RUSB2->PIPEBUF = 0x7C08;
|
||||
#endif
|
||||
RUSB2->PIPESEL = num;
|
||||
RUSB2->PIPEMAXP = mps;
|
||||
volatile uint16_t *ctr = get_pipectr(num);
|
||||
|
||||
if ( is_highspeed(rhport) ) {
|
||||
// FIXME shouldn't be after pipe selection and config, also the BUFNMB should be changed
|
||||
// depending on the allocation scheme
|
||||
rusb->PIPEBUF = 0x7C08;
|
||||
}
|
||||
|
||||
rusb->PIPESEL = num;
|
||||
rusb->PIPEMAXP = mps;
|
||||
volatile uint16_t *ctr = get_pipectr(rusb, num);
|
||||
*ctr = RUSB2_PIPE_CTR_ACLRM_Msk | RUSB2_PIPE_CTR_SQCLR_Msk;
|
||||
*ctr = 0;
|
||||
unsigned cfg = (dir << 4) | epn;
|
||||
|
||||
if (xfer == TUSB_XFER_BULK) {
|
||||
cfg |= (RUSB2_PIPECFG_TYPE_BULK | RUSB2_PIPECFG_SHTNAK_Msk | RUSB2_PIPECFG_DBLB_Msk);
|
||||
} else if (xfer == TUSB_XFER_INTERRUPT) {
|
||||
@ -800,13 +843,16 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
|
||||
} else {
|
||||
cfg |= (RUSB2_PIPECFG_TYPE_ISO | RUSB2_PIPECFG_DBLB_Msk);
|
||||
}
|
||||
RUSB2->PIPECFG = cfg;
|
||||
RUSB2->BRDYSTS = 0x1FFu ^ TU_BIT(num);
|
||||
RUSB2->BRDYENB |= TU_BIT(num);
|
||||
|
||||
rusb->PIPECFG = cfg;
|
||||
rusb->BRDYSTS = 0x1FFu ^ TU_BIT(num);
|
||||
rusb->BRDYENB |= TU_BIT(num);
|
||||
|
||||
if (dir || (xfer != TUSB_XFER_BULK)) {
|
||||
*ctr = RUSB2_PIPE_CTR_PID_BUF;
|
||||
}
|
||||
// TU_LOG1("O %d %x %x\r\n", RUSB2->PIPESEL, RUSB2->PIPECFG, RUSB2->PIPEMAXP);
|
||||
|
||||
// TU_LOG1("O %d %x %x\r\n", rusb->PIPESEL, rusb->PIPECFG, rusb->PIPEMAXP);
|
||||
dcd_int_enable(rhport);
|
||||
|
||||
return true;
|
||||
@ -826,26 +872,28 @@ void dcd_edpt_close_all(uint8_t rhport)
|
||||
|
||||
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void)rhport;
|
||||
rusb2_reg_t * rusb = RUSB2_REG(rhport);
|
||||
const unsigned epn = tu_edpt_number(ep_addr);
|
||||
const unsigned dir = tu_edpt_dir(ep_addr);
|
||||
const unsigned num = _dcd.ep[dir][epn];
|
||||
|
||||
RUSB2->BRDYENB &= ~TU_BIT(num);
|
||||
volatile uint16_t *ctr = get_pipectr(num);
|
||||
rusb->BRDYENB &= ~TU_BIT(num);
|
||||
volatile uint16_t *ctr = get_pipectr(rusb, num);
|
||||
*ctr = 0;
|
||||
RUSB2->PIPESEL = num;
|
||||
RUSB2->PIPECFG = 0;
|
||||
rusb->PIPESEL = num;
|
||||
rusb->PIPECFG = 0;
|
||||
_dcd.pipe[num].ep = 0;
|
||||
_dcd.ep[dir][epn] = 0;
|
||||
}
|
||||
|
||||
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
|
||||
{
|
||||
bool r;
|
||||
rusb2_reg_t* rusb = RUSB2_REG(rhport);
|
||||
|
||||
dcd_int_disable(rhport);
|
||||
r = process_edpt_xfer(0, ep_addr, buffer, total_bytes);
|
||||
bool r = process_edpt_xfer(rusb, 0, ep_addr, buffer, total_bytes);
|
||||
dcd_int_enable(rhport);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -853,10 +901,12 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_
|
||||
{
|
||||
// USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1
|
||||
TU_ASSERT(ff->item_size == 1);
|
||||
bool r;
|
||||
rusb2_reg_t* rusb = RUSB2_REG(rhport);
|
||||
|
||||
dcd_int_disable(rhport);
|
||||
r = process_edpt_xfer(1, ep_addr, ff, total_bytes);
|
||||
bool r = process_edpt_xfer(rusb, 1, ep_addr, ff, total_bytes);
|
||||
dcd_int_enable(rhport);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -873,8 +923,10 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
|
||||
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
rusb2_reg_t * rusb = RUSB2_REG(rhport);
|
||||
volatile uint16_t *ctr = ep_addr_to_pipectr(rhport, ep_addr);
|
||||
if (!ctr) return;
|
||||
|
||||
dcd_int_disable(rhport);
|
||||
*ctr = RUSB2_PIPE_CTR_SQCLR_Msk;
|
||||
|
||||
@ -882,8 +934,8 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
*ctr = RUSB2_PIPE_CTR_PID_BUF;
|
||||
} else {
|
||||
const unsigned num = _dcd.ep[0][tu_edpt_number(ep_addr)];
|
||||
RUSB2->PIPESEL = num;
|
||||
if (RUSB2->PIPECFG_b.TYPE != 1) {
|
||||
rusb->PIPESEL = num;
|
||||
if (rusb->PIPECFG_b.TYPE != 1) {
|
||||
*ctr = RUSB2_PIPE_CTR_PID_BUF;
|
||||
}
|
||||
}
|
||||
@ -953,9 +1005,9 @@ void dcd_int_handler(uint8_t rhport)
|
||||
}
|
||||
}
|
||||
|
||||
if ( is0 & RUSB2_INTSTS0_NRDY_Msk ) {
|
||||
rusb->NRDYSTS = 0;
|
||||
}
|
||||
// if ( is0 & RUSB2_INTSTS0_NRDY_Msk ) {
|
||||
// rusb->NRDYSTS = 0;
|
||||
// }
|
||||
|
||||
// Control transfer stage changes
|
||||
if ( is0 & RUSB2_INTSTS0_CTRT_Msk ) {
|
||||
@ -970,7 +1022,7 @@ void dcd_int_handler(uint8_t rhport)
|
||||
|
||||
// Buffer empty
|
||||
if ( is0 & RUSB2_INTSTS0_BEMP_Msk ) {
|
||||
const unsigned s = rusb->BEMPSTS;
|
||||
const uint16_t s = rusb->BEMPSTS;
|
||||
rusb->BEMPSTS = 0;
|
||||
if ( s & 1 ) {
|
||||
process_pipe0_bemp(rhport);
|
||||
|
@ -37,6 +37,8 @@ extern "C" {
|
||||
|
||||
#define RUSB2_REG_BASE (0x000A0000)
|
||||
|
||||
#define RUSB2_REG(_p) ((rusb2_reg_t *) RUSB2_REG_BASE)
|
||||
|
||||
// Start/Stop MSTP TODO implement later
|
||||
TU_ATTR_ALWAYS_INLINE static inline void rusb2_module_start(uint8_t rhport, bool start) {
|
||||
(void) rhport;
|
||||
|
@ -33,6 +33,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// CCRX specific attribute to generate a Code that Accesses Variables in the Declared Size
|
||||
#ifdef __CCRX__
|
||||
#define _ccrx_evenaccess __evenaccess
|
||||
#else
|
||||
#define _ccrx_evenaccess
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
/* Register Definitions */
|
||||
/*--------------------------------------------------------------------*/
|
||||
@ -64,7 +71,7 @@ typedef struct {
|
||||
|
||||
|
||||
/* RUSB2 Registers Structure */
|
||||
typedef struct {
|
||||
typedef struct _ccrx_evenaccess {
|
||||
union {
|
||||
volatile uint16_t SYSCFG; /* (@ 0x00000000) System Configuration Control Register */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user