cancel
Showing results for 
Search instead for 
Did you mean: 

USB CDC on STM32L device : unable to connect to host

landry1
Associate II
Posted on November 30, 2012 at 15:31

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 STM32F 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_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
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_PinAFConfig(GPIOA, GPIO_Pin_12, GPIO_AF_USB);
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
do
{
Delay(100);
}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. Regards, #usb-reenumeration-enumeration #usb-cdc-stm32l
14 REPLIES 14
jpnorair2
Associate II
Posted on June 06, 2013 at 20:26

I fixed the problem.  The method was unusual, and it required the order of calls to be just right in the USB initializer function.

Step1. Do not configure the USB pins as ALT, or do anything.  Leave them HiZ input, the default setting from startup.

Step2. Get the 32MHz PLL clock started, which is different depending on your platform.

Step3. Enable the USB peripheral on APB1

Step4. Configure NVIC for USB_LP interrupt

Step5. Activate the pullup -- this was missing from the USB lib reference code, but I saw it in a DFU implementation for STM32L.

Step6. Call USBInit()

My application also waits until the host connects to the device using SetLineCoding, so I added a routine in that callback which causes my app to startup at that point.  I found that this is the best callback to use for identifying successful and complete host connection of a CDC device.

seb1
Associate II
Posted on September 09, 2013 at 15:00 Hi norair, I would like to thank you for your answer, I can now do a software disconnection/reconnection as many times as I want. Indeed, on my STM32F3 discovery, with a 1.5kOhm resistor sledered directly between PB8 and the D+ line, I can do it like that (the 100ms tempo is really important) :

int main(void)
{
Set_USBClock();
USB_Interrupts_Config();
... (other code) ...
// start USB enumeration
Set_System();
delay(100); // need minimum 100ms for the device to be recognized by the USB host
USB_Init();
... (other code) ...
// USB software disconnection
PowerOff();
}

Thank you again. Sebastien L.
Mikk Leini
Senior
Posted on October 04, 2013 at 20:45

Hi,

I'm also struggling to get USB working on my custom PCB with STM32L152. I'm using USB library 4.0.0 and i took code from JoystickMouse demo.

I figured out Step 1. after painful trying. It's even more weird that when configuring PA11 and PA12 as USB alternate function, the MCU isn't accessable by debugger with 4-pin SWD connector anymore. It only connects under hard reset (have to check that option in debugger conf). So it looks like SWD debug interface breaks down with USB alt. functions. Anyway, by just leaving D+ and D- as they are, something starts to work (USB_LP interrupt occurs) but device is still not found.

Actually some time ago i got one of my other projects working with same chip but on older USB library. With 4.0.0 it seems that usb_pwr.c wants to put MCU to some sleep mode (suspend) and then it stops working normally. In older library it was left to do for user function (Leave_LowPowerMode in hw_config.c). I tried to avoid suspend by setting fSuspendEnabled to FALSE in usb_pwr.c and by removing CNTR_SUSPM flag from IMR_MSK but it didn't help. Does anybody know how to properly turn off the suspend?

BTW: I downloaded original JoystickMouse demo and it looked like it found the device for 1 second and then it halted. Of course all IO pins are completely different so no wonder about that.

Mikk Leini
Senior
Posted on October 04, 2013 at 21:17

It's always like that - it's starts working after you ask somebody's help.

The problem was, actually it still is, that right after downloading SW, Windows can't find device. So power-off and on is needed and then it finds my device.

And credits to Sebastian also, i had too short delay.

avashalo
Associate II
Posted on October 03, 2015 at 04:01

Hi Landry,

Had you succeeded at the end to implement USB CDC on STM32L151? I am a ST beginner and working in a project which needs to implement PC to STM32L151RD USB communication. I have started with STM32_USB_FS_4.0 examples.

Can anyone suggest me any other related tutorials.