Buffering for USB transmission

Hello to everyone. I encountered some problems in buffering data for usb serial transmission, and I would like to know if it is problem that is related to variable dimensioning or… what else?

I give you a little example. In the code you’ll find below, I am trying to implement a small circular buffer. (My long-term goal will be to use it for sampling a signal and later encode it and transmit it). As you can see, MAX_ITEMS is defined as 10. If I try to define a bigger value, or even if I try to uncomment the printf instructions in the main loop, transmission crashes after few loops. I would like to know if it is a problem related to USB buffering or other things that I, like a newbie, cannot understand.

Thanks a lot,
Tapisge

/** Ste_queue_test app:
 *
 * Simple test for a circular queue.
*/

#include <wixel.h>
#include <usb.h>
#include <usb_com.h>
#include <stdio.h>

#define MAX_ITEMS 10

typedef struct circularQueue_s
{
    int     first;
    int     last;
    int     validItems;
    int     element[MAX_ITEMS];
} circularQueue_t;

circularQueue_t  XDATA myQueue;


// A big buffer for holding a report.  This allows us to print more than
// 128 bytes at a time to USB.
uint8 XDATA report[1024];

// The length (in bytes) of the report currently in the report buffer.
// If zero, then there is no report in the buffer.
uint16 DATA reportLength = 0;

// The number of bytes of the current report that have already been
// send to the computer over USB.
uint16 DATA reportBytesSent = 0;

void initializeQueue(circularQueue_t *theQueue){
	int i;
	theQueue->validItems  =  0;
	theQueue->first       =  0;
	theQueue->last        =  0;
	for(i=0; i<MAX_ITEMS; i++)
	{
		theQueue->element[i] = 0;
	}
}

BIT isEmpty(circularQueue_t *theQueue){
    if(theQueue->validItems==0)
        return(1);
    else
        return(0);
}

BIT putItem(circularQueue_t *theQueue, int theItemValue){
    if(theQueue->validItems>=MAX_ITEMS){
        return(0);
    }
    else{
        theQueue->validItems++;
        theQueue->element[theQueue->last] = theItemValue;
        theQueue->last = (theQueue->last+1)%MAX_ITEMS;
        return(1);
    }
}

BIT getItem(circularQueue_t *theQueue, int *theItemValue){
    if(isEmpty(theQueue)){
        return(0);
    }
    else{
        *theItemValue=theQueue->element[theQueue->first];
        theQueue->first=(theQueue->first+1)%MAX_ITEMS;
        theQueue->validItems--;
        return(1);
    }
}

void printQueue(circularQueue_t *theQueue){
    int aux, aux1;
    aux  = theQueue->first;
    aux1 = theQueue->validItems;
    printf("QUEUE: ");
    while(aux1>0)
    {
        printf("%3d", theQueue->element[aux]);
        aux=(aux+1)%MAX_ITEMS;
        aux1--;
    }
    printf("\r\n");
}

void updateLeds()
{
    usbShowStatusWithGreenLed();
}

// This gets called by puts, printf, and printBar to populate
// the report buffer.  The result is sent to USB later.
void putchar(char c)
{
    report[reportLength] = c;
    reportLength++;
}

void main()
{
	static uint32 lastEvent;
	uint8 bytesToSend;
	int i, readValue;

    systemInit();
    usbInit();
    lastEvent = 0;

    LED_RED(1);
    LED_YELLOW(0);
    while(1)
    {
        boardService();
        updateLeds();
        usbComService();

        if (getMs() - lastEvent >= 1000){

        	lastEvent=getMs();

            //queue init
            initializeQueue(&myQueue);

            //printf("\x1B[0;0H");
            //printf("Time: %6lu\r\n", lastEvent);

			for(i=0; i<MAX_ITEMS+1; i++){
				putItem(&myQueue, i);
			}

			printQueue(&myQueue);

			for(i=0; i<MAX_ITEMS/2; i++){
				getItem(&myQueue, &readValue);
				printf("last = %2d\r\n", readValue);
			}

			printQueue(&myQueue);

			printf("\r\n");

		    // Create reports.
			reportBytesSent = 0;

		    // Send the report to USB in chunks.
		    if (reportLength > 0) {
		        bytesToSend = usbComTxAvailable();
		        if (bytesToSend > reportLength - reportBytesSent){
		            // Send the last part of the report.
		            usbComTxSend(report+reportBytesSent, reportLength - reportBytesSent);
		            reportLength = 0;
		        }
		        else{
		            usbComTxSend(report+reportBytesSent, bytesToSend);
		            reportBytesSent += bytesToSend;
		        }
		    }

        	LED_RED(!LED_RED_STATE);
        }
    }
}

Hello, Tapisge.

It looks like you are calling printf in lots of places. You should be careful about when you call it or else you will cause a buffer overflow in putchar. It looks like your code is based on our test_adc app, which avoids buffer overflows by only calling putchar/printf to generate a new report after the report buffer is empty. The “reportLength == 0” condition in sendReportIfNeeded takes care of that.

Also, I see you are constantly setting reportBytesSent to zero. That will interfere with the code that is using that variable and probably make it impossible to send reports longer than 128 bytes.

I did not look carefully at all of your code so there could be other problems too.

–David

In effect I was starting exactly from test_adc app. I’m trying to get in confidence with all of the apps in SDK
Thanks a lot, David.
Tapisge

[quote=“DavidEGrayson”]Hello, Tapisge.

It looks like you are calling printf in lots of places. You should be careful about when you call it or else you will cause a buffer overflow in putchar. It looks like your code is based on our test_adc app, which avoids buffer overflows by only calling putchar/printf to generate a new report after the report buffer is empty. The “reportLength == 0” condition in sendReportIfNeeded takes care of that.

Also, I see you are constantly setting reportBytesSent to zero. That will interfere with the code that is using that variable and probably make it impossible to send reports longer than 128 bytes.

I did not look carefully at all of your code so there could be other problems too.

–David[/quote]