improve nrf52 dcd, add fix for hw ACK issue with bulk

This commit is contained in:
hathach
2018-06-13 17:13:12 +07:00
parent d1ecef4fc3
commit 2b85a8fd46
2 changed files with 80 additions and 41 deletions

View File

@@ -66,13 +66,7 @@ typedef struct {
}cdcd_interface_t; }cdcd_interface_t;
// TODO multiple rhport // TODO multiple rhport
#if CFG_TUSB_MCU == OPT_MCU_NRF5X
// FIXME nrf52 OUT bug ( Controller ACK data even we didn't prepare transfer )
CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_rx_buf[600];
#else
CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_rx_buf[64]; CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_rx_buf[64];
#endif
CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_tx_buf[64]; CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_tx_buf[64];
FIFO_DEF(_rx_ff, CFG_TUD_CDC_BUFSIZE, uint8_t, true); FIFO_DEF(_rx_ff, CFG_TUD_CDC_BUFSIZE, uint8_t, true);

View File

@@ -70,6 +70,9 @@ typedef struct
uint16_t actual_len; uint16_t actual_len;
uint8_t mps; // max packet size uint8_t mps; // max packet size
// FIXME nrf52840 does not NAK OUT packet properly
bool data_received;
} nom_xfer_t; } nom_xfer_t;
/*static*/ struct /*static*/ struct
@@ -163,7 +166,7 @@ static void edpt_dma_end(void)
_dcd.dma_running = false; _dcd.dma_running = false;
} }
static void control_xact_start(void) static void xact_control_start(void)
{ {
// Each transaction is up to 64 bytes // Each transaction is up to 64 bytes
uint8_t const xact_len = min16_of(_dcd.control.total_len-_dcd.control.actual_len, MAX_PACKET_SIZE); uint8_t const xact_len = min16_of(_dcd.control.total_len-_dcd.control.actual_len, MAX_PACKET_SIZE);
@@ -200,7 +203,7 @@ bool dcd_control_xfer (uint8_t rhport, tusb_dir_t dir, uint8_t * buffer, uint16_
_dcd.control.buffer = buffer; _dcd.control.buffer = buffer;
_dcd.control.dir = (uint8_t) dir; _dcd.control.dir = (uint8_t) dir;
control_xact_start(); xact_control_start();
}else }else
{ {
// Status Phase // Status Phase
@@ -220,16 +223,45 @@ static inline nom_xfer_t* get_td(uint8_t epnum, uint8_t dir)
return &_dcd.xfer[epnum-1][dir]; return &_dcd.xfer[epnum-1][dir];
} }
static void normal_xact_start(uint8_t epnum, uint8_t dir) /*------------- Bulk/Int OUT transfer -------------*/
/**
* Prepare Bulk/Int out transaction, Endpoint start to accept/ACK Data
* @param epnum
*/
static void xact_out_prepare(uint8_t epnum)
{ {
if ( dir == TUSB_DIR_OUT ) // Write any value to size will allow hw to ACK (accept data)
{
// Overwrite size will allow hw to accept data
NRF_USBD->SIZE.EPOUT[epnum] = 0; NRF_USBD->SIZE.EPOUT[epnum] = 0;
__ISB(); __DSB(); __ISB(); __DSB();
}else }
{
nom_xfer_t* xfer = get_td(epnum, dir); static void xact_out_dma(uint8_t epnum)
{
nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_OUT);
uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[epnum];
// Trigger DMA move data from Endpoint -> SRAM
NRF_USBD->EPOUT[epnum].PTR = (uint32_t) xfer->buffer;
NRF_USBD->EPOUT[epnum].MAXCNT = xact_len;
edpt_dma_start(epnum, TUSB_DIR_OUT);
xfer->buffer += xact_len;
xfer->actual_len += xact_len;
}
/*------------- Bulk/Int IN transfer -------------*/
/**
* Prepare Bulk/Int in transaction, transfer data from Memory -> Endpoint
* @param epnum
*/
static void xact_in_prepare(uint8_t epnum)
{
nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_IN);
// Each transaction is up to Max Packet Size // Each transaction is up to Max Packet Size
uint8_t const xact_len = min16_of(xfer->total_len - xfer->actual_len, xfer->mps); uint8_t const xact_len = min16_of(xfer->total_len - xfer->actual_len, xfer->mps);
@@ -240,7 +272,6 @@ static void normal_xact_start(uint8_t epnum, uint8_t dir)
xfer->buffer += xact_len; xfer->buffer += xact_len;
edpt_dma_start(epnum, TUSB_DIR_IN); edpt_dma_start(epnum, TUSB_DIR_IN);
}
} }
bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
@@ -279,7 +310,23 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
xfer->total_len = total_bytes; xfer->total_len = total_bytes;
xfer->actual_len = 0; xfer->actual_len = 0;
normal_xact_start(epnum, dir); if ( dir == TUSB_DIR_OUT )
{
if ( xfer->data_received )
{
xfer->data_received = false;
// FIXME nrf52840 does not NAK OUT packet properly
// Data already received preivously
xact_out_dma(epnum);
}else
{
xact_out_prepare(epnum);
}
}else
{
xact_in_prepare(epnum);
}
return true; return true;
} }
@@ -382,7 +429,7 @@ void USBD_IRQHandler(void)
// IN: data transferred from Endpoint -> Host // IN: data transferred from Endpoint -> Host
if ( _dcd.control.actual_len < _dcd.control.total_len ) if ( _dcd.control.actual_len < _dcd.control.total_len )
{ {
control_xact_start(); xact_control_start();
}else }else
{ {
// Control IN complete // Control IN complete
@@ -396,7 +443,7 @@ void USBD_IRQHandler(void)
{ {
if ( _dcd.control.actual_len < _dcd.control.total_len ) if ( _dcd.control.actual_len < _dcd.control.total_len )
{ {
control_xact_start(); xact_control_start();
}else }else
{ {
// Control OUT complete // Control OUT complete
@@ -423,7 +470,7 @@ void USBD_IRQHandler(void)
if ( xfer->actual_len < xfer->total_len ) if ( xfer->actual_len < xfer->total_len )
{ {
// more to xfer // more to xfer
normal_xact_start(epnum, TUSB_DIR_IN); xact_in_prepare(epnum);
} else } else
{ {
// BULK/INT IN complete // BULK/INT IN complete
@@ -439,19 +486,17 @@ void USBD_IRQHandler(void)
{ {
nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_OUT); nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_OUT);
uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[epnum]; if (xfer->actual_len < xfer->total_len)
{
xact_out_dma(epnum);
}else
{
// FIXME nrf52840 does not NAK OUT packet properly
// It will always ACK next package although we haven't write to SIZE yet
// FIXME nrf52840 rev A does not NAK OUT packet properly // Mark this endpoint with data received
TU_ASSERT(xfer->actual_len < xfer->total_len, ); xfer->data_received = true;
}
// Trigger DMA move data from Endpoint -> SRAM
NRF_USBD->EPOUT[epnum].PTR = (uint32_t) xfer->buffer;
NRF_USBD->EPOUT[epnum].MAXCNT = xact_len;
edpt_dma_start(epnum, TUSB_DIR_OUT);
xfer->buffer += xact_len;
xfer->actual_len += xact_len;
} }
} }
} }
@@ -469,7 +514,7 @@ void USBD_IRQHandler(void)
if ( (xact_len == xfer->mps) && (xfer->actual_len < xfer->total_len) ) if ( (xact_len == xfer->mps) && (xfer->actual_len < xfer->total_len) )
{ {
// Prepare for more data from Host -> Endpoint // Prepare for more data from Host -> Endpoint
normal_xact_start(epnum, TUSB_DIR_OUT); xact_out_prepare(epnum);
}else }else
{ {
xfer->total_len = xfer->actual_len; xfer->total_len = xfer->actual_len;