This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

C6748 UPP receive problem

Hi,

I have a project that sets up a PSP UPP driver for the C6748 DSP to capture 8 bit data from an ADC.  I modeled the code from the PSP UPP example found in PSP driver 01.30.01.

I set the peripheral up for channel A receive mode, create the input channel using (SIO_create), set up the DMA using (SIO_issue), and then have the code run in a continuous for loop with the SIO_reclaim and SIO_issue functions to recycle the input buffers.

This setup  works great when I set NUM_BUFS to 1.  When I set NUM_BUFS to 2 or greater, the data collection still happens, but the data keeps shifting location within the receive buffers.  When there was only 1 buffer, the data frame remained stationary.

The ADC spits out 8 bit data where an entire frame is equal to 2546 elements.  I set up the receive buffer to be 2546 elements long.   How do I get each receive buffer to capture each full frame without shifting to take place?

 

Here is my code:

/*===============================================================================================================================================
 * Include Files  
 *=============================================================================================================================================*/

// DSP/BIOS and CSL Headers
#include <stdio.h>
#include <std.h>
#include <sio.h>
#include <iom.h>
#include <log.h>
#include <tsk.h>
#include <string.h>
#include "ti/pspiom/upp/Upp.h"

/* ========================================================================== */
/*                        IMPORTED VARIABLES                                  */
/* ========================================================================== */

extern LOG_Obj trace;

/* ========================================================================== */
/*                         MACRO DEFINITIONS                                  */
/* ========================================================================== */

#define NUM_BUFS              1             /* Max of 1 outstanding requests  */
#define BUFALIGN              128           /* align buffers to 128 bytes     */
#define BUFSIZE               2546          /* 2.5K of data receive           */

/* ========================================================================== */
/*                          LOCAL VARIABLES                                   */
/* ========================================================================== */


/* Handle for RX channel                                                        */
static SIO_Handle uppInHandle = NULL;

/* array to hold the pointer to the allocated buffers                         */
Ptr buf[NUM_BUFS];

/* Data structures to be used for submit                                      */
Upp_transParam  transParam[NUM_BUFS];

/* currently processed packet count                                           */
Uint32 pktCount = 0;

/* parameters for channel A                                                   */
Upp_ChanParams uppChanparamA =
{
    TRUE,                            /* enable cache                 */
    Upp_ChanSel_A,                    /* channel A select             */
    Upp_bitWidth_8,                    /* 8 data bits                     */
    Upp_dataRate_SINGLE,            /* single data rate             */
    Upp_ChanMode_NORMAL,            /* normal channel mode             */
    Upp_dataPackFmt_RJZE,            /* right justified data packet     */
    750000,                            /* 750KHZ data rate             */
    0xFFFF,                            /* idle value                     */
    NULL,
    NULL,
    NULL,
    NULL,
    Upp_fifoThreshold_64,            /* FIFO threshold of 64         */
    {
        TRUE,                        /* start signal                 */
        Upp_polarity_ACTIVE_HIGH,
        TRUE,                        /* enable signal                 */
        Upp_polarity_ACTIVE_HIGH,
        TRUE,                        /* wait signal                     */
        Upp_polarity_ACTIVE_HIGH,
        Upp_clkPol_RISING_EDGE_SYNC, /* sync data to rising edge of input clock */
        Upp_PinIdleState_IDLE_VAL,
    }
};


/* ========================================================================== */
/*                             LOCAL FUNCTIONS                                */
/* ========================================================================== */

static Void uppCreateStreams(Void);
static Void uppDriverPrime(Void);
void delay(Uint32 count);

/* ========================================================================== */
/*                           FUNCTION DEFINTIONS                              */
/* ========================================================================== */

/*
 * \brief   This function demonstrates the use of Upp in receive mode
 *
 * \param   None
 *
 * \return  None
 */
Void startUPP(Void)
{
    Upp_transParam    *rcv       = NULL;
    Int32              nmadus0   = 0;


    /* create the streams required for the transactions                       */
    uppCreateStreams();

    /* prime the driver                                                       */
    uppDriverPrime();
   
    printf("Starting data capture...\n");
   
    for(;;)
    {       
        /* Reclaim full buffer from the input stream                          */
        nmadus0 = SIO_reclaim(uppInHandle, (Ptr *)&rcv, NULL);
        if (nmadus0 < 0)
        {
            printf("Error reclaiming full buffer from the input stream\n");
        }
       
       
        /* Issue an empty buffer to the input stream                          */
        if (SIO_issue(uppInHandle, rcv, BUFSIZE, NULL) != SYS_OK)
        {
            printf("Failed to issue empty buffer to stream\n");
        }
       
        pktCount++;
    }
}

/**
 * \brief   Function to submit requests to the driver.
 *
 * \param   None
 *
 * \return  None
 */
static Void uppDriverPrime(Void)
{
    Uint32 count = 0;

    for (count = 0; count < NUM_BUFS; count++)
    {
        transParam[count].windowAddr = buf[count];
        transParam[count].bytesPerLine = BUFSIZE;
        transParam[count].lineCount = 1;
        transParam[count].lineOffset = 0;

        if (IOM_COMPLETED
            != SIO_issue(uppInHandle, (Ptr)&transParam[count], BUFSIZE, NULL))
        {
            printf("Issue to input stream failed.\n");
            SYS_abort("Issue to input stream failed.\n");
        }
    }
    printf("UPP DMA channel parameters set.\n");
}

/**
 * \brief    Function to create the required streams for the reception of Upp data.
 *
 * \params   NONE
 *
 * \return   NONE
 */
Void uppCreateStreams(Void)
{
    SIO_Attrs      sioAttrs  = SIO_ATTRS;
    Uint32         count     = 0;

    sioAttrs.nbufs = NUM_BUFS;
    sioAttrs.align = BUFALIGN;
    sioAttrs.model = SIO_ISSUERECLAIM;

    /* Create RX channel                                                        */
    uppInHandle  = SIO_create("/dioUppIN", SIO_INPUT, BUFSIZE, &sioAttrs);

    if (NULL == uppInHandle)
    {
        printf("Stream Creation Failed.\n");
        SYS_abort("Stream Creation Failed.\n");
    }
   
    printf("Input UPP channel created.\n");

    /* create and zero out the buffers required for the RX operation           */
    for (count = 0; count < (NUM_BUFS ); count++)
    {
        buf[count] = (Ptr)MEM_calloc(0, BUFSIZE, BUFALIGN);

        if (NULL == buf[count])
        {
            printf("MEM_calloc failed.\n");
            SYS_abort("MEM_calloc failed.\n");
        }
    }
   
    printf("Input buffers allocated.\n");
}

/*
 * \brief entry point function for the Upp task.
 *
 * \params  None
 *
 * \return  None.
 */
Void uppCaptureTask(Void)
{
    printf("Starting Capture Task.\n");
   
    startUPP();
}

  • Conrad,

    I'm not sure I understand what you mean by data "shifting" position inside the receive buffers.  Does this mean that the data starts at some offset relative to the "top" of the buffer and runs past the end of the buffer?  Or, are you capturing periodic data  (ex. a sine wave) and noticing that the phase is different  from one buffer to the next?  Maybe the concern is that you are missing some data between the end of one buffer and the start of the next.

    If you can share some more details about the shift (how many bytes, whether it gets worse or stays the same as the program runs, etc.), that could help me diagnose what is going wrong.

  • Hi Joe,

    Thanks for getting back to me quickly.  I have an ADC that we can for the moment assume is outputting constant data at a fixed frequency.  It outputs 2546 elements at 750Khz.  The data resolution is 8 bits.  It looks something like the figure below:

    If the ADC is outputting constant data as shown in the top graph, the data in the buffer fills up with the same data each time and appears to be stationary if I graph the input buffer that starts at (window address).  This is what I see if I setup 1 buffer equal to 1 line of data.

    When I add a 2nd data buffer, the data appears to shift as shown in the lower graph even if the ADC is outputting the same data at the same fixed frequency.  It appears to shift or actually rotate in and out of the buffer[0] if I setup up buffer[0] and buffer[1] with the keyword define# NUM_BUFS 2.  The ADC issues UPP_EN and UPP_START at the beginning of each frame of data.

    I am hoping to fill buffer[0] with 1 full data frame and then buffer[1] with another full data frame.  If the data coming in is constant, I should have 2 buffers that look like the top graph.  Please let me know if I am going about this wrong.

    Thanks,

    Conrad

  • Hi Joe,

    I think I figured out the problem.  The shifting of data was happening because the input start signal was not operating correctly.  I found a workaround by driving the start signal with a separate GPIO output signal.  This way, when the application is ready to receive a new line of data, it syncs with the first word of data instead of doing whatever it was doing before.

    Thanks again for responding quickly the first time.  I assume you wrote this driver peripheral so nice work doing that.

    Thank you,

    Conrad