Skip to content

Commit

Permalink
fx3_firmware: Clear DMA buffers when disabling an RX or TX module
Browse files Browse the repository at this point in the history
Stale RX and TX samples have been reported (issue #255). This occurs
because the CyU3PResetEp() call does not reset DMA channels and their
underlying DMA buffers, nor does it clear the DMA buffers associated
with an endpoint.

Use of the existing ClearDMAChannel() as is would have required some
ridiculous shoehorning, so some cleanup was done:

    - Endpoint halt & ACK operations have been removed from
      ClearDMAChannel(). These operations are outside of the scope
      of clearing DMA buffers, and have been moved to their respective
      locations in handling set/clear halt endpoint requests.

    - reset_endpoint() has been added to the NuandApplication function
      table. Internally, this operation is now used in performing
      the halt_endpoint() operation.

    - Misc return value checks added. Granted, these don't help much
      as there's no accessible debug log.
  • Loading branch information
jynik committed Jul 19, 2014
1 parent 13267cf commit 55713e8
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 51 deletions.
69 changes: 39 additions & 30 deletions fx3_firmware/bladeRF.c
Expand Up @@ -235,23 +235,28 @@ CyBool_t GetStatus(uint16_t endpoint) {
return isHandled;
}

void ClearDMAChannel(uint8_t ep, CyU3PDmaChannel * handle, uint32_t count,
CyBool_t stall_only) {

CyU3PReturnStatus_t ClearDMAChannel(uint8_t ep,
CyU3PDmaChannel * handle,
uint32_t count)
{
CyU3PReturnStatus_t status;

CyU3PDmaChannelReset (handle);
CyU3PUsbFlushEp(ep);
CyU3PUsbResetEp(ep);
status = CyU3PDmaChannelSetXfer (handle, count);
status = CyU3PDmaChannelReset(handle);
if (status != CY_U3P_SUCCESS) {
return status;
}

if (status == CY_U3P_SUCCESS) {
CyU3PUsbStall (ep, CyFalse, CyTrue);
status = CyU3PUsbFlushEp(ep);
if (status != CY_U3P_SUCCESS) {
return status;
}

if(!stall_only) {
CyU3PUsbAckSetup ();
}
status = CyU3PUsbResetEp(ep);
if (status != CY_U3P_SUCCESS) {
return status;
}

return CyU3PDmaChannelSetXfer (handle, count);
}

CyBool_t ClearHaltCondition(uint16_t endpoint) {
Expand Down Expand Up @@ -353,15 +358,6 @@ CyBool_t NuandHandleVendorRequest(
apiRetStatus = CY_U3P_SUCCESS;
use_feature = wValue;

if (!use_feature) {
apiRetStatus = CyU3PUsbResetEp(BLADE_RF_SAMPLE_EP_CONSUMER);
if(apiRetStatus != CY_U3P_SUCCESS) {
CyU3PDebugPrint (4,
"Failed reset USB, error code = %d\n",
apiRetStatus);
}
}

CyU3PGpioGetValue(GPIO_TX_EN, &txen) ;
CyU3PGpioGetValue(GPIO_RX_EN, &rxen) ;
if (txen == CyFalse && rxen == CyFalse) {
Expand All @@ -370,22 +366,24 @@ CyBool_t NuandHandleVendorRequest(
}

CyU3PGpioSetValue(GPIO_RX_EN, use_feature ? CyTrue : CyFalse);
CyU3PUsbSendRetCode(apiRetStatus);
break;

case BLADE_USB_CMD_RF_TX:
apiRetStatus = CY_U3P_SUCCESS;
use_feature = wValue;

if (!use_feature) {
apiRetStatus = CyU3PUsbResetEp(BLADE_RF_SAMPLE_EP_PRODUCER);
const uint8_t ep = BLADE_RF_SAMPLE_EP_CONSUMER;
apiRetStatus = NuandRFLink.reset_endpoint(ep);
if(apiRetStatus != CY_U3P_SUCCESS) {
CyU3PDebugPrint (4,
"Failed reset USB, error code = %d\n",
apiRetStatus);
"Failed reset ep %u, error code = %d\n",
ep, apiRetStatus);
}
}

CyU3PUsbSendRetCode(apiRetStatus);
break;

case BLADE_USB_CMD_RF_TX:
apiRetStatus = CY_U3P_SUCCESS;
use_feature = wValue;

CyU3PGpioGetValue(GPIO_TX_EN, &txen) ;
CyU3PGpioGetValue(GPIO_RX_EN, &rxen) ;
if (txen == CyFalse && rxen == CyFalse) {
Expand All @@ -394,6 +392,17 @@ CyBool_t NuandHandleVendorRequest(
}

CyU3PGpioSetValue(GPIO_TX_EN, use_feature ? CyTrue : CyFalse);

if (!use_feature) {
const uint8_t ep = BLADE_RF_SAMPLE_EP_PRODUCER;
apiRetStatus = NuandRFLink.reset_endpoint(ep);
if(apiRetStatus != CY_U3P_SUCCESS) {
CyU3PDebugPrint (4,
"Failed reset ep %u, error code = %d\n",
ep, apiRetStatus);
}
}

CyU3PUsbSendRetCode(apiRetStatus);
break;

Expand Down
4 changes: 3 additions & 1 deletion fx3_firmware/bladeRF.h
Expand Up @@ -71,7 +71,8 @@ extern const uint8_t CyFxUSBProductDscr[];

CyU3PReturnStatus_t CyFxSpiEraseSector(CyBool_t /* isErase */, uint8_t /* sector */);
void NuandGPIOReconfigure(CyBool_t /* fullGpif */, CyBool_t /* warm */);
void ClearDMAChannel(uint8_t ep, CyU3PDmaChannel * handle, uint32_t count, CyBool_t stall_only);
CyU3PReturnStatus_t ClearDMAChannel(uint8_t ep, CyU3PDmaChannel * handle,
uint32_t count);
void CyFxAppErrorHandler(CyU3PReturnStatus_t apiRetStatus);
void NuandAllowSuspend(CyBool_t set_allow_suspend);

Expand All @@ -82,6 +83,7 @@ struct NuandApplication {
void (*stop)(void);
CyBool_t (*halt_endpoint)(CyBool_t set, uint16_t endpoint);
CyBool_t (*halted)(uint16_t endpoint, uint8_t *data);
CyU3PReturnStatus_t (*reset_endpoint)(uint8_t endpoint);
};

#define GPIO_nSTATUS 52
Expand Down
29 changes: 25 additions & 4 deletions fx3_firmware/fpga.c
Expand Up @@ -235,21 +235,41 @@ uint8_t FPGA_status_bits[] = {
[BLADE_FPGA_EP_PRODUCER] = 0,
};

CyU3PReturnStatus_t NuandFpgaConfigResetEndpoint(uint8_t endpoint)
{
CyU3PReturnStatus_t status = CY_U3P_ERROR_BAD_ARGUMENT;

switch(endpoint) {
case BLADE_FPGA_EP_PRODUCER:
status = ClearDMAChannel(endpoint, &glChHandlebladeRFUtoP,
BLADE_DMA_TX_SIZE);
break;
}

return status;
}

CyBool_t NuandFpgaConfigHaltEndpoint(CyBool_t set, uint16_t endpoint)
{
CyBool_t isHandled = CyFalse;
CyU3PReturnStatus_t status = CY_U3P_ERROR_BAD_ARGUMENT;

switch(endpoint) {
case BLADE_FPGA_EP_PRODUCER:
FPGA_status_bits[endpoint] = set;
ClearDMAChannel(endpoint, &glChHandlebladeRFUtoP,
BLADE_DMA_TX_SIZE, set);

status = NuandFpgaConfigResetEndpoint(endpoint);
isHandled = !set;
break;
}

return isHandled;
if (status == CY_U3P_SUCCESS) {
CyU3PUsbStall (endpoint, CyFalse, CyTrue);
if(!set) {
CyU3PUsbAckSetup ();
}
}

return isHandled && status == CY_U3P_SUCCESS;
}

CyBool_t NuandFpgaConfigHalted(uint16_t endpoint, uint8_t * data)
Expand Down Expand Up @@ -360,4 +380,5 @@ const struct NuandApplication NuandFpgaConfig = {
.stop = NuandFpgaConfigStop,
.halt_endpoint = NuandFpgaConfigHaltEndpoint,
.halted = NuandFpgaConfigHalted,
.reset_endpoint = NuandFpgaConfigResetEndpoint
};
54 changes: 38 additions & 16 deletions fx3_firmware/rf.c
Expand Up @@ -422,9 +422,39 @@ static uint8_t RF_status_bits[] = {
[BLADE_UART_EP_CONSUMER] = 0,
};

CyU3PReturnStatus_t NuandRFLinkResetEndpoint(uint8_t endpoint)
{
CyU3PReturnStatus_t status = CY_U3P_ERROR_BAD_ARGUMENT;

switch(endpoint) {
case BLADE_RF_SAMPLE_EP_PRODUCER:
status = ClearDMAChannel(endpoint, &glChHandleUtoP,
BLADE_DMA_TX_SIZE);
break;

case BLADE_RF_SAMPLE_EP_CONSUMER:
status = ClearDMAChannel(endpoint, &glChHandlePtoU,
BLADE_DMA_TX_SIZE);
break;

case BLADE_UART_EP_PRODUCER:
status = ClearDMAChannel(endpoint, &glChHandlebladeRFUtoUART,
BLADE_DMA_TX_SIZE);
break;

case BLADE_UART_EP_CONSUMER:
status = ClearDMAChannel(endpoint, &glChHandlebladeRFUARTtoU,
BLADE_DMA_TX_SIZE);
break;
}

return status;
}

CyBool_t NuandRFLinkHaltEndpoint(CyBool_t set, uint16_t endpoint)
{
CyBool_t isHandled = CyFalse;
CyU3PReturnStatus_t status = CY_U3P_ERROR_BAD_ARGUMENT;

switch(endpoint) {
case BLADE_RF_SAMPLE_EP_PRODUCER:
Expand All @@ -433,27 +463,18 @@ CyBool_t NuandRFLinkHaltEndpoint(CyBool_t set, uint16_t endpoint)
case BLADE_UART_EP_CONSUMER:
isHandled = !set;
RF_status_bits[endpoint] = set;
status = NuandRFLinkResetEndpoint(endpoint);
break;
}

switch(endpoint) {
case BLADE_RF_SAMPLE_EP_PRODUCER:
ClearDMAChannel(endpoint, &glChHandleUtoP, BLADE_DMA_TX_SIZE, set);
break;
case BLADE_RF_SAMPLE_EP_CONSUMER:
ClearDMAChannel(endpoint, &glChHandlePtoU, BLADE_DMA_TX_SIZE, set);
break;
case BLADE_UART_EP_PRODUCER:
ClearDMAChannel(endpoint,
&glChHandlebladeRFUtoUART, BLADE_DMA_TX_SIZE, set);
break;
case BLADE_UART_EP_CONSUMER:
ClearDMAChannel(endpoint,
&glChHandlebladeRFUARTtoU, BLADE_DMA_TX_SIZE, set);
break;
if (status == CY_U3P_SUCCESS) {
CyU3PUsbStall (endpoint, CyFalse, CyTrue);
if(!set) {
CyU3PUsbAckSetup ();
}
}

return isHandled;
return isHandled && status == CY_U3P_SUCCESS;
}

CyBool_t NuandRFLinkHalted(uint16_t endpoint, uint8_t * data)
Expand All @@ -478,4 +499,5 @@ const struct NuandApplication NuandRFLink = {
.stop = NuandRFLinkStop,
.halt_endpoint = NuandRFLinkHaltEndpoint,
.halted = NuandRFLinkHalted,
.reset_endpoint = NuandRFLinkResetEndpoint,
};

0 comments on commit 55713e8

Please sign in to comment.