AnsweredAssumed Answered

USB CDC on STM32L device : unable to connect to host

Question asked by Landry on Nov 30, 2012
Latest reply on Oct 7, 2015 by Amel N
Hi all,

I try to make a device based on STM32L151 which will communicate through USB in CDC mode.

My software was initially developped on an STM32F4-discovery board, and it was working perfectly. It was also working on another board using a STM32F103. Then I switched to my own board and on STM32L-discovery and things started to go wrong...

If I compare stm32F and STM32L reference manuals, the only difference on the USB part is the internal pull up over D+ that you can manage via software (although it has been mentionned in an errata that the value was closer to 0.8kOhms than 1.5kOhms... I've tried with an external pull up without further success).

The electronic schematic of my board is pretty straightforward : D+ and D- of the STM32 are connected directly to a USB connector, no pullup. The entire board is USB powered.

I modified my working STM32F103 project for it fits the STM32L specs :
* USB_LP_CAN1_RX0_IRQn renamed in USB_LP_IRQn
* void USB_LP_CAN1_RX0_IRQHandler(void) in void USB_LP_IRQHandler(void) {

I use the same Keil RTX configuration on the other projects with USB working.

My clock settings are on HSE (driving an 8MHz quartz), with a PLL (PLLMUL12 thus PLLVCO @ 96MHz, PLLDIV3 thus SYSCLK = 32MHz), RTX SYSTICK_TIMER @ 32MHz. To be sure, I used MCO to display the SYSCLK frequency and it matched my expectations. The system_stm32l1xx.c has been generated through the xls provided by ST.

I started without defining anything for GPIO PA11 et PA12 (as it was the case for STM32F), but then I also tried in "alternate function" which I believe should be more appropriate for USB. Still, in this mode, the two data lines stay very close to 0V and hardly raise, as an output forced to low, so I keep the following setting... Here, at last, D+ and D- are moving !

My main() starts a task that initialize I/O and USB as followed :

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//to manage internal usb pullup
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);

GPIO_PinAFConfig(GPIOA, GPIO_Pin_11, GPIO_AF_USB);//alternate function in USB mode)

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;      //D+ and D- of USB
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;               //and not Mode_AF ??
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;//PP;          
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;     
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;           //Maximum speed
GPIO_Init(GPIOA, &GPIO_InitStructure);          

os_tsk_prio_self(100);   // Set task priority to medium
NVIC->ISER[((uint32_t)(USB_LP_IRQn) >> 5)] = (1 << ((uint32_t)(USB_LP_IRQn) & 0x1F));

usbd_connect(__TRUE);    // USB Device Connect
usbd_init();             // USB Device Initialization
SYSCFG->PMC |= 1;       //Set USB pull up (STM32 internal pullup)
os_tsk_prio_self(1);     // Set task priority to the lowest
// Check if usb stack initialized and device connected to the host
}while (!usbd_configured());

And my program is stuck in this loop.

I place a breakpoint in the USB_LP_IRQ handler, and it appears my interrupt never raises...

On the PC side, my windows 7 see that some kind of USB device has been pluged as soon as the pull up is activated (this, at least, seems to work correctly), but it prompts an error because it's unabled to retrieve VID and PID, so no driver assignation is possible.

I've worked with microchip PIC for a few years now, but I'm new to ST and Keil. Here I obviously miss something, but I can't simply put my finger on it.

Does somebody have any idea to make it work ?

I now suspect an issue with pin configuration / switch in USB mode... Maybe with interrupt management ? 

Some of you may have seen this on keil discussion board, but I believe it's more a device issue so I try here...

Thanks in advance for your help.