I am using C674x core in OMAP-L138 to receive data from FPGA via the peripheral uPP.
Environment:
CCS: 4.2.3.00004
DSP/BIOS: bios_5_41_10_36
pspdrivers_01_30_01
I have modified the uPP sample application of EVM to EVM communication sample for my design. Any thing about transmission is removed from the program and output channel is also removed from the BIOS .tcf configuration.
In my design, channel A is used for receiving data and uppParams.devMode has been modified to Upp_DevMode_CHAN_A_RCV in the function uppUserInit. In FPGA(which is transmitter), if the WAIT signal (which is an input signal to FPGA and an output signal from the DSP) is high, it will stop data transmission. Transmission will start again with the next word while the WAIT signal is low again.
I have modified the structure Upp_ChanParams(especially signalCfg) for my design:
1. All START, WAIT and ENABLE signals have been enabled and the polarity of START and ENABLE signal is high and WAIT is low. However, function SIO_reclaim(uppInHandle, (Ptr *)&rcv, NULL) never returns, in other words, no data received in the buffer. With our hardware engineer’s help, we can see the control signals on another computer: WAIT signal keeps HIGH all the time, so FPGA will never send data to DSP unless WAIT signal is low.
2. All START, WAIT and ENABLE signals have been enabled and the polarity is high(including WAIT). Data transferring completed just after the function SIO_create("/dioUppIN", SIO_INPUT, BUFSIZE, &sioAttrs) returns. We can view memory(view the buffer) to see the transferred data. Data is successive within one buffer, however, data is not successive between two buffers(the first LOOP is exceptional since no data in both buffers before the first LOOP). Which says data omission occurred between data transfer to the two buffers. We can see control signals on anoter computer: WAIT signal keeps LOW all the time, so the FPGA will send data to DSP with no stop, without concerning if DSP receives data succeed.
See the following picture:

I have seen from TI e2e community (http://e2e.ti.com/support/dsp/tms320c6000_high_performance_dsps/f/115/p/114045/404644.aspx#404644) that During normal operation in receive mode, the uPP peripheral will never assert WAIT. The WAIT signal is an important part of the uPP protocol, but the uPP peripheral does not actually use it in receive mode. . Can this be an explanation to my problem?
What should I do to correctly use the WAIT signal and is there any alternative method for the DSP to notify the FPGA to stop data transmission??
My program is as follows:
The same as EVM to EVM communication sample, the function uppDemoTask is called by DSP/BIOS task.
void uppUserInit()
{
Upp_init();
uppParams = Upp_PARAMS;
uppParams.devMode = Upp_DevMode_CHAN_A_RCV; //The original value of this enumeration is DUPLEX_0, modified by Jinling for receiving data testing.
uppParams.dlbMode = Upp_Loopback_DISABLE;
uppParams.emulationMode = Upp_EmuMode_RTEMU;
uppParams.pllDomain = Upp_pllDomain_0;
uppParams.pscPwrmEnable = FALSE;
}
File:uppSample_io.c
#include <std.h>
#include <sio.h>
#include <iom.h>
#include <log.h>
#include <tsk.h>
#include <string.h>
#include <time.h>
#include "C:\Program Files\Texas Instruments\pspdrivers_01_30_01\packages\ti\pspiom\upp\Upp.h"
/*All LOG_printf function has been replaced by printf. Since LOG is not available on bios configuration. */
#include <stdio.h>
extern LOG_Obj trace;
#define NUM_BUFS 2 /* Max of 1 outstanding requests */
#define BUFALIGN 128 /* align buffers to 128 bytes */
#define BUFSIZE 13824 /* 1K of data transceive */
#define LOOP_COUNT 100 /* no of iterations */
/* Handles for the RX channels */
static SIO_Handle uppInHandle = NULL;
/* array to hold the pointer to the allocated buffers */
Ptr buf[NUM_BUFS]; //The original value in the bracket is 2*NUM_BUFS
/* Data structures to be used for submit */
Upp_transParam transParam[NUM_BUFS]; //The original value in the bracket is 2 * NUM_BUFS
/* currently processed packet count */
Uint32 pktCount = 0;
/* parameters for channel A */
Upp_ChanParams uppChanparamA =
{
TRUE,
Upp_ChanSel_A,
Upp_bitWidth_16, //original value is 8
Upp_dataRate_SINGLE, //modified from single to double
Upp_ChanMode_NORMAL,
Upp_dataPackFmt_RJZE,
5000000, //has been modified from 75000000 to 10000000
0x0, //original value is FFFF
NULL,
NULL,
NULL,
NULL,
Upp_fifoThreshold_64,
{
TRUE, //Start enable
Upp_polarity_ACTIVE_HIGH, //Upp_polarity_ACTIVE_LOW
TRUE, //enable enable
Upp_polarity_ACTIVE_HIGH, //Upp_polarity_ACTIVE_LOW
TRUE, //wait enable
Upp_polarity_ACTIVE_HIGH, //Upp_polarity_ACTIVE_LOW
Upp_clkPol_RISING_EDGE_SYNC,
Upp_PinIdleState_IDLE_VAL,
}
};
static Void uppCreateStreams(Void);
static Void uppDriverPrime(Void);
static Void uppDeleteStreams(Void);
Void uppStartDemo(Void)
{
Uint32 dwWord,*p;
Uint16 wWord0,wWord1,wPrevWord;
Upp_transParam *rcv = NULL;
Uint16 *tempPtr = 0x00;
Uint32 count = 0;
Int32 nmadus0 = 0;
Uint32 i = 0x00;
Bool fail = FALSE;
/* create the streams required for the transactions */
uppCreateStreams();
/* prime the driver */
uppDriverPrime();
/* reclaim each packet and resubmit for "LOOP_COUNT" number of iteration */
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");
printf("\r\nError reclaiming full buffer from the input stream.\n");
}
else //至此说明数据已成功接收,要对接收到的数据进行校验
{
p = rcv->windowAddr;
for(i = 0;i<(BUFSIZE>>2);i++)
{
dwWord = *p++;
wPrevWord = wWord1;
wWord0 = dwWord>>16;
wWord1 = (Uint16)dwWord;
if(((wWord0|wWord1)!=0xFFFF)
||(((wPrevWord +1) != wWord1)&&(wWord1!=0)))
{
// printf("Error: %x: %04x %04x %04x \r\n",wPrevWord,wWord0, wWord1);
}
}
// if(fail==FALSE)
// printf("Data verification succeed in loop:%d\n",count);
}
/* Issue an empty buffer to the input stream */
if (SIO_issue(uppInHandle, rcv, BUFSIZE, NULL) != SYS_OK)
{
LOG_printf(&trace,"\r\nFailed to issue empty buffer to stream\n");
printf("\r\nFailed to issue empty buffer to stream\n");
}
pktCount++;
}
// OUT:;
/* reclaim all the empty receive buffers */
for (count = 0; count < NUM_BUFS; count++)
{
nmadus0 = SIO_reclaim(uppInHandle, (Ptr *)&rcv, NULL); //here xmt was replaced by rcv
if (nmadus0 < 0)
{
LOG_printf(&trace,
"\r\nError reclaiming empty buffer from the input stream");
}
}
/* 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(Void)
{
Uint32 count = 0;
/* prime the channel for the reception of data */
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))
{
LOG_printf(&trace,"Issue to Input stream failed.");
printf("Issue to Input stream failed.\n");
SYS_abort("Issue to input stream failed\n");
}
}
LOG_printf(&trace,"Requests submitted to the uPP driver.");
printf("Requests submitted to the uPP driver.\n");
}
/**
* \brief Function to create the required streams for the transmission and
* 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 a Rx channel for CHAN_A_RCV mode.*/
uppInHandle = SIO_create("/dioUppIN", SIO_INPUT, BUFSIZE, &sioAttrs);
if (NULL == uppInHandle)
{
LOG_printf(&trace,"Streams Creation Failed");
printf("Streams Creation Failed");
SYS_abort("Streams Creation Failed\n");
}
/* create the buffers required for RX operation */
for (count = 0; count < NUM_BUFS ; count++)
{
buf[count] = (Ptr)MEM_calloc(0, BUFSIZE, BUFALIGN);
if (NULL == buf[count])
{
LOG_printf(&trace,"MEM_calloc failed.");
printf("MEM_calloc failed.");
SYS_abort("MEM_calloc failed.\n");
}
}
}
/**
* \brief Function to free the allocated resources and delete the channels
*
* This function frees the memory buffers allocated and also deletes
* the uPP channels.
*
* \params NONE
*
* \return NONE
*/
static Void uppDeleteStreams(Void)
{
Int32 status = IOM_COMPLETED;
Uint32 count = 0x00;
status = SIO_delete(uppInHandle);
if (IOM_COMPLETED != status)
{
LOG_printf(&trace,"Input Stream Deletion Failed");
printf("Input Stream Deletion Failed\n");
SYS_abort("Input Stream Deletion Failed\n");
}
/* free the buffers allocated for the RX and TX channels */
for (count = 0; count < NUM_BUFS; count ++)
{
if (TRUE != MEM_free(0,buf[count],BUFSIZE))
{
LOG_printf(&trace,"Freeing Memory failed\n");
printf("Freeing Memory failed\n");
SYS_abort("Freeing Memory failed\n");
}
}
}
Void uppDemoTask(Void)
{
printf("This is in task.\n");
uppStartDemo();
LOG_printf(&trace,"Sample Application completed...");
printf("Sample Application completed...");
}
