Merge pull request #874 from kkitayam/add_xfer_fifo_for_rx63
Add dcd_edpt_xfer_fifo() for RX63N
This commit is contained in:
@@ -86,7 +86,10 @@
|
|||||||
CFG_TUSB_MCU == OPT_MCU_STM32F4 || \
|
CFG_TUSB_MCU == OPT_MCU_STM32F4 || \
|
||||||
CFG_TUSB_MCU == OPT_MCU_STM32F7 || \
|
CFG_TUSB_MCU == OPT_MCU_STM32F7 || \
|
||||||
CFG_TUSB_MCU == OPT_MCU_STM32H7 || \
|
CFG_TUSB_MCU == OPT_MCU_STM32H7 || \
|
||||||
(CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS))
|
(CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \
|
||||||
|
CFG_TUSB_MCU == OPT_MCU_RX63X || \
|
||||||
|
CFG_TUSB_MCU == OPT_MCU_RX65X || \
|
||||||
|
CFG_TUSB_MCU == OPT_MCU_RX72N
|
||||||
#define USE_LINEAR_BUFFER 0
|
#define USE_LINEAR_BUFFER 0
|
||||||
#else
|
#else
|
||||||
#define USE_LINEAR_BUFFER 1
|
#define USE_LINEAR_BUFFER 1
|
||||||
|
|||||||
@@ -122,11 +122,12 @@ typedef union {
|
|||||||
|
|
||||||
typedef struct TU_ATTR_PACKED
|
typedef struct TU_ATTR_PACKED
|
||||||
{
|
{
|
||||||
uintptr_t addr; /* the start address of a transfer data buffer */
|
void *buf; /* the start address of a transfer data buffer */
|
||||||
uint16_t length; /* the number of bytes in the buffer */
|
uint16_t length; /* the number of bytes in the buffer */
|
||||||
uint16_t remaining; /* the number of bytes remaining in the buffer */
|
uint16_t remaining; /* the number of bytes remaining in the buffer */
|
||||||
struct {
|
struct {
|
||||||
uint32_t ep : 8; /* an assigned endpoint address */
|
uint32_t ep : 8; /* an assigned endpoint address */
|
||||||
|
uint32_t ff : 1; /* `buf` is TU_FUFO or POD */
|
||||||
uint32_t : 0;
|
uint32_t : 0;
|
||||||
};
|
};
|
||||||
} pipe_state_t;
|
} pipe_state_t;
|
||||||
@@ -236,34 +237,27 @@ static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr)
|
|||||||
return ctr;
|
return ctr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned wait_for_pipe_ready(void)
|
static unsigned edpt0_max_packet_size(void)
|
||||||
{
|
{
|
||||||
unsigned ctr;
|
return USB0.DCPMAXP.BIT.MXPS;
|
||||||
do {
|
|
||||||
ctr = USB0.D0FIFOCTR.WORD;
|
|
||||||
} while (!(ctr & USB_FIFOCTR_FRDY));
|
|
||||||
return ctr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned select_pipe(unsigned num, unsigned attr)
|
static unsigned edpt_max_packet_size(unsigned num)
|
||||||
|
{
|
||||||
|
USB0.PIPESEL.WORD = num;
|
||||||
|
return USB0.PIPEMAXP.WORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pipe_wait_for_ready(unsigned num)
|
||||||
{
|
{
|
||||||
USB0.PIPESEL.WORD = num;
|
|
||||||
USB0.D0FIFOSEL.WORD = num | attr;
|
|
||||||
while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ;
|
while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ;
|
||||||
return wait_for_pipe_ready();
|
while (!USB0.D0FIFOCTR.BIT.FRDY) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 1 less than mps bytes were written to FIFO
|
static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len)
|
||||||
* 2 no bytes were written to FIFO
|
|
||||||
* 0 mps bytes were written to FIFO */
|
|
||||||
static int fifo_write(volatile void *fifo, pipe_state_t* pipe, unsigned mps)
|
|
||||||
{
|
{
|
||||||
unsigned rem = pipe->remaining;
|
|
||||||
if (!rem) return 2;
|
|
||||||
unsigned len = TU_MIN(rem, mps);
|
|
||||||
|
|
||||||
hw_fifo_t *reg = (hw_fifo_t*)fifo;
|
hw_fifo_t *reg = (hw_fifo_t*)fifo;
|
||||||
uintptr_t addr = pipe->addr + pipe->length - rem;
|
uintptr_t addr = (uintptr_t)buf;
|
||||||
while (len >= 2) {
|
while (len >= 2) {
|
||||||
reg->u16 = *(const uint16_t *)addr;
|
reg->u16 = *(const uint16_t *)addr;
|
||||||
addr += 2;
|
addr += 2;
|
||||||
@@ -273,31 +267,147 @@ static int fifo_write(volatile void *fifo, pipe_state_t* pipe, unsigned mps)
|
|||||||
reg->u8 = *(const uint8_t *)addr;
|
reg->u8 = *(const uint8_t *)addr;
|
||||||
++addr;
|
++addr;
|
||||||
}
|
}
|
||||||
if (rem < mps) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 1 less than mps bytes were read from FIFO
|
static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len)
|
||||||
* 2 the end of the buffer reached.
|
|
||||||
* 0 mps bytes were read from FIFO */
|
|
||||||
static int fifo_read(volatile void *fifo, pipe_state_t* pipe, unsigned mps, size_t len)
|
|
||||||
{
|
{
|
||||||
unsigned rem = pipe->remaining;
|
uint8_t *p = (uint8_t*)buf;
|
||||||
if (!rem) return 2;
|
|
||||||
if (rem < len) len = rem;
|
|
||||||
pipe->remaining = rem - len;
|
|
||||||
|
|
||||||
uint8_t *reg = (uint8_t*)fifo; /* byte access is always at base register address */
|
uint8_t *reg = (uint8_t*)fifo; /* byte access is always at base register address */
|
||||||
uintptr_t addr = pipe->addr;
|
while (len--) *p++ = *reg;
|
||||||
unsigned loop = len;
|
}
|
||||||
while (loop--) {
|
|
||||||
*(uint8_t *)addr = *reg;
|
static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir)
|
||||||
++addr;
|
{
|
||||||
|
static const struct {
|
||||||
|
void (*tu_fifo_get_info)(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
|
||||||
|
void (*tu_fifo_advance)(tu_fifo_t *f, uint16_t n);
|
||||||
|
void (*pipe_read_write)(void *buf, volatile void *fifo, unsigned len);
|
||||||
|
} ops[] = {
|
||||||
|
/* OUT */ {tu_fifo_get_write_info,tu_fifo_advance_write_pointer,pipe_read_packet},
|
||||||
|
/* IN */ {tu_fifo_get_read_info, tu_fifo_advance_read_pointer, pipe_write_packet},
|
||||||
|
};
|
||||||
|
tu_fifo_buffer_info_t info;
|
||||||
|
ops[dir].tu_fifo_get_info(f, &info);
|
||||||
|
unsigned total_len = len;
|
||||||
|
len = TU_MIN(total_len, info.len_lin);
|
||||||
|
ops[dir].pipe_read_write(info.ptr_lin, fifo, len);
|
||||||
|
unsigned rem = total_len - len;
|
||||||
|
if (rem) {
|
||||||
|
len = TU_MIN(rem, info.len_wrap);
|
||||||
|
ops[dir].pipe_read_write(info.ptr_wrap, fifo, len);
|
||||||
|
rem -= len;
|
||||||
}
|
}
|
||||||
pipe->addr = addr;
|
ops[dir].tu_fifo_advance(f, total_len - rem);
|
||||||
if (rem < mps) return 1;
|
}
|
||||||
if (rem == len) return 2;
|
|
||||||
return 0;
|
static bool pipe0_xfer_in(void)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
void *buf = pipe->buf;
|
||||||
|
if (len) {
|
||||||
|
if (pipe->ff) {
|
||||||
|
pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&USB0.CFIFO.WORD, len, TUSB_DIR_IN);
|
||||||
|
} else {
|
||||||
|
pipe_write_packet(buf, (volatile void*)&USB0.CFIFO.WORD, len);
|
||||||
|
pipe->buf = (uint8_t*)buf + len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len < mps) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL;
|
||||||
|
pipe->remaining = rem - len;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool pipe0_xfer_out(void)
|
||||||
|
{
|
||||||
|
pipe_state_t *pipe = &_dcd.pipe[0];
|
||||||
|
const unsigned rem = pipe->remaining;
|
||||||
|
|
||||||
|
const unsigned mps = edpt0_max_packet_size();
|
||||||
|
const unsigned vld = USB0.CFIFOCTR.BIT.DTLN;
|
||||||
|
const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
|
||||||
|
void *buf = pipe->buf;
|
||||||
|
if (len) {
|
||||||
|
if (pipe->ff) {
|
||||||
|
pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&USB0.CFIFO.WORD, len, TUSB_DIR_OUT);
|
||||||
|
} else {
|
||||||
|
pipe_read_packet(buf, (volatile void*)&USB0.CFIFO.WORD, len);
|
||||||
|
pipe->buf = (uint8_t*)buf + len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len < mps) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR;
|
||||||
|
pipe->remaining = rem - len;
|
||||||
|
if ((len < mps) || (rem == len)) {
|
||||||
|
pipe->buf = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool pipe_xfer_in(unsigned num)
|
||||||
|
{
|
||||||
|
pipe_state_t *pipe = &_dcd.pipe[num];
|
||||||
|
const unsigned rem = pipe->remaining;
|
||||||
|
|
||||||
|
if (!rem) {
|
||||||
|
pipe->buf = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0);
|
||||||
|
const unsigned mps = edpt_max_packet_size(num);
|
||||||
|
pipe_wait_for_ready(num);
|
||||||
|
const unsigned len = TU_MIN(rem, mps);
|
||||||
|
void *buf = pipe->buf;
|
||||||
|
if (len) {
|
||||||
|
if (pipe->ff) {
|
||||||
|
pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&USB0.D0FIFO.WORD, len, TUSB_DIR_IN);
|
||||||
|
} else {
|
||||||
|
pipe_write_packet(buf, (volatile void*)&USB0.D0FIFO.WORD, len);
|
||||||
|
pipe->buf = (uint8_t*)buf + len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len < mps) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL;
|
||||||
|
USB0.D0FIFOSEL.WORD = 0;
|
||||||
|
while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */
|
||||||
|
pipe->remaining = rem - len;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool pipe_xfer_out(unsigned num)
|
||||||
|
{
|
||||||
|
pipe_state_t *pipe = &_dcd.pipe[num];
|
||||||
|
const unsigned rem = pipe->remaining;
|
||||||
|
|
||||||
|
USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_8;
|
||||||
|
const unsigned mps = edpt_max_packet_size(num);
|
||||||
|
pipe_wait_for_ready(num);
|
||||||
|
const unsigned vld = USB0.D0FIFOCTR.BIT.DTLN;
|
||||||
|
const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
|
||||||
|
void *buf = pipe->buf;
|
||||||
|
if (len) {
|
||||||
|
if (pipe->ff) {
|
||||||
|
pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&USB0.D0FIFO.WORD, len, TUSB_DIR_OUT);
|
||||||
|
} else {
|
||||||
|
pipe_read_packet(buf, (volatile void*)&USB0.D0FIFO.WORD, len);
|
||||||
|
pipe->buf = (uint8_t*)buf + len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len < mps) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BCLR;
|
||||||
|
USB0.D0FIFOSEL.WORD = 0;
|
||||||
|
while (USB0.D0FIFOSEL.BIT.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)
|
static void process_setup_packet(uint8_t rhport)
|
||||||
@@ -327,11 +437,8 @@ static void process_status_completion(uint8_t rhport)
|
|||||||
dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true);
|
dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
|
static bool process_pipe0_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
|
||||||
{
|
{
|
||||||
(void)rhport;
|
|
||||||
|
|
||||||
pipe_state_t *pipe = &_dcd.pipe[0];
|
|
||||||
/* configure fifo direction and access unit settings */
|
/* configure fifo direction and access unit settings */
|
||||||
if (ep_addr) { /* IN, 2 bytes */
|
if (ep_addr) { /* IN, 2 bytes */
|
||||||
USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0);
|
USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0);
|
||||||
@@ -340,84 +447,53 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer,
|
|||||||
USB0.CFIFOSEL.WORD = USB_FIFOSEL_MBW_8;
|
USB0.CFIFOSEL.WORD = USB_FIFOSEL_MBW_8;
|
||||||
while (USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX) ;
|
while (USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pipe_state_t *pipe = &_dcd.pipe[0];
|
||||||
|
pipe->ff = buffer_type;
|
||||||
|
pipe->length = total_bytes;
|
||||||
|
pipe->remaining = total_bytes;
|
||||||
if (total_bytes) {
|
if (total_bytes) {
|
||||||
pipe->addr = (uintptr_t)buffer;
|
pipe->buf = buffer;
|
||||||
pipe->length = total_bytes;
|
|
||||||
pipe->remaining = total_bytes;
|
|
||||||
if (ep_addr) { /* IN */
|
if (ep_addr) { /* IN */
|
||||||
TU_ASSERT(USB0.DCPCTR.BIT.BSTS && (USB0.USBREQ.WORD & 0x80));
|
TU_ASSERT(USB0.DCPCTR.BIT.BSTS && (USB0.USBREQ.WORD & 0x80));
|
||||||
if (fifo_write((void*)&USB0.CFIFO.WORD, pipe, 64)) {
|
pipe0_xfer_in();
|
||||||
USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
USB0.DCPCTR.WORD = USB_PIPECTR_PID_BUF;
|
USB0.DCPCTR.WORD = USB_PIPECTR_PID_BUF;
|
||||||
} else {
|
} else {
|
||||||
/* ZLP */
|
/* ZLP */
|
||||||
pipe->addr = 0;
|
pipe->buf = NULL;
|
||||||
pipe->length = 0;
|
|
||||||
pipe->remaining = 0;
|
|
||||||
USB0.DCPCTR.WORD = USB_PIPECTR_CCPL | USB_PIPECTR_PID_BUF;
|
USB0.DCPCTR.WORD = USB_PIPECTR_CCPL | USB_PIPECTR_PID_BUF;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_edpt0_bemp(uint8_t rhport)
|
static bool process_pipe_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
|
||||||
{
|
{
|
||||||
pipe_state_t *pipe = &_dcd.pipe[0];
|
|
||||||
const unsigned rem = pipe->remaining;
|
|
||||||
if (rem > 64) {
|
|
||||||
pipe->remaining = rem - 64;
|
|
||||||
int r = fifo_write((void*)&USB0.CFIFO.WORD, &_dcd.pipe[0], 64);
|
|
||||||
if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pipe->addr = 0;
|
|
||||||
pipe->remaining = 0;
|
|
||||||
dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN),
|
|
||||||
pipe->length, XFER_RESULT_SUCCESS, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void process_edpt0_brdy(uint8_t rhport)
|
|
||||||
{
|
|
||||||
size_t len = USB0.CFIFOCTR.BIT.DTLN;
|
|
||||||
int cplt = fifo_read((void*)&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, len);
|
|
||||||
if (cplt || (len < 64)) {
|
|
||||||
if (2 != cplt) {
|
|
||||||
USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR;
|
|
||||||
}
|
|
||||||
dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_OUT),
|
|
||||||
_dcd.pipe[0].length - _dcd.pipe[0].remaining,
|
|
||||||
XFER_RESULT_SUCCESS, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
|
|
||||||
{
|
|
||||||
(void)rhport;
|
|
||||||
|
|
||||||
const unsigned epn = tu_edpt_number(ep_addr);
|
const unsigned epn = tu_edpt_number(ep_addr);
|
||||||
const unsigned dir = tu_edpt_dir(ep_addr);
|
const unsigned dir = tu_edpt_dir(ep_addr);
|
||||||
const unsigned num = _dcd.ep[dir][epn];
|
const unsigned num = _dcd.ep[dir][epn];
|
||||||
|
|
||||||
TU_ASSERT(num);
|
TU_ASSERT(num);
|
||||||
|
|
||||||
pipe_state_t *pipe = &_dcd.pipe[num];
|
pipe_state_t *pipe = &_dcd.pipe[num];
|
||||||
pipe->addr = (uintptr_t)buffer;
|
pipe->ff = buffer_type;
|
||||||
|
pipe->buf = buffer;
|
||||||
pipe->length = total_bytes;
|
pipe->length = total_bytes;
|
||||||
pipe->remaining = total_bytes;
|
pipe->remaining = total_bytes;
|
||||||
|
|
||||||
USB0.PIPESEL.WORD = num;
|
|
||||||
const unsigned mps = USB0.PIPEMAXP.WORD;
|
|
||||||
if (dir) { /* IN */
|
if (dir) { /* IN */
|
||||||
USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0);
|
if (total_bytes) {
|
||||||
while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ;
|
pipe_xfer_in(num);
|
||||||
int r = fifo_write((void*)&USB0.D0FIFO.WORD, pipe, mps);
|
} else { /* ZLP */
|
||||||
if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL;
|
USB0.D0FIFOSEL.WORD = num;
|
||||||
USB0.D0FIFOSEL.WORD = 0;
|
pipe_wait_for_ready(num);
|
||||||
while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */
|
USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL;
|
||||||
|
USB0.D0FIFOSEL.WORD = 0;
|
||||||
|
while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
volatile reg_pipetre_t *pt = get_pipetre(num);
|
volatile reg_pipetre_t *pt = get_pipetre(num);
|
||||||
if (pt) {
|
if (pt) {
|
||||||
|
const unsigned mps = edpt_max_packet_size(num);
|
||||||
volatile uint16_t *ctr = get_pipectr(num);
|
volatile uint16_t *ctr = get_pipectr(num);
|
||||||
if (*ctr & 0x3) *ctr = USB_PIPECTR_PID_NAK;
|
if (*ctr & 0x3) *ctr = USB_PIPECTR_PID_NAK;
|
||||||
pt->TRE = TU_BIT(8);
|
pt->TRE = TU_BIT(8);
|
||||||
@@ -426,51 +502,50 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer,
|
|||||||
*ctr = USB_PIPECTR_PID_BUF;
|
*ctr = USB_PIPECTR_PID_BUF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TU_LOG1("X %x %d\r\n", ep_addr, total_bytes);
|
// TU_LOG1("X %x %d %d\r\n", ep_addr, total_bytes, buffer_type);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool process_edpt_xfer(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);
|
||||||
|
} else {
|
||||||
|
return process_pipe_xfer(buffer_type, ep_addr, buffer, total_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_pipe0_bemp(uint8_t rhport)
|
||||||
|
{
|
||||||
|
bool completed = pipe0_xfer_in();
|
||||||
|
if (completed) {
|
||||||
|
pipe_state_t *pipe = &_dcd.pipe[0];
|
||||||
|
dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN),
|
||||||
|
pipe->length, XFER_RESULT_SUCCESS, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void process_pipe_brdy(uint8_t rhport, unsigned num)
|
static void process_pipe_brdy(uint8_t rhport, unsigned num)
|
||||||
{
|
{
|
||||||
pipe_state_t *pipe = &_dcd.pipe[num];
|
pipe_state_t *pipe = &_dcd.pipe[num];
|
||||||
if (tu_edpt_dir(pipe->ep)) { /* IN */
|
const unsigned dir = tu_edpt_dir(pipe->ep);
|
||||||
select_pipe(num, USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0));
|
bool completed;
|
||||||
const unsigned mps = USB0.PIPEMAXP.WORD;
|
|
||||||
unsigned rem = pipe->remaining;
|
if (dir) { /* IN */
|
||||||
rem -= TU_MIN(rem, mps);
|
completed = pipe_xfer_in(num);
|
||||||
pipe->remaining = rem;
|
|
||||||
if (rem) {
|
|
||||||
int r = 0;
|
|
||||||
r = fifo_write((void*)&USB0.D0FIFO.WORD, pipe, mps);
|
|
||||||
if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL;
|
|
||||||
USB0.D0FIFOSEL.WORD = 0;
|
|
||||||
while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
USB0.D0FIFOSEL.WORD = 0;
|
|
||||||
while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */
|
|
||||||
pipe->addr = 0;
|
|
||||||
pipe->remaining = 0;
|
|
||||||
dcd_event_xfer_complete(rhport, pipe->ep, pipe->length,
|
|
||||||
XFER_RESULT_SUCCESS, true);
|
|
||||||
} else {
|
} else {
|
||||||
const unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_8);
|
if (num) {
|
||||||
const unsigned len = ctr & USB_FIFOCTR_DTLN;
|
completed = pipe_xfer_out(num);
|
||||||
const unsigned mps = USB0.PIPEMAXP.WORD;
|
} else {
|
||||||
int cplt = fifo_read((void*)&USB0.D0FIFO.WORD, pipe, mps, len);
|
completed = pipe0_xfer_out();
|
||||||
if (cplt || (len < mps)) {
|
|
||||||
if (2 != cplt) {
|
|
||||||
USB0.D0FIFO.WORD = USB_FIFOCTR_BCLR;
|
|
||||||
}
|
|
||||||
USB0.D0FIFOSEL.WORD = 0;
|
|
||||||
while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */
|
|
||||||
dcd_event_xfer_complete(rhport, pipe->ep,
|
|
||||||
pipe->length - pipe->remaining,
|
|
||||||
XFER_RESULT_SUCCESS, true);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
USB0.D0FIFOSEL.WORD = 0;
|
}
|
||||||
while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */
|
if (completed) {
|
||||||
|
dcd_event_xfer_complete(rhport, pipe->ep,
|
||||||
|
pipe->length - pipe->remaining,
|
||||||
|
XFER_RESULT_SUCCESS, true);
|
||||||
|
// TU_LOG1("C %d %d\r\n", num, pipe->length - pipe->remaining);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,7 +724,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
|
|||||||
if (dir || (xfer != TUSB_XFER_BULK)) {
|
if (dir || (xfer != TUSB_XFER_BULK)) {
|
||||||
*ctr = USB_PIPECTR_PID_BUF;
|
*ctr = USB_PIPECTR_PID_BUF;
|
||||||
}
|
}
|
||||||
// TU_LOG1("O %d %x %x\r\n", USB0.PIPESEL.WORD, USB0.PIPECFG.WORD, USB0.PIPEMAXP.WORD);
|
// TU_LOG1("O %d %x %x\r\n", USB0.PIPESEL.WORD, USB0.PIPECFG.WORD, USB0.PIPEMAXP.WORD);
|
||||||
dcd_int_enable(rhport);
|
dcd_int_enable(rhport);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -674,13 +749,19 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
|
|||||||
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
|
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
|
||||||
{
|
{
|
||||||
bool r;
|
bool r;
|
||||||
const unsigned epn = tu_edpt_number(ep_addr);
|
|
||||||
dcd_int_disable(rhport);
|
dcd_int_disable(rhport);
|
||||||
if (0 == epn) {
|
r = process_edpt_xfer(0, ep_addr, buffer, total_bytes);
|
||||||
r = process_edpt0_xfer(rhport, ep_addr, buffer, total_bytes);
|
dcd_int_enable(rhport);
|
||||||
} else {
|
return r;
|
||||||
r = process_pipe_xfer(rhport, ep_addr, buffer, total_bytes);
|
}
|
||||||
}
|
|
||||||
|
bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
|
||||||
|
{
|
||||||
|
// USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1
|
||||||
|
TU_ASSERT(ff->item_size == 1);
|
||||||
|
bool r;
|
||||||
|
dcd_int_disable(rhport);
|
||||||
|
r = process_edpt_xfer(1, ep_addr, ff, total_bytes);
|
||||||
dcd_int_enable(rhport);
|
dcd_int_enable(rhport);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -779,7 +860,7 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
const unsigned s = USB0.BEMPSTS.WORD;
|
const unsigned s = USB0.BEMPSTS.WORD;
|
||||||
USB0.BEMPSTS.WORD = 0;
|
USB0.BEMPSTS.WORD = 0;
|
||||||
if (s & 1) {
|
if (s & 1) {
|
||||||
process_edpt0_bemp(rhport);
|
process_pipe0_bemp(rhport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is0 & USB_IS0_BRDY) {
|
if (is0 & USB_IS0_BRDY) {
|
||||||
@@ -787,10 +868,6 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
unsigned s = USB0.BRDYSTS.WORD & m;
|
unsigned s = USB0.BRDYSTS.WORD & m;
|
||||||
/* clear active bits (don't write 0 to already cleared bits according to the HW manual) */
|
/* clear active bits (don't write 0 to already cleared bits according to the HW manual) */
|
||||||
USB0.BRDYSTS.WORD = ~s;
|
USB0.BRDYSTS.WORD = ~s;
|
||||||
if (s & 1) {
|
|
||||||
process_edpt0_brdy(rhport);
|
|
||||||
s &= ~1;
|
|
||||||
}
|
|
||||||
while (s) {
|
while (s) {
|
||||||
#if defined(__CCRX__)
|
#if defined(__CCRX__)
|
||||||
static const int Mod37BitPosition[] = {
|
static const int Mod37BitPosition[] = {
|
||||||
|
|||||||
Reference in New Issue
Block a user