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 problem

Other Parts Discussed in Thread: ADS1605

Hello,

I am trying to setup UPP on a C6748 chip to move data from an ADS1605 Analog to Digital converter.  I started with the UPP example code located in

pspdrivers_01_30_01\packages\ti\pspiom\examples\evm6748\uppEvm\evmA

This code copies data from the input in Channel A to the output in Channel B of the UPP.

I modified the code to use 16 bit data transfers from the 10 bit data transfers in the EVM.  

If I leave the clock to the ADC disabled then SIO_reclaim never returns which is what I expect since the buffer never gets filled.

The problem occurs when I enable the clock to the ADC.  In this instance, SIO_reclaim returns but the return value is 0 indicating a 0 length buffer.  I don't understand why you would ever see a 0 returned from SIO_reclaim, it should block until it gets a full buffer and return the size of the buffer or it should return a negative integer indicating an error.  What would cause it to return 0?  I have included the code here, any help would be appreciated.

Thanks,

Scott

The offending code is located in uppStartDemo() in the line: nmadus0 = SIO_reclaim(uppInHandle, (Ptr *)rcv, NULL);

/*

 * uppSample_io.c

 *

 * This file contains the test / demo code to demonstrate the uPP driver

 * duplex mode in an evm to evm communication mode on DSP/BIOS 5.

*/
#include <std.h>
#include <stdio.h>
#include <string.h>
#include <sio.h>
#include <iom.h>
#include <log.h>
#include <sys.h>
#include <tsk.h>
#include <gio.h>
#include "ti/pspiom/cslr/cslr_syscfg0_C6748.h"
#include "ti/pspiom/cslr/cslr_gpio.h"
#include "ti/pspiom/cslr/soc_C6748.h"
#include "ti/pspiom/upp/Upp.h"
#include "ti/pspiom/gpio/Gpio.h"
/* ========================================================================== */
/*                         MACRO DEFINITIONS                                  */
/* ========================================================================== */
#define NUM_BUFS              2             /* Max of 1 outstanding requests  */
#define BUFALIGN              128           /* align buffers to 128 bytes     */
#define BUFSIZE               0x400          /* 1K of data transceive          */
#define LOOP_COUNT            100           /* no of iterations               */
/* ========================================================================== */
/*                          LOCAL VARIABLES                                   */
/* ========================================================================== */
extern Gpio_Handle     gpio0;
#define GPIO_BANK_0 0x00
#define GPIO_BANK_8 0x08
/* Handles for the TX and RX channels                                         */
static SIO_Handle uppOutHandle = NULL;
static SIO_Handle uppInHandle =  NULL;
/* arrays to hold the pointer to the allocated buffers                         */
Ptr rcv_buf[NUM_BUFS];
Ptr xmt_buf[NUM_BUFS];
Ptr buf[2 * NUM_BUFS];
/* Data structures to be used for submit                                      */
Upp_transParam  transParam[2 * NUM_BUFS]; // 0 to NUM_BUFS is xmt, NUM_BUFS to 2xNUM_BUFS is rcv 
/* currently processed packet count                                           */
Uint32 pktCount = 0;
int eolarg;
void upperror() {
}
void eolerror() {
}
/* parameters for channel A                                                   */
Upp_ChanParams uppChanparamA =
{
    TRUE,
    Upp_ChanSel_A,
    Upp_bitWidth_16,
    Upp_dataRate_SINGLE,
    Upp_ChanMode_NORMAL,
    Upp_dataPackFmt_RJZE,
    5000000,
    0,
    NULL,
    NULL,
    NULL,
    NULL,
    Upp_fifoThreshold_64,
    {
        TRUE,
        Upp_polarity_ACTIVE_HIGH,
        TRUE,
        Upp_polarity_ACTIVE_HIGH,
        FALSE,
        Upp_polarity_ACTIVE_HIGH,
        Upp_clkPol_RISING_EDGE_SYNC,
        Upp_PinIdleState_IDLE_VAL,
    }
};
/* parameters for channel B                                                   */
Upp_ChanParams uppChanparamB =
{
    TRUE,
    Upp_ChanSel_B,
    Upp_bitWidth_16,
    Upp_dataRate_SINGLE,
    Upp_ChanMode_NORMAL,
    Upp_dataPackFmt_RJZE,
    5000000,
    0,
    NULL,
    NULL,
    NULL,
    NULL,
    Upp_fifoThreshold_64,
    {
        FALSE,
        Upp_polarity_ACTIVE_HIGH,
        FALSE,
        Upp_polarity_ACTIVE_HIGH,
        FALSE,
        Upp_polarity_ACTIVE_HIGH,
        Upp_clkPol_RISING_EDGE_SYNC,
        Upp_PinIdleState_IDLE_VAL,
    }
};
/* ========================================================================== */
/*                             LOCAL FUNCTIONS                                */
/* ========================================================================== */
static Void uppCreateStreams(Void);
static Void uppDriverPrime(Uint32  channel);
static Void uppDeleteStreams(Void);
/* ========================================================================== */
/*                           FUNCTION DEFINTIONS                              */
/* ========================================================================== */
/*
 * Upp init function called when creating the driver.
 */
void uppUserInit()
{  
    Upp_init();
    uppParams = Upp_PARAMS;
    uppParams.devMode = Upp_DevMode_DUPLEX_0;
    uppParams.dlbMode = Upp_Loopback_DISABLE;
    uppParams.emulationMode = Upp_EmuMode_RTEMU;
    uppParams.pllDomain = Upp_pllDomain_0;
    uppParams.pscPwrmEnable = FALSE;
/* enable the GPIO in the PSC module  */
    PWRM_setDependency(PWRM_RSRC_UPP);
}
/*
 * \brief   This function demostrates the use of Upp using an EVM to EVM
 *          communication setup.
 *
 * \param   None
 *
 * \return  None
 */
Void uppStartDemo(Void)
{
    Upp_transParam    *xmt       = NULL;
    Upp_transParam    *rcv       = NULL;
    Uint16            *tempPtr   = 0x00;
Ptr  chan[4]; // storage for input data 
    Uint32            count     = 0;
    Int32             nmadus0   = 0;
    Uint32            i         = 0x00;
Int32  bufcount = 0;
    Bool              fail      = FALSE;
Gpio_PinCmdArg    pinCmdArg;
char sMsg[40];
printf("Start the uPP driver.");
for (count = 0; count < 4; count++)
    {
        chan[count] = (Ptr)MEM_calloc(0, BUFSIZE*2, BUFALIGN);
        if (NULL == chan[count])
        { 
            printf("MEM_calloc failed.");
            SYS_abort("MEM_calloc failed.\n");
        }
    }
    /* create the streams required for the transactions                       */
    uppCreateStreams();
    /* prime the driver                                                       */
uppDriverPrime(IOM_INPUT);
uppDriverPrime(IOM_OUTPUT);
// 16*8+pin #
pinCmdArg.pin   = 137; // pin8 adc clock enable
pinCmdArg.value = 0;
    Gpio_setPinVal(gpio0, &pinCmdArg);
for (count = 0; count<1000000; count++);
pinCmdArg.pin   = 138; // pin8 adc enable
pinCmdArg.value = 0;
    Gpio_setPinVal(gpio0, &pinCmdArg);
    /* reclaim each packet and resubmit for "LOOP_COUNT" number of iteration  */
    for (count = 0; count < LOOP_COUNT; count++)
    {
        for (bufcount=0; bufcount<4; bufcount++) {
       /* Reclaim full buffer from the input stream     */                 
// =========> nmadus0 returns 0 here ******
nmadus0 = SIO_reclaim(uppInHandle, (Ptr *)rcv, NULL);
         if (nmadus0 < 0)
       {
            printf("\r\nError reclaiming full buffer from the input stream\n");
         }
       else
        {
            tempPtr = (Uint16 *)rcv->windowAddr;
             /* store the received data                                      */
           for (i = 0; i < BUFSIZE; i++)
            {                
                ((Uint16 *)chan[i%4])[i/4+(bufcount*BUFSIZE)] = tempPtr[i];
             }
             if (TRUE == fail)
           {
                break;
            }
       }
       /* Issue an empty buffer to the input stream                          */
        if (i=SIO_issue(uppInHandle, rcv, BUFSIZE, NULL) != SYS_OK)
         {
             printf("\r\nFailed to issue empty buffer to stream\n");
       }
}
     /* Reclaim an empty buffer from the output stream  */
        nmadus0 = SIO_reclaim(uppOutHandle, (Ptr *)&xmt, NULL);
        if (nmadus0 < 0)
        {
            printf("\r\nError reclaiming empty buffer from the output stream\n");
        }
   tempPtr = (Uint16 *)xmt->windowAddr;
for (i = 0; i < BUFSIZE; i++)
        {        
            tempPtr[i] = ((Uint16 *)chan[0])[i];
             
        }
        /* Issue full buffer to the output stream                             */
        if (SIO_issue(uppOutHandle, xmt, BUFSIZE, NULL) != SYS_OK)
        {
            printf("\r\nFailed to issue empty buffer to stream\n");
        }
pktCount++;
    }
    /* reclaim all the empty transmit buffers                                 */
    for (count = 0; count < NUM_BUFS; count++)
    {
        nmadus0 = SIO_reclaim(uppOutHandle, (Ptr *)&xmt, NULL);
        if (nmadus0 < 0)
        {
            printf("\r\nError reclaiming empty buffer from the output stream\n");
        }
    }
    /* delete the streams and deallocate the buffers                          */
    uppDeleteStreams();
}
/**
 * \brief   Function to submit requests to the driver.Depending on the macro
 *          "NUM_BUFS" either the driver can be buffered with multiple requests
 *          or only one buffer by using the NUM_BUFS as 1.
 *
 * \param   channel [IN] channel to be primed.
 *
 * \return  None
*/
static Void uppDriverPrime(Uint32  channel)
{
    Uint32     count      = 0;
// Uint16           inbuf[NUM_BUFS][BUFSIZE];
    if (IOM_INPUT == channel)
    {
        /* prime the channel for the reception of data                        */
        for (count = NUM_BUFS; count < (2 * NUM_BUFS); count++)
        {          
            transParam[count].windowAddr = buf[count];
            transParam[count].bytesPerLine = BUFSIZE*2;
            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.");
                SYS_abort("Issue to input stream failed\n");
            }
        }
    }
    else
    {
        for (count = 0; count < NUM_BUFS; count++)
        {
            transParam[count].windowAddr = buf[count];
            transParam[count].bytesPerLine = BUFSIZE*2;
            transParam[count].lineCount = 1;
            transParam[count].lineOffset = 0;
            if (IOM_COMPLETED
                != SIO_issue(uppOutHandle, (Ptr)&transParam[count], BUFSIZE, NULL))
            {
                printf("Issue to output stream failed.");
                SYS_abort("Issue to output stream failed\n");
            }
        }
    }
    printf("Requests submitted to the uPP driver.");
}
Void uppCreateStreams(Void)
{
    SIO_Attrs      sioAttrs  = SIO_ATTRS;
    Uint32         count     = 0;
    Uint32         tempCount = 0;
    sioAttrs.nbufs = NUM_BUFS;
    sioAttrs.align = BUFALIGN;
    sioAttrs.model = SIO_ISSUERECLAIM;
sioAttrs.timeout = SYS_FOREVER;
    /* Create a TX and RX channel for the duplex 0 mode (B = TX, A = RX)       */
    uppOutHandle = SIO_create("/dioUppOUT", SIO_OUTPUT, BUFSIZE, &sioAttrs);
    uppInHandle  = SIO_create("/dioUppIN", SIO_INPUT, BUFSIZE, &sioAttrs);
    if ((NULL == uppOutHandle) || (NULL == uppInHandle))
    {
        printf("Streams Creation Failed");
        SYS_abort("Streams Creation Failed\n");
    }
    /* create the buffers required for the TX and RX operation                 */
    for (count = 0; count < (2 * NUM_BUFS ); count++)
    {
        buf[count] = (Ptr)MEM_calloc(0, BUFSIZE*2, BUFALIGN);
        if (NULL == buf[count])
        { 
            printf("MEM_calloc failed.");
            SYS_abort("MEM_calloc failed.\n");
        }
    }
    /* Fill the buffers with known data and transmit the same and check if the*
     * same pattern is received on the RX channel         */                    
    for (count = 0; count < (NUM_BUFS); count++)
    {
        for (tempCount = 0; tempCount < BUFSIZE; tempCount++)
        {
            ((Uint8 *)buf[count])[tempCount] = (tempCount % 0x100);
        }
    }
}
static Void uppDeleteStreams(Void)
{
    Int32   status = IOM_COMPLETED;
    Uint32  count  = 0x00;
    /* delete the channels for the RX and the Tx                              */
    status = SIO_delete(uppOutHandle);
    if (IOM_COMPLETED != status)
    {
        printf("Output Stream Deletion Failed");
        SYS_abort("Output Stream Deletion Failed\n");
    }
    status = SIO_delete(uppInHandle);
    if (IOM_COMPLETED != status)
    {
        printf("Input Stream Deletion Failed");
        SYS_abort("Input Stream Deletion Failed\n");
    }
    /* free the buffers allocated for the RX and TX channels                  */
    for (count = 0; count < (NUM_BUFS * 2); count ++)
    {
        if (TRUE != MEM_free(0,buf[count],BUFSIZE))
        {
            printf("Freeing Memory failed\n");
            SYS_abort("Freeing Memory failed\n");
        }
    }
}
/*
 * \brief  entry point function for the Upp demo task.
 *
 *         -> creates the required channels for the demonstration of the UPP
 *            working in EVM to EVM communication mode
 *         -> compares the transmit and receive data and prints an appropriate
 *            message
 *
 * \params  None
 *
 * \return  None.
 */
Void uppDemoTask(Void)
{
    uppStartDemo();
    printf("Sample Application completed...\n");
}

  • I put a watch on the receive buffer and when the SIO_reclaim() call returns and it appears there is valid data there but the return value is still 0.  Any idea why might be?

    Scott

  • Hi Scott,

    I'm not familiar with the driver so I need to look at it first.

    One thing I noticed was that you are not passing the address of rcv on the SIO_reclaim. The second parameter to SIO_reclaim is a double pointer. You are casting the Upp_transParam pointer to a double pointer which is wrong. (I'm assuming the Upp_transParam type is not a pointer...I'll confirm when I look at the driver...)  The SIO_reclaim later on, with the xmt variable, is correct usage of the API.

    This is not causing the SIO_reclaim to return zero. I'll get back soon in regards to that problem...

    Todd

  • Scott,

    Big disclaimer...I have no experience with the Upp peripheral...but it looks like the Upp driver is not setting the size properly in the submit function. The size is what is returned in the SIO_reclaim. Instead of setting the size variable to the size of the buffer, it is setting it to zero. So it's a bug in the Upp driver. It apears the example does not need to use the actual return code, it just needs to make sure that the return is non-negative (negative indicts a problem).

    So I'd ignore non-negative return codes from the SIO_reclaim for this driver. I've open a bug report on this: SDOCM00078022

    Please make sure to pass the address of the rcv variable also since the Upp_transParam type is a structure and not a pointer. The original example has the address of the rcv variable passed in:

    for (count = 0; count < LOOP_COUNT; count++)
        {
            nmadus0 = SIO_reclaim(uppInHandle, (Ptr *)&rcv, NULL);

            /* Reclaim full buffer from the input stream                          */
            if (nmadus0 < 0)
            {
                LOG_printf(&trace,
                    "\r\nError reclaiming full buffer from the input stream");
            }

            /* Reclaim empty buffer from the output stream to be reused           */
            nmadus0 = SIO_reclaim(uppOutHandle, (Ptr *)&xmt, NULL);

            if (nmadus0 < 0)
            {
                LOG_printf(&trace,
                    "\r\nError reclaiming empty buffer from the output stream");
            }

    Todd

  • Todd, you are a lifesaver.  Changing the receive and transmit buffers to pointers did the trick.  With the previous version of code those buffers were always null.  As a result, I checked the nmadus0 variable to get the buffer size returned by the driver which was also 0.  I figured it should never be 0 so that's what led me down this path.

     

    Anyway, thanks for all your help,

    Scott