PSOC6 USB CDC Enumerated OK after device hard reset, but fails if disconnected and reconnected to PCs USB port

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
GuGa_1322886
Level 4
Level 4
5 solutions authored 25 sign-ins First comment on KBA

Hello,

I'm workin on a custom board that use implements a single USB CDC and noticed a problem. When PSOC6 boots with power up, or by hardware reset and the USB cable is connected to the PC windows immediately recognizes it and assigns a consistent serial port #. (USB Serial Device (COM#), COM13 in my case.  However, if I momentarily disconnect the cable from the PC and connect it again, windows doesn't recognize it anymore wht the message "Device failed to enumerate".

To avoid hanging the firmware I'm monitoring the 5V VBUS line from the external device with a resistor divider to ensure that the connection is present before initializing the USB device.  I want to do this before entering the endless loop.

Why is this happening if the CDC profile is already initialized and waiting for the USB mesasages?

Do I need do a reinitialization of the USB in the reconnection scenario?

0 Likes
1 Solution
GuGa_1322886
Level 4
Level 4
5 solutions authored 25 sign-ins First comment on KBA

CASE SOLVED!

After all the tests described above I decided to eliminate all the dead weight of moudules and headers not used in for this test to make it ready for upload, living just main.c.  Then I made sure that it still compiles, and the problem went away!

What could it be that dead weight code never executed or initialized caused this problem?

it turns out that in one of my headers dealing with structures of binary records received from external devices over the serial ports I had a:

#pragma pack(1)

This is a MEA CULPA!.

I should have been more careful and use instead:

#pragma pack(push,1)

typedef struct
{
char b1;
uint16_t  b2;
// ... more fields.
} MyStruct;

#pragma pack(pop)

or, for better safety and a lot more typing apply the gcc __attrbute__ to each field of the structure like this:

struct st2 {
  char c __attribute__((packed,aligned(4)));
  double d __attribute__((packed,aligned(4)));
  short e __attribute__((packed,aligned(4)));
};

There is a good discusion about both forms here. 

View solution in original post

0 Likes
9 Replies
YuZh
Moderator
Moderator
Moderator
100 replies posted 10 likes received 50 sign-ins

Hi:

Could you describe  which phrase  your USB enumeration failed? SET ADDRESS? GET DEVICE DESC?

 

Thanks

zhichao 

0 Likes

Hi Zhichao,

When reconnecting the USB cable the message from windows says,  "The device failed to enumerate", but after posting this message I discovered that trying to access this port with a terminal program, it fails with the message "exception: the port doesn't exist", despite the fact that it gets assigned a COM13 and it is listed alone with other serial ports in Device Manager of Windows.  This seems to indicate that Windows has not fully completed the device setup after all.

I'm using Moudus Toolbox tool chain. The initialization code, USB descriptors and hardware config in Device Configurator are an exact copy of the USB_CDC_Echo sample (except for the PID, so it doesn't get the same COMx as the example). Reverting to the CDC_Echo sample, the port is quickly setup as COM12 like before, and the  echo works perfectly with the terminal emulator. Disconnecting, and reconnecting the cable with the example works fine too. The same port pops up again in Device Manager.

All of the above leads me to believe that there is some interference with other parts of the code. I also have 3 serial ports operating at various interrupt levels. At least one of them is also having issues. I suspect interrupts may be the issue common to them. I have to research this further...

0 Likes
YuZh
Moderator
Moderator
Moderator
100 replies posted 10 likes received 50 sign-ins

Hi:

From your description,  like you said, I guess that other task or function interrupt or block the USB enumeration process. 

I give some advices, you can try it.

1. You can only run USB function in your project, and then test it .

2. USB Hound can be used to capture the USB protocol , and then maybe you can find the root cause.

 

Good Luck

zhichao

 

0 Likes

Actually, that is what I did. I isolated all the code in my project, and went back to the dev board CY8CPROTO-062-4343W where I originally started the firmware development.

Unfortunately I was in the middle of a lengthy and detailed description of the steps and problems I ran into when your message arrived and I lost it all!

In summary, despite that I actually copied the main code from Echo sample into my project, copied also design.cyusbdev. and made sure that every setting in Device Configurator was identical, I couldn't make it work. Cy_USB_Dev_Connect() doesn't return, even when Windows says that the device is ready to use.

Nothing visible in the GUIs is different, except that the Echo sample has very outdated versions of BSP and libs. Tried to update them but recompiling with the new versions throws a ton of errors, and Library Manager doesn't offer the option to use the shared versions for this ECHO project, why?

Instead of wasting time tring to fix those erorrs I started from scratch with a new blank project, updated to latest versions of BSP and libs, reproduced settings in Device Configurator, and tried to create a fresh single port with USB Configurator importing a template (green down arrow), but the template for that descriptor is corrupted, half way loading throws an error (check it out). The one for two CDC ports works, but instead I copied design.cyusbdev from  the Echo sample, compiled and it works!, also connect and disconnect.

But, this is far from a solution. This leaves me with a bad aftertaste. If I can't fix the problem for good on my own code, what warranties do I have that this won't happen again once I delivered the product to the end customer on the other side of the world?

Clenaing and recompiling the project 100 times do not makes a difference, and the time I'm wasting tring to fix something that was working on the bench before for months is insane!

We must get to the end of this...

 

0 Likes
YuZh
Moderator
Moderator
Moderator
100 replies posted 10 likes received 50 sign-ins

Hi

Hey, guys. I 'm totally agree with that we need to find out the root cause.  If you need my help or want to share some evidence about this problem, You can tell me. We can resolve this issue together. 

0 Likes

Hi again, I did some debug on the faulty vesion and discover that  the reson for Cy_USB_Dev_Connect()  not returning is because the application hangs on an invalid memory access trap caused by  HandleSetConfig() in cy_usb_dev_cdc.c

I set a break point there and steping into this function. The code hangs when it tries to access the Port structure, and falls into an endless loop that fortunately preserves the stack.

GuGa_1322886_0-1654127860457.png

In this function classContext has a value of 0x8a04. In the healty app this memory address is in the 0x800nnnn range like the rest of the variables around it.

good app:
GuGa_1322886_0-1654138679948.png

 

Bad app:
GuGa_1322886_1-1654138725828.png

The fileds above are from the cy_stc_usb_dev_context_t struct.

At the time of the call to Cy_USB_Dev_Connect() classData has a healthy address in the valid range, like classObj above it.  By the time it reaches   HandleSetConfig() it has changed.

I'm trying to narrow the search to see where it actually gets corrupted, but without a memory change breakpoint is quite difficult. The debugger is limited to a handful of code breakpoints.

0 Likes
GuGa_1322886
Level 4
Level 4
5 solutions authored 25 sign-ins First comment on KBA

Hi YuZh,

Thanks for your offer to help. I deeply appreciate it.
My project has grown too complex to share it as is. I will clone it and remove all irrelevant parts and then share it.  Also need to have a look at USB Hound as zhichao suggested.

Meantime, have a look at the Single port CDC template in USB Configurator. It is corrupted, at least in my installation. It throws an error half way loading it, but the dual port loads fine.

Thanks,

Guillermo

0 Likes
GuGa_1322886
Level 4
Level 4
5 solutions authored 25 sign-ins First comment on KBA

... more testing. I did this simple proving on the usb_low_isr()

 

/* USBDEV context variables */
cy_stc_usbfs_dev_drv_context_t usb_drvContext;
cy_stc_usb_dev_context_t usb_devContext;
cy_stc_usb_dev_cdc_context_t usb_cdcContext;

int nv=0;
void* vp[1000];

static void usb_low_isr(void)
{

vp[nv++] = usb_devContext.classRoot->classData;

/* Call interrupt processing */
Cy_USBFS_Dev_Drv_Interrupt(CYBSP_USBDEV_HW,
Cy_USBFS_Dev_Drv_GetInterruptCauseLo(CYBSP_USBDEV_HW),
&usb_drvContext);
}

This ISR gets called about 70 to 80 times during USB initialization.

On the good app, as expected all the pointers are the same.
GuGa_1322886_2-1654141811924.png

on the faulty app, only the first one vp[0] logged before calling Cy_USB_Dev_Connect() is correct, but the rest is 0xD, not the value that  HandleSetConfig() gets.

 

0 Likes
GuGa_1322886
Level 4
Level 4
5 solutions authored 25 sign-ins First comment on KBA

CASE SOLVED!

After all the tests described above I decided to eliminate all the dead weight of moudules and headers not used in for this test to make it ready for upload, living just main.c.  Then I made sure that it still compiles, and the problem went away!

What could it be that dead weight code never executed or initialized caused this problem?

it turns out that in one of my headers dealing with structures of binary records received from external devices over the serial ports I had a:

#pragma pack(1)

This is a MEA CULPA!.

I should have been more careful and use instead:

#pragma pack(push,1)

typedef struct
{
char b1;
uint16_t  b2;
// ... more fields.
} MyStruct;

#pragma pack(pop)

or, for better safety and a lot more typing apply the gcc __attrbute__ to each field of the structure like this:

struct st2 {
  char c __attribute__((packed,aligned(4)));
  double d __attribute__((packed,aligned(4)));
  short e __attribute__((packed,aligned(4)));
};

There is a good discusion about both forms here. 

0 Likes