Non-working custom feeder. Modified nordic driver to disable automatic EP0STATUS task triggering at end of DMA transfer

pull/10689/head
George Beckstein 2018-12-05 15:49:09 -05:00 committed by aglass0fmilk
parent 16b3511fc1
commit bb65ee0ef6
2 changed files with 101 additions and 42 deletions

View File

@ -26,6 +26,16 @@ extern "C" {
}
class USBPhyHw : public USBPhy {
public:
// Keep track of setup transaction stages
typedef enum transaction_state_t {
SetupStage,
DataStage,
StatusStage
} transaction_state_t;
public:
USBPhyHw();
virtual ~USBPhyHw();
@ -64,6 +74,10 @@ public:
static void _usb_event_handler(nrf_drv_usbd_evt_t const * const p_event);
static void _usb_power_event_handler(nrf_drv_power_usb_evt_t event);
bool setup_feeder(nrf_drv_usbd_ep_transfer_t * p_next,
void * p_context,
size_t ep_size);
private:
USBPhyEvents *events;
@ -88,6 +102,15 @@ private:
// Buffer to hold setup packet
nrf_drv_usbd_setup_t setup_buf;
// State of the setup transaction
transaction_state_t setup_state;
// Setup bytes remaining
uint32_t setup_remaining;
// EP0 IN feeder
nrf_drv_usbd_handler_desc_t ep0_in_handler;
// Nordic transfer structures for each in/out endpoint
nrf_drv_usbd_transfer_t transfer_buf[18];

View File

@ -27,7 +27,7 @@
#define IS_OUT_EP(ep) (ep & ~0x80) // Checks if the given endpoint is an OUT endpoint (MSB clear)
// Debugging flag for tracking USB events
#define USBD_DEBUG 1
#define USBD_DEBUG 0
// Nordic USBD driver IRQ handler
extern "C" void USBD_IRQHandler(void);
@ -36,6 +36,7 @@ static USBPhyHw *instance = 0;
static void usbd_event_handler(nrf_drv_usbd_evt_t const * const p_event);
static void power_usb_event_handler(nrf_drv_power_usb_evt_t event);
bool mbed_nrf_feeder_ep0(nrf_drv_usbd_ep_transfer_t * p_next, void * p_context, size_t ep_size);
#if USBD_DEBUG
@ -233,16 +234,42 @@ uint32_t USBPhyHw::ep0_read_result() {
}
void USBPhyHw::ep0_write(uint8_t *buffer, uint32_t size) {
// First transaction chunk, transition to data stage
if(setup_state == USBPhyHw::SetupStage)
{
setup_state = USBPhyHw::DataStage;
// Give the feeder function information to pass on thru DMA
setup_remaining = setup_buf.wLength;
nrf_drv_usbd_transfer_t* transfer = get_transfer_buffer((usb_ep_t)(NRF_DRV_USBD_EPIN0));
memset(transfer, 0, sizeof(nrf_drv_usbd_transfer_t));
transfer->p_data.tx = buffer;
transfer->size = size;
nrf_drv_usbd_ep_transfer(NRF_DRV_USBD_EPIN0, transfer);
// Setup the handler
ep0_in_handler.handler.feeder = mbed_nrf_feeder_ep0;
ep0_in_handler.p_context = NULL;
// Initiate the transfer
nrf_drv_usbd_ep_handled_transfer(NRF_DRV_USBD_EPIN0,
&ep0_in_handler);
}
else if(setup_state == USBPhyHw::DataStage)
{
// Just subtract from the remaining and setup the transfer
//setup_remaining -= size;
nrf_drv_usbd_transfer_t* transfer = get_transfer_buffer((usb_ep_t)(NRF_DRV_USBD_EPIN0));
memset(transfer, 0, sizeof(nrf_drv_usbd_transfer_t));
transfer->p_data.tx = buffer;
transfer->size = size;
}
}
void USBPhyHw::ep0_stall() {
// Note: This stall must be automatically cleared by the next setup packet
// TODO: Check if this is actually happening
// Hardware appears to take care of this
// See nRF52840 product specification section 6.35.8
nrf_drv_usbd_setup_stall();
}
@ -284,6 +311,12 @@ bool USBPhyHw::endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size) {
memset(transfer, 0, sizeof(nrf_drv_usbd_transfer_t));
transfer->p_data.tx = data;
transfer->size = size;
// If this is a zero-length-packet (ZLP)
// Set the ZLP flag
if(size == 0)
transfer->flags |= NRF_DRV_USBD_TRANSFER_ZLP_FLAG;
ret_code_t ret = nrf_drv_usbd_ep_transfer(get_nordic_endpoint(endpoint), transfer);
return (ret == NRF_SUCCESS);
}
@ -298,7 +331,7 @@ void USBPhyHw::process() {
return;
else if (usb_event_type == USB_HW_EVENT_USBD) {
#ifdef USBD_DEBUG
#if USBD_DEBUG
// Save this event to the static log
memcpy(&debug_events[debug_evt_index++], &usb_event, sizeof(nrf_drv_usbd_evt_t));
// Reset index if we overflow the buffer
@ -353,15 +386,13 @@ void USBPhyHw::process() {
}
break;
case NRF_DRV_USBD_EVT_SETUP: {
// Clear endpoint 0 stalls on setup packet receive
if(nrf_drv_usbd_ep_stall_check(NRF_DRV_USBD_EPOUT0))
nrf_drv_usbd_ep_stall_clear(NRF_DRV_USBD_EPOUT0);
if(nrf_drv_usbd_ep_stall_check(NRF_DRV_USBD_EPIN0))
nrf_drv_usbd_ep_stall_clear(NRF_DRV_USBD_EPIN0);
// Copy the setup packet into the internal buffer
nrf_drv_usbd_setup_get(&setup_buf);
// Prepare the transfer context for the data stage
setup_state = USBPhyHw::SetupStage;
// Notify the Mbed stack
events->ep0_setup();
}
break;
@ -459,6 +490,22 @@ void USBPhyHw::disable_usb_interrupts(void) {
NRF_POWER_INT_USBPWRRDY_MASK);
}
bool USBPhyHw::setup_feeder(nrf_drv_usbd_ep_transfer_t* p_next, void* p_context, size_t ep_size)
{
// Set up the next DMA transfer
nrf_drv_usbd_transfer_t* transfer = get_transfer_buffer((usb_ep_t)(NRF_DRV_USBD_EPIN0));
p_next->p_data.tx = transfer->p_data.tx;
p_next->size = transfer->size;
setup_remaining -= p_next->size;
// Check if transfer should continue after this, false if:
// 1: the remaining bytes will be 0
// OR 2: the transfer size is < ep max size (including 0)
return !((setup_remaining == 0) ||
(p_next->size < ep_size));
}
static void power_usb_event_handler(nrf_drv_power_usb_evt_t event) {
if(instance) {
// Pass the event on to the USBPhyHW instance
@ -474,8 +521,6 @@ static void usbd_event_handler(nrf_drv_usbd_evt_t const * const p_event) {
}
}
extern "C" {
/**
* @brief Feeder passing data between mbed and nordic USB stacks
*
@ -486,19 +531,10 @@ extern "C" {
* @retval true Continue transfer.
* @retval false This was the last transfer.
*/
bool mbed_nrf_feeder(nrf_drv_usbd_ep_transfer_t * p_next,
bool mbed_nrf_feeder_ep0(nrf_drv_usbd_ep_transfer_t * p_next,
void * p_context,
size_t ep_size)
{
// We don't know if this is the last transfer or not at this level -- mbed doesn't tell us...
// So just tell the nordic layer that the transfer isn't over yet (so don't NAK/STALL)
return true;
MBED_ASSERT(instance != NULL);
return instance->setup_feeder(p_next, p_context, ep_size);
}
}
//extern "C" {
//void USBD_IRQHandler_v(void) { }
//}