View previous topic :: View next topic |
Author |
Message |
Snaumann
Joined: 21 Aug 2012 Posts: 4
|
Random data corruption with USB CDC communication |
Posted: Tue Aug 21, 2012 9:53 am |
|
|
Hello,
I wanted to establish a USB cdc communication between a sensor readout electronic with a PIC24FJ64GB106 device and a Graphical User Interface programmed with LabView running on a PC.
I am using PCD V4.125 C-compiler.
The communication runs in principle. I am sending frames of 2054 bytes appr. every 125ms. However I observe single corrupted data bytes occuring randomly (in average appr. 1 corrupted byte per frame every 20 frames). To exclude my sensor frontend as error source I modified my code in order to send constant values instead of data values from sensor data aquissition.
There is only one ISR (TIMER1#) used which simply increments a variable.
Following is an extract of the relevant parts of my code:
Code: |
#include <24FJ64GB106.h>
//----- device options ---------------------------------------------------------------------
#fuses HS,PR_PLL,NOPROTECT, NOWDT,DISUVREG,NOWRT,NODEBUG,PLL5,
#build (stack=512)
#device ADC=10
#use delay(clock=32M) // FCY = 16MHz
#define T1_10MS 45536
//----- include files ----------------------------------------------------------------------
#include <usb_cdc.h>
unsigned int8 tx_buf[3000];
#INT_TIMER1
//------------------------------------------------------------------------------------------
void timer1_isr(void)
//------------------------------------------------------------------------------------------
{
set_timer1(T1_10MS);
msec10_timer++;
}
//------------------------------------------------------------------------------------------
void send_frame()
//------------------------------------------------------------------------------------------
{
unsigned int16 i;
int16 j;
// send message header
tx_buf[0] = 0xE2;
tx_buf[1] = 0x20;
tx_buf[2] = 0x01;
tx_buf[3] = 0xF4;
tx_buf[4] = 0x02;
tx_buf[5] = 0x80;
j=6;
// send data
for(i = 0; i < 1024; i++)
{
tx_buf[j++] = i >> 8; // MSB
tx_buf[j++] = i; // LSB
}
for (j=0; j < 2054; j++)
{
usb_cdc_putc(tx_buf[j]);
}
while(!usb_cdc_put_buffer_free());
usb_cdc_flush_out_buffer();
}
main()
{
//--- Timer 1 Setup --------------------------------------------------------------------
Setup_timer1(TMR_INTERNAL | TMR_DIV_BY_8); // Setup timer 1
set_timer1(T1_10MS);
enable_interrupts(INT_TIMER1);
enable_interrupts(INTR_GLOBAL);
usb_init_cs();
usb_status = 0;
while(TRUE)
{
usb_task();
delay_ms(90); // simulates the time demand of data aquissition
send_frame();
}
}
|
I have tried to analyse the USB data transfer by USB Sniffer S/W SnoopyPro 0.22 and I can see that Windows driver receives already false data. Hence the root cause must be most likely the above code running on the PIC or the microcontroller.
I have checked several times the USB hardware interface of my microcontroller and I am pretty confident that this is ok (20MHz quartz oscillator, 1uF tantalum cap. connected to VUSB etc...).
Actually I am running out of ideas what else I could do.
I hope you can inspire me with some ideas and will appriciate your kind help.
Kind regards
Stefan |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Tue Aug 21, 2012 2:40 pm |
|
|
I'd disable the timer ISR and run the 'fixed data' program to see what happens.
If it doesn't fail, then the problem is associated with the timer ISR.
If it still fails.. try a smaller amount of data...
On the PC side...is it dedicated to this project or do you have other applications open/running/??? that might 'upset' the data flow ???
hth
jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Aug 22, 2012 1:03 am |
|
|
The corruption would appear to be at almost exactly 2.5 second intervals. Same comment as Temtronic. is there anything possible on the PC side?. Have you tried with a different PC?. Is this a physical PC, or a 'virtual' system (there have been a couple of issues with VMWare systems giving corruption at this interval).
Consider adding a CRC to the packet. Then at least you will know when the problem has occurred.
Best Wishes |
|
|
Snaumann
Joined: 21 Aug 2012 Posts: 4
|
|
Posted: Wed Aug 22, 2012 8:43 am |
|
|
Hello temtronic,
thanks for your reply. Disabling the timer ISR and smaller amount of data data does not make a difference.
If data corruption occurs it is almost always in the beginning of the frame. Most of the time the 3rd byte of the frame is corrupted and if not, then one (and only one) of the following 50 to 60 bytes of the frame is corrupted.
Hello Ttelmah
thanks for your reply. The failure rate (every 20 frames) was an average value, but the corruption does not appear in exact regular intervals. Sometimes there are only 2 frames sometimes there are 60 frames without corruption.
I have tried with different PC, I have started the program out of the LabView development environment and as an executable. I tested on physical PCs as well as on VMWare system and in different Windows versions. The corruption always occurs.
Providing a CRC is a good idea for a short term workaround, but we also intend to sell the microcontroller wo. GUI to customers who want to develop their own GUI and in this case the failure rate unacceptable high.
I hope someone in the forum has other ideas.
Kind regards |
|
|
Snaumann
Joined: 21 Aug 2012 Posts: 4
|
|
Posted: Wed Sep 19, 2012 9:00 am |
|
|
Recently I had the chance to work together with a Microchip FAE and to check the USB communication with a USB sniffer tool were we could see that the corruption occurs on the microcontroller side. We also tried to vary the message size down to 10 Bytes only but still saw similar corruption.
In addition we have setup a USB CDC stack with the Microchip's C3O Compiler and could transmit appr. 30000 frames without any corruption before we stopped the transmission. This leads to the conclusion that the USB related hardware is working as expected and not causing the corruption.
After having isolated the root cause I contacted CCS technical support directly. Meanwhile I received a fix of the usb_cdc.h which helped to solve my issue. USB communication runs now without corruption. The new usb_cdc.h will be part of 4.136 compiler.
In addition I got the following hints from CCS:
In send_frame(), I was using usb_cdc_put_buffer_free() and usb_cdc_flush_out_buffer() to make sure the buffers were fully flushed. This should be avoided, since those routines were not meant to be called by the user. You don't have to worry about flushing the data, this is automatically handled by usb_cdc_putc() and the USB ISR. If you aren't using the USB ISR, then usb_task() will flush the data once the appropriate endpoint is free.
usb_cdc_putc() shouldn't be called unless USB is enumerated, otherwise this can cause a lockup condition while usb_cdc_putc() waits for the buffer to be free. To resolve this, send_frame() shall only be called if usb_enumerated() is TRUE.
I hope this information is helpful to others who might observe similar issues in their projects.
I personally would like to thank Microchip's FAE for his excellent support and Darren from CCS tech. support for providing the fix.
Kind regards
Snaumann |
|
|
Damaso
Joined: 07 Nov 2012 Posts: 11
|
|
Posted: Mon Feb 18, 2013 8:34 am |
|
|
Hi, I'm also running an USB application in a PIC24FJ128GB106 and I found similar problems. I get corrupted data and also the PIC will reset randomly. I'm sure that the capacitors used are correct and the program works if I eliminate the USB part.
Can you please send me the fixed usb_cdc.h or tell me who to contact in order to get it? |
|
|
Snaumann
Joined: 21 Aug 2012 Posts: 4
|
|
Posted: Mon Feb 18, 2013 8:46 am |
|
|
Hello Damaso,
CCS did not allow to forward the fixed usb_cdc.h. But you can try to contact Darren Rook <darren@ccsinfo.com>. He provided the bug fix.
Good luck |
|
|
|