add Errata 104 for out transfer, seems to work with cdc bootloader
This commit is contained in:
parent
e7d7cb222a
commit
8af60fded3
|
@ -74,6 +74,7 @@ typedef struct
|
||||||
|
|
||||||
// FIXME Errata 104 walkaround
|
// FIXME Errata 104 walkaround
|
||||||
uint16_t frame_num;
|
uint16_t frame_num;
|
||||||
|
uint8_t prev_size;
|
||||||
} nom_xfer_t;
|
} nom_xfer_t;
|
||||||
|
|
||||||
/*static*/ struct
|
/*static*/ struct
|
||||||
|
@ -142,7 +143,10 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num)
|
||||||
static void edpt_dma_start(uint8_t epnum, uint8_t dir)
|
static void edpt_dma_start(uint8_t epnum, uint8_t dir)
|
||||||
{
|
{
|
||||||
// Only one dma could be active, TODO resolve when this is called in ISR and dma is running
|
// Only one dma could be active, TODO resolve when this is called in ISR and dma is running
|
||||||
while ( _dcd.dma_running ) { }
|
while ( _dcd.dma_running )
|
||||||
|
{
|
||||||
|
TU_ASSERT ( 0 == (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk), );
|
||||||
|
}
|
||||||
|
|
||||||
_dcd.dma_running = true;
|
_dcd.dma_running = true;
|
||||||
|
|
||||||
|
@ -187,25 +191,6 @@ static void control_xact_start(void)
|
||||||
_dcd.control.len -= xact_len;
|
_dcd.control.len -= xact_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
//static void control_xact_done(void)
|
|
||||||
//{
|
|
||||||
// if ( _dcd_data.control.xfer_len > 0 )
|
|
||||||
// {
|
|
||||||
// if ( _dcd_data.control.dir == TUSB_DIR_OUT )
|
|
||||||
// {
|
|
||||||
// // out control need to wait for END EPOUT event before updating Pointer
|
|
||||||
// edpt_dma_start(0, TUSB_DIR_OUT);
|
|
||||||
// }else
|
|
||||||
// {
|
|
||||||
// control_xact_start();
|
|
||||||
// }
|
|
||||||
// }else
|
|
||||||
// {
|
|
||||||
// dcd_xfer_complete(0, 0, 0, true);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
bool dcd_control_xfer (uint8_t rhport, tusb_dir_t dir, uint8_t * buffer, uint16_t length)
|
bool dcd_control_xfer (uint8_t rhport, tusb_dir_t dir, uint8_t * buffer, uint16_t length)
|
||||||
{
|
{
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
|
@ -310,7 +295,8 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
|
||||||
// FIXME Errata 104 walkaround
|
// FIXME Errata 104 walkaround
|
||||||
if ( nrf_drv_usbd_errata_104() )
|
if ( nrf_drv_usbd_errata_104() )
|
||||||
{
|
{
|
||||||
xfer->frame_num = (uint16_t) NRF_USBD->FRAMECNTR;
|
xfer->frame_num = (uint16_t) NRF_USBD->FRAMECNTR;
|
||||||
|
xfer->prev_size = NRF_USBD->SIZE.EPOUT[epnum];
|
||||||
}
|
}
|
||||||
|
|
||||||
normal_xact_start(epnum, dir);
|
normal_xact_start(epnum, dir);
|
||||||
|
@ -360,22 +346,35 @@ bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr)
|
||||||
/*------------------------------------------------------------------*/
|
/*------------------------------------------------------------------*/
|
||||||
/*
|
/*
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static uint16_t frame_sofar(uint16_t fr)
|
||||||
|
{
|
||||||
|
uint16_t diff = (uint16_t) NRF_USBD->FRAMECNTR;
|
||||||
|
|
||||||
|
if ( diff > fr )
|
||||||
|
{
|
||||||
|
diff -= fr;
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
diff = (diff + 1024) - fr; // Frame counter cap at 1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void USBD_IRQHandler(void)
|
void USBD_IRQHandler(void)
|
||||||
{
|
{
|
||||||
uint32_t const inten = NRF_USBD->INTEN;
|
uint32_t const inten = NRF_USBD->INTEN;
|
||||||
uint32_t int_status = 0;
|
uint32_t int_status = 0;
|
||||||
|
|
||||||
volatile uint32_t* regclr = &NRF_USBD->EVENTS_USBRESET;
|
volatile uint32_t* regevt = &NRF_USBD->EVENTS_USBRESET;
|
||||||
|
|
||||||
for(int i=0; i<32; i++)
|
for(int i=0; i<32; i++)
|
||||||
{
|
{
|
||||||
if ( BIT_TEST_(inten, i) && regclr[i] )
|
if ( BIT_TEST_(inten, i) && regevt[i] )
|
||||||
{
|
{
|
||||||
int_status |= BIT_(i);
|
int_status |= BIT_(i);
|
||||||
|
|
||||||
// nrf_usbd_event_clear()
|
// event clear
|
||||||
regclr[i] = 0;
|
regevt[i] = 0;
|
||||||
|
|
||||||
__ISB(); __DSB();
|
__ISB(); __DSB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,9 +425,9 @@ void USBD_IRQHandler(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OUT data moved from Endpoint -> SRAM
|
||||||
if ( int_status & USBD_INTEN_ENDEPOUT0_Msk)
|
if ( int_status & USBD_INTEN_ENDEPOUT0_Msk)
|
||||||
{
|
{
|
||||||
// OUT data moved from Endpoint -> SRAM
|
|
||||||
if ( _dcd.control.len > 0 )
|
if ( _dcd.control.len > 0 )
|
||||||
{
|
{
|
||||||
control_xact_start();
|
control_xact_start();
|
||||||
|
@ -476,6 +475,14 @@ void USBD_IRQHandler(void)
|
||||||
|
|
||||||
uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[epnum];
|
uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[epnum];
|
||||||
|
|
||||||
|
TU_ASSERT(xfer->actual_len < xfer->total_len, );
|
||||||
|
// FIXME Errata 104 walkaround
|
||||||
|
if ( nrf_drv_usbd_errata_104() )
|
||||||
|
{
|
||||||
|
xfer->prev_size = xact_len;
|
||||||
|
xfer->frame_num = (uint16_t) NRF_USBD->FRAMECNTR;
|
||||||
|
}
|
||||||
|
|
||||||
// Trigger DMA move data from Endpoint -> SRAM
|
// Trigger DMA move data from Endpoint -> SRAM
|
||||||
NRF_USBD->EPOUT[epnum].PTR = (uint32_t) xfer->buffer;
|
NRF_USBD->EPOUT[epnum].PTR = (uint32_t) xfer->buffer;
|
||||||
NRF_USBD->EPOUT[epnum].MAXCNT = xact_len;
|
NRF_USBD->EPOUT[epnum].MAXCNT = xact_len;
|
||||||
|
@ -516,12 +523,39 @@ void USBD_IRQHandler(void)
|
||||||
// SOF interrupt
|
// SOF interrupt
|
||||||
if ( int_status & USBD_INTEN_SOF_Msk )
|
if ( int_status & USBD_INTEN_SOF_Msk )
|
||||||
{
|
{
|
||||||
#if 0
|
dcd_bus_event(0, USBD_BUS_EVENT_SOF);
|
||||||
|
|
||||||
|
#if 1
|
||||||
// FIXME Errata 104 The EPDATA event might not be generated, and the related update of EPDATASTATUS does not occur.
|
// FIXME Errata 104 The EPDATA event might not be generated, and the related update of EPDATASTATUS does not occur.
|
||||||
// There is no way for software to tell if a xfer is complete or not.
|
// There is no way for software to tell if a xfer is complete or not.
|
||||||
// Walkaround: we will asssume an non-control IN transfer is always complete after 10 frames
|
// Walkaround: we will asssume an non-control IN transfer is always complete after 10 frames
|
||||||
if ( nrf_drv_usbd_errata_104() )
|
if ( nrf_drv_usbd_errata_104() )
|
||||||
{
|
{
|
||||||
|
// Check all OUT transfer, if the SIZE changes --> consider it is complete
|
||||||
|
for (int ep=1; ep<= 8; ep++)
|
||||||
|
{
|
||||||
|
nom_xfer_t* xfer = get_td(ep, TUSB_DIR_OUT);
|
||||||
|
if ((xfer->actual_len < xfer->total_len) && (xfer->prev_size != NRF_USBD->SIZE.EPOUT[ep]) )
|
||||||
|
{
|
||||||
|
if ( frame_sofar(xfer->frame_num) > 2)
|
||||||
|
{
|
||||||
|
uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[ep];
|
||||||
|
xfer->prev_size = xact_len;
|
||||||
|
xfer->frame_num = (uint16_t) NRF_USBD->FRAMECNTR;
|
||||||
|
|
||||||
|
// Trigger DMA move data from Endpoint -> SRAM
|
||||||
|
NRF_USBD->EPOUT[ep].PTR = (uint32_t) xfer->buffer;
|
||||||
|
NRF_USBD->EPOUT[ep].MAXCNT = xact_len;
|
||||||
|
|
||||||
|
edpt_dma_start(ep, TUSB_DIR_OUT);
|
||||||
|
|
||||||
|
xfer->buffer += xact_len;
|
||||||
|
xfer->actual_len += xact_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
// Check all the queued IN transfer, retire all transfer if 10 frames has passed
|
// Check all the queued IN transfer, retire all transfer if 10 frames has passed
|
||||||
for (int ep=1; ep<= 8; ep++)
|
for (int ep=1; ep<= 8; ep++)
|
||||||
{
|
{
|
||||||
|
@ -529,28 +563,18 @@ void USBD_IRQHandler(void)
|
||||||
|
|
||||||
if (xfer->actual_len < xfer->total_len)
|
if (xfer->actual_len < xfer->total_len)
|
||||||
{
|
{
|
||||||
uint16_t diff = (uint16_t) NRF_USBD->FRAMECNTR;
|
|
||||||
|
|
||||||
if ( diff > xfer->frame_num )
|
|
||||||
{
|
|
||||||
diff -= xfer->frame_num;
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
diff = (diff + 1024) - xfer->frame_num; // Frame counter cap at 1024
|
|
||||||
}
|
|
||||||
|
|
||||||
// Walkaround, mark this transfer as complete
|
// Walkaround, mark this transfer as complete
|
||||||
if (diff > 10)
|
if (frame_sofar(xfer->frame_num) > 10)
|
||||||
{
|
{
|
||||||
xfer->actual_len = xfer->total_len;
|
xfer->actual_len = xfer->total_len;
|
||||||
dcd_xfer_complete(0, ep | TUSB_DIR_IN_MASK, xfer->actual_len, true);
|
dcd_xfer_complete(0, ep | TUSB_DIR_IN_MASK, xfer->actual_len, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dcd_bus_event(0, USBD_BUS_EVENT_SOF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue