CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

PIC18F2550 runs well with USB 2.0 but not with USB 3.0

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mendezmh



Joined: 03 Jun 2009
Posts: 4
Location: Argentina

View user's profile Send private message

PIC18F2550 runs well with USB 2.0 but not with USB 3.0
PostPosted: Sat Feb 13, 2016 8:55 am     Reply with quote

Hi guys, I'm facing a problem that I can't find what to do.

I have a device with a PIC18F2550 that receives some data from a computer by the USB port (bulk mode). The software running in the PC is very simple, programmed in C#. Everytime that someone click a button, this software sends 2 bytes to the 18F2550. Depending on the data in those bytes, the 18F2550 do some actions and also sends the second byte to another PIC via a simple rs-232 communication.

If I use the device with a USB 2.0 port everything runs smoothly. But, if the PC has at least one USB 3.0 port, only the first 2 bytes are sent. I mean, the 18F2550 only executes the action and sends the first-second-byte via rs-232. Even though I keep clicking the same or others buttons, nothing happens.

So, is there any consideration to keep in mind when the version of the USB port in the PC is 3.0? Any suggestion will be very welcomed!

I've tried on Windows 7, Windows 8 and Windows 10. But, no matter the version of the OS, always the problem is when the PC has USB 3.0 ports.

Windows drivers looks good because PC recognize the device and for the first press runs OK.

Here is the PIC18F2550 code:
Code:

#include <18F2550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#device  ADC=8
#use delay(clock=48000000)
#define USB_HID_DEVICE     FALSE             //Desabhilito modo HID
#define USB_EP1_TX_ENABLE  USB_ENABLE_BULK   //Habilito EndPoint de transferencia
#define USB_EP1_RX_ENABLE  USB_ENABLE_BULK   //Habilito EndPoint de recepción
#define USB_EP1_TX_SIZE    7                 //Tamaño del EndPoint de transferencia
#define USB_EP1_RX_SIZE    7                 //Tamaño del EndPoint de recepción
#include <pic18_usb.h>     //Directivas de la capa física de USB para PIC18Fxx5x
#include <32C_USB.h>     //Descriptores y configuraciones para la placa adquisidora de datos
#include <usb.c>           //Funciones para obtener control de USB

#define TX1       PIN_B0
#define TX2       PIN_B1
#define TX3       PIN_B2
#define TX4       PIN_B3
#define TX5       PIN_B4
#define TX6       PIN_B5
#define TX7       PIN_B6
#define TX8       PIN_B7


#define Prende    output_high
#define Apaga     output_low

void main(void){
   int8 iBuff[2];                   //Buffer de entrada
   int8 oBuff[2];                   //Buffer de salida
   #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
   setup_spi(SPI_SS_DISABLED);
   Apaga(TX1);
   Apaga(TX2);
   Apaga(TX3);
   Apaga(TX4);
   Apaga(TX5);
   Apaga(TX6);
   Apaga(TX7);
   Apaga(TX8);
   usb_init();                      //Enciendo el modo USB
   usb_task();                      //Habilito las tareas USB
   usb_wait_for_enumeration();      //Espera a que la PC enumere a la placa
   while(1){
   if(usb_enumerated()){            // Si la placa está enumerada
      if (usb_kbhit(1)){            //Si hay datos en el endpoint
         usb_get_packet(1, iBuff, 2); // Lee el paquete de 2bytes del EndPoint y lo guarda en el buffer de entrada
         if (iBuff[0] == 0){           // MODO DISPARO
            if(iBuff[1]>=0 && iBuff[1]<=31){
               Prende(TX1);
               Apaga(TX2);
               Apaga(TX3);
               Apaga(TX4);
               Apaga(TX5);
               Apaga(TX6);
               Apaga(TX7);
               Apaga(TX8);
               delay_ms(10);
               putc(iBuff[1]);
               delay_ms(10);
            }
            if(iBuff[1]>=32 && iBuff[1]<=63){
               Apaga(TX1);
               Prende(TX2);
               Apaga(TX3);
               Apaga(TX4);
               Apaga(TX5);
               Apaga(TX6);
               Apaga(TX7);
               Apaga(TX8);
               delay_ms(10);
               putc(iBuff[1]-32);
               delay_ms(10);
            }
            if(iBuff[1]>=64 && iBuff[1]<=95){
               Apaga(TX1);
               Apaga(TX2);
               Prende(TX3);
               Apaga(TX4);
               Apaga(TX5);
               Apaga(TX6);
               Apaga(TX7);
               Apaga(TX8);
               delay_ms(10);
               putc(iBuff[1]-64);
               delay_ms(10);
            }
            if(iBuff[1]>=96 && iBuff[1]<=127){
               Apaga(TX1);
               Apaga(TX2);
               Apaga(TX3);
               Prende(TX4);
               Apaga(TX5);
               Apaga(TX6);
               Apaga(TX7);
               Apaga(TX8);
               delay_ms(10);
               putc(iBuff[1]-96);
               delay_ms(10);
            }
            if(iBuff[1]>=128 && iBuff[1]<=159){
               Apaga(TX1);
               Apaga(TX2);
               Apaga(TX3);
               Apaga(TX4);
               Prende(TX5);
               Apaga(TX6);
               Apaga(TX7);
               Apaga(TX8);
               delay_ms(10);
               putc(iBuff[1]-128);
               delay_ms(10);
            }
            if(iBuff[1]>=160 && iBuff[1]<=191){
               Apaga(TX1);
               Apaga(TX2);
               Apaga(TX3);
               Apaga(TX4);
               Apaga(TX5);
               Prende(TX6);
               Apaga(TX7);
               Apaga(TX8);
               delay_ms(10);
               putc(iBuff[1]-160);
               delay_ms(10);
            }
            if(iBuff[1]>=192 && iBuff[1]<=223){
               Apaga(TX1);
               Apaga(TX2);
               Apaga(TX3);
               Apaga(TX4);
               Apaga(TX5);
               Apaga(TX6);
               Prende(TX7);
               Apaga(TX8);
               delay_ms(10);
               putc(iBuff[1]-192);
               delay_ms(10);
            }
            if(iBuff[1]>=224 && iBuff[1]<=255){
               Apaga(TX1);
               Apaga(TX2);
               Apaga(TX3);
               Apaga(TX4);
               Apaga(TX5);
               Apaga(TX6);
               Apaga(TX7);
               Prende(TX8);
               delay_ms(10);
               putc(iBuff[1]-224);
               delay_ms(10);
            }
         }
      }
   }
   }
}


Here is a part of the PC software (just 3 buttons events code):
Code:

private void button6_Click(object sender, EventArgs e)
        {
            bool bres;
            byte[] sdBuffer = new byte[2];
            sdBuffer[0] = 0x00;    //Modo LEDs
            string canal = Convert.ToString((Convert.ToByte(button6.Text.Substring(3)) - 1));
            sdBuffer[1] = Convert.ToByte(canal);
            bres = Form1.picwinusbapi.Write_FCEIA_USB(Form1.iHandle, sdBuffer);
        }

        private void button7_Click(object sender, EventArgs e)
        {
            bool bres;
            byte[] sdBuffer = new byte[2];
            sdBuffer[0] = 0x00;    //Modo LEDs
            string canal = Convert.ToString((Convert.ToByte(button7.Text.Substring(3))  -1));
            sdBuffer[1] = Convert.ToByte(canal);
            bres = Form1.picwinusbapi.Write_FCEIA_USB(Form1.iHandle, sdBuffer);
        }

        private void button8_Click(object sender, EventArgs e)
        {
            bool bres;
            byte[] sdBuffer = new byte[2];
            sdBuffer[0] = 0x00;    //Modo LEDs
            string canal = Convert.ToString((Convert.ToByte(button8.Text.Substring(3)) -1));
            sdBuffer[1] = Convert.ToByte(canal);
            bres = Form1.picwinusbapi.Write_FCEIA_USB(Form1.iHandle, sdBuffer);
        }


This C# software uses winusb.dll with this function to send data:
Code:

public bool Write_FCEIA_USB(IntPtr iHandle, byte[] dBuffer)
        {
            byte PipeID = 0x01;     // send pipe
            int szBuffer = dBuffer.GetLength(0);
            uint bytesWritten;
            bool bResult;
           
            bResult = WinUsb_WritePipe(iHandle, PipeID, dBuffer, szBuffer, out bytesWritten, IntPtr.Zero);
            //Debug.WriteLine(bytesWritten);

            return bResult;
        }


Thanks!!
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Feb 13, 2016 9:01 am     Reply with quote

Wondered when this was going to come up...

My knee jerk, common sense reply is to FORCE the PC USB3 ports to become USB2. Now HOW you do this is not in my quiver of arrows however it must be possible, same as setting baudrate, monitor defaults, etc.
Hmm.. I wonder if you can use different pullups on D+, D- to tell the PC it's a 2.0 device ?? Just thinking out loud here.

maybe Google can help ?

Jay
mendezmh



Joined: 03 Jun 2009
Posts: 4
Location: Argentina

View user's profile Send private message

PostPosted: Sat Feb 13, 2016 9:13 am     Reply with quote

temtronic wrote:
Wondered when this was going to come up...

My knee jerk, common sense reply is to FORCE the PC USB3 ports to become USB2. Now HOW you do this is not in my quiver of arrows however it must be possible, same as setting baudrate, monitor defaults, etc.
Hmm.. I wonder if you can use different pullups on D+, D- to tell the PC it's a 2.0 device ?? Just thinking out loud here.

maybe Google can help ?

Jay


Hey temtronic, thanks for your reply. I forgot to mention that I've already tried with external resistors at both terminals D+, D-, also at the same time. Moreover I tried with 2 27 Ohm series resistors at D- and D+. That was all suggestion that I could find on google... None of them worked
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Feb 13, 2016 10:19 am     Reply with quote

I downloaded a 'basic usb3.0' PDF from element14 and read it real quick. Seems resistors aren't used as the detection of 'super speed'...and the'se a 3.0 'descriptor' block required.
Introduction to USB 3.0 protocol.pdf

I still maintain you must be able to force the OS (win7,8,xx) to set the USB 3.0 port to usb2.0 though.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Sat Feb 13, 2016 10:21 am     Reply with quote

A 2550, is always going to be USB2, and will be seen as USB2 by Windows.

What you are describing, was common. Emphasize _was. When USB3 launched (and for a couple of years afterwards), there were a huge number of USB3 chipsets that dd not correctly handle switching to handle USB2 devices. The simplest solution at the time, was to add a USB2 hub between the device and the PC. For some reason the hub was correctly seen as USB2, and forced the chipset to change 'down' correctly.
Go back a couple of years, and you will find literally tens of thousands of threads for just about every USB2 device. Generally, It was a chipset driver problem, and gradually most have been fixed. However there are a couple of chipsets that have hardware issues, and still give this problem.

So, first thing to do is make sure the PC involved does have the latest drivers. In some cases the default Windows drivers are not the latest, and these have to be loaded separately.

Then as a separate issue, if the actual board layout is a little less than ideal (traces to the USB socket are not quite matched in length and impedance), then this can tend to show problems because the uSB3 drivers can generate faster edges. Adding 22 to 27R series resistors in the D+/D- right adjacent to the PIC, can help if this is the problem. I see you have tried this, though have to ask where you put them?. They do want to be close to the PIC.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Sat Feb 13, 2016 11:38 am     Reply with quote

As a comment, your code is faulty.

usb_task needs to be inside the while loop. It is _required_ to be called when certain events occur on the USB bus. It should be called at regular intervals to ensure these are handled.
I'd guess that this is being required when the USB3 host renegotiates the bus speed, and hence the code fails.
This will cause problems on USB2 as well, but presumably you are being lucky and not triggering these....
drolleman



Joined: 03 Feb 2011
Posts: 116

View user's profile Send private message

PostPosted: Sat Feb 13, 2016 1:49 pm     Reply with quote

I have a 2550 I use regularly. it works fine, and stable weeks at a time. it connects to many different mb's with usb 3.0. I don't even have resistors on the d+ and d-. when I first designed it I didn't know they are required, but they work fine. I have over 20 of these boards in service, before upgrading to 26j50/53. it also works connected to a 3.0 port. I would look at your code.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Sat Feb 13, 2016 2:14 pm     Reply with quote

The resistors aren't required. The match is generally OK without them. However only with very short runs to the chip.
I think the failure to call usb_task is actually the problem. This handles the USB 'housekeeping'. If you aren't enabling USB interrupts, this has to be called fairly frequently. With interrupts enabled it can just be called 'occasionally'.
The code posted doesn't enable interrupts, so usb_task has to be called.
Problem is that the speed change is seen as a disconnect/reconnect cycle, and since this is only called once to handle the original connection, USB on any machine that has the USB3 stack, will hang.
Some chipsets are really fussy, while others worked pretty much from the first.
mendezmh



Joined: 03 Jun 2009
Posts: 4
Location: Argentina

View user's profile Send private message

PostPosted: Sun Feb 28, 2016 5:00 pm     Reply with quote

Hi guys, thanks a lot for your considerations! I was out of the office, so I will try your suggestions regarding the 2.0 hub and usb_task() inside the main loop this week.
mendezmh



Joined: 03 Jun 2009
Posts: 4
Location: Argentina

View user's profile Send private message

PostPosted: Tue Mar 08, 2016 4:33 pm     Reply with quote

Hello,
I finally solved the problem.
I have to eliminate the usb_kbhit(1) function, and now it's working! I'm polling the USB data all the time and when I detect that data has changed I do the actions.
I know that isn't it an elegant solution, but it's working... And for this old development should be enough.
Even thought I've tried your suggestion regarding usb_task inside the main loop and the hub, but none of them worked.
Thanks again for your support!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group