Difference between revisions of "STM32 USB Device Renumeration"

From Stm32World Wiki
Jump to navigation Jump to search
Line 11: Line 11:
 
   /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
 
   /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
  
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
+
/*
GPIO_InitStruct.Pin = GPIO_PIN_12;
+
* Force host to re-enumerate device
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+
*/
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
+
GPIO_InitTypeDef GPIO_InitStruct = { 0 };             // All zeroed out
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
+
GPIO_InitStruct.Pin = GPIO_PIN_12;                     // Hardcoding this - PA12 is D+
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;           // Push-pull mode
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
+
GPIO_InitStruct.Pull = GPIO_PULLDOWN;                 // Resetting so pull low
HAL_Delay(50);
+
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;               // Really shouldn't matter in this case
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);
+
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);               // Initialize with above settings
 +
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET); // Yank low
 +
HAL_Delay(50);                                         // Enough time for host to disconnect device
 +
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);   // Back high - so host will enumerate
  
 
   /* USER CODE END USB_DEVICE_Init_PreTreatment */
 
   /* USER CODE END USB_DEVICE_Init_PreTreatment */

Revision as of 05:15, 23 July 2021

USB devices need a 1.5 kOhm pull-up resistor on the D+ line in order for them to identify as devices (rather than hosts). On many STM32 MCUs this pull-up resistor is built-in. Unfortunately on the "device only" STM32's - like the STM32F103 this is not the case, so in modules using those processors one often see something like this in the schematics:

USB Circuit w. 1.5 kOhm pull-up.png

This generally works just fine with one noticeable exception - since the D+ line is permanently pulled high, the device will not re-enumerate when it is soft restarted (for example when flashing new firmware). This is of course a major PITA when doing USB related development.

Fortunately there is a rather elegant work-around. In "usb_device.c" add the following at the top of the MX_USB_DEVICE_Init function:

  /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */

	/*
	 * Force host to re-enumerate device
	 */
	GPIO_InitTypeDef GPIO_InitStruct = { 0 };              // All zeroed out
	GPIO_InitStruct.Pin = GPIO_PIN_12;                     // Hardcoding this - PA12 is D+
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;            // Push-pull mode
	GPIO_InitStruct.Pull = GPIO_PULLDOWN;                  // Resetting so pull low
	GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;               // Really shouldn't matter in this case
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);                // Initialize with above settings
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET); // Yank low
	HAL_Delay(50);                                         // Enough time for host to disconnect device
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);   // Back high - so host will enumerate

  /* USER CODE END USB_DEVICE_Init_PreTreatment */

What this does is essentially to configure the PA12 pin (USB D+) as a GPIO output pin and pull that to GND for 50 ms, before letting the USB initialisation continue as normal. The result is that the host notice the device has been disconnected and thus tries to re-enumerate immediately.

After adding the above piece of code, the device will re-enumerate each time it is flashed (or otherwise restarted).