nrf52 cdc example work on nrf52840pdk

- add tud_cdc_flush(), auto flush with sof is enabled by default.
-
This commit is contained in:
hathach 2018-03-20 18:33:06 +07:00
parent 7a628f4dfc
commit 2f0fcf80e0
4 changed files with 64 additions and 28 deletions

View File

@ -134,12 +134,10 @@ static void power_usb_event_handler(nrf_drv_power_usb_evt_t event)
nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half); nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half);
// Enable interrupt // Enable interrupt. SOF is used as CDC auto flush
NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_ACCESSFAULT_Msk | NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_ACCESSFAULT_Msk |
USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk |
USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk | USBD_INTEN_EPDATA_Msk | USBD_INTEN_SOF_Msk;
/*USBD_INTEN_STARTED_Msk |*/ USBD_INTEN_EPDATA_Msk ;
//USBD_INTEN_SOF_Msk
// if (enable_sof || nrf_drv_usbd_errata_104()) // if (enable_sof || nrf_drv_usbd_errata_104())
// { // {
@ -200,7 +198,7 @@ bool tusb_dcd_init (uint8_t port)
{ {
.handler = power_usb_event_handler .handler = power_usb_event_handler
}; };
VERIFY( NRF_SUCCESS == nrf_drv_power_usbevt_init(&config) ); return ( NRF_SUCCESS == nrf_drv_power_usbevt_init(&config) );
} }
void tusb_dcd_connect (uint8_t port) void tusb_dcd_connect (uint8_t port)
@ -215,7 +213,6 @@ void tusb_dcd_disconnect (uint8_t port)
void tusb_dcd_set_address (uint8_t port, uint8_t dev_addr) void tusb_dcd_set_address (uint8_t port, uint8_t dev_addr)
{ {
(void) port; (void) port;
// Set Address is automatically update by hw controller // Set Address is automatically update by hw controller
} }
@ -223,7 +220,6 @@ void tusb_dcd_set_config (uint8_t port, uint8_t config_num)
{ {
(void) port; (void) port;
(void) config_num; (void) config_num;
// Nothing to do // Nothing to do
} }
@ -330,16 +326,24 @@ void tusb_dcd_control_stall (uint8_t port)
*------------------------------------------------------------------*/ *------------------------------------------------------------------*/
static void normal_xact_start(uint8_t epnum, uint8_t dir) static void normal_xact_start(uint8_t epnum, uint8_t dir)
{ {
// Each transaction is up to Max Packet Size
nom_xfer_t* xfer = &_dcd.xfer[dir][epnum-1]; nom_xfer_t* xfer = &_dcd.xfer[dir][epnum-1];
// 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);
if ( dir == TUSB_DIR_OUT ) if ( dir == TUSB_DIR_OUT )
{ {
// HW issue on nrf5284 sample, SIZE.EPOUT won't trigger ACK as spec
// use the back door interface as sdk for walk around
#if 0
// Overwrite size will allow hw to 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
*((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7C5 + 2*epnum;
*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = 0;
(void) (((volatile uint32_t *)(NRF_USBD_BASE + 0x804)));
#endif
}else }else
{ {
NRF_USBD->EPIN[epnum].PTR = (uint32_t) xfer->buffer; NRF_USBD->EPIN[epnum].PTR = (uint32_t) xfer->buffer;
@ -413,10 +417,19 @@ void tusb_dcd_edpt_clear_stall (uint8_t port, uint8_t ep_addr)
} }
// TODO may remove
bool tusb_dcd_edpt_busy (uint8_t port, uint8_t ep_addr) bool tusb_dcd_edpt_busy (uint8_t port, uint8_t ep_addr)
{ {
return true; (void) port;
// USBD shouldn't check control endpoint state
if ( 0 == ep_addr ) return false;
uint8_t const epnum = edpt_number(ep_addr);
uint8_t const dir = edpt_dir(ep_addr);
nom_xfer_t* xfer = &_dcd.xfer[dir][epnum-1];
return xfer->actual_len < xfer->total_len;
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
@ -443,7 +456,6 @@ void USBD_IRQHandler(void)
} }
/*------------- Interrupt Processing -------------*/ /*------------- Interrupt Processing -------------*/
if ( int_status & USBD_INTEN_USBRESET_Msk ) if ( int_status & USBD_INTEN_USBRESET_Msk )
{ {
bus_reset(); bus_reset();
@ -451,6 +463,11 @@ void USBD_IRQHandler(void)
tusb_dcd_bus_event(0, USBD_BUS_EVENT_RESET); tusb_dcd_bus_event(0, USBD_BUS_EVENT_RESET);
} }
if ( int_status & USBD_INTEN_SOF_Msk )
{
tusb_dcd_bus_event(0, USBD_BUS_EVENT_SOF);
}
if ( int_status & EDPT_END_ALL_MASK ) if ( int_status & EDPT_END_ALL_MASK )
{ {
// DMA complete move data from SRAM -> Endpoint // DMA complete move data from SRAM -> Endpoint
@ -524,7 +541,7 @@ void USBD_IRQHandler(void)
normal_xact_start(epnum, TUSB_DIR_IN); normal_xact_start(epnum, TUSB_DIR_IN);
} else } else
{ {
// xfer complete // BULK/INT IN complete
tusb_dcd_xfer_complete(0, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, true); tusb_dcd_xfer_complete(0, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, true);
} }
} }
@ -562,10 +579,23 @@ void USBD_IRQHandler(void)
if ( (NRF_USBD->EPOUT[epnum].AMOUNT == xfer->mps) && (xfer->actual_len < xfer->total_len) ) if ( (NRF_USBD->EPOUT[epnum].AMOUNT == xfer->mps) && (xfer->actual_len < xfer->total_len) )
{ {
// Allow Host -> Endpoint // Allow Host -> Endpoint
// HW issue on nrf5284 sample, SIZE.EPOUT won't trigger ACK as spec
// use the back door interface as sdk for walk around
#if 0
// 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
*((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7C5 + 2*epnum;
*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = 0;
(void) (((volatile uint32_t *)(NRF_USBD_BASE + 0x804)));
#endif
}else }else
{ {
xfer->total_len = xfer->actual_len;
// BULK/INT OUT complete
tusb_dcd_xfer_complete(0, epnum, xfer->actual_len, true); tusb_dcd_xfer_complete(0, epnum, xfer->actual_len, true);
} }
} }

View File

@ -280,18 +280,24 @@ tusb_error_t cdcd_xfer_cb(uint8_t port, uint8_t ep_addr, tusb_event_t event, uin
return TUSB_ERROR_NONE; return TUSB_ERROR_NONE;
} }
void cdcd_sof(uint8_t port) bool tud_n_cdc_flush (uint8_t port)
{ {
if ( !tud_n_cdc_connected(port) ) return; VERIFY( tud_n_cdc_connected(port) );
uint8_t edpt = cdcd_data[port].ep_addr[CDC_PIPE_DATA_IN]; uint8_t edpt = cdcd_data[port].ep_addr[CDC_PIPE_DATA_IN];
if ( !tusb_dcd_edpt_busy(port, edpt) ) VERIFY( !tusb_dcd_edpt_busy(port, edpt) );
{
uint16_t count = fifo_read_n(&_tx_ff, _tmp_tx_buf, sizeof(_tmp_tx_buf));
TU_ASSERT( tusb_dcd_edpt_xfer(port, edpt, _tmp_tx_buf, count, false), TUSB_ERROR_DCD_EDPT_XFER);
} uint16_t count = fifo_read_n(&_tx_ff, _tmp_tx_buf, sizeof(_tmp_tx_buf));
TU_ASSERT( tusb_dcd_edpt_xfer(port, edpt, _tmp_tx_buf, count, false) );
return true;
}
void cdcd_sof(uint8_t port)
{
tud_n_cdc_flush(port);
} }
#endif #endif

View File

@ -63,18 +63,20 @@ uint32_t tud_n_cdc_read (uint8_t port, void* buffer, uint32_t bufsize);
uint32_t tud_n_cdc_write_char (uint8_t port, char ch); uint32_t tud_n_cdc_write_char (uint8_t port, char ch);
uint32_t tud_n_cdc_write (uint8_t port, void const* buffer, uint32_t bufsize); uint32_t tud_n_cdc_write (uint8_t port, void const* buffer, uint32_t bufsize);
bool tud_n_cdc_flush (uint8_t port);
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// APPLICATION API (Single Port) // APPLICATION API (Single Port)
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
static inline bool tud_cdc_connected (void) { return tud_n_cdc_connected(0); } static inline bool tud_cdc_connected (void) { return tud_n_cdc_connected(0); }
static inline uint32_t tud_cdc_available (void) { return tud_n_cdc_available(0); } static inline uint32_t tud_cdc_available (void) { return tud_n_cdc_available(0); }
static inline int tud_cdc_read_char (void) { return tud_n_cdc_read_char(0); } static inline int tud_cdc_read_char (void) { return tud_n_cdc_read_char(0); }
static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize) { return tud_n_cdc_read(0, buffer, bufsize); } static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize) { return tud_n_cdc_read(0, buffer, bufsize); }
static inline uint32_t tud_cdc_write_char (char ch) { return tud_n_cdc_write_char(0, ch); } static inline uint32_t tud_cdc_write_char (char ch) { return tud_n_cdc_write_char(0, ch); }
static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize) { return tud_n_cdc_write(0, buffer, bufsize); } static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize) { return tud_n_cdc_write(0, buffer, bufsize); }
static inline bool tud_cdc_flush (void) { return tud_n_cdc_flush(0); }
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// APPLICATION CALLBACK API // APPLICATION CALLBACK API

View File

@ -87,13 +87,11 @@ void tusb_dcd_control_stall (uint8_t port);
bool tusb_dcd_edpt_open (uint8_t port, tusb_descriptor_endpoint_t const * p_endpoint_desc); bool tusb_dcd_edpt_open (uint8_t port, tusb_descriptor_endpoint_t const * p_endpoint_desc);
bool tusb_dcd_edpt_xfer (uint8_t port, uint8_t edpt_addr, uint8_t * buffer, uint16_t total_bytes, bool int_on_complete); bool tusb_dcd_edpt_xfer (uint8_t port, uint8_t edpt_addr, uint8_t * buffer, uint16_t total_bytes, bool int_on_complete);
bool tusb_dcd_edpt_queue_xfer (uint8_t port, uint8_t edpt_addr, uint8_t * buffer, uint16_t total_bytes); // only queue, not transferring yet bool tusb_dcd_edpt_queue_xfer (uint8_t port, uint8_t edpt_addr, uint8_t * buffer, uint16_t total_bytes); // only queue, not transferring yet
bool tusb_dcd_edpt_busy (uint8_t port, uint8_t edpt_addr);
void tusb_dcd_edpt_stall (uint8_t port, uint8_t edpt_addr); void tusb_dcd_edpt_stall (uint8_t port, uint8_t edpt_addr);
void tusb_dcd_edpt_clear_stall (uint8_t port, uint8_t edpt_addr); void tusb_dcd_edpt_clear_stall (uint8_t port, uint8_t edpt_addr);
// TODO may remove
bool tusb_dcd_edpt_busy (uint8_t port, uint8_t edpt_addr);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif