7 Replies Latest reply on Nov 18, 2020 8:55 AM by ThAl_4704151

    DMA_ready flag seems to do the opposite of what I expect.

    ThAl_4704151

      I'm using a GPIF-II interface to communicate with another chip, and I have FLAGA set up to be connected to Current_Thread_DMA_ready, initially low and with active high. I'm only using 4 endpoints, so if I understand correctly, each thread corresponds to only one GPIF address and one USB endpoint, so that should hopefully keep things simple.

       

      My chip sets the address pins to 3, and then checks the pin connected to FLAGA. Then I wait a bit to make sure the flags have time to get updated, and FLAGA is 0. This is the first time I've written anything to the endpoint, so I doubt it's full. I'm not sure what else could be making it not ready, but waiting for it more doesn't seem to help at all.

       

      Next, as a test, I negated the check, so it only tries to send the message when the Current_Thread_DMA_ready flag is false, ostensibly meaning that the thread associated with the endpoint is not ready. That said, when I configured it that way I was able to send data to the host without any trouble. What gives?

       

      It's possible that I'm a bit unclear about what exactly the DMA_ready flag in the GPIF-II interface means. I see a couple places in a couple manuals that say things along the lines of "This is true when the DMA is ready to send or receive data." What exactly is the criteria for "ready" though? Does that just mean the buffer has enough space to queue up a message? Does the state machine also need to be in one of the states with the DATA_IN action? Is there some other constraint?

        • 1. Re: DMA_ready flag seems to do the opposite of what I expect.
          YashwantK_46

          Hello ThAl_4704151,


          For more info on the GPIF flags, please go through the section 8 Flag Configuration of the app note AN65974 from the following link: https://www.cypress.com/file/136056/download

           

          Also, please share your GPIF state machine so that i can review it on my end.


          Regards,

          Yashwant

          • 2. Re: DMA_ready flag seems to do the opposite of what I expect.
            ThAl_4704151

            Sure thing. Here's the GPIF-II designer project.

            • 3. Re: DMA_ready flag seems to do the opposite of what I expect.
              YashwantK_46

              Hello ThAl_4704151,

               

              Can you please let me know if you have made any changes to the firmware provided with AN65974?

               

              Also, can you let me know which data path out of the two mentioned is failing in your case:

              1.) Host => FX3 => FPGA (Host Write to FPGA)

              2.) FPGA => FX3 => Host (Host Read from FPGA)

               

              Also, in the firmware can you let me know what are the 4 data paths between USB endpoints and the GPIF sockets?

               

              "Next, as a test, I negated the check, so it only tries to send the message when the Current_Thread_DMA_ready flag is false, ostensibly meaning that the thread associated with the endpoint is not ready."

              => Can you please let me know how this negation is done? Is it done on the FPGA side?

               

              Regards,

              Yashwant

              • 4. Re: DMA_ready flag seems to do the opposite of what I expect.
                YashwantK_46

                Hello,

                 

                "My chip sets the address pins to 3, and then checks the pin connected to FLAGA. Then I wait a bit to make sure the flags have time to get updated, and FLAGA is 0. This is the first time I've written anything to the endpoint, so I doubt it's full. I'm not sure what else could be making it not ready, but waiting for it more doesn't seem to help at all."

                => Does it mean that the FPGA is trying to write data to the FX3 when the FLAGA is going low?

                 

                Regards,

                Yashwant

                • 5. Re: DMA_ready flag seems to do the opposite of what I expect.
                  ThAl_4704151

                  Can you please let me know if you have made any changes to the firmware provided with AN65974?

                  Yes, I'm running my own firmware.

                   

                  Here's the part of it that configures the DMA and connects the data paths. I'll add comments so you know the constants and what values I parsed out of the descriptor.

                   

                  // Configure the corresponding endpoint
                  CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof (epCfg));
                  epCfg.enable  = CyTrue;
                  epCfg.epType  = endpoint->type; // 3, aka interrupt endpoint
                  epCfg.burstLen = 1;
                  epCfg.streams  = 0;
                  epCfg.pcktSize = endpoint->packetSize; // 512 if it enumerates as high speed, 64 if it enumerates as full speed. We've enumerated at high speed.
                  
                  apiRetStatus = CyU3PSetEpConfig(endpoint->address, &epCfg); // address is 0b10001000, aka 8 | 0b10000000
                  switch(apiRetStatus){
                  case CY_U3P_ERROR_NOT_STARTED:
                      errorLoop();
                      break;
                  case CY_U3P_ERROR_NULL_POINTER:
                      // Should never happen
                      errorLoop();
                      break;
                  case CY_U3P_ERROR_BAD_ARGUMENT:
                      // We got a bad endpoint number from the descriptor
                      return USB_INVALID_ADDRESS;
                  case CY_U3P_ERROR_INVALID_CONFIGURATION:
                      // bursts of more than 1 are only supported on certain endpoints
                      // We're hardcoding this to false for now anyway, so this should never happen
                      errorLoop();
                  break;
                  }
                  
                  // Set up the DMA buffer for the endpoint
                  uint8_t epLeadsToHost = endpoint->address & IN_Endpoint;
                  uint8_t addressNum = endpoint->address & ~IN_Endpoint;
                  dmaCfg.size          = endpoint->packetSize; //again, 512 if it enumerates as high speed, 64 if it enumerates as full speed
                  dmaCfg.count          = DMA_CHANNEL_SIZE / endpoint->packetSize; // DMA_CHANNEL_SIZE is 2048
                  if (epLeadsToHost){
                      // Data goes from the device to the host
                      // FX3 is the producer
                      dmaCfg.notification = CY_U3P_DMA_CB_CONS_EVENT; // Callback on produce event
                      dmaCfg.prodSckId = CY_U3P_PIB_SOCKET_0 + USB_ADDRESS_TO_PIB(addressNum); // USB_ADDRESS_TO_PIB maps 2,4,6,8 to 0,1,2,3. addressNum is 8, so producer socket id is PIB socket 3.
                      dmaCfg.consSckId = CY_U3P_UIB_SOCKET_CONS_0 + addressNum;
                      dmaType = CY_U3P_DMA_TYPE_AUTO_SIGNAL;
                  }
                  else {
                      //Data goes from the host to the device
                      // FX3 is the consumer
                      dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT; // Callback on produce event
                      dmaCfg.prodSckId = CY_U3P_UIB_SOCKET_PROD_0 + addressNum;
                      dmaCfg.consSckId = CY_U3P_PIB_SOCKET_0 + USB_ADDRESS_TO_PIB(addressNum); // USB_ADDRESS_TO_PIB maps 2,4,6,8 to 0,1,2,3. addressNum is 8, so producer socket id is PIB socket 3.
                      dmaType = CY_U3P_DMA_TYPE_AUTO_SIGNAL;
                  }
                  dmaCfg.dmaMode        = CY_U3P_DMA_MODE_BYTE;
                  
                  dmaCfg.cb            = CyFxDmaCallback; // Sends off an interrupt when we receive data from the host; does nothing otherwise
                  dmaCfg.prodHeader    = 0;
                  dmaCfg.prodFooter    = 0;
                  dmaCfg.consHeader    = 0;
                  dmaCfg.prodAvailCount = 0;
                  apiRetStatus = CyU3PDmaChannelCreate(&endpoint->dmaHandle, dmaType, &dmaCfg);
                  switch (apiRetStatus){
                  case CY_U3P_ERROR_BAD_ARGUMENT:
                  case CY_U3P_ERROR_NULL_POINTER:
                      // Shouldn't happen
                      errorLoop();
                      break;
                  case CY_U3P_ERROR_MEMORY_ERROR:
                      // Could not allocate buffers
                      errorLoop();
                  }
                  
                  // the 0 tells the DMA not to limit the transfers.
                  apiRetStatus = CyU3PDmaChannelSetXfer(&endpoint->dmaHandle, 0);
                  switch (apiRetStatus){
                  case CY_U3P_ERROR_NULL_POINTER:
                  case CY_U3P_ERROR_NOT_CONFIGURED:
                  case CY_U3P_ERROR_NOT_SUPPORTED:
                      // we passed a null pointer, which shouldn't happen
                      // our configuration was wrong, which shouldn't happen
                      // no buffer was allocated, which shouldn't happen
                      errorLoop();
                  }
                  
                  // Configure endpoint watermarks
                  endpoint->dmaThreadNum = USB_ADDRESS_TO_PIB(addressNum) % 4;
                  apiRetStatus = CyU3PGpifSocketConfigure(
                      endpoint->dmaThreadNum,
                      CY_U3P_PIB_SOCKET_0 + USB_ADDRESS_TO_PIB(addressNum),
                      0, // watermark at zero indicates when the buffer has data to read
                      CyTrue,
                      0);
                  if (apiRetStatus != CY_U3P_SUCCESS){
                      errorLoop();
                  }
                  
                  // Flush the endpoint
                  CyU3PUsbFlushEp(endpoint->address);
                  

                   

                  Also, can you let me know which data path out of the two mentioned is failing in your case:

                  The path I'm testing right now is Legacy Microcontroller => FX3 => Host. I will be testing host to the microcontroller next.

                   

                  Also, in the firmware can you let me know what are the 4 data paths between USB endpoints and the GPIF sockets?

                  I mentioned it in one of the comments in the code snippet, but the mapping from GPIF sockets to USB endpoints is 0:2, 1:4, 2:6, 3:8. That is, add one to the GPIF socket number, and multiply it by 2 to get the corresponding USB endpoint. This is just to maintain the legacy interface so the app on the host doesn't need to change.

                   

                  Can you please let me know how this negation is done? Is it done on the FPGA side?

                  When I said I negated the Current_Thread_DMA_ready check, I meant I changed the logic in the legacy microcontroller. I've also tried it by switching the polarity of the signal in the GPIF-II designer, and that works just as well.

                   

                  "My chip sets the address pins to 3, and then checks the pin connected to FLAGA. Then I wait a bit to make sure the flags have time to get updated, and FLAGA is 0. This is the first time I've written anything to the endpoint, so I doubt it's full. I'm not sure what else could be making it not ready, but waiting for it more doesn't seem to help at all."

                  => Does it mean that the FPGA is trying to write data to the FX3 when the FLAGA is going low?

                  Initially no, the logic in the legacy microcontroller was that it checked FLAGA to see if it was ready, and because it came back low (meaning that it wasn't ready), it bailed out to try again later. The trouble was that FLAGA never indicated that it was ready, so it always bailed out. Later on, I tried negating the check as an experiment (meaning that it would write data only when FLAGA is low), and that was able to transmit data just fine.

                   

                  Thanks for your help and patience, and have a nice day!

                   

                  Thomas

                  • 6. Re: DMA_ready flag seems to do the opposite of what I expect.
                    YashwantK_46

                    Hello ThAl_4704151,

                     

                    "When I said I negated the Current_Thread_DMA_ready check, I meant I changed the logic in the legacy microcontroller. I've also tried it by switching the polarity of the signal in the GPIF-II designer, and that works just as well."

                    => Please refer to section b. Output pins (when used as DMA Flags): of the following KBA: GPIF Pin Polarity – KBA224208

                     

                    Since the flag is configured with initial value: LOW and polarity: Active High, this means that initially, the flag would be low, but as soon as the initialization is done, the flag will:

                    1.) stay LOW, if there is buffer space available for the thread.

                    2.) go HIGH, if there is no buffer space available for the thread.

                     

                    So, your understanding of the FLAG is correct.

                     

                     

                    Regards,

                    Yashwant

                    • 7. Re: DMA_ready flag seems to do the opposite of what I expect.
                      ThAl_4704151

                      I see, so with the DMA ready flag set to active high, a high signal actually means that it's not ready for new input, and I was thinking it meant that it was ready.