cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 Change USB PID at boot time

JBlackann
Associate III

Hello,

I have a product that connects to a computer via USB. I also have a test application that can be run on the computer as well. The test application on the PC can look for a default PID or one can type in a different PID and the application will connect to that device with the inserted PID if one is connected. I know that I can modify the PID at compile time but I would like to just have a default PID, and then through either a USB or UART command, tell the device to change its PID to a different value, for example from 0x5751 to 0x5800. I am ok with the device having to be power cycled to switch to the new "stored" PID.

There was another post by someone that looked like someone was trying to do something similar but they didn't want to power cycle the device for the new PID to take effect.

https://community.st.com/s/question/0D50X00009XkiBt/stm32f4-usb-hid-change-pid-product-id-during-runtime?t=1621012365077

The code for setting the PID is contained in usb_desc.c and inside the following USBD_FS_DeviceDesc. I tried replacing the constant USBD_PID_FS with a variable that will be read out of EEPROM at boot prior to starting USB.

__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
{
  0x12,                       /*bLength */
  USB_DESC_TYPE_DEVICE,       /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
  0x01,                       /*bcdUSB */ /* changed to USB version 2.01
                                             in order to support LPM L1 suspend
                                             resume test of USBCV3.0*/
#else
  0x00,                       /*bcdUSB */
#endif /* (USBD_LPM_ENABLED == 1) */
  0x02,
  0x00,                       /*bDeviceClass*/
  0x00,                       /*bDeviceSubClass*/
  0x00,                       /*bDeviceProtocol*/
  USB_MAX_EP0_SIZE,           /*bMaxPacketSize*/
  LOBYTE(USBD_VID),           /*idVendor*/
  HIBYTE(USBD_VID),           /*idVendor*/
  ((uint8_t)(0x00FF & stored_usb_pid)),	 /* use stored PID instead of default */
  ((uint8_t)(0xFF00 & stored_usb_pid)),	 /* use stored PID instead of default */
//  LOBYTE(USBD_PID_FS),        /*idProduct*/
//  HIBYTE(USBD_PID_FS),        /*idProduct*/
  0x00,                       /*bcdDevice rel. 2.00*/
  0x02,
  USBD_IDX_MFC_STR,           /*Index of manufacturer  string*/
  USBD_IDX_PRODUCT_STR,       /*Index of product string*/
  USBD_IDX_SERIAL_STR,        /*Index of serial number string*/
  USBD_MAX_NUM_CONFIGURATION  /*bNumConfigurations*/
};

When I try compiling, I get the following error. ../USB_DEVICE/App/usbd_desc.c:186:3: error: initializer element is not constant

It seems that I cannot replace that USBD_PID_FS with a variable.

How best can I modify this PID value on boot?

Doing a search on "initializer element is not constant" resulted in finding the following page.

https://stackoverflow.com/questions/3025050/error-initializer-element-is-not-constant-when-trying-to-initialize-variable-w

In this thread there is a note about STM32. I am using the STM32 Cube IDE with I believe the compiler recommended. See attached image.

0693W00000AOPsVQAX.pngIf anyone has suggestions as how to change the PID and store/restore a different PID on boot I would love any suggestions.

Or if anyone has suggestions as how to connect multiple devices to a computer (that have the same VID/PID) and have the PC be able to select which device the PC application wants to communicate with? I don't have a lot of experience with creating PC side USB applications.

Thanks.

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

Replace that entry in the array before you use it.

USBD_FS_DeviceDesc[10] = stored_usb_pid;
USBD_FS_DeviceDesc[11] = stored_usb_pid >> 8;

Do this within your program, just prior to USB enumeration, not within the initialization. You can't use non-constant variables within an initialization structure because they aren't yet assigned a useful value.

Also note that this evaluates to 0 regardless of the value of stored_usb_pid:

((uint8_t)(0xFF00 & stored_usb_pid))

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

2 REPLIES 2
TDK
Guru

Replace that entry in the array before you use it.

USBD_FS_DeviceDesc[10] = stored_usb_pid;
USBD_FS_DeviceDesc[11] = stored_usb_pid >> 8;

Do this within your program, just prior to USB enumeration, not within the initialization. You can't use non-constant variables within an initialization structure because they aren't yet assigned a useful value.

Also note that this evaluates to 0 regardless of the value of stored_usb_pid:

((uint8_t)(0xFF00 & stored_usb_pid))

If you feel a post has answered your question, please click "Accept as Solution".
JBlackann
Associate III

Thanks for the suggestion. That worked great!!

Now would you have any suggestions on how to possibly have multiple USB devices (with the same VID and PID) connected to a PC and then from an app (C# or other app) how to individually select that device and communicate to it. Currently I just have been changing the PID of a device and then I can open multiple instance of my application, and I can change the PID in the C# app. I would like to be able to see the devices available inside my app (C#) and then be able to select that device to communicate/control the device.

Thanks.