How to change DMA configuration while running

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
rainmen747
Level 2
Level 2
50 sign-ins 5 replies posted 25 sign-ins

I would like to hear advice if there is a way to update the socket by changing the DMA type while running.

I am using Manytoone multichannel.There is no problem in various reset->load operations by configuring several gpif state-machines suitable for this.However, when I try to switch to Singlechannel SlaveFifo mode, it does not work normally.
If the configuration of the DMA channel is completely different, is there a way to properly convert it during execution.
Currently, the only alternative I can do is reset the device and re-enumerating the usb, which is very inconvenient.

 

0 Likes
1 Solution
rainmen747
Level 2
Level 2
50 sign-ins 5 replies posted 25 sign-ins

Thanks to your kind help, the cause was found and resolved.
When I used the Vendor command in the Event method, it works fine.
In the case of simply switching SM, the event method was not used, but I have missed that point.

Regards,

View solution in original post

0 Likes
9 Replies
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello,

I understand that the Multi DMA channel needs to be reconfigured as a Single DMA channel.

In this case, the Multi DMA channel should be reset (CyU3PDmaMultiChannelReset) and destroyed (CyU3PDmaMultiChannelDestroy) and a new channel can be created.

Please note to stop the data transfer when the channel is destroyed. For example, if the  Multi DMA channel is between PIB and UIB block, the GPIF state machine should be disabled and the for USB , flushing the endpoint, disabling the endpoints need to be done.

You can refer CyFxBulkSrcSinkApplnStop function of USBBulkSrcSink for more details. There is no need to reset the device and  re numerate USB device

Regards,
Rashi
0 Likes
rainmen747
Level 2
Level 2
50 sign-ins 5 replies posted 25 sign-ins

Hello, Thank you for your support.

We will send you the code with the current problem. Please check it.
1) change_SM() and 2) Change_SM_sfifo() work fine respectively.
The problem is that the operation stops when 1) is switched back to 2) while it is running.

The reason seems to be that the dma type is changed from Multichannel to SingleChannel.

Where should I look?

 

----

 
// switch SM with same MultiChannel DMA
// work fine
void Change_SM(CyU3PGpifConfig_t config_d) {
 
CyU3PGpifDisable(CyTrue);
 CyU3PGpifLoad (&config_d);
 CyU3PGpifSMStart(RESET, ALPHA_RESET);
 
 CyU3PDmaMultiChannelReset (&glChHandleBulk_P_2_U);
 CyU3PDmaMultiChannelReset (&glChHandleBulk_U_2_P);
 
 CyU3PUsbFlushEp(CY_FX_EP_CONSUMER);
 CyU3PUsbResetEp (CY_FX_EP_CONSUMER);
 
 CyU3PUsbFlushEp(CY_FX_EP_PRODUCER);
 CyU3PUsbResetEp (CY_FX_EP_PRODUCER);
 
 
 CyU3PDmaMultiChannelSetXfer (&glChHandleBulk_P_2_U, CY_FX_BULKLP_DMA_TX_SIZE, 0);
 CyU3PDmaMultiChannelSetXfer (&glChHandleBulk_U_2_P, CY_FX_BULKLP_DMA_RX_SIZE, 0);
 
 glIsApplnActive = CyTrue;
 
}
 
// switch SM changing MultiDMA to SingleDMA
// stop working
void Change_SM_sfifo(CyU3PGpifConfig_t config_d) {
 
CyU3PGpifDisable(CyTrue);
 CyU3PGpifLoad (&config_d);// Slavefifo 2bit SM
 CyU3PGpifSMStart(RESET, ALPHA_RESET);
 
 CyU3PDmaMultiChannelDestroy(&glChHandleBulk_P_2_U);
 CyU3PDmaMultiChannelDestroy(&glChHandleBulk_U_2_P);
 
make_sfifo_dma();
 
 CyU3PUsbFlushEp(CY_FX_EP_CONSUMER);
 CyU3PUsbResetEp (CY_FX_EP_CONSUMER);
 
 CyU3PUsbFlushEp(CY_FX_EP_PRODUCER);
 CyU3PUsbResetEp (CY_FX_EP_PRODUCER);
 
 glIsApplnActive = CyTrue;
 
}
 
// exact same as original slavefifo source
void make_sfifo_dma(){
 
 
CyU3PDmaChannelConfig_t dmaCfg;
CyU3PReturnStatus_t apiRetStatus = CY_U3P_SUCCESS;
 
CyU3PMemSet ((uint8_t *)&dmaCfg, 0, sizeof (dmaCfg));
 
 
 
     dmaCfg.size  = gsize*16;//gsize=1024
     dmaCfg.count = 1;
     dmaCfg.prodSckId = CY_FX_PRODUCER_USB_SOCKET;
     dmaCfg.consSckId = CY_FX_CONSUMER_PPORT_SOCKET;
     dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
     dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT;
     dmaCfg.cb = CyFxSlFifoUtoPDmaCallback;
     dmaCfg.prodHeader = 0;
     dmaCfg.prodFooter = 0;
     dmaCfg.consHeader = 0;
     dmaCfg.prodAvailCount = 0;
 
     apiRetStatus = CyU3PDmaChannelCreate (&glChHandleSlFifoUtoP,
             CY_U3P_DMA_TYPE_MANUAL, &dmaCfg);
     if (apiRetStatus != CY_U3P_SUCCESS)
     {
         CyU3PDebugPrint (4, "CyU3PDmaChannelCreate failed, Error code = %d\n", apiRetStatus);
         CyFxAppErrorHandler(apiRetStatus);
     }
 
     /* Create a DMA MANUAL channel for P2U transfer. */
     //dmaCfg.notification = CY_U3P_DMA_CB_CONS_EVENT;
     dmaCfg.prodSckId = CY_FX_PRODUCER_PPORT_SOCKET;
     dmaCfg.consSckId = CY_FX_CONSUMER_USB_SOCKET;
     dmaCfg.cb = CyFxSlFifoPtoUDmaCallback;
     apiRetStatus = CyU3PDmaChannelCreate (&glChHandleSlFifoPtoU,
             CY_U3P_DMA_TYPE_MANUAL, &dmaCfg);
     if (apiRetStatus != CY_U3P_SUCCESS)
     {
         CyU3PDebugPrint (4, "CyU3PDmaChannelCreate failed, Error code = %d\n", apiRetStatus);
         CyFxAppErrorHandler(apiRetStatus);
     }
 
 
    /* Flush the Endpoint memory */
   CyU3PUsbFlushEp(CY_FX_EP_PRODUCER);
    CyU3PUsbFlushEp(CY_FX_EP_CONSUMER);
 
    /* Set DMA channel transfer size. */
    apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleSlFifoUtoP, CY_FX_SLFIFO_DMA_TX_SIZE);
    if (apiRetStatus != CY_U3P_SUCCESS)
    {
        CyU3PDebugPrint (4, "CyU3PDmaChannelSetXfer Failed, Error code = %d\n", apiRetStatus);
        CyFxAppErrorHandler(apiRetStatus);
    }
 
    apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleSlFifoPtoU, CY_FX_SLFIFO_DMA_RX_SIZE);
    if (apiRetStatus != CY_U3P_SUCCESS)
    {
        CyU3PDebugPrint (4, "CyU3PDmaChannelSetXfer Failed, Error code = %d\n", apiRetStatus);
        CyFxAppErrorHandler(apiRetStatus);
    }
 
    /* Update the status flag. */
  
}

 

0 Likes

Hello,

Please follow the following sequence to change/reconfigure the DMA channel as a single DMA channel from multi DMA channel

- Disable GPIF state machine ->CyU3PGpifDisable()

- Destroy the Multi DMA channel - >CyU3PDmaMultiChannelDestroy()

- Flush & reset the endpoints

- Create the single DMA channel - CyU3PDmaChannelCreate

- Set the DMA transfer size - CyU3PDmaChannelSetXfer for single DMA channel

- CyU3PGpifLoad with new state machine

- Start the GPIF state machine CyU3PGpifSMStart

Regards,
Rashi
0 Likes
rainmen747
Level 2
Level 2
50 sign-ins 5 replies posted 25 sign-ins

Hello, Thank you for supports.

The problem has not been resolved yet, so please help.
As I checked, regardless of multi and single, the operation always stops when the dma configuration is changed.
To briefly summarize the job, it is to  change from bulksrcsink to slavefifo.
 
We proceeded as follows.
 
1) I used cyfxbulksrcsink(single socket)  from the SDK 1.3.4.
2) And I added the following two functions,
3) Included gpif header for slave fifo 2 addr (work well)
4) To change sm, call change_sm_fifo(..) using the vendor command (Request=0x10,Wvalue=0x08)(work well)
5) Then the motion stops immediately.
 
 
// this function is exact same as your suggestion.
 
void change_sm_fifo(CyU3PGpifConfig_t config_d,int no){
 
 
glIsApplnActive=CyFalse;
CyU3PReturnStatus_t apiRetStatus = CY_U3P_SUCCESS;
 
CyU3PGpifDisable(CyTrue);
 
 
CyU3PDmaChannelDestroy (&glChHandleBulkSink);
CyU3PDmaChannelDestroy (&glChHandleBulkSrc);
 
 
  CyU3PUsbFlushEp(CY_FX_EP_PRODUCER);
  CyU3PUsbFlushEp(CY_FX_EP_CONSUMER);
 
    CyU3PUsbResetEp (CY_FX_EP_PRODUCER);
    CyU3PUsbResetEp (CY_FX_EP_CONSUMER);
 
    set_fifo_dma(1024);
 
  apiRetStatus = CyU3PGpifLoad (&config_d);
  if (apiRetStatus != CY_U3P_SUCCESS)
    {
  CyFxAppErrorHandler(apiRetStatus);
    }
 
 
  CyU3PGpifSocketConfigure (0,CY_U3P_PIB_SOCKET_0,6,CyFalse,1);
  CyU3PGpifSocketConfigure (3,CY_U3P_PIB_SOCKET_3,6,CyFalse,1);
 
 
  apiRetStatus = CyU3PGpifSMStart(RESET, ALPHA_RESET_fifo);
 
 
  glIsApplnActive = CyTrue;
 
 
 
}
 
 
//This function is running well wiith no problem in operation.
void set_fifo_dma(uint16_t size){
 
   CyU3PDmaChannelConfig_t dmaCfg;
   CyU3PReturnStatus_t apiRetStatus = CY_U3P_SUCCESS;
 
 
    CyU3PMemSet ((uint8_t *)&dmaCfg, 0, sizeof (dmaCfg));
 
     dmaCfg.size  = size*16;
     dmaCfg.count = 3;
     dmaCfg.prodSckId = CY_U3P_UIB_SOCKET_PROD_1;
     dmaCfg.consSckId = CY_U3P_PIB_SOCKET_3;
     dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
     dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT;
     dmaCfg.cb = CyFxSlFifoUtoPDmaCallback;
     dmaCfg.prodHeader = 0;
     dmaCfg.prodFooter = 0;
     dmaCfg.consHeader = 0;
     dmaCfg.prodAvailCount = 0;
 
     apiRetStatus = CyU3PDmaChannelCreate (&glChHandleSlFifoUtoP,
             CY_U3P_DMA_TYPE_MANUAL, &dmaCfg);
     if (apiRetStatus != CY_U3P_SUCCESS)
     {
         CyU3PDebugPrint (4, "CyU3PDmaChannelCreate failed, Error code = %d\n", apiRetStatus);
         CyFxAppErrorHandler(apiRetStatus);
     }
 
     dmaCfg.prodSckId = CY_U3P_PIB_SOCKET_0;
     dmaCfg.consSckId = CY_U3P_UIB_SOCKET_CONS_1;
     dmaCfg.cb = CyFxSlFifoPtoUDmaCallback;
     apiRetStatus = CyU3PDmaChannelCreate (&glChHandleSlFifoPtoU,
             CY_U3P_DMA_TYPE_MANUAL, &dmaCfg);
     if (apiRetStatus != CY_U3P_SUCCESS)
     {
         CyU3PDebugPrint (4, "CyU3PDmaChannelCreate failed, Error code = %d\n", apiRetStatus);
         CyFxAppErrorHandler(apiRetStatus);
     }
 
 
   // CyU3PUsbFlushEp(CY_FX_EP_PRODUCER);
   // CyU3PUsbFlushEp(CY_FX_EP_CONSUMER);
 
    /* Set DMA channel transfer size. */
    apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleSlFifoUtoP, CY_FX_SLFIFO_DMA_TX_SIZE);
    if (apiRetStatus != CY_U3P_SUCCESS)
    {
        CyU3PDebugPrint (4, "CyU3PDmaChannelSetXfer Failed, Error code = %d\n", apiRetStatus);
        CyFxAppErrorHandler(apiRetStatus);
    }
 
    apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleSlFifoPtoU, CY_FX_SLFIFO_DMA_RX_SIZE);
    if (apiRetStatus != CY_U3P_SUCCESS)
    {
        CyU3PDebugPrint (4, "CyU3PDmaChannelSetXfer Failed, Error code = %d\n", apiRetStatus);
        CyFxAppErrorHandler(apiRetStatus);
    }
 
 
}
 
0 Likes

Hello,

Please confirm that none of the APIs fails when change_sm_fifo is called.

If there are no failures, please check if there are any CY_U3P_DMA_CB_PROD_EVENT in the  CyFxSlFifoPtoUDmaCallback after the  change_sm_fifo is executed.

Also, please try to disable the USB endpoint 1 and re enable it in set_fifo_dma

Regards,
Rashi
0 Likes
rainmen747
Level 2
Level 2
50 sign-ins 5 replies posted 25 sign-ins

Hello,I am really appreciate for your time.

In the above my source, I found the missing part of initializing the Pib clock. Now converting from cyfxbulksrcsink to SlaveFifo works fine.The reason I guess is that DMA has the same structure.
Using the above function is no problem in operation.

But still converting from USBBulkLoopManualManytoOne (SDK 1.3.4) to SlaveFifo doesn't work at all.
The reason I think is because the DMA structure is different.
At Now, using below function  reset and re-numerate is woking but very uncomfortable.  

void reboot_mode(uint8_t dmode)
{
                        gpif_mode=dmode;
                        CyU3PUsbAckSetup ();
                        CyU3PThreadSleep (100);
                        CyFxBulkLpApplnStop();//CyFxBulkSrcSinkApplnStop ();
                        CyU3PConnectState (CyFalse, CyTrue);
                        CyU3PThreadSleep (10);
                        CyU3PConnectState (CyTrue, CyTrue);
}
0 Likes
rainmen747
Level 2
Level 2
50 sign-ins 5 replies posted 25 sign-ins

I will inspect following your suggestion,and report again.
-none of the APIs fails
-any CY_U3P_DMA_CB_PROD_EVENT

and How can I disable the USB endpoint 1 and re enable ?
Do you mean flush and reset?

0 Likes

Hello,

The endpoint can be disabled using CyU3PSetEpConfig API by setting  epCfg.enable = CyFalse;

/* Flush the endpoint memory */
    CyU3PUsbFlushEp(CY_FX_EP_CONSUMER);

    /* Disable endpoints. */
    CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof (epCfg));
    epCfg.enable = CyFalse;

    /* Disable the GPIF->USB endpoint. */
    apiRetStatus = CyU3PSetEpConfig(EP_IN, &epCfg);
    if (apiRetStatus != CY_U3P_SUCCESS)
    {
        CyU3PDebugPrint (4, "CyU3PSetEpConfig failed, Error code = %d\n", apiRetStatus);
        CyFxAppErrorHandler (apiRetStatus);
    }

    
Regards,
Rashi
0 Likes
rainmen747
Level 2
Level 2
50 sign-ins 5 replies posted 25 sign-ins

Thanks to your kind help, the cause was found and resolved.
When I used the Vendor command in the Event method, it works fine.
In the case of simply switching SM, the event method was not used, but I have missed that point.

Regards,

0 Likes