cancel
Showing results for 
Search instead for 
Did you mean: 

problem with USB and timer

Jsong
Associate II

Hello,

I need your help to recognize my issue correctly, please help me,

background:

I am having trouble using the stm32l053RB NUCLEO development board for USB protocol parsing.

issue:

When​ using timer to generate PWM, once the USB receive data is configured, the PWM waveform frequency will be greatly reduced.

Also when using the timer to generate a timed interrupt, once the USB work is configured, the CNT data will be stuck, and the timer will stop unless the USB is reset.

I have tried all the timers of this chip and will have the same problem.

Why is this happening, does USB work affect the clock of TIMER?

 if you can help to solve issue or give any advice, I am very thankful for your kindness in advance.

Thanks.​

my email is jysong@mindpointeye.com

1 ACCEPTED SOLUTION

Accepted Solutions
Jsong
Associate II

Thank you very much for your guidance.

This problem has been solved by closed USB low_power_enable.

Bit 2 LP_MODE: Low-power mode 

This mode is used when the suspend-mode power constraints require that all static power 

dissipation is avoided, except the one required to supply the external pull-up resistor. This 

condition should be entered when the application is ready to stop all system clocks, or 

reduce their frequency in order to meet the power consumption requirements of the USB 

suspend condition. The USB activity during the suspend mode (WKUP event) 

asynchronously resets this bit (it can also be reset by software). 

0: No Low-power mode.

1: Enter Low-power mode.

View solution in original post

12 REPLIES 12

You gave us little information, but I guess you attempt to run timer interrupts at a very high rate (too often), or the timer's Interrupt Service Routine (ISR) is too long.

JW

Jsong
Associate II

@Community member​ 

Thank you very much for your reply and suggestions.

Using the timer to generate the PWM waveform does not require timer's Interrupt Service Routine (ISR), but after the USB work, the PWM waveform frequency is from the original 1.316KHz changed to 2.718Hz, So I think this problem should be independent of the timer's Interrupt Service Routine (ISR).

I also tried to generate low-frequency PWM waveforms. The problem encountered after USB work is the same.

I am sorry for the small amount of information I provided.

The main function code is as follows:

int main(void)

{

/* Buffer used for USB transmission/reception*/

uint8_t usb_send[4], usb_recive[4];

HAL_Init();

/* Configure the system clock to get correspondent USB clock source */

SystemClock_Config();

/* Init Device Library */

USBD_Init(&USBD_Device, &HID_Desc, 0);

/* Register the HID class */

USBD_RegisterClass(&USBD_Device, &USBD_HID);

/* Start Device Process */

USBD_Start(&USBD_Device);

USBD_LL_PrepareReceive(&USBD_Device, HID_EPOUT_ADDR, usb_recive, 4);

              /* Compute the prescaler value to have TIM2 counter clock equal to 16 MHz */

             uwPrescalerValue = (SystemCoreClock / 16000000) - 1;

             tim = 2;//TIM2产生4channelPWM TIM21/22产生2channel PWM

             period_vl = 1600 - 1;

             pulse_vl[0] = 1200;

             pulse_vl[1] = 800;

             pulse_vl[2] = 533;

             pulse_vl[3] = 400;

             channel = 1;

             pwm_init(tim, period_vl);

             pwm_enable(channel++, pulse_vl[0]);

}

static void pwm_init(uint8_t time, uint16_t period)

{

                    

             switch (tim) {

                    case 2:

                           TimHandle.Instance = TIM2;

                           break;

                    case 21:

                           TimHandle.Instance = TIM21;

                           break;

                    case 22:

                           TimHandle.Instance = TIM22;

                           break;

                    default:

                           Error_Handler();

             }

TimHandle.Init.Prescaler    = uwPrescalerValue;

 TimHandle.Init.Period       = period;

 TimHandle.Init.ClockDivision = 0;

 TimHandle.Init.CounterMode  = TIM_COUNTERMODE_UP;

 if(HAL_TIM_PWM_Init(&TimHandle) != HAL_OK)

 {

   /* Initialization Error */

   Error_Handler();

 }

 /*##-2- Configure the PWM channels #########################################*/

  /* Common configuration for all channels */

 sConfig.OCMode    = TIM_OCMODE_PWM1;

 sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;

 sConfig.OCFastMode = TIM_OCFAST_DISABLE;

}

static void pwm_enable(uint8_t channel, uint16_t pulse)

{

      uint32_t pwm_channel;

      if (channel > 4)

             Error_Handler();

      if ((TimHandle.Instance != TIM2) && (channel > 2))

             Error_Handler();

      switch (channel) {

             case 1:

                    pwm_channel = TIM_CHANNEL_1;

                    break;

             case 2:

                    pwm_channel = TIM_CHANNEL_2;

                    break;

             case 3:

                    pwm_channel = TIM_CHANNEL_3;

                    break;

             case 4:

                    pwm_channel = TIM_CHANNEL_4;

                    break;

             default:

                    Error_Handler();

      }

      sConfig.Pulse = pulse; 

  if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, pwm_channel) != HAL_OK)

 {

   /* Configuration Error */

   Error_Handler();

 }

      if(HAL_TIM_PWM_Start(&TimHandle, pwm_channel) != HAL_OK)

 {

   /* Starting Error */

   Error_Handler();

 }

}    

I don't know if this is the culprit, but main() in microcontrollers should never return, it should end with an endless loop. The program then should remain in this loop, and should never get into the hardfault handler.

JW

I am sorry for this mistake, I missed the while(1) loop when I intercepted the code.

The complete code is as follows:

int main(void)

{

/* Buffer used for USB transmission/reception*/

  uint8_t usb_send[4], usb_recive[4];

#ifdef I2CEN

/* Buffer used for I2C transmission/reception*/

uint8_t i2c_tx[4], i2c_rx[2], count;

#endif

#ifdef PWMEN

/* pwm parameter */

uint16_t period_vl, pulse_vl[4];

uint8_t channel;

 #endif

 HAL_Init();

  

 /* Configure the system clock to get correspondent USB clock source */

 SystemClock_Config();

/* Configure Key button for remote wakeup */

 /* Init Device Library */

 USBD_Init(&USBD_Device, &HID_Desc, 0); 

 /* Register the HID class */

 USBD_RegisterClass(&USBD_Device, &USBD_HID);

 /* Start Device Process */

 USBD_Start(&USBD_Device);

USBD_LL_PrepareReceive(&USBD_Device, HID_EPOUT_ADDR, usb_recive, 4);

#ifdef I2CEN

//if(usb_recive[0]==1) {

i2c = 2;

i2c_tx[0] = 0x92;

i2c_tx[1] = 0x02;

i2c_tx[2] = 0x42;

i2c_tx[3] = 0x00;

count = 2;//register value size

I2c_init();

I2c_read(i2c_tx, i2c_rx, count);

I2c_write(i2c_tx, count);

I2c_read(i2c_tx, i2c_rx, count);

usb_send[0] = i2c_rx[0];

usb_send[1] = i2c_rx[1];

#endif

#ifdef PWMEN

 /* Compute the prescaler value to have TIM2 counter clock equal to 16 MHz */

uwPrescalerValue = (SystemCoreClock / 16000000) - 1;//16000000

tim = 2;//TIM2产生4channelPWM TIM21/22产生2channel PWM

period_vl = 3200 - 1;

pulse_vl[0] = 2400;

pulse_vl[1] = 1600;

pulse_vl[2] = 1040;

pulse_vl[3] = 800;

channel = 1;

pwm_init(tim, period_vl);

pwm_enable(channel++, pulse_vl[0]);

pwm_enable(channel++, pulse_vl[1]);

pwm_enable(channel++, pulse_vl[2]);

pwm_enable(channel++, pulse_vl[3]);

#endif

#ifdef WGEN

TIM_Init(); 

  

if(HAL_TIM_Base_Start_IT(&TimHandle_WG) != HAL_OK)

{

/* Starting Error */

Error_Handler();

}

wiegand_init();

 /* -2- Configure EXTI Line13 (connected to PC13 pin) in interrupt mode */

 EXTILine4_15_Config();

while(1) {

if(WGResult.update) {

WGResult.readNum++;

WGResult.update = 0;

}

}

#endif

#ifdef GPIOEN

BSP_LED2_Init(LED2);

BSP_LED2_On(LED2);

EXTILine4_15_Config();

#endif

USBD_LL_Transmit (&USBD_Device, HID_EPIN_ADDR, usb_send, 1);

//}

 while (1) {

}

}

Well, I don't have any specific advice - you'd need to debug this in the same way as with any other code.

Make sure the code does not jump into the hardfault handler.

If some of the timer's register content changes during USB operation, you may want to place a data breakpoint onto that register in the debugger, that should help to find out which code changed it.

JW

Jsong
Associate II

Thanks for your suggestion, I will continue to debug in this direction.

Now I have some questions about the TIMER clock source and need your guidance.

When I calculate the divider value of timer, SystemCoreClock is 16Mhz.

uwPrescalerValue = (SystemCoreClock / 16000000) - 1, the TIMx_PSC register Is setted to 0 ;

But when I actually calculate the main frequency according to the frequency of PWM waveform, the result is 32.768Khz*2^6;

Why is there such a difference, which value is the clock source of the timer?

This may be a stupid question, but I need your help to understand the problem.

Thanks!

That depends on which oscillator has been chosen as the system clock source, its setting, and then setting of the respective APB prescaler.

JW

Hi JW,

I spent some time on the systemClock_Config of the STM32L053R8.

When the TIMER and USB work at the same time, the problem of the timer counter has been repositioned.

Please take a moment to help analyze;

After ​SystemClock_Config,The RCC register as follow

0690X000009YxAYQA0.pngIf run with breakpoint,the RCC register will modify the configuration correctly. Once run without breakpoint,

RCC register will be cleaned as follow:

0690X000009YxAdQAK.png

Urgently need your help, if you need additional information or need to reproduce this problem, please feel free to contact me.

The configs as follows:​

static void SystemClock_Config(void)

{

 RCC_ClkInitTypeDef RCC_ClkInitStruct;

 RCC_OscInitTypeDef RCC_OscInitStruct;

  

 /* Enable Power Control clock */

 __HAL_RCC_PWR_CLK_ENABLE();

  

 /* The voltage scaling allows optimizing the power consumption when the device is 

   clocked below the maximum system frequency, to update the voltage scaling value 

   regarding system frequency refer to product datasheet. */

 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

 /* Enable HSI Oscillator and activate PLL with HSI as source */

 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;

 RCC_OscInitStruct.HSEState = RCC_HSE_OFF;

 RCC_OscInitStruct.HSIState = RCC_HSI_ON;

 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;

 RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;

 RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV2;

 RCC_OscInitStruct.HSICalibrationValue = 0x10;

 HAL_RCC_OscConfig(&RCC_OscInitStruct);  

  

 /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 

   clocks dividers */

 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | 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;  

 HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);

}

​PS:In the case of USB or TIMER only, the system clock configuration has been tested and is working properlyand.

I have no idea what could cause such change in RCC/system clock settings. It's very unusual for the system clock to be changed during run. Again, you may want to set data breakpoint on some of the RCC registers to see, which part of the code causes the changes.

JW