cancel
Showing results for 
Search instead for 
Did you mean: 

USB CDC example for stm32l432

Jacob Pfeifer
Associate II
Posted on December 21, 2016 at 00:05

Does anyone have a working example of usb-cdc for an stm32l432 processor? The stm32l4xxCube libraries only have usb-hid examples for the stm32l432kc processor, however I need to have working usb-cdc capabilities. I have not been able to easily adapt the usb-cdc examples for other l4 devices to the l432.

#stm32l432 #usb-cdc #example #usb #l432
1 ACCEPTED SOLUTION

Accepted Solutions
Jacob Pfeifer
Associate II
Posted on December 27, 2016 at 23:57

Here's my working CDC Example for the stm32l4 System clockand general device setup has been pulled from the stm32l432 nucleo usb hid example. CDC setup has been pulled from CubeMx generated code and the STM32L476G_EVAL usb cdc example. This project echos anything written to the com port. The echo transmission occurs in the CDC_Itf_Recieve function of usbd_cdc_interface.c. CDC_Itf_Recieve is called by the usb interrupt after receiving data on the port. I haven't cleaned up the code, so it's a little messy in parts and not all of the comments make sense, but it should still be good enough to get started.

Edit: Code is attached to the comment in a zip. Click

https://community.st.com/0D50X00009XkYWiSAN

to view the attachment.

Edit 2: I have found new clock settings that get more consistent results:

RCC_OscInitTypeDef RCC_OscInitStruct;

RCC_ClkInitTypeDef RCC_ClkInitStruct;

RCC_PeriphCLKInitTypeDef PeriphClkInit;

RCC_CRSInitTypeDef RCC_CRSInitStruct;

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;

RCC_OscInitStruct.LSEState = RCC_LSE_OFF;

RCC_OscInitStruct.MSIState = RCC_MSI_ON;

RCC_OscInitStruct.MSICalibrationValue = 0;

RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;

RCC_OscInitStruct.PLL.PLLM = 1;

RCC_OscInitStruct.PLL.PLLN = 16;

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;

RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;

RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

Error_Handler();

}

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)

{

Error_Handler();

}

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;

PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1;

//PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_MSI;

//PeriphClkInit.PLLSAI1.PLLSAI1M = 1;

PeriphClkInit.PLLSAI1.PLLSAI1N = 24;

PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;

PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;

PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;

PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_48M2CLK;

if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)

{

Error_Handler();

}

__HAL_RCC_PWR_CLK_ENABLE();

if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)

{

Error_Handler();

}

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

HAL_RCCEx_EnableMSIPLLMode();

__HAL_RCC_CRS_CLK_ENABLE();

RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1;

RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB;

RCC_CRSInitStruct.Polarity = RCC_CRS_SYNC_POLARITY_RISING;

RCC_CRSInitStruct.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000,1000);

RCC_CRSInitStruct.ErrorLimitValue = 34;

RCC_CRSInitStruct.HSI48CalibrationValue = 32;

HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct);

/* SysTick_IRQn interrupt configuration */

HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

________________

Attachments :

usb_test.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006Hywp&d=%2Fa%2F0X0000000bFG%2Ffi9kGTkFZ_r1t6fcjjEZkibIaHFO4u.C7feyx.fCiKU&asPdf=false

View solution in original post

6 REPLIES 6
shingadaddy
Senior
Posted on December 21, 2016 at 16:42

Success with CDC/VCP from CubeL4 EVAL ported to L476 RG on Nucleo.

Commented out the LED inits in main and the LED control toggle in Systick and it worked on Nucleo.

On What?

Dev board?

Your own Board?

Self powered?

Bus powered?

What have you got done?

What's it do?

You have some special Crystal-less clock concerns to take care of.

shingadaddy
Senior
Posted on December 21, 2016 at 17:16

You're very welcome

Pfeifer.Jacob

. Best of luck with it.

Let us know what comes of it.

Posted on December 21, 2016 at 16:49

Currently I am using a stm32l432kc nucleo board.

It is self powered from the usb code perspective (it is being powered through the onboard debugger which is connected to the usb bus).

I tried creating a project using cubemx, but it didn't enumerate with the computer. I suppose this could be do to an incorrect clock configuration. I then took an example for another board and managed to get the usb code to enumerate with the computer, but I get a babble error when the computer requests the line coding.

From what I understand the l432kc should be capable of crystal-less usb.

Posted on December 21, 2016 at 17:05

Last I checked - CubeMX is buggy. It Enables Vbus sensing -even if you tell it NO VBUS- and then doesn't enable the Vbus sense pin. They know about it....

https://community.st.com/0D50X00009Xkgo7SAB

So you Enumerate and then babble error. Not seen that but that sounds like a clock problem. Your device uses the HSI for the crystal-less and then uses some magic with the SOF, an LSE input or other some such SYNCABLE signal to trim the HSI if I remember right. Sorry to not be more conclusive but at least it enumerated (step one past)

Sounds clockish to me.

Posted on December 21, 2016 at 17:11

Thanks, I at least have another rabbit hole to run down now. I'll let you know if I get any results after looking at the clock

Jacob Pfeifer
Associate II
Posted on December 27, 2016 at 23:57

Here's my working CDC Example for the stm32l4 System clockand general device setup has been pulled from the stm32l432 nucleo usb hid example. CDC setup has been pulled from CubeMx generated code and the STM32L476G_EVAL usb cdc example. This project echos anything written to the com port. The echo transmission occurs in the CDC_Itf_Recieve function of usbd_cdc_interface.c. CDC_Itf_Recieve is called by the usb interrupt after receiving data on the port. I haven't cleaned up the code, so it's a little messy in parts and not all of the comments make sense, but it should still be good enough to get started.

Edit: Code is attached to the comment in a zip. Click

https://community.st.com/0D50X00009XkYWiSAN

to view the attachment.

Edit 2: I have found new clock settings that get more consistent results:

RCC_OscInitTypeDef RCC_OscInitStruct;

RCC_ClkInitTypeDef RCC_ClkInitStruct;

RCC_PeriphCLKInitTypeDef PeriphClkInit;

RCC_CRSInitTypeDef RCC_CRSInitStruct;

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;

RCC_OscInitStruct.LSEState = RCC_LSE_OFF;

RCC_OscInitStruct.MSIState = RCC_MSI_ON;

RCC_OscInitStruct.MSICalibrationValue = 0;

RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;

RCC_OscInitStruct.PLL.PLLM = 1;

RCC_OscInitStruct.PLL.PLLN = 16;

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;

RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;

RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

Error_Handler();

}

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)

{

Error_Handler();

}

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;

PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1;

//PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_MSI;

//PeriphClkInit.PLLSAI1.PLLSAI1M = 1;

PeriphClkInit.PLLSAI1.PLLSAI1N = 24;

PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;

PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;

PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;

PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_48M2CLK;

if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)

{

Error_Handler();

}

__HAL_RCC_PWR_CLK_ENABLE();

if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)

{

Error_Handler();

}

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

HAL_RCCEx_EnableMSIPLLMode();

__HAL_RCC_CRS_CLK_ENABLE();

RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1;

RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB;

RCC_CRSInitStruct.Polarity = RCC_CRS_SYNC_POLARITY_RISING;

RCC_CRSInitStruct.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000,1000);

RCC_CRSInitStruct.ErrorLimitValue = 34;

RCC_CRSInitStruct.HSI48CalibrationValue = 32;

HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct);

/* SysTick_IRQn interrupt configuration */

HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

________________

Attachments :

usb_test.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006Hywp&d=%2Fa%2F0X0000000bFG%2Ffi9kGTkFZ_r1t6fcjjEZkibIaHFO4u.C7feyx.fCiKU&asPdf=false