Data Overwritten in CPU Producer and GPIF Consumer

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

cross mob
Anonymous
Not applicable

Hi,

I am using the GPIF to interface with a NAND chip. The protocol is to send a command byte, then 5 address bytes, then a page of data (2048 bytes), then 2nd command byte to initiate NAND programming. The GPIF state machine gets data bytes from USB socket thread 3, and command/address bytes from CPU socket thread2. I need to keep CPU sending command/addr bytes as fast as GPIF consumes them. In state machine, I am using the DMA_WM_TH2 to send a CPU_INTR when thread2 data falls below the watermark. I am not sure what watermarl level is best to use. The CPU interrupt routine is to set up the command and address bytes in the manual DMA CPU to GPIF channel buffer, and to use the CyU3PDmaChannelCommitBuffer() to send a set of data in multiple of 7 to thread 2. Please note that the DMA between CPU and GPIF is a Manual Out DMA. The buffer size is 2048 or 512 , buffer count is 2.

Using a digital oscilloscope, I see that data on thread 2 are incorrect. It seems the data in buffer are overwritten. If I change the DMA_WM_TH2 to DMA_RDY_TH2 to trigger a CPU_INTR, the data on thread 2 are correct, but throughput is slower because state machine has to wait for thread 2 data to be filled. I like to keep thread2 buffer not reaching empty to maximum throughput in state machine.

Is there a way for CPU to write data to GPIF socket thread 2 repeatedly without losing any data? The data size is multiple of 7.

How can CPU tell that the GPIF socket thread 2 is almost full, and cannot accept any more data from CPU?

When GPIF socket thread 2 is not empty, does writing new data to its buffer overwrite the existing data?

How can I avoid that?

Is there other API beside CyU3PDmaChannelCommitBuffer() for sending data to consumer socket from CPU?

Thanks

Phil

Below are the code snippets.

/* Create a DMA MANUAL channel for CPU2P transfer. */

//dmaCfgCPU.size  = 2048;

dmaCfgCPU.size  = 64*8;

dmaCfgCPU.count = 2; //must be greater than 1 to write buffer continuously

dmaCfgCPU.prodSckId = CY_U3P_CPU_SOCKET_PROD; //CPU Socket for producer

dmaCfgCPU.consSckId = CY_U3P_PIB_SOCKET_2; //P port socket 2 for consumer

dmaCfgCPU.dmaMode = CY_U3P_DMA_MODE_BYTE;

  /* Enabling the callback for produce event. */

dmaCfgCPU.notification = 0;

dmaCfgCPU.cb = NULL;

dmaCfgCPU.prodHeader = 0;

dmaCfgCPU.prodFooter = 0;

dmaCfgCPU.consHeader = 0;

dmaCfgCPU.prodAvailCount = 0;

**********************************************************************

       /* This will create a ManualOut DMA channel that will carry data from the CPU to the GPIF.

         FX3 CPU will be involved in the data transfer */

       apiRetStatus = CyU3PDmaChannelCreate (&glChHandleCPUtoP,

      CY_U3P_DMA_TYPE_MANUAL_OUT, &dmaCfgCPU);

       if (apiRetStatus != CY_U3P_SUCCESS)

       {

           CyU3PDebugPrint (CY_FX_DEBUG_PRIORITY, "CyU3PDmaChannelCreate failed, Error code = %d\n", apiRetStatus);

           CyFxAppErrorHandler(apiRetStatus);

       }

       //set watermark, true when count falls below the mark.

       //Watermark must be at least 12, and addrSetCount is 64 in interrupt routine

       apiRetStatus = CyU3PGpifSocketConfigure(2, CY_U3P_PIB_SOCKET_2, 12, CyFalse, 1);

       if (apiRetStatus != CY_U3P_SUCCESS)

       {

           CyU3PDebugPrint (CY_FX_DEBUG_PRIORITY, "CyU3PGpifSocketConfigure Failed, Error code = %d\n", apiRetStatus);

           CyFxAppErrorHandler(apiRetStatus);

       }

       /* Set DMA channel transfer size. */

       apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleCPUtoP, 0);

       if (apiRetStatus != CY_U3P_SUCCESS)

       {

           CyU3PDebugPrint (CY_FX_DEBUG_PRIORITY, "CyU3PDmaChannelSetXfer Failed, Error code = %d\n", apiRetStatus);

           CyFxAppErrorHandler(apiRetStatus);

       }

    /* Update the status flag. */

    glIsApplnActive = CyTrue;

    /* Start the GPIF state machine which will read and write data to/from SRAM whenever requested */

    //apiRetStatus = CyU3PGpifSMStart (START,ALPHA_START);

    apiRetStatus = CyU3PGpifSMStart (START_PROG,ALPHA_START);  //phil

**********************************************************************************

// CPU Interrupt routine to set up data in buffer and send to GPIF consumer socket

void GpifCallBack(CyU3PGpifEventType Event, uint8_t State)

{

int addrSetCount = 64; //send # of set of NAND addr bytes

//must set Control Counter to 15 to prevent additional interrupt issued in GPIF state machine

CyU3PGpifInitCtrlCounter(0, 15, CyFalse, CyTrue, 1 ); //phil,

int i = 0;

for(i=0; i< 1; i++)

{

CyU3PGpioSetValue (LED_GPIO, CyFalse); /* Turn LED-OFF */

CyU3PGpioSetValue (LED_GPIO, CyTrue); /* Turn LED-ON */

}

CyU3PGpioSetValue (LED_GPIO, CyFalse); /* Turn LED-OFF */

uint8_t cmd1 = 0x0;

uint8_t cmd2 = 0x0;

CyU3PDmaChannelGetBuffer(&glChHandleCPUtoP, &gUserBuffer, 0); //get the DMA buffer so content can be modified

int offset = 0;

for(i=0; i<addrSetCount; i++)

{

offset = i*7;

gUserBuffer.buffer[3 + offset] = (gNANDPageBlock>> 0) & 0xFF; //3rd NAND Addr byte

if(gNANDplane == 0)

{

gUserBuffer.buffer[3 + offset] = gUserBuffer.buffer[3 + offset] & 0xFFFFFFBF; //set plane# bit 6 to 0

gNANDplane = 1;

cmd1 = 0x80;

cmd2 = 0x11;

}

else

{

gUserBuffer.buffer[3 + offset] = gUserBuffer.buffer[3 + offset] | 0x40; //set plane# bit 6 to 1

gNANDplane = 0;

cmd1 = 0x81;

cmd2 = 0xAA;

}

gUserBuffer.buffer[0 + offset] = cmd1;

gUserBuffer.buffer[1 + offset] = (gNANDAddr>> 0) & 0xFF; //1st NAND Addr byte

gUserBuffer.buffer[2 + offset] = (gNANDAddr>> 😎 & 0xFF; //2nd NAND Addr byte

//gUserBuffer.buffer[3 + offset] = (gNANDPageBlock>> 0) & 0xFF; //3rd NAND Addr byte

gUserBuffer.buffer[4 + offset] = (gNANDPageBlock>> 😎 & 0xFF; //4th NAND Addr byte

gUserBuffer.buffer[5 + offset] = (gNANDPageBlock>> 16) & 0xFF; //5th NAND Addr byte

gUserBuffer.buffer[6 + offset] = cmd2;

if(gNANDplane == 0)

{

//increment page addr only if next plane is 0

if((gNANDPageBlock & 0x3F) == 0x3F)

gNANDPageBlock += 0x41; //skip over the plane bit (bit 6)

else

gNANDPageBlock += 0x01; //Cypress S34ML04G2, each block has 64 pages

}

}

//do I need to use CyU3PDmaChannelSetupSendBuffer()?

//CyU3PDmaChannelSetupSendBuffer(&glChHandleCPUtoP, &gUserBuffer); //setup buffer for DMA chan to send to GPIFCyU3PDmaChannelCommitBuffer(&glChHandleCPUtoP, i*7, 0); //commit to send data to GPIF

CyU3PGpioSetValue (LED_GPIO, CyTrue); /* Turn LED-ON */

}

0 Likes
1 Reply
KandlaguntaR_36
Moderator
Moderator
Moderator
25 solutions authored 10 solutions authored 5 solutions authored

Phil,

In general, the flag assigned to consumer p-port shows empty/not-empty, so that external processor can decide whether it can read. Similarly, producer sockets are assigned full/not-full flag, so that external processor can decide whether it can write.

As we know that there is latency in flag gets asserted as mentioned in section 7 in AN65974, the partial flag helps to know the status of the buffer before it is filled or emptied as per water mark value.

It is not clear how you are handling the data flow between NAND and FX3.

Let us know how the flow of data is handling between NAND and GPIF?

How the data is provided to CPU Producer?

Attach the GPIF Project and FX3 project for further debugging?

Regards,

Srdr

0 Likes